This commit is contained in:
Ghommie
2019-07-03 02:36:23 +02:00
748 changed files with 20974 additions and 13981 deletions

View File

@@ -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.

View File

@@ -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.)

20
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,20 @@
---
name: Bug report
about: Create a report to help reproduce and fix the issue
---
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may not be viewable -->
## Round ID:
<!--- **INCLUDE THE ROUND ID**
If you discovered this issue from playing tgstation hosted servers:
[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're certain the issue is to be caused by a test merge [OOC tab -> Show Server Revision], report it in the pull request's comment section rather than on the tracker(If you're unsure you can refer to the issue number by prefixing said number with #. The issue number can be found beside the title after submitting it to the tracker).If no testmerges are active, feel free to remove this section. -->
## 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. -->

View File

@@ -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.

View File

@@ -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)
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull request process. -->
:cl: optional name here
## About The Pull Request
<!-- Describe The Pull Request. Please be sure every change is documented or this can delay review and even discourage maintainers from merging your PR! -->
## Why It's Good For The Game
<!-- Please add a short description of why you think these changes would benefit the game. If you can't justify it in words, it might not be worth adding. -->
## 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.)
<!-- Both :cl:'s are required for the changelog to work! You can put your name to the right of the first :cl: if you want to overwrite your GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the icon ingame) and delete the unneeded ones. Despite some of the tags, changelogs should generally represent how a player might be affected by the changes rather than a summary of the PR's contents. -->

View File

@@ -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

View File

@@ -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" = (

View File

@@ -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

View File

@@ -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
"}

View File

@@ -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
"}

View File

@@ -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
"}

View File

@@ -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,

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -515,10 +515,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" = (
@@ -846,8 +849,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 +1457,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" = (
@@ -1673,6 +1684,12 @@
"adM" = (
/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)
@@ -2053,6 +2070,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" = (
@@ -11691,7 +11711,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 +11835,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
},
@@ -56882,12 +56902,6 @@
/obj/item/pen,
/turf/open/floor/plasteel/white,
/area/science/circuit)
"ium" = (
/mob/living/simple_animal/bot/cleanbot{
name = "C.L.E.A.N."
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"izv" = (
/obj/machinery/vending/clothing,
/obj/machinery/light/small{
@@ -57122,6 +57136,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
@@ -88468,7 +88488,7 @@ aaa
aaf
aaf
aaa
abp
adR
abP
aco
acO
@@ -88982,7 +89002,7 @@ aaa
aaa
aaf
aaa
abp
adR
abO
acq
acq
@@ -89496,15 +89516,15 @@ aaa
aaa
aaa
aaf
abp
adR
abR
abP
abP
abP
abP
abp
abp
abp
adR
adR
adR
agA
afU
ahF
@@ -94188,7 +94208,7 @@ blm
bmL
boi
bpw
ium
lKX
bsx
btX
bvj

View File

@@ -79373,12 +79373,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 +80186,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";

View File

@@ -47699,12 +47699,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
},

View File

@@ -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
},
@@ -35713,13 +35713,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" = (

View File

@@ -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

View File

@@ -136,6 +136,7 @@
#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_KEY_CHANGE "mob_key_change" //from base of /mob/transfer_key()
#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" //from base of /mob/update_sight(): ()
// /mob/living signals
#define COMSIG_LIVING_RESIST "living_resist" //from base of mob/living/resist() (/mob/living)

View File

@@ -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

View File

@@ -56,9 +56,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)

View File

@@ -16,3 +16,4 @@
#define DRINK_GOOD 2
#define DRINK_VERYGOOD 3
#define DRINK_FANTASTIC 4
#define FOOD_AMAZING 5

View File

@@ -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"

View File

@@ -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'

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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,15 @@
#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_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
#define TRAIT_ALCOHOL_TOLERANCE "alcohol_tolerance"
#define TRAIT_AGEUSIA "ageusia"
@@ -72,7 +138,11 @@
#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"
@@ -95,4 +165,3 @@
#define STASIS_MUTE "stasis"
#define GENETICS_SPELL "genetics_spell"
#define EYES_COVERED "eyes_covered"
#define CULT_EYES "cult_eyes"

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -170,7 +170,7 @@
"balls_amount" = 2,
"balls_sack_size" = BALLS_SACK_SIZE_DEF,
"balls_size" = BALLS_SIZE_DEF,
"balls_shape" = "Pair",
"balls_shape" = "Single",
"balls_cum_rate" = CUM_RATE,
"balls_cum_mult" = CUM_RATE_MULT,
"balls_efficiency" = CUM_EFFICIENCY,

View File

@@ -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

View File

@@ -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))

View File

@@ -115,9 +115,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,
@@ -158,13 +155,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,

View File

@@ -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") + "")

View File

@@ -44,6 +44,7 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/flashlight = 4,
/obj/item/flashlight/pen = 1,
/obj/item/flashlight/glowstick/random = 4,
/obj/effect/spawner/lootdrop/mre = 3,
/obj/item/multitool = 2,
/obj/item/radio/off = 2,
/obj/item/t_scanner = 5,
@@ -109,5 +110,8 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/reagent_containers/pill/floorpill = 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,
"" = 3
))

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -64,7 +64,7 @@
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
return // CIT CHANGE - ditto
if(force && user.has_trait(TRAIT_PACIFISM))
if(force && HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
return

View File

@@ -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

View File

@@ -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)
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()

View File

@@ -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

View File

@@ -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))

View File

@@ -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

View File

@@ -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)

View File

@@ -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"

View File

@@ -42,7 +42,7 @@
lose_text = "<span class='notice'>You feel smart again.</span>"
/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")
..()

View File

@@ -13,11 +13,11 @@
lose_text = "<span class='notice'>You suddenly remember how to speak.</span>"
/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 = "<span class='warning'>You can't feel your body anymore!</span>"
lose_text = "<span class='notice'>You can feel your limbs again!</span>"
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 = "<span class='warning'>You can't feel [subject] anymore!</span>"
lose_text = "<span class='notice'>You can feel [subject] again!</span>"
/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 = "<span class='notice'>You feel in control of your hands again.</span>"
/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 = "<span class='notice'>You no longer feel compelled to not harm.</span>"
/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)
..()
REMOVE_TRAIT(owner, TRAIT_PACIFISM, TRAUMA_TRAIT)
..()

View File

@@ -192,7 +192,7 @@
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, "<span class='warning'>[codeword]</span>")

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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, "<span class='notice'>Now orbiting [parent].</span>")
/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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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, "<span class='notice'>Your vision slowly returns...</span>")
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, "<span class='notice'>You can finally focus your eyes on distant objects.</span>")
M.cure_nearsighted(EYE_DAMAGE)
M.blur_eyes(10)

View File

@@ -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, "<span class='userdanger'>You go blind!</span>")
M.become_blind(EYE_DAMAGE)
else

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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("<span class='warning'>[A] leg sweeps [D]!</span>", \
"<span class='userdanger'>[A] leg sweeps you!</span>")
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 = "black"
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)

View File

@@ -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, "<span class ='warning'>You club yourself over the head with [src].</span>")
user.Knockdown(60)
if(ishuman(user))

View File

@@ -22,3 +22,8 @@
description = "<span class='nicegreen'>That drink was amazing!</span>\n"
mood_change = 4
timeout = 1200
/datum/mood_event/amazingtaste
description = "<span class='nicegreen'>Amazing taste!</span>\n"
mood_change = 50
timeout = 10 MINUTES

View File

@@ -117,6 +117,16 @@
description = "<span class='warning'>I'm missing my family heirloom...</span>\n"
mood_change = -4
/datum/mood_event/loud_gong
description = "<span class='warning'>That loud gong noise really hurt my ears!</span>\n"
mood_change = -3
timeout = 1200
/datum/mood_event/spooked
description = "<span class='warning'>The rattling of those bones...It still haunts me.</span>\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 = "<span class='boldwarning'>I recently saw my own corpse...</span>\n"
@@ -125,3 +135,11 @@
/datum/mood_event/surgery
description = "<span class='boldwarning'>HE'S CUTTING ME OPEN!!</span>\n"
mood_change = -8
/datum/mood_event/sad_empath
description = "<span class='warning'>Someone seems upset...</span>\n"
mood_change = -2
timeout = 600
/datum/mood_event/sad_empath/add_effects(mob/sadtarget)
description = "<span class='warning'>[sadtarget.name] seems upset...</span>\n"

View File

@@ -75,3 +75,27 @@
description = "<span class='nicegreen'>There is something soothing about this music.</span>\n"
mood_change = 3
timeout = 600
/datum/mood_event/betterhug
description = "<span class='nicegreen'>Someone was very nice to me.</span>\n"
mood_change = 3
timeout = 3000
/datum/mood_event/betterhug/add_effects(mob/friend)
description = "<span class='nicegreen'>[friend.name] was very nice to me.</span>\n"
/datum/mood_event/besthug
description = "<span class='nicegreen'>Someone is great to be around, they make me feel so happy!</span>\n"
mood_change = 5
timeout = 3000
/datum/mood_event/besthug/add_effects(mob/friend)
description = "<span class='nicegreen'>[friend.name] is great to be around, [friend.p_they()] makes me feel so happy!</span>\n"
/datum/mood_event/happy_empath
description = "<span class='warning'>Someone seems happy!</span>\n"
mood_change = 2
timeout = 600
/datum/mood_event/happy_empath/add_effects(var/mob/happytarget)
description = "<span class='warning'>[happytarget.name]'s happiness is infectious!</span>\n"

View File

@@ -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.

View File

@@ -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())

View File

@@ -11,8 +11,8 @@
/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)
@@ -28,8 +28,8 @@
/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")

View File

@@ -30,12 +30,12 @@
/datum/mutation/human/mute/on_acquiring(mob/living/carbon/human/owner)
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(..())
return
owner.remove_trait(TRAIT_MUTE, GENETIC_MUTATION)
REMOVE_TRAIT(owner, TRAIT_MUTE, GENETIC_MUTATION)
/datum/mutation/human/smile
@@ -229,4 +229,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)

View File

@@ -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."

View File

@@ -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, "<i><font color=#800080>We can faintly sense an outsider trying to communicate through the hivemind...</font></i>")
if(LINGHIVE_LING)
if (user.has_trait(CHANGELING_HIVEMIND_MUTE))
if (HAS_TRAIT(user, CHANGELING_HIVEMIND_MUTE))
to_chat(user, "<span class='warning'>The poison in the air hinders our ability to interact with the hivemind.</span>")
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))

View File

@@ -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)

View File

@@ -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 = "<span class='danger'>Things far away from you start looking blurry.</span>"

View File

@@ -35,6 +35,14 @@
lose_text = "<span class='danger'>You no longer feel like drinking would ease your pain.</span>"
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 = "<span class='notice'>You feel in tune with those around you.</span>"
lose_text = "<span class='danger'>You feel isolated from others.</span>"
/datum/quirk/freerunning
name = "Freerunning"
desc = "You're great at quick moves! You can climb tables more quickly."
@@ -43,6 +51,15 @@
gain_text = "<span class='notice'>You feel lithe on your feet!</span>"
lose_text = "<span class='danger'>You feel clumsy again.</span>"
/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 = "<span class='notice'>You want to hug someone.</span>"
lose_text = "<span class='danger'>You no longer feel compelled to hug others.</span>"
mood_quirk = TRUE
/datum/quirk/jolly
name = "Jolly"
desc = "You sometimes just feel happy, for no reason at all."

View File

@@ -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, "<span class='boldannounce'>Your antagonistic nature has caused you to renounce your pacifism.</span>")
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)

View File

@@ -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))

View File

@@ -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

View File

@@ -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

View File

@@ -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, "<span class='notice'>It has [reagents.total_volume] unit\s left.</span>")
else

View File

@@ -31,6 +31,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 +297,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 +319,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)

View File

@@ -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

View File

@@ -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

View File

@@ -62,5 +62,6 @@
/datum/outfit/syndicate/clownop/leader
name = "Clown Operative Leader - Basic"
id = /obj/item/card/id/syndicate/nuke_leader
gloves = /obj/item/clothing/gloves/krav_maga/combatglovesplus
r_hand = /obj/item/nuclear_challenge/clownops
command_radio = TRUE

View File

@@ -26,7 +26,7 @@
return FALSE
else
return FALSE
if(M.has_trait(TRAIT_MINDSHIELD) || issilicon(M) || isbot(M) || isdrone(M) || is_servant_of_ratvar(M) || !M.client)
if(HAS_TRAIT(M, TRAIT_MINDSHIELD) || issilicon(M) || isbot(M) || isdrone(M) || is_servant_of_ratvar(M) || !M.client)
return FALSE //can't convert machines, shielded, braindead, or ratvar's dogs
return TRUE

View File

@@ -137,6 +137,7 @@
/datum/outfit/syndicate/leader
name = "Syndicate Leader - Basic"
id = /obj/item/card/id/syndicate/nuke_leader
gloves = /obj/item/clothing/gloves/krav_maga/combatglovesplus
r_hand = /obj/item/nuclear_challenge
command_radio = TRUE

View File

@@ -542,6 +542,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
return checking.researched_nodes.len >= target_amount
/datum/objective/capture
var/captured_amount = 0
/datum/objective/capture/proc/gen_amount_goal()
target_amount = rand(5,10)
@@ -549,8 +550,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
return target_amount
/datum/objective/capture/check_completion()//Basically runs through all the mobs in the area to determine how much they are worth.
var/captured_amount = 0
var/area/centcom/holding/A = GLOB.areas_by_type[/area/centcom/holding]
/*var/area/centcom/holding/A = GLOB.areas_by_type[/area/centcom/holding]
for(var/mob/living/carbon/human/M in A)//Humans.
if(M.stat == DEAD)//Dead folks are worth less.
captured_amount+=0.5
@@ -573,7 +573,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
if(M.stat == DEAD)
captured_amount+=1
continue
captured_amount+=2
captured_amount+=2*/ //Removed in favour of adding points on capture, in energy_net_nets.dm
return captured_amount >= target_amount

View File

@@ -124,7 +124,7 @@
/datum/objective_item/steal/plasma/check_special_completion(obj/item/tank/T)
var/target_amount = text2num(name)
var/found_amount = 0
found_amount += T.air_contents.gases[/datum/gas/plasma] ? T.air_contents.gases[/datum/gas/plasma][MOLES] : 0
found_amount += T.air_contents.gases[/datum/gas/plasma]
return found_amount>=target_amount

View File

@@ -35,15 +35,14 @@
/obj/item/pda/clear,
/obj/item/pda/syndicate,
/obj/item/pda/chameleon,
/obj/item/pda/chameleon/broken)
/obj/item/pda/chameleon/broken,
/obj/item/pda/lieutenant)
for(var/P in typesof(/obj/item/pda) - blocked)
var/obj/item/pda/D = new P
//D.name = "PDA Style [colorlist.len+1]" //Gotta set the name, otherwise it all comes up as "PDA"
D.name = D.icon_state //PDAs don't have unique names, but using the sprite names works.
src.colorlist += D
for(var/A in typesof(/obj/item/pda) - blocked)
var/obj/item/pda/P = A
var/PDA_name = initial(P.name)
colorlist += PDA_name
colorlist[PDA_name] = list(initial(P.icon_state), initial(P.desc), initial(P.overlays_offsets), initial(P.overlays_icons))
/obj/machinery/pdapainter/Destroy()
QDEL_NULL(storedpda)
@@ -108,22 +107,20 @@
if(.)
return
if(storedpda)
var/obj/item/pda/P
P = input(user, "Select your color!", "PDA Painting") as null|anything in colorlist
if(!P)
return
if(!in_range(src, user))
return
if(!storedpda)//is the pda still there?
return
storedpda.icon_state = P.icon_state
storedpda.desc = P.desc
ejectpda()
else
if(!storedpda)
to_chat(user, "<span class='notice'>[src] is empty.</span>")
return
var/choice = input(user, "Select the new skin!", "PDA Painting") as null|anything in colorlist
if(!choice || !storedpda || !in_range(src, user))
return
var/list/P = colorlist[choice]
storedpda.icon_state = P[1]
storedpda.desc = P[2]
storedpda.overlays_offsets = P[3]
storedpda.overlays_icons = P[4]
storedpda.set_new_overlays()
storedpda.update_icon()
ejectpda()
/obj/machinery/pdapainter/verb/ejectpda()
set name = "Eject PDA"

View File

@@ -168,9 +168,11 @@ Class Procs:
update_icon()
updateUsrDialog()
/obj/machinery/proc/dropContents()
/obj/machinery/proc/dropContents(list/subset = null)
var/turf/T = get_turf(src)
for(var/atom/movable/A in contents)
if(subset && !(A in subset))
continue
A.forceMove(T)
if(isliving(A))
var/mob/living/L = A

View File

@@ -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)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,206 @@
// ** 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
var/turn_speed = 5 //Measured in deciseconds.
/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 = "<a href='byond://?src=[REF(src)];close=1'>Close</a>"
dat += "<center><h4>[enemy_name]</h4></center>"
dat += "<br><center><h3>[temp]</h3></center>"
dat += "<br><center>Health: [player_hp] | Magic: [player_mp] | Enemy Health: [enemy_hp]</center>"
if (gameover)
dat += "<center><b><a href='byond://?src=[REF(src)];newgame=1'>New Game</a>"
else
dat += "<center><b><a href='byond://?src=[REF(src)];attack=1'>Attack</a> | "
dat += "<a href='byond://?src=[REF(src)];heal=1'>Heal</a> | "
dat += "<a href='byond://?src=[REF(src)];charge=1'>Recharge Power</a>"
dat += "</b></center>"
var/datum/browser/popup = new(user, "arcade", "Space Villain 2000")
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
popup.open()
/obj/machinery/computer/arcade/battle/Topic(href, href_list)
if(..())
return
if (!blocked && !gameover)
if (href_list["attack"])
blocked = TRUE
var/attackamt = rand(2,6)
temp = "You attack for [attackamt] damage!"
playsound(loc, 'sound/arcade/hit.ogg', 50, 1, extrarange = -3, falloff = 10)
updateUsrDialog()
if(turtle > 0)
turtle--
sleep(turn_speed)
enemy_hp -= attackamt
arcade_action(usr)
else if (href_list["heal"])
blocked = TRUE
var/pointamt = rand(1,3)
var/healamt = rand(6,8)
temp = "You use [pointamt] magic to heal for [healamt] damage!"
playsound(loc, 'sound/arcade/heal.ogg', 50, 1, extrarange = -3, falloff = 10)
updateUsrDialog()
turtle++
sleep(turn_speed)
player_mp -= pointamt
player_hp += healamt
blocked = TRUE
updateUsrDialog()
arcade_action(usr)
else if (href_list["charge"])
blocked = TRUE
var/chargeamt = rand(4,7)
temp = "You regain [chargeamt] points"
playsound(loc, 'sound/arcade/mana.ogg', 50, 1, extrarange = -3, falloff = 10)
player_mp += chargeamt
if(turtle > 0)
turtle--
updateUsrDialog()
sleep(turn_speed)
arcade_action(usr)
if (href_list["close"])
usr.unset_machine()
usr << browse(null, "window=arcade")
else if (href_list["newgame"]) //Reset everything
temp = "New Round"
player_hp = initial(player_hp)
player_mp = initial(player_mp)
enemy_hp = initial(enemy_hp)
enemy_mp = initial(enemy_mp)
gameover = FALSE
turtle = 0
if(obj_flags & EMAGGED)
Reset()
obj_flags &= ~EMAGGED
add_fingerprint(usr)
updateUsrDialog()
return
/obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user)
if ((enemy_mp <= 0) || (enemy_hp <= 0))
if(!gameover)
gameover = TRUE
temp = "[enemy_name] has fallen! Rejoice!"
playsound(loc, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 10)
if(obj_flags & EMAGGED)
new /obj/effect/spawner/newbomb/timer/syndicate(loc)
new /obj/item/clothing/head/collectable/petehat(loc)
message_admins("[ADMIN_LOOKUPFLW(usr)] has outbombed Cuban Pete and been awarded a bomb.")
log_game("[key_name(usr)] has outbombed Cuban Pete and been awarded a bomb.")
Reset()
obj_flags &= ~EMAGGED
else
prizevend(user)
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("win", (obj_flags & EMAGGED ? "emagged":"normal")))
else if ((obj_flags & EMAGGED) && (turtle >= 4))
var/boomamt = rand(5,10)
temp = "[enemy_name] throws a bomb, exploding you for [boomamt] damage!"
playsound(loc, 'sound/arcade/boom.ogg', 50, 1, extrarange = -3, falloff = 10)
player_hp -= boomamt
else if ((enemy_mp <= 5) && (prob(70)))
var/stealamt = rand(2,3)
temp = "[enemy_name] steals [stealamt] of your power!"
playsound(loc, 'sound/arcade/steal.ogg', 50, 1, extrarange = -3, falloff = 10)
player_mp -= stealamt
updateUsrDialog()
if (player_mp <= 0)
gameover = TRUE
sleep(turn_speed)
temp = "You have been drained! GAME OVER"
playsound(loc, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 10)
if(obj_flags & EMAGGED)
usr.gib()
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "mana", (obj_flags & EMAGGED ? "emagged":"normal")))
else if ((enemy_hp <= 10) && (enemy_mp > 4))
temp = "[enemy_name] heals for 4 health!"
playsound(loc, 'sound/arcade/heal.ogg', 50, 1, extrarange = -3, falloff = 10)
enemy_hp += 4
enemy_mp -= 4
else
var/attackamt = rand(3,6)
temp = "[enemy_name] attacks for [attackamt] damage!"
playsound(loc, 'sound/arcade/hit.ogg', 50, 1, extrarange = -3, falloff = 10)
player_hp -= attackamt
if ((player_mp <= 0) || (player_hp <= 0))
gameover = TRUE
temp = "You have been crushed! GAME OVER"
playsound(loc, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 10)
if(obj_flags & EMAGGED)
usr.gib()
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal")))
blocked = FALSE
return
/obj/machinery/computer/arcade/battle/emag_act(mob/user)
if(obj_flags & EMAGGED)
return
to_chat(user, "<span class='warning'>A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!</span>")
temp = "If you die in the game, you die for real!"
player_hp = 30
player_mp = 10
enemy_hp = 45
enemy_mp = 20
gameover = FALSE
blocked = FALSE
obj_flags |= EMAGGED
enemy_name = "Cuban Pete"
name = "Outbomb Cuban Pete"
updateUsrDialog()

View File

@@ -0,0 +1,390 @@
#define MINESWEEPER_GAME_MAIN_MENU 0
#define MINESWEEPER_GAME_PLAYING 1
#define MINESWEEPER_GAME_LOST 2
#define MINESWEEPER_GAME_WON 3
#define MINESWEEPERIMG(what) {"<img style='border:0' <span class="minesweeper16x16 [#what]"></span>"} //Basically bypassing asset.icon_tag()
/obj/machinery/computer/arcade/minesweeper
name = "Minesweeper"
desc = "An arcade machine that generates grids. It seems that the machine sparks and screeches when a grid is generated, as if it cannot cope with the intensity of generating the grid."
icon_state = "arcade"
circuit = /obj/item/circuitboard/computer/arcade/minesweeper
var/area
var/difficulty = "" //To show what difficulty you are playing
var/flag_text = ""
var/flagging = FALSE
var/game_status = MINESWEEPER_GAME_MAIN_MENU
var/mine_limit = 0
var/mine_placed = 0
var/mine_sound = TRUE //So it doesn't get repeated when multiple mines are exposed
var/randomcolour = 1
var/randomnumber = 1 //Random emagged game iteration number to be displayed, put here so it is persistent across one individual arcade machine
var/safe_squares_revealed
var/saved_web = "" //To display the web if you click on the arcade
var/win_condition
var/rows = 1
var/columns = 1
var/table[31][51] //Make the board boys, 30x50 board
var/spark_spam = FALSE
/obj/machinery/computer/arcade/minesweeper/interact(mob/user)
var/emagged = CHECK_BITFIELD(obj_flags, EMAGGED)
var/dat
if(game_status == MINESWEEPER_GAME_MAIN_MENU)
dat += "<head><title>Minesweeper</title></head><div align='center'><b>Minesweeper[emagged ? " <font color='red'>EXTREME EDITION</font>: Iteration <font color='[randomcolour]'>#[randomnumber]</font>" : ""]</b><br>" //Different colour mix for every random number made
dat += "<font size='2'> [emagged ? "Explode in the game, explode in real life" : "Reveal all the squares without hitting a mine"]!<br>What difficulty do you want to play?<br><br><br><br><b><a href='byond://?src=[REF(src)];Easy=1'><font color='#cc66ff'>Easy (9x9 board, 10 mines)</font></a><br><a href='byond://?src=[REF(src)];Intermediate=1'><font color='#cc66ff'>Intermediate (16x16 board, 40 mines)</font></a><br><a href='byond://?src=[REF(src)];Hard=1'><font color='#cc66ff'>Hard (16x30 board, 99 mines)</font></a><br><a href='byond://?src=[REF(src)];Custom=1'><font color='#cc66ff'>Custom</font>"
else
dat = saved_web
user = usr
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/simple/minesweeper)
assets.send(user)
user << browse(dat,"window=minesweeper,size=400x500")
add_fingerprint(user)
. = ..()
/obj/machinery/computer/arcade/minesweeper/proc/reset_spark_spam()
spark_spam = FALSE
/obj/machinery/computer/arcade/minesweeper/Topic(href, href_list)
. = ..()
if(.)
return
var/exploding_hell = FALSE //For emagged failures
var/reset_board = FALSE
var/mob/living/user = usr //To identify who the hell is using this window, this should also make things like aliens and monkeys able to use the machine!!
var/web_difficulty_menu = "<font size='2'> Reveal all the squares without hitting a mine!<br>What difficulty do you want to play?<br><br><br><br><b><a href='byond://?src=[REF(src)];Easy=1'><font color='#cc66ff'>Easy (9x9 board, 10 mines)</font></a><br><a href='byond://?src=[REF(src)];Intermediate=1'><font color='#cc66ff'>Intermediate (16x16 board, 40 mines)</font></a><br><a href='byond://?src=[REF(src)];Hard=1'><font color='#cc66ff'>Hard (16x30 board, 99 mines)</font></a><br><a href='byond://?src=[REF(src)];Custom=1'><font color='#cc66ff'>Custom</font>"
var/web = "<head><title>Minesweeper</title></head><div align='center'><b>Minesweeper</b><br>"
var/static_web = "<head><title>Minesweeper</title></head><div align='center'><b>Minesweeper</b><br>" //When we need to revert to the main menu we set web as this
web = static_web
if(CHECK_BITFIELD(obj_flags, EMAGGED))
web = "<head><title>Minesweeper</title></head><body><div align='center'><b>Minesweeper <font color='red'>EXTREME EDITION</font>: Iteration <font color='[randomcolour]'>#[randomnumber]</font></b><br>" //Different colour mix for every random number made
if(!spark_spam)
do_sparks(5, 1, src)
spark_spam = TRUE
addtimer(CALLBACK(src, .proc/reset_spark_spam), 30)
var/startup_sound = CHECK_BITFIELD(obj_flags, EMAGGED) ? 'sound/arcade/minesweeper_emag2.ogg' : 'sound/arcade/minesweeper_startup.ogg'
if(href_list["Main_Menu"])
game_status = MINESWEEPER_GAME_MAIN_MENU
mine_limit = 0
rows = 0
columns = 0
mine_placed = 0
if(href_list["Easy"])
playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10)
flag_text = "OFF"
game_status = MINESWEEPER_GAME_PLAYING
reset_board = TRUE
difficulty = "Easy"
rows = 10 //9x9 board
columns = 10
mine_limit = 10
if(href_list["Intermediate"])
playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10)
flag_text = "OFF"
game_status = MINESWEEPER_GAME_PLAYING
reset_board = TRUE
difficulty = "Intermediate"
rows = 17 //16x16 board
columns = 17
mine_limit = 40
if(href_list["Hard"])
playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10)
flag_text = "OFF"
game_status = MINESWEEPER_GAME_PLAYING
reset_board = TRUE
difficulty = "Hard"
rows = 17 //16x30 board
columns = 31
mine_limit = 99
if(href_list["Custom"])
if(custom_generation(usr))
flag_text = "OFF"
game_status = MINESWEEPER_GAME_PLAYING
reset_board = TRUE
difficulty = "Custom"
playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10)
if(href_list["Flag"])
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, 0, extrarange = -3, falloff = 10)
if(!flagging)
flagging = TRUE
flag_text = "ON"
else
flagging = FALSE
flag_text = "OFF"
if(game_status == MINESWEEPER_GAME_MAIN_MENU)
if(CHECK_BITFIELD(obj_flags, EMAGGED))
playsound(loc, 'sound/arcade/minesweeper_emag2.ogg', 50, 0, extrarange = -3, falloff = 10)
web += "<font size='2'>Explode in the game, explode in real life!<br>What difficulty do you want to play?<br><br><br><br><b><a href='byond://?src=[REF(src)];Easy=1'><font color='#cc66ff'>Easy (9x9 board, 10 mines)</font></a><br><a href='byond://?src=[REF(src)];Intermediate=1'><font color='#cc66ff'>Intermediate (16x16 board, 40 mines)</font></a><br><a href='byond://?src=[REF(src)];Hard=1'><font color='#cc66ff'>Hard (16x30 board, 99 mines)</font></a><br><a href='byond://?src=[REF(src)];Custom=1'><font color='#cc66ff'>Custom</font>"
else
playsound(loc, 'sound/arcade/minesweeper_startup.ogg', 50, 0, extrarange = -3, falloff = 10)
web += web_difficulty_menu
if(game_status == MINESWEEPER_GAME_PLAYING)
mine_sound = TRUE
area = (rows-1)*(columns-1)
if(reset_board)
mine_placed = 0
var/reset_everything = TRUE
make_mines(reset_everything)
safe_squares_revealed = 0
win_condition = area-mine_placed
if(game_status != MINESWEEPER_GAME_MAIN_MENU)
for(var/y1=1;y1<rows;y1++)
for(var/x1=1;x1<columns;x1++)
var/coordinates
coordinates = (y1*100)+x1
if(href_list["[coordinates]"])
if(game_status == MINESWEEPER_GAME_PLAYING) //Don't do anything if we won or something
if(!flagging)
if(table[y1][x1] < 10 && table[y1][x1] >= 0) //Check that it's not already revealed, and stop flag removal if we're out of flag mode
table[y1][x1] += 10
if(table[y1][x1] != 10)
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, 0, extrarange = -3, falloff = 10)
else
if(game_status != MINESWEEPER_GAME_LOST && game_status != MINESWEEPER_GAME_WON)
game_status = MINESWEEPER_GAME_LOST
if(CHECK_BITFIELD(obj_flags, EMAGGED) && !exploding_hell)
exploding_hell = TRUE
explode_EVERYTHING()
if(mine_sound)
switch(rand(1,3)) //Play every time a mine is hit
if(1)
playsound(loc, 'sound/arcade/minesweeper_explosion1.ogg', 50, 0, extrarange = -3, falloff = 10)
if(2)
playsound(loc, 'sound/arcade/minesweeper_explosion2.ogg', 50, 0, extrarange = -3, falloff = 10)
if(3)
playsound(loc, 'sound/arcade/minesweeper_explosion3.ogg', 50, 0, extrarange = -3, falloff = 10)
mine_sound = FALSE
else
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, 0, extrarange = -3, falloff = 10)
if(table[y1][x1] >= 0) //Check that it's not already flagged
table[y1][x1] -= 10
else if(table[y1][x1] < 0) //If flagged, remove the flag
table[y1][x1] += 10
if(href_list["same_board"]) //Reset the board... kinda
if(game_status != MINESWEEPER_GAME_PLAYING)
game_status = MINESWEEPER_GAME_PLAYING
if(table[y1][x1] >= 10) //If revealed, become unrevealed!
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
table[y1][x1] -= 10
if(table[y1][x1] > 10 && !reset_board)
safe_squares_revealed += 1
var/y2 = y1
var/x2 = x1
work_squares(y2, x2) //Work squares while in this loop so there's less load
reset_board = FALSE
web += "<table>" //Start setting up the html table
web += "<tbody>"
for(var/y1=1;y1<rows;y1++)
web += "<tr>"
for(var/x1=1;x1<columns;x1++)
var/coordinates
coordinates = (y1*100)+x1
switch(table[y1][x1])
if(-10 to -1)
if(game_status != MINESWEEPER_GAME_PLAYING)
web += "<td>[MINESWEEPERIMG(flag)]</td>"
else
web += "<td><a href='byond://?src=[REF(src)];[coordinates]=1'>[MINESWEEPERIMG(flag)]</a></td>"
if(0)
if(game_status != MINESWEEPER_GAME_PLAYING)
web += "<td>[MINESWEEPERIMG(mine)]</td>"
else
web += "<td><a href='byond://?src=[REF(src)];[coordinates]=1'>[MINESWEEPERIMG(hidden)]</a></td>" //Make unique hrefs for every square
if(1 to 9)
if(game_status != MINESWEEPER_GAME_PLAYING)
web += "<td>[MINESWEEPERIMG(hidden)]</td>"
else
web += "<td><a href='byond://?src=[REF(src)];[coordinates]=1'>[MINESWEEPERIMG(hidden)]</a></td>" //Make unique hrefs for every square
if(10)
web += "<td>[MINESWEEPERIMG(minehit)]</td>"
if(11)
web += "<td>[MINESWEEPERIMG(empty)]</td>"
if(12)
web += "<td>[MINESWEEPERIMG(1)]</td>"
if(13)
web += "<td>[MINESWEEPERIMG(2)]</td>"
if(14)
web += "<td>[MINESWEEPERIMG(3)]</td>"
if(15)
web += "<td>[MINESWEEPERIMG(4)]</td>"
if(16)
web += "<td>[MINESWEEPERIMG(5)]</td>"
if(17)
web += "<td>[MINESWEEPERIMG(6)]</td>"
if(18)
web += "<td>[MINESWEEPERIMG(7)]</td>"
if(19)
web += "<td>[MINESWEEPERIMG(8)]</td>"
web += "</tr>"
web += "</table>"
web += "</tbody>"
web += "<br>"
if(safe_squares_revealed >= win_condition && game_status == MINESWEEPER_GAME_PLAYING)
game_status = MINESWEEPER_GAME_WON
if(rows < 10 || columns < 10) //If less than easy difficulty
playsound(loc, 'sound/arcade/minesweeper_winfail.ogg', 50, 0, extrarange = -3, falloff = 10)
say("You cleared the board of all mines, but you picked too small of a board! Try again with at least a 9x9 board!")
else
playsound(loc, 'sound/arcade/minesweeper_win.ogg', 50, 0, extrarange = -3, falloff = 10)
say("You cleared the board of all mines! Congratulations!")
if(CHECK_BITFIELD(obj_flags, EMAGGED))
var/itemname
switch(rand(1,3))
if(1)
itemname = "a syndicate bomb beacon"
new /obj/item/sbeacondrop/bomb(loc)
if(2)
itemname = "a grenade launcher"
new /obj/item/gun/ballistic/revolver/grenadelauncher/unrestricted(loc)
new /obj/item/ammo_casing/a40mm(loc)
new /obj/item/ammo_casing/a40mm(loc)
new /obj/item/ammo_casing/a40mm(loc)
if(3)
itemname = "two bags of c4"
new /obj/item/storage/backpack/duffelbag/syndie/c4(loc)
new /obj/item/storage/backpack/duffelbag/syndie/x4(loc)
message_admins("[key_name_admin(user)] won emagged Minesweeper and got [itemname]!")
visible_message("<span class='notice'>[src] dispenses [itemname]!</span>", "<span class='notice'>You hear a chime and a clunk.</span>")
DISABLE_BITFIELD(obj_flags, EMAGGED)
else
var/dope_prizes = (area >= 480) ? list(ARCADE_WEIGHT_RARE) : (area >= 256) ? list(ARCADE_WEIGHT_RARE, ARCADE_WEIGHT_TRICK) : null
prizevend(user, dope_prizes)
if(game_status == MINESWEEPER_GAME_WON)
web += "[(rows < 10 || columns < 10) ? "<font size='4'>You won, but your board was too small! Pick a bigger board next time!" : "<font size='6'>Congratulations, you have won!"]<br><font size='3'>Want to play again?<br><b><a href='byond://?src=[REF(src)];Easy=1'><font color='#cc66ff'>Easy (9x9 board, 10 mines)</font></a><br><a href='byond://?src=[REF(src)];Intermediate=1'><font color='#cc66ff'>Intermediate (16x16 board, 40 mines)</font></a><br><a href='byond://?src=[REF(src)];Hard=1'><font color='#cc66ff'>Hard (16x30 board, 99 mines)</font></a><br><a href='byond://?src=[REF(src)];Custom=1'><font color='#cc66ff'>Custom</font></a></b><br><a href='byond://?src=[REF(src)];same_board=1'><font color='#cc66ff'>Play on the same board</font></a><br><a href='byond://?src=[REF(src)];Main_Menu=1'><font color='#cc66ff'>Return to Main Menu</font></a></b><br>"
if(game_status == MINESWEEPER_GAME_LOST)
web += "<font size='6'>You have lost!<br><font size='3'>Try again?<br><b><a href='byond://?src=[REF(src)];Easy=1'><font color='#cc66ff'>Easy (9x9 board, 10 mines)</font></a><br><a href='byond://?src=[REF(src)];Intermediate=1'><font color='#cc66ff'>Intermediate (16x16 board, 40 mines)</font></a><br><a href='byond://?src=[REF(src)];Hard=1'><font color='#cc66ff'>Hard (16x30 board, 99 mines)</font></a><br><a href='byond://?src=[REF(src)];Custom=1'><font color='#cc66ff'>Custom</font></a></b><br><a href='byond://?src=[REF(src)];same_board=1'><font color='#cc66ff'>Play on the same board</font></a><br><a href='byond://?src=[REF(src)];Main_Menu=1'><font color='#cc66ff'>Return to Main Menu</font></a></b><br>"
if(game_status == MINESWEEPER_GAME_PLAYING)
web += "<a href='byond://?src=[REF(src)];Main_Menu=1'><font color='#cc66ff'>Return to Main Menu</font></a><br>"
web += "<div align='right'>Difficulty: [difficulty]<br>Mines: [mine_placed]<br>Rows: [rows-1]<br>Columns: [columns-1]<br><a href='byond://?src=[REF(src)];Flag=1'><font color='#cc66ff'>Flagging mode: [flag_text]</font></a></div>"
web += "</div>"
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/minesweeper)
saved_web = sheet.css_tag()
saved_web += web
updateDialog()
return
/obj/machinery/computer/arcade/minesweeper/emag_act(mob/user)
if(CHECK_BITFIELD(obj_flags, EMAGGED))
return
desc = "An arcade machine that generates grids. It's clunking and sparking everywhere, almost as if threatening to explode at any moment!"
do_sparks(5, 1, src)
randomnumber = rand(1,255)
randomcolour = rgb(randomnumber,randomnumber/2,randomnumber/3)
ENABLE_BITFIELD(obj_flags, EMAGGED)
if(game_status == MINESWEEPER_GAME_MAIN_MENU)
to_chat(user, "<span class='warning'>An ominous tune plays from the arcade's speakers!</span>")
playsound(user, 'sound/arcade/minesweeper_emag1.ogg', 100, 0, extrarange = 3, falloff = 10)
else //Can't let you do that, star fox!
to_chat(user, "<span class='warning'>The machine buzzes and sparks... the game has been reset!</span>")
playsound(user, 'sound/machines/buzz-sigh.ogg', 100, 0, extrarange = 3, falloff = 10) //Loud buzz
game_status = MINESWEEPER_GAME_MAIN_MENU
/obj/machinery/computer/arcade/minesweeper/proc/custom_generation(mob/user)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) //Entered into the menu so ping sound
var/new_rows = input(user, "How many rows do you want? (Minimum: 4, Maximum: 30)", "Minesweeper Rows") as null|num
if(!new_rows || !user.canUseTopic(src, !issilicon(user)))
return FALSE
new_rows = CLAMP(new_rows + 1, 4, 30)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
var/new_columns = input(user, "How many columns do you want? (Minimum: 4, Maximum: 50)", "Minesweeper Squares") as null|num
if(!new_columns || !user.canUseTopic(src, !issilicon(user)))
return FALSE
new_columns = CLAMP(new_columns + 1, 4, 50)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
var/grid_area = (new_rows - 1) * (new_columns - 1)
var/lower_limit = round(grid_area*0.156)
var/upper_limit = round(grid_area*0.85)
var/new_mine_limit = input(user, "How many mines do you want? (Minimum: [lower_limit], Maximum: [upper_limit])", "Minesweeper Mines") as null|num
if(!new_mine_limit || !user.canUseTopic(src, !issilicon(user)))
return FALSE
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
rows = new_rows
columns = new_columns
mine_limit = CLAMP(new_mine_limit, lower_limit, upper_limit)
return TRUE
/obj/machinery/computer/arcade/minesweeper/proc/make_mines(var/reset_everything)
if(mine_placed < mine_limit)
for(var/y1=1;y1<rows;y1++) //Board resetting and mine building
for(var/x1=1;x1<columns;x1++)
if(prob(area/mine_limit) && mine_placed < mine_limit && table[y1][x1] != 0) //Unlikely for this to happen but this has eaten mines before
table[y1][x1] = 0
mine_placed += 1
else if(reset_everything)
table[y1][x1] = 1
reset_everything = FALSE
make_mines() //In case the first pass doesn't generate enough mines
/obj/machinery/computer/arcade/minesweeper/proc/work_squares(var/y2, var/x2, var/y3, var/x3)
if(y3 > 0 && x3 > 0)
y2 = y3
x2 = x3
if(table[y2][x2] == 1)
for(y3=y2-1;y3<y2+2;y3++)
if(y3 >= rows || y3 < 1)
continue
for(x3=x2-1;x3<x2+2;x3++)
if(x3 >= columns || x3 < 1)
continue
if(table[y3][x3] == 0)
table[y2][x2] += 1
if(table[y2][x2] == 11)
for(y3=y2-1;y3<y2+2;y3++)
if(y3 >= rows || y3 < 1)
continue
for(x3=x2-1;x3<x2+2;x3++)
if(x3 >= columns || x3 < 1)
continue
if(table[y3][x3] > 0 && table[y3][x3] < 10)
table[y3][x3] += 10
work_squares(y3, x3) //Refresh so we check everything we might be missing
/obj/machinery/computer/arcade/minesweeper/proc/explode_EVERYTHING()
var/mob/living/user = usr
to_chat(user, "<span class='boldwarning'>You feel a great sense of dread wash over you, as if you just unleashed armageddon upon yourself!</span>")
var/row_limit = rows-1
var/column_limit = columns-1
var/mine_limit_v2 = mine_limit
if(rows > 11)
row_limit = 10
if(columns > 11)
column_limit = 10
if(mine_limit > (rows*columns) * 0.25)
mine_limit_v2 = 24
message_admins("[key_name_admin(user)] failed an emagged Minesweeper arcade and has unleashed an explosion armageddon of size [row_limit],[column_limit] around [ADMIN_LOOKUPFLW(user.loc)]!")
if(mine_limit_v2 < 10)
explosion(loc, 2, 5, 10, 15) //Thought you could survive by putting as few mines as possible, huh??
else
explosion(loc, 1, 3, rand(1,5), rand(1,10))
for(var/y69=y-row_limit;y69<y+row_limit;y69++) //Create a shitton of explosions in irl turfs if we lose, it will probably kill us
for(var/x69=x-column_limit;x69<x+column_limit;x69++)
if(prob(mine_limit_v2)) //Probability of explosion happening, according to how many mines were on the board... up to a limit
var/explosionloc
explosionloc = locate(y69,x69,z)
explosion(explosionloc, 0, rand(1,2),rand(1,5),rand(3,10), adminlog = FALSE)
#undef MINESWEEPERIMG
#undef MINESWEEPER_GAME_MAIN_MENU
#undef MINESWEEPER_GAME_PLAYING
#undef MINESWEEPER_GAME_LOST
#undef MINESWEEPER_GAME_WON

View File

@@ -0,0 +1,31 @@
// Memeorable yet too short arcade games ahead.
// ** AMPUTATION ** //
/obj/machinery/computer/arcade/amputation
name = "Mediborg's Amputation Adventure"
desc = "A picture of a blood-soaked medical cyborg flashes on the screen. The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a <b>coward!</b>\""
icon_state = "arcade"
circuit = /obj/item/circuitboard/computer/arcade/amputation
/obj/machinery/computer/arcade/amputation/attack_hand(mob/user)
if(!iscarbon(user))
return
var/mob/living/carbon/c_user = user
if(!c_user.get_bodypart(BODY_ZONE_L_ARM) && !c_user.get_bodypart(BODY_ZONE_R_ARM))
return
to_chat(c_user, "<span class='warning'>You move your hand towards the machine, and begin to hesitate as a bloodied guillotine emerges from inside of it...</span>")
if(do_after(c_user, 50, target = src))
to_chat(c_user, "<span class='userdanger'>The guillotine drops on your arm, and the machine sucks it in!</span>")
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
var/which_hand = BODY_ZONE_L_ARM
if(!(c_user.active_hand_index % 2))
which_hand = BODY_ZONE_R_ARM
var/obj/item/bodypart/chopchop = c_user.get_bodypart(which_hand)
chopchop.dismember()
qdel(chopchop)
playsound(loc, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 10)
for(var/i=1; i<=rand(3,5); i++)
prizevend(user)
else
to_chat(c_user, "<span class='notice'>You (wisely) decide against putting your hand in the machine.</span>")

View File

@@ -0,0 +1,809 @@
// *** THE ORION TRAIL ** //
#define ORION_TRAIL_WINTURN 9
//Orion Trail Events
#define ORION_TRAIL_RAIDERS "Raiders"
#define ORION_TRAIL_FLUX "Interstellar Flux"
#define ORION_TRAIL_ILLNESS "Illness"
#define ORION_TRAIL_BREAKDOWN "Breakdown"
#define ORION_TRAIL_LING "Changelings?"
#define ORION_TRAIL_LING_ATTACK "Changeling Ambush"
#define ORION_TRAIL_MALFUNCTION "Malfunction"
#define ORION_TRAIL_COLLISION "Collision"
#define ORION_TRAIL_SPACEPORT "Spaceport"
#define ORION_TRAIL_BLACKHOLE "BlackHole"
#define ORION_STATUS_START 1
#define ORION_STATUS_NORMAL 2
#define ORION_STATUS_GAMEOVER 3
#define ORION_STATUS_MARKET 4
/obj/machinery/computer/arcade/orion_trail
name = "The Orion Trail"
desc = "Learn how our ancestors got to Orion, and have fun in the process!"
icon_state = "arcade"
circuit = /obj/item/circuitboard/computer/arcade/orion_trail
var/busy = FALSE //prevent clickspam that allowed people to ~speedrun~ the game.
var/engine = 0
var/hull = 0
var/electronics = 0
var/food = 80
var/fuel = 60
var/turns = 4
var/alive = 4
var/eventdat = null
var/event = null
var/list/settlers = list("Harry","Larry","Bob")
var/list/events = list(ORION_TRAIL_RAIDERS = 3,
ORION_TRAIL_FLUX = 1,
ORION_TRAIL_ILLNESS = 3,
ORION_TRAIL_BREAKDOWN = 2,
ORION_TRAIL_LING = 3,
ORION_TRAIL_MALFUNCTION = 2,
ORION_TRAIL_COLLISION = 1,
ORION_TRAIL_SPACEPORT = 2
)
var/list/stops = list()
var/list/stopblurbs = list()
var/lings_aboard = 0
var/spaceport_raided = 0
var/spaceport_freebie = 0
var/last_spaceport_action = ""
var/gameStatus = ORION_STATUS_START
var/canContinueEvent = 0
/obj/machinery/computer/arcade/orion_trail/kobayashi
name = "Kobayashi Maru control computer"
desc = "A test for cadets"
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "control_boxp"
events = list("Raiders" = 3, "Interstellar Flux" = 1, "Illness" = 3, "Breakdown" = 2, "Malfunction" = 2, "Collision" = 1, "Spaceport" = 2)
prizes = list(/obj/item/paper/fluff/holodeck/trek_diploma = 1)
settlers = list("Kirk","Worf","Gene")
/obj/machinery/computer/arcade/orion_trail/Reset()
// Sets up the main trail
stops = list("Pluto","Asteroid Belt","Proxima Centauri","Dead Space","Rigel Prime","Tau Ceti Beta","Black Hole","Space Outpost Beta-9","Orion Prime")
stopblurbs = list(
"Pluto, long since occupied with long-range sensors and scanners, stands ready to, and indeed continues to probe the far reaches of the galaxy.",
"At the edge of the Sol system lies a treacherous asteroid belt. Many have been crushed by stray asteroids and misguided judgement.",
"The nearest star system to Sol, in ages past it stood as a reminder of the boundaries of sub-light travel, now a low-population sanctuary for adventurers and traders.",
"This region of space is particularly devoid of matter. Such low-density pockets are known to exist, but the vastness of it is astounding.",
"Rigel Prime, the center of the Rigel system, burns hot, basking its planetary bodies in warmth and radiation.",
"Tau Ceti Beta has recently become a waypoint for colonists headed towards Orion. There are many ships and makeshift stations in the vicinity.",
"Sensors indicate that a black hole's gravitational field is affecting the region of space we were headed through. We could stay of course, but risk of being overcome by its gravity, or we could change course to go around, which will take longer.",
"You have come into range of the first man-made structure in this region of space. It has been constructed not by travellers from Sol, but by colonists from Orion. It stands as a monument to the colonists' success.",
"You have made it to Orion! Congratulations! Your crew is one of the few to start a new foothold for mankind!"
)
/obj/machinery/computer/arcade/orion_trail/proc/newgame()
// Set names of settlers in crew
settlers = list()
for(var/i = 1; i <= 3; i++)
add_crewmember()
add_crewmember("[usr]")
// Re-set items to defaults
engine = 1
hull = 1
electronics = 1
food = 80
fuel = 60
alive = 4
turns = 1
event = null
gameStatus = ORION_STATUS_NORMAL
lings_aboard = 0
//spaceport junk
spaceport_raided = 0
spaceport_freebie = 0
last_spaceport_action = ""
/obj/machinery/computer/arcade/orion_trail/ui_interact(mob/user)
. = ..()
if(fuel <= 0 || food <=0 || settlers.len == 0)
gameStatus = ORION_STATUS_GAMEOVER
event = null
var/dat = ""
if(gameStatus == ORION_STATUS_GAMEOVER)
dat = "<center><h1>Game Over</h1></center>"
dat += "Like many before you, your crew never made it to Orion, lost to space... <br><b>Forever</b>."
if(!settlers.len)
dat += "<br>Your entire crew died, and your ship joins the fleet of ghost-ships littering the galaxy."
else
if(food <= 0)
dat += "<br>You ran out of food and starved."
if(obj_flags & EMAGGED)
user.nutrition = 0 //yeah you pretty hongry
to_chat(user, "<span class='userdanger'>Your body instantly contracts to that of one who has not eaten in months. Agonizing cramps seize you as you fall to the floor.</span>")
if(fuel <= 0)
dat += "<br>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, "<span class='userdanger'>You feel an immense wave of heat emanate from the arcade machine. Your skin bursts into flames.</span>")
if(obj_flags & EMAGGED)
to_chat(user, "<span class='userdanger'>You're never going to make it to Orion...</span>")
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 += "<P ALIGN=Right><a href='byond://?src=[REF(src)];menu=1'>May They Rest In Peace</a></P>"
else if(event)
dat = eventdat
else if(gameStatus == ORION_STATUS_NORMAL)
var/title = stops[turns]
var/subtext = stopblurbs[turns]
dat = "<center><h1>[title]</h1></center>"
dat += "[subtext]"
dat += "<h3><b>Crew:</b></h3>"
dat += english_list(settlers)
dat += "<br><b>Food: </b>[food] | <b>Fuel: </b>[fuel]"
dat += "<br><b>Engine Parts: </b>[engine] | <b>Hull Panels: </b>[hull] | <b>Electronics: </b>[electronics]"
if(turns == 7)
dat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];pastblack=1'>Go Around</a> <a href='byond://?src=[REF(src)];blackhole=1'>Continue</a></P>"
else
dat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];continue=1'>Continue</a></P>"
dat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];killcrew=1'>Kill a Crewmember</a></P>"
dat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
else
dat = "<center><h2>The Orion Trail</h2></center>"
dat += "<br><center><h3>Experience the journey of your ancestors!</h3></center><br><br>"
dat += "<center><b><a href='byond://?src=[REF(src)];newgame=1'>New Game</a></b></center>"
dat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
var/datum/browser/popup = new(user, "arcade", "The Orion Trail",400,700)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
popup.open()
return
/obj/machinery/computer/arcade/orion_trail/Topic(href, href_list)
if(..())
return
if(href_list["close"])
usr.unset_machine()
usr << browse(null, "window=arcade")
if(busy)
return
busy = TRUE
if (href_list["continue"]) //Continue your travels
if(gameStatus == ORION_STATUS_NORMAL && !event && turns != 7)
if(turns >= ORION_TRAIL_WINTURN)
win(usr)
else
food -= (alive+lings_aboard)*2
fuel -= 5
if(turns == 2 && prob(30))
event = ORION_TRAIL_COLLISION
event()
else if(prob(75))
event = pickweight(events)
if(lings_aboard)
if(event == ORION_TRAIL_LING || prob(55))
event = ORION_TRAIL_LING_ATTACK
event()
turns += 1
if(obj_flags & EMAGGED)
var/mob/living/carbon/M = usr //for some vars
switch(event)
if(ORION_TRAIL_RAIDERS)
if(prob(50))
to_chat(usr, "<span class='userdanger'>You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?</span>")
M.hallucination += 30
else
to_chat(usr, "<span class='userdanger'>Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there...</span>")
M.take_bodypart_damage(30)
playsound(loc, 'sound/weapons/genhit2.ogg', 100, 1)
if(ORION_TRAIL_ILLNESS)
var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS
if(severity == 1)
to_chat(M, "<span class='userdanger'>You suddenly feel slightly nauseated.</span>" )
if(severity == 2)
to_chat(usr, "<span class='userdanger'>You suddenly feel extremely nauseated and hunch over until it passes.</span>")
M.Stun(60)
if(severity >= 3) //you didn't pray hard enough
to_chat(M, "<span class='warning'>An overpowering wave of nausea consumes over you. You hunch over, your stomach's contents preparing for a spectacular exit.</span>")
M.Stun(100)
sleep(30)
M.vomit(10, distance = 5)
if(ORION_TRAIL_FLUX)
if(prob(75))
M.Knockdown(60)
say("A sudden gust of powerful wind slams [M] into the floor!")
M.take_bodypart_damage(25)
playsound(loc, 'sound/weapons/genhit.ogg', 100, 1)
else
to_chat(M, "<span class='userdanger'>A violent gale blows past you, and you barely manage to stay standing!</span>")
if(ORION_TRAIL_COLLISION) //by far the most damaging event
if(prob(90))
playsound(loc, 'sound/effects/bang.ogg', 100, 1)
var/turf/open/floor/F
for(F in orange(1, src))
F.ScrapeAway()
say("Something slams into the floor around [src], exposing it to space!")
if(hull)
sleep(10)
say("A new floor suddenly appears around [src]. What the hell?")
playsound(loc, 'sound/weapons/genhit.ogg', 100, 1)
var/turf/open/space/T
for(T in orange(1, src))
T.PlaceOnTop(/turf/open/floor/plating)
else
say("Something slams into the floor around [src] - luckily, it didn't get through!")
playsound(loc, 'sound/effects/bang.ogg', 50, 1)
if(ORION_TRAIL_MALFUNCTION)
playsound(loc, 'sound/effects/empulse.ogg', 50, 1)
visible_message("<span class='danger'>[src] malfunctions, randomizing in-game stats!</span>")
var/oldfood = food
var/oldfuel = fuel
food = rand(10,80) / rand(1,2)
fuel = rand(10,60) / rand(1,2)
if(electronics)
sleep(10)
if(oldfuel > fuel && oldfood > food)
audible_message("<span class='danger'>[src] lets out a somehow reassuring chime.</span>")
else if(oldfuel < fuel || oldfood < food)
audible_message("<span class='danger'>[src] lets out a somehow ominous chime.</span>")
food = oldfood
fuel = oldfuel
playsound(loc, 'sound/machines/chime.ogg', 50, 1)
else if(href_list["newgame"]) //Reset everything
if(gameStatus == ORION_STATUS_START)
newgame()
else if(href_list["menu"]) //back to the main menu
if(gameStatus == ORION_STATUS_GAMEOVER)
gameStatus = ORION_STATUS_START
event = null
food = 80
fuel = 60
settlers = list("Harry","Larry","Bob")
else if(href_list["slow"]) //slow down
if(event == ORION_TRAIL_FLUX)
food -= (alive+lings_aboard)*2
fuel -= 5
event = null
else if(href_list["pastblack"]) //slow down
if(turns == 7)
food -= ((alive+lings_aboard)*2)*3
fuel -= 15
turns += 1
event = null
else if(href_list["useengine"]) //use parts
if(event == ORION_TRAIL_BREAKDOWN)
engine = max(0, --engine)
event = null
else if(href_list["useelec"]) //use parts
if(event == ORION_TRAIL_MALFUNCTION)
electronics = max(0, --electronics)
event = null
else if(href_list["usehull"]) //use parts
if(event == ORION_TRAIL_COLLISION)
hull = max(0, --hull)
event = null
else if(href_list["wait"]) //wait 3 days
if(event == ORION_TRAIL_BREAKDOWN || event == ORION_TRAIL_MALFUNCTION || event == ORION_TRAIL_COLLISION)
food -= ((alive+lings_aboard)*2)*3
event = null
else if(href_list["keepspeed"]) //keep speed
if(event == ORION_TRAIL_FLUX)
if(prob(75))
event = "Breakdown"
event()
else
event = null
else if(href_list["blackhole"]) //keep speed past a black hole
if(turns == 7)
if(prob(75))
event = ORION_TRAIL_BLACKHOLE
event()
if(obj_flags & EMAGGED)
playsound(loc, 'sound/effects/supermatter.ogg', 100, 1)
say("A miniature black hole suddenly appears in front of [src], devouring [usr] alive!")
if(isliving(usr))
var/mob/living/L = usr
L.Stun(200, ignore_canstun = TRUE) //you can't run :^)
var/S = new /obj/singularity/academy(usr.loc)
addtimer(CALLBACK(src, /atom/movable/proc/say, "[S] winks out, just as suddenly as it appeared."), 50)
QDEL_IN(S, 50)
else
event = null
turns += 1
else if(href_list["holedeath"])
if(event == ORION_TRAIL_BLACKHOLE)
gameStatus = ORION_STATUS_GAMEOVER
event = null
else if(href_list["eventclose"]) //end an event
if(canContinueEvent)
event = null
else if(href_list["killcrew"]) //shoot a crewmember
if(gameStatus == ORION_STATUS_NORMAL || event == ORION_TRAIL_LING)
var/sheriff = remove_crewmember() //I shot the sheriff
playsound(loc,'sound/weapons/gunshot.ogg', 100, 1)
if(settlers.len == 0 || alive == 0)
say("The last crewmember [sheriff], shot themselves, GAME OVER!")
if(obj_flags & EMAGGED)
usr.death(0)
obj_flags &= EMAGGED
gameStatus = ORION_STATUS_GAMEOVER
event = null
else if(obj_flags & EMAGGED)
if(usr.name == sheriff)
say("The crew of the ship chose to kill [usr.name]!")
usr.death(0)
if(event == ORION_TRAIL_LING) //only ends the ORION_TRAIL_LING event, since you can do this action in multiple places
event = null
//Spaceport specific interactions
//they get a header because most of them don't reset event (because it's a shop, you leave when you want to)
//they also call event() again, to regen the eventdata, which is kind of odd but necessary
else if(href_list["buycrew"]) //buy a crewmember
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided && food >= 10 && fuel >= 10)
var/bought = add_crewmember()
last_spaceport_action = "You hired [bought] as a new crewmember."
fuel -= 10
food -= 10
event()
else if(href_list["sellcrew"]) //sell a crewmember
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided && settlers.len > 1)
var/sold = remove_crewmember()
last_spaceport_action = "You sold your crewmember, [sold]!"
fuel += 7
food += 7
event()
else if(href_list["leave_spaceport"])
if(gameStatus == ORION_STATUS_MARKET)
event = null
gameStatus = ORION_STATUS_NORMAL
spaceport_raided = 0
spaceport_freebie = 0
last_spaceport_action = ""
else if(href_list["raid_spaceport"])
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided)
var/success = min(15 * alive,100) //default crew (4) have a 60% chance
spaceport_raided = 1
var/FU = 0
var/FO = 0
if(prob(success))
FU = rand(5,15)
FO = rand(5,15)
last_spaceport_action = "You successfully raided the spaceport! You gained [FU] Fuel and [FO] Food! (+[FU]FU,+[FO]FO)"
else
FU = rand(-5,-15)
FO = rand(-5,-15)
last_spaceport_action = "You failed to raid the spaceport! You lost [FU*-1] Fuel and [FO*-1] Food in your scramble to escape! ([FU]FU,[FO]FO)"
//your chance of lose a crewmember is 1/2 your chance of success
//this makes higher % failures hurt more, don't get cocky space cowboy!
if(prob(success*5))
var/lost_crew = remove_crewmember()
last_spaceport_action = "You failed to raid the spaceport! You lost [FU*-1] Fuel and [FO*-1] Food, AND [lost_crew] in your scramble to escape! ([FU]FI,[FO]FO,-Crew)"
if(obj_flags & EMAGGED)
say("WEEWOO! WEEWOO! Spaceport security en route!")
playsound(src, 'sound/items/weeoo1.ogg', 100, FALSE)
for(var/i, i<=3, i++)
var/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion/O = new/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion(get_turf(src))
O.target = usr
fuel += FU
food += FO
event()
else if(href_list["buyparts"])
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided && fuel > 5)
switch(text2num(href_list["buyparts"]))
if(1) //Engine Parts
engine++
last_spaceport_action = "Bought Engine Parts"
if(2) //Hull Plates
hull++
last_spaceport_action = "Bought Hull Plates"
if(3) //Spare Electronics
electronics++
last_spaceport_action = "Bought Spare Electronics"
fuel -= 5 //they all cost 5
event()
else if(href_list["trade"])
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided)
switch(text2num(href_list["trade"]))
if(1) //Fuel
if(fuel > 5)
fuel -= 5
food += 5
last_spaceport_action = "Traded Fuel for Food"
event()
if(2) //Food
if(food > 5)
fuel += 5
food -= 5
last_spaceport_action = "Traded Food for Fuel"
event()
add_fingerprint(usr)
updateUsrDialog()
busy = FALSE
return
/obj/machinery/computer/arcade/orion_trail/proc/event()
eventdat = "<center><h1>[event]</h1></center>"
canContinueEvent = 0
switch(event)
if(ORION_TRAIL_RAIDERS)
eventdat += "Raiders have come aboard your ship!"
if(prob(50))
var/sfood = rand(1,10)
var/sfuel = rand(1,10)
food -= sfood
fuel -= sfuel
eventdat += "<br>They have stolen [sfood] <b>Food</b> and [sfuel] <b>Fuel</b>."
else if(prob(10))
var/deadname = remove_crewmember()
eventdat += "<br>[deadname] tried to fight back, but was killed."
else
eventdat += "<br>Fortunately, you fended them off without any trouble."
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];eventclose=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
canContinueEvent = 1
if(ORION_TRAIL_FLUX)
eventdat += "This region of space is highly turbulent. <br>If we go slowly we may avoid more damage, but if we keep our speed we won't waste supplies."
eventdat += "<br>What will you do?"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];slow=1'>Slow Down</a> <a href='byond://?src=[REF(src)];keepspeed=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
if(ORION_TRAIL_ILLNESS)
eventdat += "A deadly illness has been contracted!"
var/deadname = remove_crewmember()
eventdat += "<br>[deadname] was killed by the disease."
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];eventclose=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
canContinueEvent = 1
if(ORION_TRAIL_BREAKDOWN)
eventdat += "Oh no! The engine has broken down!"
eventdat += "<br>You can repair it with an engine part, or you can make repairs for 3 days."
if(engine >= 1)
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];useengine=1'>Use Part</a><a href='byond://?src=[REF(src)];wait=1'>Wait</a></P>"
else
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];wait=1'>Wait</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
if(ORION_TRAIL_MALFUNCTION)
eventdat += "The ship's systems are malfunctioning!"
eventdat += "<br>You can replace the broken electronics with spares, or you can spend 3 days troubleshooting the AI."
if(electronics >= 1)
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];useelec=1'>Use Part</a><a href='byond://?src=[REF(src)];wait=1'>Wait</a></P>"
else
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];wait=1'>Wait</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
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 += "<br>[sfood] <b>Food</b> and [sfuel] <b>Fuel</b> was vented out into space."
if(prob(10))
var/deadname = remove_crewmember()
eventdat += "<br>[deadname] was killed by rapid depressurization."
eventdat += "<br>You can repair the damage with hull plates, or you can spend the next 3 days welding scrap together."
if(hull >= 1)
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];usehull=1'>Use Part</a><a href='byond://?src=[REF(src)];wait=1'>Wait</a></P>"
else
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];wait=1'>Wait</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
if(ORION_TRAIL_BLACKHOLE)
eventdat += "You were swept away into the black hole."
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];holedeath=1'>Oh...</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
settlers = list()
if(ORION_TRAIL_LING)
eventdat += "Strange reports warn of changelings infiltrating crews on trips to Orion..."
if(settlers.len <= 2)
eventdat += "<br>Your crew's chance of reaching Orion is so slim the changelings likely avoided your ship..."
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];eventclose=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
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 += "<P ALIGN=Right><a href='byond://?src=[REF(src)];killcrew=1'>Kill a Crewmember</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];eventclose=1'>Risk it</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
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 += "<br>(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 += "<br>[ling1] and [ling2]'s arms twist and contort into grotesque blades!"
else
eventdat += "<br>[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 += "<br>[murder_text]"
else
eventdat += "<br><br><b>You valiantly fight off the changeling[ling2 ? "s":""]!</b>"
if(ling2)
food += 30
lings_aboard = max(0,lings_aboard-2)
else
food += 15
lings_aboard = max(0,--lings_aboard)
eventdat += "<br><i>Well, it's perfectly good food...</i>\
<br>You cut the changeling[ling2 ? "s" : ""] into meat, gaining <b>[ling2 ? "30" : "15"]</b> Food!"
else
eventdat += "<br><br>[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 += "<P ALIGN=Right><a href='byond://?src=[REF(src)];eventclose=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
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 += "<br><b>Last Spaceport Action:</b> [last_spaceport_action]"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];leave_spaceport=1'>Depart Spaceport</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
else
eventdat += "Your jump into the sector yields a spaceport - a lucky find!"
eventdat += "<br>This spaceport is home to travellers who failed to reach Orion, but managed to find a different home..."
eventdat += "<br>Trading terms: FU = Fuel, FO = Food"
if(last_spaceport_action)
eventdat += "<br><b>Last action:</b> [last_spaceport_action]"
eventdat += "<h3><b>Crew:</b></h3>"
eventdat += english_list(settlers)
eventdat += "<br><b>Food: </b>[food] | <b>Fuel: </b>[fuel]"
eventdat += "<br><b>Engine Parts: </b>[engine] | <b>Hull Panels: </b>[hull] | <b>Electronics: </b>[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 += "<br>The traders of the spaceport take pity on you, and generously give you some free supplies! (+[FU]FU, +[FO]FO)"
if(freecrew)
eventdat += "<br>You also gain a new crewmember!"
fuel += FU
food += FO
//CREW INTERACTIONS
eventdat += "<P ALIGN=Right>Crew Management:</P>"
//Buy crew
if(food >= 10 && fuel >= 10)
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];buycrew=1'>Hire a New Crewmember (-10FU, -10FO)</a></P>"
else
eventdat += "<P ALIGN=Right>You cannot afford a new crewmember.</P>"
//Sell crew
if(settlers.len > 1)
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];sellcrew=1'>Sell Crew for Fuel and Food (+7FU, +7FO)</a></P>"
else
eventdat += "<P ALIGN=Right>You have no other crew to sell.</P>"
//BUY/SELL STUFF
eventdat += "<P ALIGN=Right>Spare Parts:</P>"
//Engine parts
if(fuel > 5)
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];buyparts=1'>Buy Engine Parts (-5FU)</a></P>"
else
eventdat += "<P ALIGN=Right>You cannot afford engine parts.</a>"
//Hull plates
if(fuel > 5)
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];buyparts=2'>Buy Hull Plates (-5FU)</a></P>"
else
eventdat += "<P ALIGN=Right>You cannot afford hull plates.</a>"
//Electronics
if(fuel > 5)
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];buyparts=3'>Buy Spare Electronics (-5FU)</a></P>"
else
eventdat += "<P ALIGN=Right>You cannot afford spare electronics.</a>"
//Trade
if(fuel > 5)
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];trade=1'>Trade Fuel for Food (-5FU,+5FO)</a></P>"
else
eventdat += "<P ALIGN=Right>You don't have 5FU to trade.</P"
if(food > 5)
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];trade=2'>Trade Food for Fuel (+5FU,-5FO)</a></P>"
else
eventdat += "<P ALIGN=Right>You don't have 5FO to trade.</P"
//Raid the spaceport
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];raid_spaceport=1'>!! Raid Spaceport !!</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];leave_spaceport=1'>Depart Spaceport</a></P>"
//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, "<span class='notice'>You override the cheat code menu and skip to Cheat #[rand(1, 50)]: Realism Mode.</span>")
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, "<span class='notice'>There's a little switch on the bottom. It's flipped down.</span>")
else
to_chat(user, "<span class='notice'>There's a little switch on the bottom. It's flipped up.</span>")
/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, "<span class='warning'>You flip the switch on the underside of [src].</span>")
active = 1
visible_message("<span class='notice'>[src] softly beeps and whirs to life!</span>")
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("<span class='warning'>[src] begins to vibrate...</span>")
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("<span class='userdanger'>[src] explodes!</span>")
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

Some files were not shown because too many files have changed in this diff Show More