mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-13 08:03:43 +01:00
Merge remote-tracking branch 'ParadiseSS13/master' into skills_rework
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# dmdoc
|
||||
[DOCUMENTATION]: https://codedocs.paradisestation.org/
|
||||
|
||||
[BYOND]: https://secure.byond.com/
|
||||
|
||||
[DMDOC]: https://github.com/AffectedArc07/ParaSpacemanDMM/tree/master/src/dmdoc
|
||||
|
||||
[DMDOC] is a documentation generator for DreamMaker, the scripting language
|
||||
of the [BYOND] game engine. It produces simple static HTML files based on
|
||||
documented files, macros, types, procs, and vars.
|
||||
|
||||
We use **dmdoc** to generate [DOCUMENTATION] for our code, and that documentation
|
||||
is automatically generated and built on every new commit to the master branch
|
||||
|
||||
This gives new developers a clickable reference [DOCUMENTATION] they can browse to better help
|
||||
gain understanding of the Paradise codebase structure and api reference.
|
||||
|
||||
## Documenting code on Paradise
|
||||
We use block comments to document procs and classes, and we use `///` line comments
|
||||
when documenting individual variables.
|
||||
|
||||
Documentation is not required at Paradise, but it is highly recommended that all new code be covered with DMdoc code, according to the [Specifications](#Specification)
|
||||
|
||||
We also recommend that when you touch older code, you document the functions that you
|
||||
have touched in the process of updating that code
|
||||
|
||||
### Specification
|
||||
A class *should* always be autodocumented, and all public functions *should* be documented
|
||||
|
||||
All class level defined variables *should* be documented
|
||||
|
||||
Internal functions *can* be documented, but may not be
|
||||
|
||||
A public function is any function that a developer might reasonably call while using
|
||||
or interacting with your object. Internal functions are helper functions that your
|
||||
public functions rely on to implement logic
|
||||
|
||||
|
||||
### Documenting a proc
|
||||
When documenting a proc, we give a short one line description (as this is shown
|
||||
next to the proc definition in the list of all procs for a type or global
|
||||
namespace), then a longer paragraph which will be shown when the user clicks on
|
||||
the proc to jump to it's definition
|
||||
```
|
||||
/**
|
||||
* Short description of the proc
|
||||
*
|
||||
* Longer detailed paragraph about the proc
|
||||
* including any relevant detail
|
||||
* Arguments:
|
||||
* * arg1 - Relevance of this argument
|
||||
* * arg2 - Relevance of this argument
|
||||
*/
|
||||
```
|
||||
|
||||
### Documenting a class
|
||||
We first give the name of the class as a header, this can be omitted if the name is
|
||||
just going to be the typepath of the class, as dmdoc uses that by default
|
||||
|
||||
Then we give a short oneline description of the class
|
||||
|
||||
Finally we give a longer multi paragraph description of the class and it's details
|
||||
```
|
||||
/**
|
||||
* # Classname (Can be omitted if it's just going to be the typepath)
|
||||
*
|
||||
* The short overview
|
||||
*
|
||||
* A longer
|
||||
* paragraph of functionality about the class
|
||||
* including any assumptions/special cases
|
||||
*
|
||||
*/
|
||||
```
|
||||
|
||||
### Documenting a variable/define
|
||||
Give a short explanation of what the variable, in the context of the class, or define is.
|
||||
```
|
||||
/// Type path of item to go in suit slot
|
||||
var/suit = null
|
||||
```
|
||||
|
||||
## Module level description of code
|
||||
Modules are the best way to describe the structure/intent of a package of code
|
||||
where you don't want to be tied to the formal layout of the class structure.
|
||||
|
||||
On Paradise we do this by adding markdown files inside the `code` directory
|
||||
that will also be rendered and added to the modules tree. The structure for
|
||||
these is deliberately not defined, so you can be as freeform and as wheeling as
|
||||
you would like.
|
||||
|
||||
[Here is a representative example of what you might write](https://codedocs.paradisestation.org/code/modules/keybindings/readme.html)
|
||||
|
||||
## Special variables
|
||||
You can use certain special template variables in DM DOC comments and they will be expanded
|
||||
```
|
||||
[DEFINE_NAME] - Expands to a link to the define definition if documented
|
||||
[/mob] - Expands to a link to the docs for the /mob class
|
||||
[/mob/proc/Dizzy] - Expands to a link that will take you to the /mob class and anchor you to the dizzy proc docs
|
||||
[/mob/var/stat] - Expands to a link that will take you to the /mob class and anchor you to the stat var docs
|
||||
```
|
||||
|
||||
You can customise the link name by using `[link name][link shorthand].`
|
||||
|
||||
eg. `[see more about dizzy here] [/mob/proc/Dizzy]`
|
||||
|
||||
This is very useful to quickly link to other parts of the autodoc code to expand
|
||||
upon a comment made, or reasoning about code
|
||||
@@ -0,0 +1,32 @@
|
||||
name: Generate Documentation
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # Every day at the very start of the day
|
||||
|
||||
jobs:
|
||||
generate_docs:
|
||||
name: 'Generate Documentation'
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: 'Update Branch'
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
ref: master
|
||||
|
||||
- name: 'Generate Documentation'
|
||||
run: |
|
||||
./tools/github-actions/doc-generator
|
||||
touch dmdoc/.nojekyll
|
||||
# Nojekyll is important to disable jeykll syntax, which can mess with files that start with underscores
|
||||
|
||||
- name: 'Deploy Documentation'
|
||||
uses: crazy-max/ghaction-github-pages@v2
|
||||
with:
|
||||
keep_history: false
|
||||
build_dir: dmdoc
|
||||
jekyll: false
|
||||
fqdn: codedocs.paradisestation.org
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,6 @@
|
||||
[langserver]
|
||||
dreamchecker = true
|
||||
|
||||
[code_standards]
|
||||
disallow_relative_type_definitions = true
|
||||
disallow_relative_proc_definitions = true
|
||||
@@ -40663,40 +40663,16 @@
|
||||
/turf/simulated/wall/r_wall,
|
||||
/area/engine/break_room)
|
||||
"byz" = (
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-4";
|
||||
d2 = 4
|
||||
},
|
||||
/obj/machinery/modular_computer/console/preset/engineering,
|
||||
/obj/machinery/status_display{
|
||||
pixel_x = -32
|
||||
},
|
||||
/obj/machinery/computer/security/engineering,
|
||||
/turf/simulated/floor/plasteel{
|
||||
dir = 8;
|
||||
icon_state = "caution"
|
||||
},
|
||||
/area/atmos)
|
||||
"byA" = (
|
||||
/obj/structure/cable{
|
||||
d1 = 4;
|
||||
d2 = 8;
|
||||
icon_state = "4-8";
|
||||
tag = ""
|
||||
},
|
||||
/obj/structure/chair/office/dark{
|
||||
dir = 8
|
||||
},
|
||||
/turf/simulated/floor/plasteel{
|
||||
dir = 8;
|
||||
icon_state = "neutralfull"
|
||||
},
|
||||
/area/atmos)
|
||||
"byB" = (
|
||||
/obj/structure/cable{
|
||||
d1 = 1;
|
||||
d2 = 8;
|
||||
icon_state = "1-8"
|
||||
},
|
||||
/obj/structure/cable{
|
||||
d1 = 1;
|
||||
d2 = 4;
|
||||
@@ -41937,12 +41913,7 @@
|
||||
icon_state = "1-2";
|
||||
tag = ""
|
||||
},
|
||||
/obj/machinery/modular_computer/console/preset/command,
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-2";
|
||||
pixel_y = 1;
|
||||
d2 = 2
|
||||
},
|
||||
/obj/machinery/computer/shuttle/mining,
|
||||
/turf/simulated/floor/plasteel{
|
||||
dir = 1;
|
||||
icon_state = "darkpurple"
|
||||
@@ -51367,18 +51338,6 @@
|
||||
icon_state = "dark"
|
||||
},
|
||||
/area/engine/break_room)
|
||||
"bQf" = (
|
||||
/obj/structure/cable{
|
||||
d1 = 4;
|
||||
d2 = 8;
|
||||
icon_state = "4-8";
|
||||
pixel_x = 0
|
||||
},
|
||||
/turf/simulated/floor/plasteel{
|
||||
icon_state = "neutral";
|
||||
dir = 4
|
||||
},
|
||||
/area/crew_quarters/chief)
|
||||
"bQg" = (
|
||||
/obj/structure/cable{
|
||||
d1 = 1;
|
||||
@@ -51405,11 +51364,6 @@
|
||||
},
|
||||
/obj/structure/table/reinforced,
|
||||
/obj/item/clipboard,
|
||||
/obj/structure/cable{
|
||||
d1 = 1;
|
||||
d2 = 8;
|
||||
icon_state = "1-8"
|
||||
},
|
||||
/obj/item/toy/figure/ce,
|
||||
/turf/simulated/floor/plasteel{
|
||||
dir = 8;
|
||||
@@ -54089,12 +54043,6 @@
|
||||
/area/crew_quarters/chief)
|
||||
"bUq" = (
|
||||
/obj/machinery/hologram/holopad,
|
||||
/obj/structure/cable{
|
||||
d1 = 4;
|
||||
d2 = 8;
|
||||
icon_state = "4-8";
|
||||
pixel_x = 0
|
||||
},
|
||||
/obj/effect/decal/warning_stripes/yellow/hollow,
|
||||
/turf/simulated/floor/plasteel{
|
||||
dir = 8;
|
||||
@@ -55398,11 +55346,6 @@
|
||||
},
|
||||
/area/crew_quarters/chief)
|
||||
"bWl" = (
|
||||
/obj/machinery/modular_computer/console/preset/engineering,
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-4";
|
||||
d2 = 4
|
||||
},
|
||||
/obj/machinery/keycard_auth{
|
||||
pixel_x = -24
|
||||
},
|
||||
@@ -55420,6 +55363,7 @@
|
||||
pixel_y = -8;
|
||||
req_access_txt = "11"
|
||||
},
|
||||
/obj/machinery/computer/security/engineering,
|
||||
/turf/simulated/floor/plasteel{
|
||||
icon_state = "dark"
|
||||
},
|
||||
@@ -60477,6 +60421,9 @@
|
||||
icon_state = "4-8";
|
||||
tag = ""
|
||||
},
|
||||
/obj/machinery/computer/monitor{
|
||||
name = "Grid Power Monitoring Computer"
|
||||
},
|
||||
/turf/simulated/floor/plasteel{
|
||||
dir = 5;
|
||||
icon_state = "dark";
|
||||
@@ -61203,10 +61150,6 @@
|
||||
/obj/machinery/tcomms/core/station,
|
||||
/turf/simulated/floor/bluegrid,
|
||||
/area/tcommsat/chamber)
|
||||
"cgA" = (
|
||||
/obj/machinery/ntnet_relay,
|
||||
/turf/simulated/floor/bluegrid,
|
||||
/area/tcommsat/chamber)
|
||||
"cgB" = (
|
||||
/obj/machinery/camera{
|
||||
c_tag = "Singularity NorthEast";
|
||||
@@ -62511,7 +62454,6 @@
|
||||
dir = 1;
|
||||
network = list("Engineering","SS13")
|
||||
},
|
||||
/obj/machinery/modular_computer/console/preset/engineering,
|
||||
/obj/machinery/firealarm{
|
||||
dir = 8;
|
||||
pixel_x = -26;
|
||||
@@ -62521,6 +62463,9 @@
|
||||
icon_state = "0-4";
|
||||
d2 = 4
|
||||
},
|
||||
/obj/machinery/computer/monitor{
|
||||
name = "Grid Power Monitoring Computer"
|
||||
},
|
||||
/turf/simulated/floor/plasteel{
|
||||
dir = 5;
|
||||
icon_state = "dark";
|
||||
@@ -88629,7 +88574,7 @@
|
||||
/area/maintenance/starboard)
|
||||
"dey" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/modular_computer/tablet/preset/cheap,
|
||||
/obj/effect/spawner/lootdrop/maintenance,
|
||||
/turf/simulated/floor/plasteel{
|
||||
icon_state = "wood"
|
||||
},
|
||||
@@ -97237,7 +97182,6 @@
|
||||
},
|
||||
/area/crew_quarters/hor)
|
||||
"dtZ" = (
|
||||
/obj/structure/cable,
|
||||
/obj/structure/cable{
|
||||
d1 = 1;
|
||||
d2 = 4;
|
||||
@@ -97247,7 +97191,6 @@
|
||||
pixel_x = 0;
|
||||
pixel_y = -30
|
||||
},
|
||||
/obj/machinery/modular_computer/console/preset/research,
|
||||
/turf/simulated/floor/plasteel{
|
||||
dir = 2;
|
||||
icon_state = "whitepurplecorner"
|
||||
@@ -114776,6 +114719,9 @@
|
||||
"qrT" = (
|
||||
/turf/simulated/wall/r_wall,
|
||||
/area/tcommsat/chamber)
|
||||
"rSI" = (
|
||||
/turf/simulated/floor/bluegrid,
|
||||
/area/tcommsat/chamber)
|
||||
"udT" = (
|
||||
/obj/structure/chair/comfy/shuttle{
|
||||
dir = 8
|
||||
@@ -123162,9 +123108,9 @@ bVO
|
||||
bPI
|
||||
bNM
|
||||
qrT
|
||||
eaH
|
||||
rSI
|
||||
ceL
|
||||
cgu
|
||||
eaH
|
||||
qrT
|
||||
qrT
|
||||
bkt
|
||||
@@ -123934,7 +123880,7 @@ bXJ
|
||||
bZh
|
||||
caX
|
||||
ccW
|
||||
ccW
|
||||
cgu
|
||||
ccW
|
||||
chW
|
||||
qrT
|
||||
@@ -124704,9 +124650,9 @@ bVT
|
||||
bXL
|
||||
bNM
|
||||
qrT
|
||||
hng
|
||||
rSI
|
||||
vzz
|
||||
cgA
|
||||
hng
|
||||
qrT
|
||||
qrT
|
||||
bkt
|
||||
@@ -138061,7 +138007,7 @@ bIr
|
||||
bKe
|
||||
bMh
|
||||
bOa
|
||||
bQf
|
||||
bOa
|
||||
bOa
|
||||
bUh
|
||||
bWk
|
||||
@@ -142420,7 +142366,7 @@ btt
|
||||
buD
|
||||
bvO
|
||||
ban
|
||||
byA
|
||||
bzY
|
||||
bzY
|
||||
bBK
|
||||
aOg
|
||||
|
||||
@@ -38185,7 +38185,7 @@
|
||||
d2 = 2;
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/obj/machinery/modular_computer/console/preset/command,
|
||||
/obj/machinery/computer/card,
|
||||
/turf/simulated/floor/plasteel{
|
||||
icon_state = "dark"
|
||||
},
|
||||
@@ -96408,10 +96408,7 @@
|
||||
d2 = 2;
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/turf/simulated/floor/plasteel/dark,
|
||||
/area/tcommsat/server)
|
||||
"gIG" = (
|
||||
/obj/machinery/ntnet_relay,
|
||||
/obj/machinery/tcomms/core/station,
|
||||
/turf/simulated/floor/bluegrid,
|
||||
/area/tcommsat/server)
|
||||
"gRw" = (
|
||||
@@ -96643,10 +96640,6 @@
|
||||
},
|
||||
/turf/space,
|
||||
/area/solar/starboard)
|
||||
"rUQ" = (
|
||||
/obj/machinery/tcomms/core/station,
|
||||
/turf/simulated/floor/bluegrid,
|
||||
/area/tcommsat/server)
|
||||
"sjF" = (
|
||||
/obj/structure/window/reinforced{
|
||||
dir = 1
|
||||
@@ -151146,7 +151139,7 @@ bDf
|
||||
bFi
|
||||
bIz
|
||||
bKl
|
||||
gIG
|
||||
bOa
|
||||
bOb
|
||||
odO
|
||||
bKl
|
||||
@@ -152174,7 +152167,7 @@ bDj
|
||||
bFm
|
||||
bRo
|
||||
bKl
|
||||
rUQ
|
||||
bOa
|
||||
dRN
|
||||
kwJ
|
||||
bKl
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
/turf/simulated/floor/wood,
|
||||
/area/ruin/powered/snow_cabin)
|
||||
"aL" = (
|
||||
/obj/structure/displaycase/captain,
|
||||
/obj/mecha/working/ripley/mining,
|
||||
/turf/simulated/floor/wood,
|
||||
/area/ruin/powered/snow_cabin)
|
||||
"aM" = (
|
||||
@@ -392,12 +392,6 @@
|
||||
/obj/structure/filingcabinet,
|
||||
/turf/simulated/floor/pod/dark,
|
||||
/area/ruin/powered/snow_biodome)
|
||||
"UM" = (
|
||||
/obj/machinery/computer/monitor/secret{
|
||||
dir = 1
|
||||
},
|
||||
/turf/simulated/floor/pod/dark,
|
||||
/area/ruin/powered/snow_biodome)
|
||||
"Wg" = (
|
||||
/turf/simulated/wall/r_wall,
|
||||
/area/ruin/powered/snow_biodome)
|
||||
@@ -484,7 +478,7 @@ HP
|
||||
tl
|
||||
PK
|
||||
gz
|
||||
UM
|
||||
HP
|
||||
Wg
|
||||
ak
|
||||
ak
|
||||
|
||||
@@ -68,7 +68,6 @@
|
||||
"an" = (
|
||||
/obj/machinery/navbeacon/invisible{
|
||||
codes_txt = "patrol;next_patrol=SDNW";
|
||||
invisibility = 100;
|
||||
location = "SDNE"
|
||||
},
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
@@ -292,15 +291,13 @@
|
||||
"aU" = (
|
||||
/obj/machinery/navbeacon/invisible{
|
||||
codes_txt = "patrol;next_patrol=SDSW";
|
||||
invisibility = 100;
|
||||
location = "SDNW"
|
||||
},
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
/area/syndicate_depot/outer)
|
||||
"aV" = (
|
||||
/obj/machinery/light{
|
||||
dir = 4;
|
||||
icon_state = "tube1"
|
||||
dir = 4
|
||||
},
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
/area/syndicate_depot/outer)
|
||||
@@ -429,8 +426,7 @@
|
||||
/area/syndicate_depot/core)
|
||||
"bo" = (
|
||||
/obj/machinery/light{
|
||||
dir = 4;
|
||||
icon_state = "tube1"
|
||||
dir = 4
|
||||
},
|
||||
/obj/effect/spawner/random_spawners/syndicate/loot,
|
||||
/turf/simulated/floor/plasteel{
|
||||
@@ -512,7 +508,6 @@
|
||||
id = "syndi_depot_rear";
|
||||
idle_power_usage = 0;
|
||||
name = "mysterious button";
|
||||
normaldoorcontrol = 0;
|
||||
pixel_x = 24;
|
||||
use_power = 0
|
||||
},
|
||||
@@ -663,8 +658,8 @@
|
||||
/obj/machinery/turretid/syndicate{
|
||||
name = "external turret controls";
|
||||
pixel_x = -32;
|
||||
pixel_y = 0;
|
||||
req_access = list(150)
|
||||
req_access = null;
|
||||
req_access_txt = "150"
|
||||
},
|
||||
/turf/simulated/floor/plasteel{
|
||||
icon_state = "dark"
|
||||
@@ -745,9 +740,8 @@
|
||||
/area/syndicate_depot/core)
|
||||
"ce" = (
|
||||
/obj/machinery/light/small{
|
||||
tag = "icon-bulb1 (EAST)";
|
||||
icon_state = "bulb1";
|
||||
dir = 4
|
||||
dir = 4;
|
||||
tag = "icon-bulb1 (EAST)"
|
||||
},
|
||||
/turf/simulated/floor/mineral/silver,
|
||||
/area/syndicate_depot/core)
|
||||
@@ -757,7 +751,6 @@
|
||||
id = "syndi_depot_rear";
|
||||
idle_power_usage = 0;
|
||||
name = "mysterious button";
|
||||
normaldoorcontrol = 0;
|
||||
use_power = 0
|
||||
},
|
||||
/obj/structure/sign/poster/contraband/syndicate_recruitment,
|
||||
@@ -774,8 +767,8 @@
|
||||
/area/syndicate_depot/core)
|
||||
"ci" = (
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-2";
|
||||
d2 = 2
|
||||
d2 = 2;
|
||||
icon_state = "0-2"
|
||||
},
|
||||
/obj/machinery/power/smes/upgraded{
|
||||
charge = 5e+006;
|
||||
@@ -845,7 +838,6 @@
|
||||
"cr" = (
|
||||
/obj/structure/sink{
|
||||
dir = 4;
|
||||
icon_state = "sink";
|
||||
pixel_x = 12
|
||||
},
|
||||
/turf/simulated/floor/mineral/silver,
|
||||
@@ -1154,7 +1146,6 @@
|
||||
"dc" = (
|
||||
/obj/machinery/navbeacon/invisible{
|
||||
codes_txt = "patrol;next_patrol=SDSE";
|
||||
invisibility = 100;
|
||||
location = "SDSW"
|
||||
},
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
@@ -1179,7 +1170,6 @@
|
||||
"df" = (
|
||||
/obj/machinery/navbeacon/invisible{
|
||||
codes_txt = "patrol;next_patrol=SDNE";
|
||||
invisibility = 100;
|
||||
location = "SDSE"
|
||||
},
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
|
||||
@@ -26723,10 +26723,6 @@
|
||||
dir = 4
|
||||
},
|
||||
/area/security/nuke_storage)
|
||||
"aXS" = (
|
||||
/obj/machinery/vending/modularpc,
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/storage/primary)
|
||||
"aXU" = (
|
||||
/obj/item/flag/mime,
|
||||
/obj/machinery/power/apc{
|
||||
@@ -26847,23 +26843,13 @@
|
||||
},
|
||||
/area/crew_quarters/bar)
|
||||
"aYf" = (
|
||||
/obj/machinery/modular_computer/console/preset/command,
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-2";
|
||||
pixel_y = 1;
|
||||
d2 = 2
|
||||
},
|
||||
/obj/machinery/computer/card,
|
||||
/turf/simulated/floor/plasteel{
|
||||
dir = 10;
|
||||
icon_state = "green"
|
||||
},
|
||||
/area/bridge)
|
||||
"aYg" = (
|
||||
/obj/structure/cable{
|
||||
d1 = 1;
|
||||
d2 = 2;
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/turf/simulated/floor/plasteel{
|
||||
dir = 1;
|
||||
icon_state = "greencorner"
|
||||
@@ -38277,11 +38263,6 @@
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/bridge)
|
||||
"bup" = (
|
||||
/obj/structure/cable{
|
||||
d1 = 1;
|
||||
d2 = 2;
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/obj/machinery/atmospherics/unary/vent_pump/on,
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/bridge)
|
||||
@@ -38894,11 +38875,6 @@
|
||||
icon_state = "4-8";
|
||||
tag = ""
|
||||
},
|
||||
/obj/structure/cable{
|
||||
d1 = 1;
|
||||
d2 = 4;
|
||||
icon_state = "1-4"
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/bridge)
|
||||
@@ -95344,6 +95320,11 @@
|
||||
icon_state = "vault"
|
||||
},
|
||||
/area/shuttle/escape)
|
||||
"kIR" = (
|
||||
/obj/structure/lattice/catwalk,
|
||||
/obj/machinery/atmospherics/pipe/simple/hidden/yellow,
|
||||
/turf/space,
|
||||
/area/space/nearstation)
|
||||
"kLF" = (
|
||||
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
|
||||
dir = 9
|
||||
@@ -95977,11 +95958,6 @@
|
||||
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
|
||||
/turf/simulated/wall,
|
||||
/area/crew_quarters/dorms)
|
||||
"rOX" = (
|
||||
/obj/machinery/atmospherics/pipe/simple/hidden/yellow,
|
||||
/obj/machinery/ntnet_relay,
|
||||
/turf/simulated/floor/plasteel/dark,
|
||||
/area/tcommsat/chamber)
|
||||
"rSv" = (
|
||||
/obj/structure/shuttle/engine/propulsion{
|
||||
dir = 8;
|
||||
@@ -96028,10 +96004,6 @@
|
||||
icon_state = "floor4"
|
||||
},
|
||||
/area/shuttle/administration)
|
||||
"sag" = (
|
||||
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
|
||||
/turf/simulated/floor/plasteel/dark,
|
||||
/area/tcommsat/chamber)
|
||||
"sbp" = (
|
||||
/turf/simulated/shuttle/wall{
|
||||
icon_state = "wall3"
|
||||
@@ -115856,7 +115828,7 @@ aKb
|
||||
aNx
|
||||
aVi
|
||||
aWt
|
||||
aXS
|
||||
aXQ
|
||||
aZr
|
||||
bbp
|
||||
bdk
|
||||
@@ -131629,7 +131601,7 @@ dmW
|
||||
aaa
|
||||
aab
|
||||
aaa
|
||||
iUc
|
||||
aaa
|
||||
iUc
|
||||
iUc
|
||||
iUc
|
||||
@@ -131886,10 +131858,10 @@ ddC
|
||||
doE
|
||||
ddM
|
||||
ddO
|
||||
kIR
|
||||
oOZ
|
||||
dQC
|
||||
fAw
|
||||
rOX
|
||||
mkE
|
||||
dpe
|
||||
dpl
|
||||
@@ -132144,8 +132116,8 @@ dmB
|
||||
bfu
|
||||
dnT
|
||||
dpf
|
||||
iUc
|
||||
rTy
|
||||
sag
|
||||
wbr
|
||||
hyv
|
||||
dpd
|
||||
|
||||
@@ -4296,55 +4296,20 @@
|
||||
dir = 2
|
||||
},
|
||||
/area/centcom/control)
|
||||
"mE" = (
|
||||
/obj/structure/flora/ausbushes/lavendergrass,
|
||||
/turf/unsimulated/floor{
|
||||
icon_state = "grass1";
|
||||
name = "grass"
|
||||
},
|
||||
/area/centcom/specops)
|
||||
"mF" = (
|
||||
/obj/structure/flora/ausbushes/stalkybush,
|
||||
/turf/unsimulated/floor{
|
||||
icon_state = "grass1";
|
||||
name = "grass"
|
||||
},
|
||||
/area/centcom/specops)
|
||||
"mG" = (
|
||||
/obj/structure/flora/ausbushes/pointybush,
|
||||
/turf/unsimulated/floor{
|
||||
icon_state = "grass1";
|
||||
name = "grass"
|
||||
},
|
||||
/area/centcom/specops)
|
||||
"mH" = (
|
||||
/obj/structure/flora/ausbushes/ywflowers,
|
||||
/turf/unsimulated/floor{
|
||||
icon_state = "grass1";
|
||||
name = "grass"
|
||||
},
|
||||
/area/centcom/specops)
|
||||
"mI" = (
|
||||
/obj/structure/flora/ausbushes/brflowers,
|
||||
/turf/unsimulated/floor{
|
||||
icon_state = "grass1";
|
||||
name = "grass"
|
||||
},
|
||||
/area/centcom/specops)
|
||||
"mJ" = (
|
||||
/obj/structure/flora/ausbushes/sparsegrass,
|
||||
/turf/unsimulated/floor{
|
||||
icon_state = "grass1";
|
||||
name = "grass"
|
||||
},
|
||||
/area/centcom/specops)
|
||||
/area/centcom/control)
|
||||
"mK" = (
|
||||
/obj/structure/flora/ausbushes/reedbush,
|
||||
/turf/unsimulated/floor{
|
||||
icon_state = "grass1";
|
||||
name = "grass"
|
||||
},
|
||||
/area/centcom/specops)
|
||||
/area/centcom/control)
|
||||
"mL" = (
|
||||
/turf/unsimulated/floor{
|
||||
dir = 1;
|
||||
@@ -36255,7 +36220,7 @@ lH
|
||||
lH
|
||||
mu
|
||||
su
|
||||
mF
|
||||
mZ
|
||||
mY
|
||||
su
|
||||
nD
|
||||
@@ -36512,7 +36477,7 @@ mc
|
||||
lH
|
||||
lH
|
||||
su
|
||||
mE
|
||||
nd
|
||||
mX
|
||||
su
|
||||
nD
|
||||
@@ -36769,7 +36734,7 @@ mc
|
||||
lH
|
||||
lH
|
||||
su
|
||||
mH
|
||||
mY
|
||||
na
|
||||
su
|
||||
nD
|
||||
@@ -37026,7 +36991,7 @@ lH
|
||||
lH
|
||||
lH
|
||||
su
|
||||
mG
|
||||
WW
|
||||
mZ
|
||||
su
|
||||
nD
|
||||
@@ -37283,7 +37248,7 @@ lH
|
||||
mk
|
||||
mw
|
||||
su
|
||||
mJ
|
||||
na
|
||||
ne
|
||||
su
|
||||
nD
|
||||
|
||||
@@ -173,6 +173,7 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new())
|
||||
add_fingerprint(user)
|
||||
|
||||
var/unsafe_wrenching = FALSE
|
||||
var/safefromgusts = FALSE
|
||||
var/I = int_air ? int_air.return_pressure() : 0
|
||||
var/E = env_air ? env_air.return_pressure() : 0
|
||||
var/internal_pressure = I - E
|
||||
@@ -190,9 +191,16 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new())
|
||||
"<span class='italics'>You hear ratchet.</span>")
|
||||
investigate_log("was <span class='warning'>REMOVED</span> by [key_name(usr)]", "atmos")
|
||||
|
||||
for(var/obj/item/clothing/shoes/magboots/usermagboots in user.get_equipped_items())
|
||||
if(usermagboots.gustprotection && usermagboots.magpulse)
|
||||
safefromgusts = TRUE
|
||||
|
||||
//You unwrenched a pipe full of pressure? let's splat you into the wall silly.
|
||||
if(unsafe_wrenching)
|
||||
unsafe_pressure_release(user,internal_pressure)
|
||||
if(safefromgusts)
|
||||
to_chat(user, "<span class='italics'>Your magboots cling to the floor as a great burst of wind bellows against you.</span>")
|
||||
else
|
||||
unsafe_pressure_release(user,internal_pressure)
|
||||
deconstruct(TRUE)
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -137,51 +137,56 @@
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/atmospherics/binary/passive_gate/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
user.set_machine(src)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 385, 115, state = state)
|
||||
ui = new(user, src, ui_key, "AtmosPump", name, 310, 110, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["pressure"] = round(target_pressure)
|
||||
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
|
||||
/obj/machinery/atmospherics/binary/passive_gate/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"on" = on,
|
||||
"rate" = round(target_pressure),
|
||||
"max_rate" = MAX_OUTPUT_PRESSURE,
|
||||
"gas_unit" = "kPa",
|
||||
"step" = 10 // This is for the TGUI <NumberInput> step. It's here since multiple pumps share the same UI, but need different values.
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/Topic(href,href_list)
|
||||
/obj/machinery/atmospherics/binary/passive_gate/tgui_act(action, list/params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
|
||||
if(href_list["power"])
|
||||
switch(action)
|
||||
if("power")
|
||||
toggle()
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
return TRUE
|
||||
|
||||
if("max_rate")
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
|
||||
if("min_rate")
|
||||
target_pressure = 0
|
||||
. = TRUE
|
||||
|
||||
if("custom_rate")
|
||||
target_pressure = clamp(text2num(params["rate"]), 0 , MAX_OUTPUT_PRESSURE)
|
||||
. = TRUE
|
||||
if(.)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/proc/toggle()
|
||||
if(powered())
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
. = TRUE
|
||||
if(href_list["pressure"])
|
||||
var/pressure = href_list["pressure"]
|
||||
if(pressure == "max")
|
||||
pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
else if(pressure == "input")
|
||||
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
|
||||
if(!isnull(pressure))
|
||||
. = TRUE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
. = TRUE
|
||||
if(.)
|
||||
target_pressure = clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
|
||||
update_icon()
|
||||
SSnanoui.update_uis(src)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/attackby(obj/item/W, mob/user, params)
|
||||
if(!istype(W, /obj/item/wrench))
|
||||
|
||||
@@ -192,51 +192,51 @@ Thus, the two variables affect pump operation are set in New():
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/atmospherics/binary/pump/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
user.set_machine(src)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 385, 115, state = state)
|
||||
ui = new(user, src, ui_key, "AtmosPump", name, 310, 110, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["pressure"] = round(target_pressure)
|
||||
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
|
||||
/obj/machinery/atmospherics/binary/pump/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"on" = on,
|
||||
"rate" = round(target_pressure),
|
||||
"max_rate" = MAX_OUTPUT_PRESSURE,
|
||||
"gas_unit" = "kPa",
|
||||
"step" = 10 // This is for the TGUI <NumberInput> step. It's here since multiple pumps share the same UI, but need different values.
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/Topic(href,href_list)
|
||||
/obj/machinery/atmospherics/binary/pump/tgui_act(action, list/params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
. = TRUE
|
||||
if(href_list["pressure"])
|
||||
var/pressure = href_list["pressure"]
|
||||
if(pressure == "max")
|
||||
pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
else if(pressure == "input")
|
||||
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
|
||||
if(!isnull(pressure))
|
||||
. = TRUE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
. = TRUE
|
||||
if(.)
|
||||
target_pressure = clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
switch(action)
|
||||
if("power")
|
||||
toggle()
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
return TRUE
|
||||
|
||||
update_icon()
|
||||
SSnanoui.update_uis(src)
|
||||
if("max_rate")
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
|
||||
if("min_rate")
|
||||
target_pressure = 0
|
||||
. = TRUE
|
||||
|
||||
if("custom_rate")
|
||||
target_pressure = clamp(text2num(params["rate"]), 0 , MAX_OUTPUT_PRESSURE)
|
||||
. = TRUE
|
||||
if(.)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/power_change()
|
||||
var/old_stat = stat
|
||||
|
||||
@@ -188,51 +188,51 @@ Thus, the two variables affect pump operation are set in New():
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/volume_pump/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/binary/volume_pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/atmospherics/binary/volume_pump/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
user.set_machine(src)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 310, 115, state = state)
|
||||
ui = new(user, src, ui_key, "AtmosPump", name, 310, 110, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/binary/volume_pump/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["rate"] = round(transfer_rate)
|
||||
data["max_rate"] = round(MAX_TRANSFER_RATE)
|
||||
/obj/machinery/atmospherics/binary/volume_pump/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"on" = on,
|
||||
"rate" = round(transfer_rate),
|
||||
"max_rate" = round(MAX_TRANSFER_RATE),
|
||||
"gas_unit" = "L/s",
|
||||
"step" = 1 // This is for the TGUI <NumberInput> step. It's here since multiple pumps share the same UI, but need different values.
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/binary/volume_pump/Topic(href,href_list)
|
||||
/obj/machinery/atmospherics/binary/volume_pump/tgui_act(action, list/params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
. = TRUE
|
||||
if(href_list["rate"])
|
||||
var/rate = href_list["rate"]
|
||||
if(rate == "max")
|
||||
rate = MAX_TRANSFER_RATE
|
||||
. = TRUE
|
||||
else if(rate == "input")
|
||||
rate = input("New transfer rate (0-[MAX_TRANSFER_RATE] L/s):", name, transfer_rate) as num|null
|
||||
if(!isnull(rate))
|
||||
. = TRUE
|
||||
else if(text2num(rate) != null)
|
||||
rate = text2num(rate)
|
||||
. = TRUE
|
||||
if(.)
|
||||
transfer_rate = clamp(rate, 0, MAX_TRANSFER_RATE)
|
||||
investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos")
|
||||
switch(action)
|
||||
if("power")
|
||||
toggle()
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
return TRUE
|
||||
|
||||
update_icon()
|
||||
SSnanoui.update_uis(src)
|
||||
if("max_rate")
|
||||
transfer_rate = MAX_TRANSFER_RATE
|
||||
. = TRUE
|
||||
|
||||
if("min_rate")
|
||||
transfer_rate = 0
|
||||
. = TRUE
|
||||
|
||||
if("custom_rate")
|
||||
transfer_rate = clamp(text2num(params["rate"]), 0 , MAX_TRANSFER_RATE)
|
||||
. = TRUE
|
||||
if(.)
|
||||
investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos")
|
||||
|
||||
/obj/machinery/atmospherics/binary/volume_pump/power_change()
|
||||
var/old_stat = stat
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
//--------------------------------------------
|
||||
// Omni device port types
|
||||
//--------------------------------------------
|
||||
#define ATM_NONE 0
|
||||
#define ATM_INPUT 1
|
||||
#define ATM_OUTPUT 2
|
||||
|
||||
#define ATM_O2 3
|
||||
#define ATM_N2 4
|
||||
#define ATM_CO2 5
|
||||
#define ATM_P 6 //Plasma
|
||||
#define ATM_N2O 7
|
||||
|
||||
//--------------------------------------------
|
||||
// Omni port datum
|
||||
//
|
||||
// Used by omni devices to manage connections
|
||||
// to other atmospheric objects.
|
||||
//--------------------------------------------
|
||||
/datum/omni_port
|
||||
var/obj/machinery/atmospherics/omni/master
|
||||
var/dir
|
||||
var/update = 1
|
||||
var/mode = 0
|
||||
var/concentration = 0
|
||||
var/con_lock = 0
|
||||
var/transfer_moles = 0
|
||||
var/datum/gas_mixture/air
|
||||
var/obj/machinery/atmospherics/node
|
||||
var/datum/pipeline/parent
|
||||
|
||||
/datum/omni_port/New(var/obj/machinery/atmospherics/omni/M, var/direction = NORTH)
|
||||
..()
|
||||
dir = direction
|
||||
if(istype(M))
|
||||
master = M
|
||||
air = new
|
||||
air.volume = 200
|
||||
|
||||
/datum/omni_port/proc/connect()
|
||||
if(node)
|
||||
return
|
||||
master.atmos_init()
|
||||
if(node)
|
||||
node.atmos_init()
|
||||
node.addMember(master)
|
||||
master.build_network()
|
||||
|
||||
/datum/omni_port/proc/disconnect()
|
||||
if(node)
|
||||
node.disconnect(master)
|
||||
node = null
|
||||
master.nullifyPipenet(parent)
|
||||
|
||||
//--------------------------------------------
|
||||
// Need to find somewhere else for these
|
||||
//--------------------------------------------
|
||||
|
||||
//returns a text string based on the direction flag input
|
||||
// if capitalize is true, it will return the string capitalized
|
||||
// otherwise it will return the direction string in lower case
|
||||
/proc/dir_name(var/dir, var/capitalize = 0)
|
||||
var/string = null
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
string = "North"
|
||||
if(SOUTH)
|
||||
string = "South"
|
||||
if(EAST)
|
||||
string = "East"
|
||||
if(WEST)
|
||||
string = "West"
|
||||
|
||||
if(!capitalize && string)
|
||||
string = lowertext(string)
|
||||
|
||||
return string
|
||||
|
||||
//returns a direction flag based on the string passed to it
|
||||
// case insensitive
|
||||
/proc/dir_flag(var/dir)
|
||||
dir = lowertext(dir)
|
||||
switch(dir)
|
||||
if("north")
|
||||
return NORTH
|
||||
if("south")
|
||||
return SOUTH
|
||||
if("east")
|
||||
return EAST
|
||||
if("west")
|
||||
return WEST
|
||||
else
|
||||
return 0
|
||||
|
||||
@@ -1,273 +0,0 @@
|
||||
//--------------------------------------------
|
||||
// Gas filter - omni variant
|
||||
//--------------------------------------------
|
||||
/obj/machinery/atmospherics/omni/filter
|
||||
name = "omni gas filter"
|
||||
icon_state = "map_filter"
|
||||
|
||||
var/list/o_filters = new()
|
||||
var/datum/omni_port/input
|
||||
var/datum/omni_port/output
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/Destroy()
|
||||
input = null
|
||||
output = null
|
||||
o_filters.Cut()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/sort_ports()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.update)
|
||||
if(output == P)
|
||||
output = null
|
||||
if(input == P)
|
||||
input = null
|
||||
if(o_filters.Find(P))
|
||||
o_filters -= P
|
||||
|
||||
P.air.volume = 200
|
||||
switch(P.mode)
|
||||
if(ATM_INPUT)
|
||||
input = P
|
||||
if(ATM_OUTPUT)
|
||||
output = P
|
||||
if(ATM_O2 to ATM_N2O)
|
||||
o_filters += P
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/error_check()
|
||||
if(!input || !output || !o_filters)
|
||||
return 1
|
||||
if(o_filters.len < 1 || o_filters.len > 2) //requires 1 or 2 o_filters ~otherwise why are you using a filter?
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/process_atmos()
|
||||
..()
|
||||
if(!on)
|
||||
return 0
|
||||
|
||||
if(!input || !output)
|
||||
return 0
|
||||
|
||||
var/datum/gas_mixture/output_air = output.air //BYOND doesn't like referencing "output.air.return_pressure()" so we need to make a direct reference
|
||||
var/datum/gas_mixture/input_air = input.air // it's completely happy with them if they're in a loop though i.e. "P.air.return_pressure()"... *shrug*
|
||||
|
||||
var/output_pressure = output_air.return_pressure()
|
||||
|
||||
if(output_pressure >= target_pressure)
|
||||
return 1
|
||||
for(var/datum/omni_port/P in o_filters)
|
||||
if(P.air.return_pressure() >= target_pressure)
|
||||
return 1
|
||||
|
||||
var/pressure_delta = target_pressure - output_pressure
|
||||
|
||||
if(input_air.return_temperature() > 0)
|
||||
input.transfer_moles = pressure_delta * output_air.volume / (input_air.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
if(input.transfer_moles > 0)
|
||||
var/datum/gas_mixture/removed = input_air.remove(input.transfer_moles)
|
||||
|
||||
if(!removed)
|
||||
return 1
|
||||
|
||||
for(var/datum/omni_port/P in o_filters)
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
filtered_out.temperature = removed.return_temperature()
|
||||
|
||||
switch(P.mode)
|
||||
if(ATM_O2)
|
||||
filtered_out.oxygen = removed.oxygen
|
||||
removed.oxygen = 0
|
||||
if(ATM_N2)
|
||||
filtered_out.nitrogen = removed.nitrogen
|
||||
removed.nitrogen = 0
|
||||
if(ATM_CO2)
|
||||
filtered_out.carbon_dioxide = removed.carbon_dioxide
|
||||
removed.carbon_dioxide = 0
|
||||
if(ATM_P)
|
||||
filtered_out.toxins = removed.toxins
|
||||
removed.toxins = 0
|
||||
|
||||
filtered_out.agent_b = removed.agent_b
|
||||
removed.agent_b = 0
|
||||
if(ATM_N2O)
|
||||
filtered_out.sleeping_agent = removed.sleeping_agent
|
||||
removed.sleeping_agent = 0
|
||||
else
|
||||
filtered_out = null
|
||||
|
||||
P.air.merge(filtered_out)
|
||||
P.parent.update = 1
|
||||
|
||||
output_air.merge(removed)
|
||||
output.parent.update = 1
|
||||
|
||||
input.transfer_moles = 0
|
||||
input.parent.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, force_open = 0)
|
||||
usr.set_machine(src)
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "omni_filter.tmpl", "Omni Filter Control", 330, 330)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/ui_data(mob/user, datum/topic_state/state)
|
||||
var/data[0]
|
||||
|
||||
data["power"] = on
|
||||
data["config"] = configuring
|
||||
|
||||
var/portData[0]
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(!configuring && P.mode == 0)
|
||||
continue
|
||||
|
||||
var/input = 0
|
||||
var/output = 0
|
||||
var/filter = 1
|
||||
var/f_type = null
|
||||
switch(P.mode)
|
||||
if(ATM_INPUT)
|
||||
input = 1
|
||||
filter = 0
|
||||
if(ATM_OUTPUT)
|
||||
output = 1
|
||||
filter = 0
|
||||
if(ATM_O2 to ATM_N2O)
|
||||
f_type = mode_send_switch(P.mode)
|
||||
|
||||
portData[++portData.len] = list("dir" = dir_name(P.dir, capitalize = 1), \
|
||||
"input" = input, \
|
||||
"output" = output, \
|
||||
"filter" = filter, \
|
||||
"f_type" = f_type)
|
||||
|
||||
if(portData.len)
|
||||
data["ports"] = portData
|
||||
if(output)
|
||||
data["pressure"] = target_pressure
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/mode_send_switch(var/mode = ATM_NONE)
|
||||
switch(mode)
|
||||
if(ATM_O2)
|
||||
return "Oxygen"
|
||||
if(ATM_N2)
|
||||
return "Nitrogen"
|
||||
if(ATM_CO2)
|
||||
return "Carbon Dioxide"
|
||||
if(ATM_P)
|
||||
return "Plasma" //*cough* Plasma *cough*
|
||||
if(ATM_N2O)
|
||||
return "Nitrous Oxide"
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
switch(href_list["command"])
|
||||
if("power")
|
||||
if(!configuring)
|
||||
on = !on
|
||||
else
|
||||
on = 0
|
||||
if("configure")
|
||||
configuring = !configuring
|
||||
if(configuring)
|
||||
on = 0
|
||||
|
||||
//only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on
|
||||
if(configuring && !on)
|
||||
switch(href_list["command"])
|
||||
if("set_pressure")
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",target_pressure) as num
|
||||
target_pressure = between(0, new_pressure, 4500)
|
||||
if("switch_mode")
|
||||
switch_mode(dir_flag(href_list["dir"]), mode_return_switch(href_list["mode"]))
|
||||
if("switch_filter")
|
||||
var/new_filter = input(usr,"Select filter mode:","Change filter",href_list["mode"]) in list("None", "Oxygen", "Nitrogen", "Carbon Dioxide", "Plasma", "Nitrous Oxide")
|
||||
switch_filter(dir_flag(href_list["dir"]), mode_return_switch(new_filter))
|
||||
|
||||
update_icon()
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/mode_return_switch(var/mode)
|
||||
switch(mode)
|
||||
if("Oxygen")
|
||||
return ATM_O2
|
||||
if("Nitrogen")
|
||||
return ATM_N2
|
||||
if("Carbon Dioxide")
|
||||
return ATM_CO2
|
||||
if("Plasma")
|
||||
return ATM_P
|
||||
if("Nitrous Oxide")
|
||||
return ATM_N2O
|
||||
if("in")
|
||||
return ATM_INPUT
|
||||
if("out")
|
||||
return ATM_OUTPUT
|
||||
if("None")
|
||||
return ATM_NONE
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/switch_filter(var/dir, var/mode)
|
||||
//check they aren't trying to disable the input or output ~this can only happen if they hack the cached tmpl file
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.dir == dir)
|
||||
if(P.mode == ATM_INPUT || P.mode == ATM_OUTPUT)
|
||||
return
|
||||
|
||||
switch_mode(dir, mode)
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/switch_mode(var/port, var/mode)
|
||||
if(mode == null || !port)
|
||||
return
|
||||
var/datum/omni_port/target_port = null
|
||||
var/list/other_ports = new()
|
||||
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.dir == port)
|
||||
target_port = P
|
||||
else
|
||||
other_ports += P
|
||||
|
||||
var/previous_mode = null
|
||||
if(target_port)
|
||||
previous_mode = target_port.mode
|
||||
target_port.mode = mode
|
||||
if(target_port.mode != previous_mode)
|
||||
handle_port_change(target_port)
|
||||
else
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
for(var/datum/omni_port/P in other_ports)
|
||||
if(P.mode == mode)
|
||||
var/old_mode = P.mode
|
||||
P.mode = previous_mode
|
||||
if(P.mode != old_mode)
|
||||
handle_port_change(P)
|
||||
|
||||
update_ports()
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/handle_port_change(var/datum/omni_port/P)
|
||||
switch(P.mode)
|
||||
if(ATM_NONE)
|
||||
initialize_directions &= ~P.dir
|
||||
P.disconnect()
|
||||
else
|
||||
initialize_directions |= P.dir
|
||||
P.connect()
|
||||
P.update = 1
|
||||
@@ -1,291 +0,0 @@
|
||||
//--------------------------------------------
|
||||
// Gas mixer - omni variant
|
||||
//--------------------------------------------
|
||||
/obj/machinery/atmospherics/omni/mixer
|
||||
name = "omni gas mixer"
|
||||
icon_state = "map_mixer"
|
||||
|
||||
var/list/inputs = new()
|
||||
var/datum/omni_port/output
|
||||
|
||||
//setup tags for initial concentration values (must be decimal)
|
||||
var/tag_north_con
|
||||
var/tag_south_con
|
||||
var/tag_east_con
|
||||
var/tag_west_con
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/New()
|
||||
..()
|
||||
if(mapper_set())
|
||||
var/con = 0
|
||||
for(var/datum/omni_port/P in ports)
|
||||
switch(P.dir)
|
||||
if(NORTH)
|
||||
if(tag_north_con && tag_north == 1)
|
||||
P.concentration = tag_north_con
|
||||
con += max(0, tag_north_con)
|
||||
if(SOUTH)
|
||||
if(tag_south_con && tag_south == 1)
|
||||
P.concentration = tag_south_con
|
||||
con += max(0, tag_south_con)
|
||||
if(EAST)
|
||||
if(tag_east_con && tag_east == 1)
|
||||
P.concentration = tag_east_con
|
||||
con += max(0, tag_east_con)
|
||||
if(WEST)
|
||||
if(tag_west_con && tag_west == 1)
|
||||
P.concentration = tag_west_con
|
||||
con += max(0, tag_west_con)
|
||||
|
||||
//mappers who are bad at maths will be punished (total concentration must be 100%)
|
||||
if(con != 1)
|
||||
tag_north_con = null
|
||||
tag_south_con = null
|
||||
tag_east_con = null
|
||||
tag_west_con = null
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/Destroy()
|
||||
inputs.Cut()
|
||||
output = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/sort_ports()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.update)
|
||||
if(output == P)
|
||||
output = null
|
||||
if(inputs.Find(P))
|
||||
inputs -= P
|
||||
|
||||
P.air.volume = 200
|
||||
switch(P.mode)
|
||||
if(ATM_INPUT)
|
||||
inputs += P
|
||||
if(ATM_OUTPUT)
|
||||
output = P
|
||||
|
||||
if(!mapper_set())
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
P.concentration = 1 / max(1, inputs.len)
|
||||
|
||||
if(output)
|
||||
output.air.volume *= 0.75 * inputs.len
|
||||
output.concentration = 1
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/mapper_set()
|
||||
return (tag_north_con || tag_south_con || tag_east_con || tag_west_con)
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/error_check()
|
||||
if(!output || !inputs)
|
||||
return 1
|
||||
if(inputs.len < 2 || inputs.len > 3) //requires 2 or 3 inputs ~otherwise why are you using a mixer?
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/process_atmos()
|
||||
..()
|
||||
if(!on)
|
||||
return 0
|
||||
|
||||
var/datum/gas_mixture/output_air = output.air
|
||||
var/output_pressure = output_air.return_pressure()
|
||||
|
||||
|
||||
if(output_pressure >= target_pressure * 0.999)
|
||||
//No need to mix if target is already full! - 0.1% margin of error so we minimize processing minor gas volumes
|
||||
return 1
|
||||
|
||||
//Calculate necessary moles to transfer using PV=nRT
|
||||
|
||||
var/pressure_delta = target_pressure - output_pressure
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.air.return_temperature() > 0)
|
||||
P.transfer_moles = (P.concentration * pressure_delta) * output_air.return_volume() / (P.air.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/ratio_check = null
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(!P.transfer_moles)
|
||||
return 1
|
||||
if(P.air.total_moles() < P.transfer_moles)
|
||||
ratio_check = 1
|
||||
continue
|
||||
|
||||
if(ratio_check)
|
||||
var/list/ratio_list = new()
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
ratio_list.Add(P.air.total_moles() / P.transfer_moles)
|
||||
|
||||
var/ratio = min(ratio_list)
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
P.transfer_moles *= ratio
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.transfer_moles > 0)
|
||||
output_air.merge(P.air.remove(P.transfer_moles))
|
||||
P.parent.update = 1
|
||||
P.transfer_moles = 0
|
||||
|
||||
output.parent.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, force_open = 0)
|
||||
usr.set_machine(src)
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "omni_mixer.tmpl", "Omni Mixer Control", 360, 330)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/ui_data(mob/user, datum/topic_state/state)
|
||||
var/data[0]
|
||||
|
||||
data["power"] = on
|
||||
data["config"] = configuring
|
||||
|
||||
var/portData[0]
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(!configuring && P.mode == 0)
|
||||
continue
|
||||
|
||||
var/input = 0
|
||||
var/output = 0
|
||||
switch(P.mode)
|
||||
if(ATM_INPUT)
|
||||
input = 1
|
||||
if(ATM_OUTPUT)
|
||||
output = 1
|
||||
|
||||
portData[++portData.len] = list("dir" = dir_name(P.dir, capitalize = 1), \
|
||||
"concentration" = P.concentration, \
|
||||
"input" = input, \
|
||||
"output" = output, \
|
||||
"con_lock" = P.con_lock)
|
||||
|
||||
if(portData.len)
|
||||
data["ports"] = portData
|
||||
if(output)
|
||||
data["pressure"] = target_pressure
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
switch(href_list["command"])
|
||||
if("power")
|
||||
if(!configuring)
|
||||
on = !on
|
||||
else
|
||||
on = 0
|
||||
if("configure")
|
||||
configuring = !configuring
|
||||
if(configuring)
|
||||
on = 0
|
||||
|
||||
//only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on
|
||||
if(configuring && !on)
|
||||
switch(href_list["command"])
|
||||
if("set_pressure")
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",target_pressure) as num
|
||||
target_pressure = between(0, new_pressure, 4500)
|
||||
if("switch_mode")
|
||||
switch_mode(dir_flag(href_list["dir"]), href_list["mode"])
|
||||
if("switch_con")
|
||||
change_concentration(dir_flag(href_list["dir"]))
|
||||
if("switch_conlock")
|
||||
con_lock(dir_flag(href_list["dir"]))
|
||||
|
||||
update_icon()
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/switch_mode(var/port = NORTH, var/mode = ATM_NONE)
|
||||
if(mode != ATM_INPUT && mode != ATM_OUTPUT)
|
||||
switch(mode)
|
||||
if("in")
|
||||
mode = ATM_INPUT
|
||||
if("out")
|
||||
mode = ATM_OUTPUT
|
||||
else
|
||||
mode = ATM_NONE
|
||||
|
||||
for(var/datum/omni_port/P in ports)
|
||||
var/old_mode = P.mode
|
||||
if(P.dir == port)
|
||||
switch(mode)
|
||||
if(ATM_INPUT)
|
||||
if(P.mode == ATM_OUTPUT)
|
||||
return
|
||||
P.mode = mode
|
||||
if(ATM_OUTPUT)
|
||||
P.mode = mode
|
||||
if(ATM_NONE)
|
||||
if(P.mode == ATM_OUTPUT)
|
||||
return
|
||||
if(P.mode == ATM_INPUT && inputs.len > 2)
|
||||
P.mode = mode
|
||||
else if(P.mode == ATM_OUTPUT && mode == ATM_OUTPUT)
|
||||
P.mode = ATM_INPUT
|
||||
if(P.mode != old_mode)
|
||||
switch(P.mode)
|
||||
if(ATM_NONE)
|
||||
initialize_directions &= ~P.dir
|
||||
P.disconnect()
|
||||
else
|
||||
initialize_directions |= P.dir
|
||||
P.connect()
|
||||
P.update = 1
|
||||
|
||||
update_ports()
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/change_concentration(var/port = NORTH)
|
||||
tag_north_con = null
|
||||
tag_south_con = null
|
||||
tag_east_con = null
|
||||
tag_west_con = null
|
||||
|
||||
var/old_con = 0
|
||||
var/non_locked = 0
|
||||
var/remain_con = 1
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.dir == port)
|
||||
old_con = P.concentration
|
||||
else if(!P.con_lock)
|
||||
non_locked++
|
||||
else
|
||||
remain_con -= P.concentration
|
||||
|
||||
//return if no adjustable ports
|
||||
if(non_locked < 1)
|
||||
return
|
||||
|
||||
var/new_con = (input(usr,"Enter a new concentration (0-[round(remain_con * 100, 0.5)])%","Concentration control", min(remain_con, old_con)*100) as num) / 100
|
||||
|
||||
//cap it between 0 and the max remaining concentration
|
||||
new_con = between(0, new_con, remain_con)
|
||||
|
||||
//new_con = min(remain_con, new_con)
|
||||
|
||||
//clamp remaining concentration so we don't go into negatives
|
||||
remain_con = max(0, remain_con - new_con)
|
||||
|
||||
//distribute remaining concentration between unlocked ports evenly
|
||||
remain_con /= max(1, non_locked)
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.dir == port)
|
||||
P.concentration = new_con
|
||||
else if(!P.con_lock)
|
||||
P.concentration = remain_con
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/con_lock(var/port = NORTH)
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.dir == port)
|
||||
P.con_lock = !P.con_lock
|
||||
@@ -1,302 +0,0 @@
|
||||
//--------------------------------------------
|
||||
// Base omni device
|
||||
//--------------------------------------------
|
||||
/obj/machinery/atmospherics/omni
|
||||
name = "omni device"
|
||||
icon = 'icons/atmos/omni_devices.dmi'
|
||||
icon_state = "base"
|
||||
use_power = IDLE_POWER_USE
|
||||
initialize_directions = 0
|
||||
|
||||
can_unwrench = 1
|
||||
|
||||
var/on = 0
|
||||
var/configuring = 0
|
||||
var/target_pressure = ONE_ATMOSPHERE
|
||||
|
||||
var/tag_north = ATM_NONE
|
||||
var/tag_south = ATM_NONE
|
||||
var/tag_east = ATM_NONE
|
||||
var/tag_west = ATM_NONE
|
||||
|
||||
var/overlays_on[5]
|
||||
var/overlays_off[5]
|
||||
var/overlays_error[2]
|
||||
var/underlays_current[4]
|
||||
|
||||
var/list/ports = new()
|
||||
|
||||
/obj/machinery/atmospherics/omni/New()
|
||||
..()
|
||||
icon_state = "base"
|
||||
|
||||
ports = new()
|
||||
for(var/d in GLOB.cardinal)
|
||||
var/datum/omni_port/new_port = new(src, d)
|
||||
switch(d)
|
||||
if(NORTH)
|
||||
new_port.mode = tag_north
|
||||
if(SOUTH)
|
||||
new_port.mode = tag_south
|
||||
if(EAST)
|
||||
new_port.mode = tag_east
|
||||
if(WEST)
|
||||
new_port.mode = tag_west
|
||||
if(new_port.mode > 0)
|
||||
initialize_directions |= d
|
||||
ports += new_port
|
||||
|
||||
build_icons()
|
||||
|
||||
/obj/machinery/atmospherics/omni/Destroy()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.node)
|
||||
P.node.disconnect(src)
|
||||
P.node = null
|
||||
nullifyPipenet(P.parent)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/omni/atmos_init()
|
||||
..()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.node || P.mode == 0)
|
||||
continue
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src, P.dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
P.node = target
|
||||
break
|
||||
|
||||
for(var/datum/omni_port/P in ports)
|
||||
P.update = 1
|
||||
|
||||
update_ports()
|
||||
|
||||
/obj/machinery/atmospherics/omni/update_icon()
|
||||
..()
|
||||
|
||||
if(stat & NOPOWER)
|
||||
overlays = overlays_off
|
||||
on = 0
|
||||
else if(error_check())
|
||||
overlays = overlays_error
|
||||
on = 0
|
||||
else
|
||||
overlays = on ? (overlays_on) : (overlays_off)
|
||||
|
||||
underlays = underlays_current
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/error_check()
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/omni/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/omni/attackby(var/obj/item/W as obj, var/mob/user as mob, params)
|
||||
if(!istype(W, /obj/item/wrench))
|
||||
return ..()
|
||||
|
||||
if(can_unwrench)
|
||||
var/int_pressure = 0
|
||||
for(var/datum/omni_port/P in ports)
|
||||
int_pressure += P.air.return_pressure()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if((int_pressure - env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
to_chat(user, "<span class='danger'>You cannot unwrench [src], it is too exerted due to internal pressure.</span>")
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(loc, W.usesound, 50, 1)
|
||||
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
|
||||
if(do_after(user, 40 * W.toolspeed, target = src))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"<span class='notice'>You have unfastened \the [src].</span>", \
|
||||
"You hear a ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
qdel(src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/omni/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
add_fingerprint(usr)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/omni/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/build_icons()
|
||||
if(!check_icon_cache())
|
||||
return
|
||||
|
||||
var/core_icon = null
|
||||
if(istype(src, /obj/machinery/atmospherics/omni/mixer))
|
||||
core_icon = "mixer"
|
||||
else if(istype(src, /obj/machinery/atmospherics/omni/filter))
|
||||
core_icon = "filter"
|
||||
else
|
||||
return
|
||||
|
||||
//directional icons are layers 1-4, with the core icon on layer 5
|
||||
if(core_icon)
|
||||
overlays_off[5] = GLOB.pipe_icon_manager.get_atmos_icon("omni", , , core_icon)
|
||||
overlays_on[5] = GLOB.pipe_icon_manager.get_atmos_icon("omni", , , core_icon + "_glow")
|
||||
|
||||
overlays_error[1] = GLOB.pipe_icon_manager.get_atmos_icon("omni", , , core_icon)
|
||||
overlays_error[2] = GLOB.pipe_icon_manager.get_atmos_icon("omni", , , "error")
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/update_port_icons()
|
||||
if(!check_icon_cache())
|
||||
return
|
||||
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.update)
|
||||
var/ref_layer = 0
|
||||
switch(P.dir)
|
||||
if(NORTH)
|
||||
ref_layer = 1
|
||||
if(SOUTH)
|
||||
ref_layer = 2
|
||||
if(EAST)
|
||||
ref_layer = 3
|
||||
if(WEST)
|
||||
ref_layer = 4
|
||||
|
||||
if(!ref_layer)
|
||||
continue
|
||||
|
||||
var/list/port_icons = select_port_icons(P)
|
||||
if(port_icons)
|
||||
if(P.node)
|
||||
underlays_current[ref_layer] = port_icons["pipe_icon"]
|
||||
else
|
||||
underlays_current[ref_layer] = null
|
||||
overlays_off[ref_layer] = port_icons["off_icon"]
|
||||
overlays_on[ref_layer] = port_icons["on_icon"]
|
||||
else
|
||||
underlays_current[ref_layer] = null
|
||||
overlays_off[ref_layer] = null
|
||||
overlays_on[ref_layer] = null
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/select_port_icons(var/datum/omni_port/P)
|
||||
if(!istype(P))
|
||||
return
|
||||
|
||||
if(P.mode > 0)
|
||||
var/ic_dir = dir_name(P.dir)
|
||||
var/ic_on = ic_dir
|
||||
var/ic_off = ic_dir
|
||||
switch(P.mode)
|
||||
if(ATM_INPUT)
|
||||
ic_on += "_in_glow"
|
||||
ic_off += "_in"
|
||||
if(ATM_OUTPUT)
|
||||
ic_on += "_out_glow"
|
||||
ic_off += "_out"
|
||||
if(ATM_O2 to ATM_N2O)
|
||||
ic_on += "_filter"
|
||||
ic_off += "_out"
|
||||
|
||||
ic_on = GLOB.pipe_icon_manager.get_atmos_icon("omni", , , ic_on)
|
||||
ic_off = GLOB.pipe_icon_manager.get_atmos_icon("omni", , , ic_off)
|
||||
|
||||
var/pipe_state
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
if(T.intact && istype(P.node, /obj/machinery/atmospherics/pipe) && P.node.level == 1 )
|
||||
//pipe_state = GLOB.pipe_icon_manager.get_atmos_icon("underlay_down", P.dir, color_cache_name(P.node))
|
||||
pipe_state = GLOB.pipe_icon_manager.get_atmos_icon("underlay", P.dir, color_cache_name(P.node), "down")
|
||||
else
|
||||
//pipe_state = GLOB.pipe_icon_manager.get_atmos_icon("underlay_intact", P.dir, color_cache_name(P.node))
|
||||
pipe_state = GLOB.pipe_icon_manager.get_atmos_icon("underlay", P.dir, color_cache_name(P.node), "intact")
|
||||
|
||||
return list("on_icon" = ic_on, "off_icon" = ic_off, "pipe_icon" = pipe_state)
|
||||
|
||||
/obj/machinery/atmospherics/omni/update_underlays()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
P.update = 1
|
||||
update_ports()
|
||||
|
||||
/obj/machinery/atmospherics/omni/hide(var/i)
|
||||
update_underlays()
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/update_ports()
|
||||
sort_ports()
|
||||
update_port_icons()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
P.update = 0
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/sort_ports()
|
||||
return
|
||||
|
||||
// Pipenet procs
|
||||
/obj/machinery/atmospherics/omni/build_network(remove_deferral = FALSE)
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(!P.parent)
|
||||
P.parent = new /datum/pipeline()
|
||||
P.parent.build_pipeline(src)
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/omni/disconnect(obj/machinery/atmospherics/reference)
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(reference == P.node)
|
||||
if(istype(P.node, /obj/machinery/atmospherics/pipe))
|
||||
qdel(P.parent)
|
||||
P.node = null
|
||||
update_ports()
|
||||
|
||||
/obj/machinery/atmospherics/omni/nullifyPipenet(datum/pipeline/P)
|
||||
..()
|
||||
if(!P)
|
||||
return
|
||||
for(var/datum/omni_port/PO in ports)
|
||||
if(P == PO.parent)
|
||||
PO.parent.other_airs -= PO.air
|
||||
PO.parent = null
|
||||
|
||||
/obj/machinery/atmospherics/omni/returnPipenetAir(datum/pipeline/P)
|
||||
for(var/datum/omni_port/PO in ports)
|
||||
if(P == PO.parent)
|
||||
return PO.air
|
||||
|
||||
/obj/machinery/atmospherics/omni/pipeline_expansion(datum/pipeline/P)
|
||||
if(P)
|
||||
for(var/datum/omni_port/PO in ports)
|
||||
if(PO.parent == P)
|
||||
return list(PO.node)
|
||||
else
|
||||
var/list/nodes = list()
|
||||
for(var/datum/omni_port/PO in ports)
|
||||
nodes += PO.node
|
||||
|
||||
return nodes
|
||||
|
||||
/obj/machinery/atmospherics/omni/setPipenet(datum/pipeline/P, obj/machinery/atmospherics/A)
|
||||
for(var/datum/omni_port/PO in ports)
|
||||
if(A == PO.node)
|
||||
PO.parent = P
|
||||
|
||||
/obj/machinery/atmospherics/omni/returnPipenet(obj/machinery/atmospherics/A)
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(A == P.node)
|
||||
return P.parent
|
||||
|
||||
/obj/machinery/atmospherics/omni/replacePipenet(datum/pipeline/Old, datum/pipeline/New)
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(Old == P.parent)
|
||||
P.parent = New
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/omni/process_atmos()
|
||||
..()
|
||||
for(var/datum/omni_port/port in ports)
|
||||
if(!port.parent)
|
||||
return 0
|
||||
return 1
|
||||
@@ -1,26 +1,39 @@
|
||||
|
||||
/// Nothing will be filtered.
|
||||
#define FILTER_NOTHING -1
|
||||
/// Plasma, and Oxygen Agent B.
|
||||
#define FILTER_TOXINS 0
|
||||
/// Oxygen only.
|
||||
#define FILTER_OXYGEN 1
|
||||
/// Nitrogen only.
|
||||
#define FILTER_NITROGEN 2
|
||||
/// Carbon dioxide only.
|
||||
#define FILTER_CO2 3
|
||||
/// Nitrous oxide only.
|
||||
#define FILTER_N2O 4
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter
|
||||
name = "gas filter"
|
||||
icon = 'icons/atmos/filter.dmi'
|
||||
icon_state = "map"
|
||||
|
||||
can_unwrench = 1
|
||||
|
||||
name = "gas filter"
|
||||
|
||||
can_unwrench = TRUE
|
||||
/// The amount of pressure the filter wants to operate at.
|
||||
var/target_pressure = ONE_ATMOSPHERE
|
||||
|
||||
var/filter_type = 0
|
||||
/*
|
||||
Filter types:
|
||||
-1: Nothing
|
||||
0: Toxins: Toxins, Oxygen Agent B
|
||||
1: Oxygen: Oxygen ONLY
|
||||
2: Nitrogen: Nitrogen ONLY
|
||||
3: Carbon Dioxide: Carbon Dioxide ONLY
|
||||
4: Sleeping Agent (N2O)
|
||||
*/
|
||||
|
||||
var/frequency = 0
|
||||
/// The type of gas we want to filter. Valid values that go here are from the `FILTER` defines at the top of the file.
|
||||
var/filter_type = FILTER_NOTHING
|
||||
/// The frequency of the filter. Used with `radio_connection`.
|
||||
var/frequency = NONE
|
||||
/// A reference to the filter's `datum/radio_frequency`.
|
||||
var/datum/radio_frequency/radio_connection
|
||||
/// A list of available filter options. Used with `tgui_data`.
|
||||
var/list/filter_list = list(
|
||||
"Nothing" = FILTER_NOTHING,
|
||||
"Plasma" = FILTER_TOXINS,
|
||||
"O2" = FILTER_OXYGEN,
|
||||
"N2" = FILTER_NITROGEN,
|
||||
"CO2" = FILTER_CO2,
|
||||
"N2O" = FILTER_N2O
|
||||
)
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/CtrlClick(mob/living/user)
|
||||
if(!istype(user) || user.incapacitated())
|
||||
@@ -146,26 +159,26 @@ Filter types:
|
||||
filtered_out.temperature = removed.temperature
|
||||
|
||||
switch(filter_type)
|
||||
if(0) //removing hydrocarbons
|
||||
if(FILTER_TOXINS)
|
||||
filtered_out.toxins = removed.toxins
|
||||
removed.toxins = 0
|
||||
|
||||
filtered_out.agent_b = removed.agent_b
|
||||
removed.agent_b = 0
|
||||
|
||||
if(1) //removing O2
|
||||
if(FILTER_OXYGEN)
|
||||
filtered_out.oxygen = removed.oxygen
|
||||
removed.oxygen = 0
|
||||
|
||||
if(2) //removing N2
|
||||
if(FILTER_NITROGEN)
|
||||
filtered_out.nitrogen = removed.nitrogen
|
||||
removed.nitrogen = 0
|
||||
|
||||
if(3) //removing CO2
|
||||
if(FILTER_CO2)
|
||||
filtered_out.carbon_dioxide = removed.carbon_dioxide
|
||||
removed.carbon_dioxide = 0
|
||||
|
||||
if(4)//removing N2O
|
||||
if(FILTER_N2O)
|
||||
filtered_out.sleeping_agent = removed.sleeping_agent
|
||||
removed.sleeping_agent = 0
|
||||
else
|
||||
@@ -188,7 +201,7 @@ Filter types:
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/attack_hand(mob/user)
|
||||
if(..())
|
||||
@@ -199,53 +212,56 @@ Filter types:
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/atmospherics/trinary/filter/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
user.set_machine(src)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_filter.tmpl", name, 475, 155, state = state)
|
||||
ui = new(user, src, ui_key, "AtmosFilter", name, 380, 140, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["pressure"] = round(target_pressure)
|
||||
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
|
||||
data["filter_type"] = filter_type
|
||||
/obj/machinery/atmospherics/trinary/filter/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"on" = on,
|
||||
"pressure" = round(target_pressure),
|
||||
"max_pressure" = round(MAX_OUTPUT_PRESSURE),
|
||||
"filter_type" = filter_type
|
||||
)
|
||||
data["filter_type_list"] = list()
|
||||
for(var/label in filter_list)
|
||||
data["filter_type_list"] += list(list("label" = label, "gas_type" = filter_list[label]))
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/Topic(href, href_list) // -- TLE
|
||||
/obj/machinery/atmospherics/trinary/filter/tgui_act(action, list/params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
. = TRUE
|
||||
if(href_list["pressure"])
|
||||
var/pressure = href_list["pressure"]
|
||||
if(pressure == "max")
|
||||
pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
else if(pressure == "input")
|
||||
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
|
||||
if(!isnull(pressure) && !..())
|
||||
. = TRUE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
. = TRUE
|
||||
if(.)
|
||||
target_pressure = clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
if(href_list["filter"])
|
||||
filter_type = text2num(href_list["filter"])
|
||||
investigate_log("was set to filter [filter_type] by [key_name(usr)]", "atmos")
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("power")
|
||||
toggle()
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
return TRUE
|
||||
|
||||
update_icon()
|
||||
SSnanoui.update_uis(src)
|
||||
if("set_filter")
|
||||
filter_type = text2num(params["filter"])
|
||||
investigate_log("was set to filter [filter_type] by [key_name(usr)]", "atmos")
|
||||
return TRUE
|
||||
|
||||
if("max_pressure")
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
|
||||
if("min_pressure")
|
||||
target_pressure = 0
|
||||
. = TRUE
|
||||
|
||||
if("custom_pressure")
|
||||
target_pressure = clamp(text2num(params["pressure"]), 0, MAX_OUTPUT_PRESSURE)
|
||||
. = TRUE
|
||||
if(.)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/pen))
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/attack_hand(mob/user)
|
||||
if(..())
|
||||
@@ -163,62 +163,62 @@
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/atmospherics/trinary/mixer/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
user.set_machine(src)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_mixer.tmpl", name, 370, 165, state = state)
|
||||
ui = new(user, src, ui_key, "AtmosMixer", name, 330, 165, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["pressure"] = round(target_pressure)
|
||||
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
|
||||
data["node1_concentration"] = round(node1_concentration*100)
|
||||
data["node2_concentration"] = round(node2_concentration*100)
|
||||
/obj/machinery/atmospherics/trinary/mixer/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"on" = on,
|
||||
"pressure" = round(target_pressure, 0.01),
|
||||
"max_pressure" = MAX_OUTPUT_PRESSURE,
|
||||
"node1_concentration" = round(node1_concentration * 100),
|
||||
"node2_concentration" = round(node2_concentration * 100)
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/Topic(href,href_list)
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/tgui_act(action, list/params)
|
||||
if(..())
|
||||
return 1
|
||||
return
|
||||
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
. = TRUE
|
||||
if(href_list["pressure"])
|
||||
var/pressure = href_list["pressure"]
|
||||
if(pressure == "max")
|
||||
pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
else if(pressure == "input")
|
||||
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
|
||||
if(!isnull(pressure) && !..())
|
||||
. = TRUE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
. = TRUE
|
||||
if(.)
|
||||
target_pressure = clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
if(href_list["node1"])
|
||||
var/value = text2num(href_list["node1"])
|
||||
node1_concentration = max(0, min(1, node1_concentration + value))
|
||||
node2_concentration = max(0, min(1, node2_concentration - value))
|
||||
investigate_log("was set to [node1_concentration] % on node 1 by [key_name(usr)]", "atmos")
|
||||
. = TRUE
|
||||
if(href_list["node2"])
|
||||
var/value = text2num(href_list["node2"])
|
||||
node2_concentration = max(0, min(1, node2_concentration + value))
|
||||
node1_concentration = max(0, min(1, node1_concentration - value))
|
||||
investigate_log("was set to [node2_concentration] % on node 2 by [key_name(usr)]", "atmos")
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("power")
|
||||
toggle()
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
return TRUE
|
||||
|
||||
update_icon()
|
||||
SSnanoui.update_uis(src)
|
||||
if("set_node")
|
||||
if(params["node_name"] == "Node 1")
|
||||
node1_concentration = clamp(round(text2num(params["concentration"]), 0.01), 0, 1)
|
||||
node2_concentration = round(1 - node1_concentration, 0.01)
|
||||
investigate_log("was set to [node1_concentration] % on node 1 by [key_name(usr)]", "atmos")
|
||||
return TRUE
|
||||
else
|
||||
node2_concentration = clamp(round(text2num(params["concentration"]), 0.01), 0, 1)
|
||||
node1_concentration = round(1 - node2_concentration, 0.01)
|
||||
investigate_log("was set to [node2_concentration] % on node 2 by [key_name(usr)]", "atmos")
|
||||
return TRUE
|
||||
|
||||
if("max_pressure")
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
. = TRUE
|
||||
|
||||
if("min_pressure")
|
||||
target_pressure = 0
|
||||
. = TRUE
|
||||
|
||||
if("custom_pressure")
|
||||
target_pressure = clamp(text2num(params["pressure"]), 0, MAX_OUTPUT_PRESSURE)
|
||||
. = TRUE
|
||||
if(.)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/pen))
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
//var/list/underlays_intact[]
|
||||
//var/list/pipe_underlays_exposed[]
|
||||
//var/list/pipe_underlays_intact[]
|
||||
var/list/omni_icons[]
|
||||
|
||||
/datum/pipe_icon_manager/New()
|
||||
check_icons()
|
||||
@@ -53,8 +52,6 @@
|
||||
return manifold_icons[state + color]
|
||||
if("device")
|
||||
return device_icons[state]
|
||||
if("omni")
|
||||
return omni_icons[state]
|
||||
if("underlay")
|
||||
return underlays[state + dir + color]
|
||||
//if("underlay_intact")
|
||||
@@ -75,8 +72,6 @@
|
||||
gen_manifold_icons()
|
||||
if(!device_icons)
|
||||
gen_device_icons()
|
||||
if(!omni_icons)
|
||||
gen_omni_icons()
|
||||
//if(!underlays_intact || !underlays_down || !underlays_exposed || !pipe_underlays_exposed || !pipe_underlays_intact)
|
||||
if(!underlays)
|
||||
gen_underlay_icons()
|
||||
@@ -150,18 +145,6 @@
|
||||
continue
|
||||
device_icons["scrubber" + state] = image('icons/atmos/vent_scrubber.dmi', icon_state = state)
|
||||
|
||||
/datum/pipe_icon_manager/proc/gen_omni_icons()
|
||||
if(!omni_icons)
|
||||
omni_icons = new()
|
||||
|
||||
var/icon/omni = new('icons/atmos/omni_devices.dmi')
|
||||
|
||||
for(var/state in omni.IconStates())
|
||||
if(!state || findtext(state, "map"))
|
||||
continue
|
||||
omni_icons[state] = image('icons/atmos/omni_devices.dmi', icon_state = state)
|
||||
|
||||
|
||||
/datum/pipe_icon_manager/proc/gen_underlay_icons()
|
||||
|
||||
if(!underlays)
|
||||
|
||||
@@ -32,13 +32,13 @@
|
||||
if(!R)
|
||||
return 1
|
||||
|
||||
atom/movable/proc/CanAtmosPass()
|
||||
/atom/movable/proc/CanAtmosPass()
|
||||
return 1
|
||||
|
||||
atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5)
|
||||
/atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5)
|
||||
return (!density || !height)
|
||||
|
||||
turf/CanPass(atom/movable/mover, turf/target, height=1.5)
|
||||
/turf/CanPass(atom/movable/mover, turf/target, height=1.5)
|
||||
if(!target) return 0
|
||||
|
||||
if(istype(mover)) // turf/Enter(...) will perform more advanced checks
|
||||
|
||||
@@ -473,7 +473,7 @@
|
||||
SSair.active_super_conductivity -= src
|
||||
return 0
|
||||
|
||||
turf/simulated/proc/consider_superconductivity(starting)
|
||||
/turf/simulated/proc/consider_superconductivity(starting)
|
||||
if(!thermal_conductivity)
|
||||
return 0
|
||||
|
||||
@@ -489,7 +489,7 @@ turf/simulated/proc/consider_superconductivity(starting)
|
||||
SSair.active_super_conductivity |= src
|
||||
return 1
|
||||
|
||||
turf/simulated/proc/radiate_to_spess() //Radiate excess tile heat to space
|
||||
/turf/simulated/proc/radiate_to_spess() //Radiate excess tile heat to space
|
||||
if(temperature > T0C) //Considering 0 degC as te break even point for radiation in and out
|
||||
var/delta_temperature = (temperature_archived - TCMB) //hardcoded space temperature
|
||||
if((heat_capacity > 0) && (abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER))
|
||||
|
||||
@@ -36,7 +36,7 @@ Be sure to include required js functions in your page, or it'll raise an excepti
|
||||
|
||||
And yes I know this is a proc in a defines file, but its highly relevant so it can be here
|
||||
*/
|
||||
proc/send_byjax(receiver, control_id, target_element, new_content=null, callback=null, list/callback_args=null)
|
||||
/proc/send_byjax(receiver, control_id, target_element, new_content=null, callback=null, list/callback_args=null)
|
||||
if(receiver && target_element && control_id) // && winexists(receiver, control_id))
|
||||
var/list/argums = list(target_element, new_content)
|
||||
if(callback)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#define MARTIAL_COMBO_FAIL 0 // If the combo failed
|
||||
#define MARTIAL_COMBO_CONTINUE 1 // If the combo should continue
|
||||
#define MARTIAL_COMBO_DONE 2 // If the combo is successful and done
|
||||
#define MARTIAL_COMBO_DONE_NO_CLEAR 3 // If the combo is successful and done but the others should have a chance to finish
|
||||
#define MARTIAL_COMBO_DONE_BASIC_HIT 4 // If the combo should do a basic hit after it's done
|
||||
#define MARTIAL_COMBO_DONE_CLEAR_COMBOS 5 // If the combo should do a basic hit after it's done
|
||||
|
||||
#define MARTIAL_ARTS_CANNOT_USE -1
|
||||
|
||||
#define MARTIAL_COMBO_STEP_HARM "Harm"
|
||||
#define MARTIAL_COMBO_STEP_DISARM "Disarm"
|
||||
#define MARTIAL_COMBO_STEP_GRAB "Grab"
|
||||
#define MARTIAL_COMBO_STEP_HELP "Help"
|
||||
|
||||
// A check used for all act types. Such as disarm_act
|
||||
#define MARTIAL_ARTS_ACT_CHECK if((. = ..()) != FALSE) return .
|
||||
@@ -208,6 +208,7 @@
|
||||
#define isguardian(A) (istype((A), /mob/living/simple_animal/hostile/guardian))
|
||||
#define isnymph(A) (istype((A), /mob/living/simple_animal/diona))
|
||||
#define ishostile(A) (istype(A, /mob/living/simple_animal/hostile))
|
||||
#define isterrorspider(A) (istype((A), /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
|
||||
#define issilicon(A) (istype((A), /mob/living/silicon))
|
||||
#define isAI(A) (istype((A), /mob/living/silicon/ai))
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#define PIPE_TVALVE 18
|
||||
#define PIPE_MANIFOLD4W 19
|
||||
#define PIPE_CAP 20
|
||||
#define PIPE_OMNI_MIXER 21
|
||||
#define PIPE_OMNI_FILTER 22
|
||||
#define PIPE_UNIVERSAL 23
|
||||
#define PIPE_SUPPLY_STRAIGHT 24
|
||||
#define PIPE_SUPPLY_BENT 25
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#define INIT_ORDER_GARBAGE 21
|
||||
#define INIT_ORDER_DBCORE 20
|
||||
#define INIT_ORDER_BLACKBOX 19
|
||||
#define INIT_ORDER_SERVER_MAINT 18
|
||||
#define INIT_ORDER_CLEANUP 18
|
||||
#define INIT_ORDER_INPUT 17
|
||||
#define INIT_ORDER_SOUNDS 16
|
||||
#define INIT_ORDER_INSTRUMENTS 15
|
||||
@@ -90,7 +90,7 @@
|
||||
#define FIRE_PRIORITY_NANOMOB 10
|
||||
#define FIRE_PRIORITY_NIGHTSHIFT 10
|
||||
#define FIRE_PRIORITY_IDLE_NPC 10
|
||||
#define FIRE_PRIORITY_SERVER_MAINT 10
|
||||
#define FIRE_PRIORITY_CLEANUP 10
|
||||
#define FIRE_PRIORITY_TICKETS 10
|
||||
#define FIRE_PRIORITY_RESEARCH 10
|
||||
#define FIRE_PRIORITY_GARBAGE 15
|
||||
|
||||
+14
-14
@@ -1,4 +1,4 @@
|
||||
proc/GetOppositeDir(var/dir)
|
||||
/proc/GetOppositeDir(var/dir)
|
||||
switch(dir)
|
||||
if(NORTH) return SOUTH
|
||||
if(SOUTH) return NORTH
|
||||
@@ -10,7 +10,7 @@ proc/GetOppositeDir(var/dir)
|
||||
if(SOUTHEAST) return NORTHWEST
|
||||
return 0
|
||||
|
||||
proc/random_underwear(gender, species = "Human")
|
||||
/proc/random_underwear(gender, species = "Human")
|
||||
var/list/pick_list = list()
|
||||
switch(gender)
|
||||
if(MALE) pick_list = GLOB.underwear_m
|
||||
@@ -18,7 +18,7 @@ proc/random_underwear(gender, species = "Human")
|
||||
else pick_list = GLOB.underwear_list
|
||||
return pick_species_allowed_underwear(pick_list, species)
|
||||
|
||||
proc/random_undershirt(gender, species = "Human")
|
||||
/proc/random_undershirt(gender, species = "Human")
|
||||
var/list/pick_list = list()
|
||||
switch(gender)
|
||||
if(MALE) pick_list = GLOB.undershirt_m
|
||||
@@ -26,7 +26,7 @@ proc/random_undershirt(gender, species = "Human")
|
||||
else pick_list = GLOB.undershirt_list
|
||||
return pick_species_allowed_underwear(pick_list, species)
|
||||
|
||||
proc/random_socks(gender, species = "Human")
|
||||
/proc/random_socks(gender, species = "Human")
|
||||
var/list/pick_list = list()
|
||||
switch(gender)
|
||||
if(MALE) pick_list = GLOB.socks_m
|
||||
@@ -34,7 +34,7 @@ proc/random_socks(gender, species = "Human")
|
||||
else pick_list = GLOB.socks_list
|
||||
return pick_species_allowed_underwear(pick_list, species)
|
||||
|
||||
proc/pick_species_allowed_underwear(list/all_picks, species)
|
||||
/proc/pick_species_allowed_underwear(list/all_picks, species)
|
||||
var/list/valid_picks = list()
|
||||
for(var/test in all_picks)
|
||||
var/datum/sprite_accessory/S = all_picks[test]
|
||||
@@ -46,7 +46,7 @@ proc/pick_species_allowed_underwear(list/all_picks, species)
|
||||
|
||||
return pick(valid_picks)
|
||||
|
||||
proc/random_hair_style(var/gender, species = "Human", var/datum/robolimb/robohead)
|
||||
/proc/random_hair_style(var/gender, species = "Human", var/datum/robolimb/robohead)
|
||||
var/h_style = "Bald"
|
||||
var/list/valid_hairstyles = list()
|
||||
for(var/hairstyle in GLOB.hair_styles_public_list)
|
||||
@@ -75,7 +75,7 @@ proc/random_hair_style(var/gender, species = "Human", var/datum/robolimb/robohea
|
||||
|
||||
return h_style
|
||||
|
||||
proc/random_facial_hair_style(var/gender, species = "Human", var/datum/robolimb/robohead)
|
||||
/proc/random_facial_hair_style(var/gender, species = "Human", var/datum/robolimb/robohead)
|
||||
var/f_style = "Shaved"
|
||||
var/list/valid_facial_hairstyles = list()
|
||||
for(var/facialhairstyle in GLOB.facial_hair_styles_list)
|
||||
@@ -104,7 +104,7 @@ proc/random_facial_hair_style(var/gender, species = "Human", var/datum/robolimb/
|
||||
|
||||
return f_style
|
||||
|
||||
proc/random_head_accessory(species = "Human")
|
||||
/proc/random_head_accessory(species = "Human")
|
||||
var/ha_style = "None"
|
||||
var/list/valid_head_accessories = list()
|
||||
for(var/head_accessory in GLOB.head_accessory_styles_list)
|
||||
@@ -119,7 +119,7 @@ proc/random_head_accessory(species = "Human")
|
||||
|
||||
return ha_style
|
||||
|
||||
proc/random_marking_style(var/location = "body", species = "Human", var/datum/robolimb/robohead, var/body_accessory, var/alt_head)
|
||||
/proc/random_marking_style(var/location = "body", species = "Human", var/datum/robolimb/robohead, var/body_accessory, var/alt_head)
|
||||
var/m_style = "None"
|
||||
var/list/valid_markings = list()
|
||||
for(var/marking in GLOB.marking_styles_list)
|
||||
@@ -158,7 +158,7 @@ proc/random_marking_style(var/location = "body", species = "Human", var/datum/ro
|
||||
|
||||
return m_style
|
||||
|
||||
proc/random_body_accessory(species = "Vulpkanin")
|
||||
/proc/random_body_accessory(species = "Vulpkanin")
|
||||
var/body_accessory = null
|
||||
var/list/valid_body_accessories = list()
|
||||
for(var/B in GLOB.body_accessory_by_name)
|
||||
@@ -174,7 +174,7 @@ proc/random_body_accessory(species = "Vulpkanin")
|
||||
|
||||
return body_accessory
|
||||
|
||||
proc/random_name(gender, species = "Human")
|
||||
/proc/random_name(gender, species = "Human")
|
||||
|
||||
var/datum/species/current_species
|
||||
if(species)
|
||||
@@ -188,7 +188,7 @@ proc/random_name(gender, species = "Human")
|
||||
else
|
||||
return current_species.get_random_name(gender)
|
||||
|
||||
proc/random_skin_tone(species = "Human")
|
||||
/proc/random_skin_tone(species = "Human")
|
||||
if(species == "Human" || species == "Drask")
|
||||
switch(pick(60;"caucasian", 15;"afroamerican", 10;"african", 10;"latino", 5;"albino"))
|
||||
if("caucasian") . = -10
|
||||
@@ -202,7 +202,7 @@ proc/random_skin_tone(species = "Human")
|
||||
. = rand(1, 6)
|
||||
return .
|
||||
|
||||
proc/skintone2racedescription(tone, species = "Human")
|
||||
/proc/skintone2racedescription(tone, species = "Human")
|
||||
if(species == "Human")
|
||||
switch(tone)
|
||||
if(30 to INFINITY) return "albino"
|
||||
@@ -225,7 +225,7 @@ proc/skintone2racedescription(tone, species = "Human")
|
||||
else
|
||||
return "unknown"
|
||||
|
||||
proc/age2agedescription(age)
|
||||
/proc/age2agedescription(age)
|
||||
switch(age)
|
||||
if(0 to 1) return "infant"
|
||||
if(1 to 3) return "toddler"
|
||||
|
||||
@@ -196,7 +196,7 @@
|
||||
//checks text for html tags
|
||||
//if tag is not in whitelist (var/list/paper_tag_whitelist in global.dm)
|
||||
//relpaces < with <
|
||||
proc/checkhtml(var/t)
|
||||
/proc/checkhtml(var/t)
|
||||
t = sanitize_simple(t, list("&#"="."))
|
||||
var/p = findtext(t,"<",1)
|
||||
while(p) //going through all the tags
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
return time2text(station_time(time, TRUE), format)
|
||||
|
||||
/* Returns 1 if it is the selected month and day */
|
||||
proc/isDay(var/month, var/day)
|
||||
/proc/isDay(var/month, var/day)
|
||||
if(isnum(month) && isnum(day))
|
||||
var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
|
||||
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
|
||||
@@ -95,7 +95,7 @@ proc/isDay(var/month, var/day)
|
||||
/proc/seconds_to_time(var/seconds as num)
|
||||
var/numSeconds = seconds % 60
|
||||
var/numMinutes = (seconds - numSeconds) / 60
|
||||
return "[numMinutes] [numMinutes > 1 ? "minutes" : "minute"] and [numSeconds] seconds."
|
||||
return "[numMinutes] [numMinutes > 1 ? "minutes" : "minute"] and [numSeconds] seconds"
|
||||
|
||||
//Take a value in seconds and makes it display like a clock
|
||||
/proc/seconds_to_clock(var/seconds as num)
|
||||
|
||||
+11
-36
@@ -20,31 +20,6 @@
|
||||
|
||||
return 0
|
||||
|
||||
//Inverts the colour of an HTML string
|
||||
/proc/invertHTML(HTMLstring)
|
||||
|
||||
if(!( istext(HTMLstring) ))
|
||||
CRASH("Given non-text argument!")
|
||||
else
|
||||
if(length(HTMLstring) != 7)
|
||||
CRASH("Given non-HTML argument!")
|
||||
var/textr = copytext(HTMLstring, 2, 4)
|
||||
var/textg = copytext(HTMLstring, 4, 6)
|
||||
var/textb = copytext(HTMLstring, 6, 8)
|
||||
var/r = hex2num(textr)
|
||||
var/g = hex2num(textg)
|
||||
var/b = hex2num(textb)
|
||||
textr = num2hex(255 - r)
|
||||
textg = num2hex(255 - g)
|
||||
textb = num2hex(255 - b)
|
||||
if(length(textr) < 2)
|
||||
textr = text("0[]", textr)
|
||||
if(length(textg) < 2)
|
||||
textr = text("0[]", textg)
|
||||
if(length(textb) < 2)
|
||||
textr = text("0[]", textb)
|
||||
return text("#[][][]", textr, textg, textb)
|
||||
|
||||
//Returns the middle-most value
|
||||
/proc/dd_range(var/low, var/high, var/num)
|
||||
return max(low,min(high,num))
|
||||
@@ -529,7 +504,7 @@ Returns 1 if the chain up to the area contains the given typepath
|
||||
return max(min(middle, high), low)
|
||||
|
||||
//returns random gauss number
|
||||
proc/GaussRand(var/sigma)
|
||||
/proc/GaussRand(var/sigma)
|
||||
var/x,y,rsq
|
||||
do
|
||||
x=2*rand()-1
|
||||
@@ -539,7 +514,7 @@ proc/GaussRand(var/sigma)
|
||||
return sigma*y*sqrt(-2*log(rsq)/rsq)
|
||||
|
||||
//returns random gauss number, rounded to 'roundto'
|
||||
proc/GaussRandRound(var/sigma,var/roundto)
|
||||
/proc/GaussRandRound(var/sigma,var/roundto)
|
||||
return round(GaussRand(sigma),roundto)
|
||||
|
||||
//Will return the contents of an atom recursivly to a depth of 'searchDepth'
|
||||
@@ -583,7 +558,7 @@ proc/GaussRandRound(var/sigma,var/roundto)
|
||||
|
||||
return 1
|
||||
|
||||
proc/is_blocked_turf(turf/T, exclude_mobs)
|
||||
/proc/is_blocked_turf(turf/T, exclude_mobs)
|
||||
if(T.density)
|
||||
return 1
|
||||
for(var/i in T)
|
||||
@@ -984,16 +959,16 @@ proc/is_blocked_turf(turf/T, exclude_mobs)
|
||||
|
||||
|
||||
|
||||
proc/get_cardinal_dir(atom/A, atom/B)
|
||||
/proc/get_cardinal_dir(atom/A, atom/B)
|
||||
var/dx = abs(B.x - A.x)
|
||||
var/dy = abs(B.y - A.y)
|
||||
return get_dir(A, B) & (rand() * (dx+dy) < dy ? 3 : 12)
|
||||
|
||||
//chances are 1:value. anyprob(1) will always return true
|
||||
proc/anyprob(value)
|
||||
/proc/anyprob(value)
|
||||
return (rand(1,value)==value)
|
||||
|
||||
proc/view_or_range(distance = world.view , center = usr , type)
|
||||
/proc/view_or_range(distance = world.view , center = usr , type)
|
||||
switch(type)
|
||||
if("view")
|
||||
. = view(distance,center)
|
||||
@@ -1001,7 +976,7 @@ proc/view_or_range(distance = world.view , center = usr , type)
|
||||
. = range(distance,center)
|
||||
return
|
||||
|
||||
proc/oview_or_orange(distance = world.view , center = usr , type)
|
||||
/proc/oview_or_orange(distance = world.view , center = usr , type)
|
||||
switch(type)
|
||||
if("view")
|
||||
. = oview(distance,center)
|
||||
@@ -1009,7 +984,7 @@ proc/oview_or_orange(distance = world.view , center = usr , type)
|
||||
. = orange(distance,center)
|
||||
return
|
||||
|
||||
proc/get_mob_with_client_list()
|
||||
/proc/get_mob_with_client_list()
|
||||
var/list/mobs = list()
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
if(M.client)
|
||||
@@ -1233,10 +1208,10 @@ GLOBAL_LIST_INIT(wall_items, typecacheof(list(/obj/machinery/power/apc, /obj/mac
|
||||
return 0
|
||||
|
||||
|
||||
proc/get_angle(atom/a, atom/b)
|
||||
/proc/get_angle(atom/a, atom/b)
|
||||
return atan2(b.y - a.y, b.x - a.x)
|
||||
|
||||
proc/atan2(x, y)
|
||||
/proc/atan2(x, y)
|
||||
if(!x && !y) return 0
|
||||
return y >= 0 ? arccos(x / sqrt(x * x + y * y)) : -arccos(x / sqrt(x * x + y * y))
|
||||
|
||||
@@ -1329,7 +1304,7 @@ Standard way to write links -Sayu
|
||||
return FACING_INIT_FACING_TARGET_TARGET_FACING_PERPENDICULAR
|
||||
|
||||
|
||||
atom/proc/GetTypeInAllContents(typepath)
|
||||
/atom/proc/GetTypeInAllContents(typepath)
|
||||
var/list/processing_list = list(src)
|
||||
var/list/processed = list()
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ GLOBAL_DATUM_INIT(command_announcer, /obj/item/radio/intercom/command, create_co
|
||||
|
||||
// Load order issues means this can't be new'd until other code runs
|
||||
// This is probably not the way I should be doing this, but I don't know how to do it right!
|
||||
proc/create_global_announcer()
|
||||
/proc/create_global_announcer()
|
||||
spawn(0)
|
||||
GLOB.global_announcer = new(null)
|
||||
return
|
||||
|
||||
proc/create_command_announcer()
|
||||
/proc/create_command_announcer()
|
||||
spawn(0)
|
||||
GLOB.command_announcer = new(null)
|
||||
return
|
||||
@@ -92,6 +92,7 @@ GLOBAL_VAR(map_name) // Self explanatory
|
||||
GLOBAL_DATUM_INIT(data_core, /datum/datacore, new) // Station datacore, manifest, etc
|
||||
|
||||
GLOBAL_VAR_INIT(panic_bunker_enabled, FALSE) // Is the panic bunker enabled
|
||||
GLOBAL_VAR_INIT(pending_server_update, FALSE)
|
||||
|
||||
//Database connections
|
||||
//A connection is established on world creation. Ideally, the connection dies when the server restarts (After feedback logging.).
|
||||
|
||||
@@ -231,6 +231,13 @@
|
||||
to_chat(user, "<span class='notice'>The door bolt lights have been enabled.</span>")
|
||||
update_icon()
|
||||
|
||||
// FIRE ALARMS
|
||||
|
||||
/obj/machinery/firealarm/AICtrlClick()
|
||||
if(enabled)
|
||||
reset()
|
||||
else
|
||||
alarm()
|
||||
|
||||
// AI-CONTROLLED SLIP GENERATOR IN AI CORE
|
||||
|
||||
|
||||
@@ -170,6 +170,9 @@
|
||||
/obj/machinery/ai_slipper/BorgAltClick() //Dispenses liquid if on
|
||||
Activate()
|
||||
|
||||
/obj/machinery/firealarm/BorgCtrlClick()
|
||||
AICtrlClick()
|
||||
|
||||
/*
|
||||
As with AI, these are not used in click code,
|
||||
because the code for robots is specific, not generic.
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* # Cleanup Subsystem
|
||||
*
|
||||
* For now, all it does is periodically clean the supplied global lists of any null values they may contain.
|
||||
*
|
||||
* Why is this important?
|
||||
*
|
||||
* Sometimes, these lists can gain nulls due to errors.
|
||||
* For example, when a dead player trasitions from the `dead_mob_list` to the `alive_mob_list`, a null value may get stuck in the dead mob list.
|
||||
* This can cause issues when other code tries to do things with the values in the list, but are instead met with null values.
|
||||
* These problems are incredibly hard to track down and fix, so this subsystem is a solution to that.
|
||||
*/
|
||||
SUBSYSTEM_DEF(cleanup)
|
||||
name = "Null cleanup"
|
||||
wait = 30 SECONDS
|
||||
flags = SS_POST_FIRE_TIMING
|
||||
priority = FIRE_PRIORITY_CLEANUP
|
||||
init_order = INIT_ORDER_CLEANUP
|
||||
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
|
||||
offline_implications = "Certain global lists will no longer be cleared of nulls, which may result in runtimes. No immediate action is needed."
|
||||
/// A list of global lists we want the subsystem to clean.
|
||||
var/list/lists_to_clean
|
||||
|
||||
/datum/controller/subsystem/cleanup/Initialize(start_timeofday)
|
||||
// If you want this subsystem to clean out nulls from a specific list, add it here.
|
||||
lists_to_clean = list(
|
||||
GLOB.clients = "clients",
|
||||
GLOB.player_list = "player_list",
|
||||
GLOB.mob_list = "mob_list",
|
||||
GLOB.alive_mob_list = "alive_mob_list",
|
||||
GLOB.dead_mob_list = "dead_mob_list",
|
||||
GLOB.human_list = "human_list",
|
||||
GLOB.carbon_list = "carbon_list"
|
||||
)
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/cleanup/fire(resumed)
|
||||
for(var/L in lists_to_clean)
|
||||
var/list/_list = L
|
||||
var/prev_length = length(_list)
|
||||
listclearnulls(_list)
|
||||
|
||||
if(length(_list) < prev_length)
|
||||
stack_trace("Found a null value in GLOB.[lists_to_clean[_list]]!")
|
||||
@@ -620,20 +620,32 @@ SUBSYSTEM_DEF(jobs)
|
||||
var/mob/M = tgtcard.getPlayer()
|
||||
for(var/datum/job/job in occupations)
|
||||
if(tgtcard.assignment && tgtcard.assignment == job.title)
|
||||
jobs_to_formats[job.title] = "disabled" // the job they already have is pre-selected
|
||||
jobs_to_formats[job.title] = "green" // the job they already have is pre-selected
|
||||
else if(tgtcard.assignment == "Demoted" || tgtcard.assignment == "Terminated")
|
||||
jobs_to_formats[job.title] = "grey"
|
||||
else if(!job.would_accept_job_transfer_from_player(M))
|
||||
jobs_to_formats[job.title] = "linkDiscourage" // jobs which are karma-locked and not unlocked for this player are discouraged
|
||||
jobs_to_formats[job.title] = "grey" // jobs which are karma-locked and not unlocked for this player are discouraged
|
||||
else if((job.title in GLOB.command_positions) && istype(M) && M.client && job.available_in_playtime(M.client))
|
||||
jobs_to_formats[job.title] = "linkDiscourage" // command jobs which are playtime-locked and not unlocked for this player are discouraged
|
||||
jobs_to_formats[job.title] = "grey" // command jobs which are playtime-locked and not unlocked for this player are discouraged
|
||||
else if(job.total_positions && !job.current_positions && job.title != "Civilian")
|
||||
jobs_to_formats[job.title] = "linkEncourage" // jobs with nobody doing them at all are encouraged
|
||||
jobs_to_formats[job.title] = "teal" // jobs with nobody doing them at all are encouraged
|
||||
else if(job.total_positions >= 0 && job.current_positions >= job.total_positions)
|
||||
jobs_to_formats[job.title] = "linkDiscourage" // jobs that are full (no free positions) are discouraged
|
||||
jobs_to_formats[job.title] = "grey" // jobs that are full (no free positions) are discouraged
|
||||
if(tgtcard.assignment == "Demoted" || tgtcard.assignment == "Terminated")
|
||||
jobs_to_formats["Custom"] = "grey"
|
||||
return jobs_to_formats
|
||||
|
||||
|
||||
/datum/controller/subsystem/jobs/proc/log_job_transfer(transferee, oldvalue, newvalue, whodidit)
|
||||
id_change_records["[id_change_counter]"] = list("transferee" = transferee, "oldvalue" = oldvalue, "newvalue" = newvalue, "whodidit" = whodidit, "timestamp" = station_time_timestamp())
|
||||
|
||||
/datum/controller/subsystem/jobs/proc/log_job_transfer(transferee, oldvalue, newvalue, whodidit, reason)
|
||||
id_change_records["[id_change_counter]"] = list(
|
||||
"transferee" = transferee,
|
||||
"oldvalue" = oldvalue,
|
||||
"newvalue" = newvalue,
|
||||
"whodidit" = whodidit,
|
||||
"timestamp" = station_time_timestamp(),
|
||||
"reason" = reason
|
||||
)
|
||||
id_change_counter++
|
||||
|
||||
/datum/controller/subsystem/jobs/proc/slot_job_transfer(oldtitle, newtitle)
|
||||
@@ -663,45 +675,35 @@ SUBSYSTEM_DEF(jobs)
|
||||
return
|
||||
var/datum/data/pda/app/messenger/PM = target_pda.find_program(/datum/data/pda/app/messenger)
|
||||
if(PM && PM.can_receive())
|
||||
PM.notify("<b>Automated Notification: </b>\"[antext]\" (Unable to Reply)")
|
||||
PM.notify("<b>Automated Notification: </b>\"[antext]\" (Unable to Reply)", 0) // the 0 means don't make the PDA flash
|
||||
|
||||
/datum/controller/subsystem/jobs/proc/notify_by_name(target_name, antext)
|
||||
// Used to notify a specific crew member based on their real_name
|
||||
if(!target_name || !antext)
|
||||
return
|
||||
var/obj/item/pda/target_pda
|
||||
for(var/obj/item/pda/check_pda in GLOB.PDAs)
|
||||
if(check_pda.owner == target_name)
|
||||
target_pda = check_pda
|
||||
break
|
||||
if(!target_pda)
|
||||
return
|
||||
var/datum/data/pda/app/messenger/PM = target_pda.find_program(/datum/data/pda/app/messenger)
|
||||
if(PM && PM.can_receive())
|
||||
PM.notify("<b>Automated Notification: </b>\"[antext]\" (Unable to Reply)", 0) // the 0 means don't make the PDA flash
|
||||
|
||||
/datum/controller/subsystem/jobs/proc/fetch_transfer_record_html(var/centcom)
|
||||
var/record_html = "<TABLE border=\"1\">"
|
||||
|
||||
var/table_headers = list("Crewman", "Old Rank", "New Rank", "Authorized By", "Time")
|
||||
var/hidden_fields = list("deletedby")
|
||||
if(centcom)
|
||||
table_headers += "<span class='bad'>Deleted By</span>"
|
||||
record_html += "<TR>"
|
||||
for(var/thisheader in table_headers)
|
||||
record_html += "<TD><B>[thisheader]</B></TD>"
|
||||
record_html += "</TR>"
|
||||
|
||||
var/visible_record_count = 0
|
||||
/datum/controller/subsystem/jobs/proc/format_job_change_records(centcom)
|
||||
var/list/formatted = list()
|
||||
for(var/thisid in id_change_records)
|
||||
var/thisrecord = id_change_records[thisid]
|
||||
|
||||
if(thisrecord["deletedby"] && !centcom)
|
||||
continue
|
||||
|
||||
record_html += "<TR>"
|
||||
var/list/newlist = list()
|
||||
for(var/lkey in thisrecord)
|
||||
if(lkey in hidden_fields)
|
||||
if(centcom)
|
||||
record_html += "<TD><span class='bad'>[thisrecord[lkey]]<span></TD>"
|
||||
else
|
||||
continue
|
||||
else
|
||||
record_html += "<TD>[thisrecord[lkey]]</TD>"
|
||||
record_html += "</TR>"
|
||||
visible_record_count++
|
||||
newlist[lkey] = thisrecord[lkey]
|
||||
formatted.Add(list(newlist))
|
||||
return formatted
|
||||
|
||||
record_html += "</TABLE>"
|
||||
|
||||
if(!visible_record_count)
|
||||
return "No records on file yet."
|
||||
return record_html
|
||||
|
||||
/datum/controller/subsystem/jobs/proc/delete_log_records(sourceuser, delete_all)
|
||||
. = 0
|
||||
|
||||
@@ -34,7 +34,7 @@ SUBSYSTEM_DEF(parallax)
|
||||
for (A; isloc(A.loc) && !isturf(A.loc); A = A.loc);
|
||||
|
||||
if(A != C.movingmob)
|
||||
if(C.movingmob != null)
|
||||
if(C.movingmob != null && C.movingmob.client_mobs_in_contents)
|
||||
C.movingmob.client_mobs_in_contents -= C.mob
|
||||
UNSETEMPTY(C.movingmob.client_mobs_in_contents)
|
||||
LAZYINITLIST(A.client_mobs_in_contents)
|
||||
|
||||
@@ -93,6 +93,11 @@ SUBSYSTEM_DEF(shuttle)
|
||||
return S
|
||||
WARNING("couldn't find dock with id: [id]")
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/secondsToRefuel()
|
||||
var/elapsed = world.time - SSticker.round_start_time
|
||||
var/remaining = round((config.shuttle_refuel_delay - elapsed) / 10)
|
||||
return remaining > 0 ? remaining : 0
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/requestEvac(mob/user, call_reason)
|
||||
if(!emergency)
|
||||
WARNING("requestEvac(): There is no emergency shuttle, but the shuttle was called. Using the backup shuttle instead.")
|
||||
@@ -107,7 +112,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
return
|
||||
emergency = backup_shuttle
|
||||
|
||||
if(world.time - SSticker.round_start_time < config.shuttle_refuel_delay)
|
||||
if(secondsToRefuel())
|
||||
to_chat(user, "The emergency shuttle is refueling. Please wait another [abs(round(((world.time - SSticker.round_start_time) - config.shuttle_refuel_delay)/600))] minutes before trying again.")
|
||||
return
|
||||
|
||||
@@ -131,7 +136,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
call_reason = trim(html_encode(call_reason))
|
||||
|
||||
if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH)
|
||||
to_chat(user, "You must provide a reason.")
|
||||
to_chat(user, "Reason is too short. [CALL_SHUTTLE_REASON_LENGTH] character minimum.")
|
||||
return
|
||||
|
||||
var/area/signal_origin = get_area(user)
|
||||
@@ -192,7 +197,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
var/obj/machinery/computer/communications/C = thing
|
||||
if(C.stat & BROKEN)
|
||||
continue
|
||||
else if(istype(thing, /datum/computer_file/program/comm) || istype(thing, /obj/item/circuitboard/communications))
|
||||
else if(istype(thing, /obj/item/circuitboard/communications))
|
||||
continue
|
||||
|
||||
var/turf/T = get_turf(thing)
|
||||
|
||||
@@ -450,6 +450,7 @@
|
||||
/datum/action/spell_action
|
||||
check_flags = 0
|
||||
background_icon_state = "bg_spell"
|
||||
var/recharge_text_color = "#FFFFFF"
|
||||
|
||||
/datum/action/spell_action/New(Target)
|
||||
..()
|
||||
@@ -487,6 +488,18 @@
|
||||
return spell.can_cast(owner)
|
||||
return 0
|
||||
|
||||
/datum/action/spell_action/UpdateButtonIcon()
|
||||
if(button && !(. = ..()))
|
||||
var/obj/effect/proc_holder/spell/S = target
|
||||
if(!istype(S))
|
||||
return
|
||||
var/progress = S.get_availability_percentage()
|
||||
var/col_val_high = 72 * progress + 128
|
||||
var/col_val_low = 200 * progress
|
||||
button.maptext = "<div style=\"font-size:6pt;color:[recharge_text_color];font:'Small Fonts';text-align:center;\" valign=\"bottom\">[round_down(progress * 100)]%</div>"
|
||||
button.color = rgb(col_val_high, col_val_low, col_val_low, col_val_high)
|
||||
else
|
||||
button.maptext = null
|
||||
/*
|
||||
/datum/action/spell_action/alien
|
||||
|
||||
|
||||
Vendored
+5
-1
@@ -1,3 +1,5 @@
|
||||
#define AIR_ALARM_DATA_CACHE_DURATION 10 SECONDS
|
||||
|
||||
GLOBAL_DATUM_INIT(air_alarm_repository, /datum/repository/air_alarm, new())
|
||||
|
||||
/datum/repository/air_alarm/proc/air_alarm_data(var/list/monitored_alarms, var/refresh = 0, var/obj/machinery/alarm/passed_alarm)
|
||||
@@ -8,7 +10,7 @@ GLOBAL_DATUM_INIT(air_alarm_repository, /datum/repository/air_alarm, new())
|
||||
cache_entry = new/datum/cache_entry
|
||||
cache_data = cache_entry
|
||||
|
||||
if(!refresh)
|
||||
if(!refresh && cache_entry.timestamp + AIR_ALARM_DATA_CACHE_DURATION > world.time)
|
||||
return cache_entry.data
|
||||
|
||||
if(SSticker && SSticker.current_state < GAME_STATE_PLAYING && istype(passed_alarm)) // Generating the list for the first time as the game hasn't started - no need to run through the machines list everything every time
|
||||
@@ -29,3 +31,5 @@ GLOBAL_DATUM_INIT(air_alarm_repository, /datum/repository/air_alarm, new())
|
||||
|
||||
/datum/repository/air_alarm/proc/update_cache(var/obj/machinery/alarm/alarm)
|
||||
return air_alarm_data(refresh = 1, passed_alarm = alarm)
|
||||
|
||||
#undef AIR_ALARM_DATA_CACHE_DURATION
|
||||
|
||||
Vendored
+13
-1
@@ -1,5 +1,8 @@
|
||||
GLOBAL_DATUM_INIT(crew_repository, /datum/repository/crew, new())
|
||||
|
||||
/datum/repository/crew
|
||||
var/static/list/bold_jobs
|
||||
|
||||
/datum/repository/crew/New()
|
||||
cache_data = list()
|
||||
..()
|
||||
@@ -18,6 +21,13 @@ GLOBAL_DATUM_INIT(crew_repository, /datum/repository/crew, new())
|
||||
if(world.time < cache_entry.timestamp)
|
||||
return cache_entry.data
|
||||
|
||||
// Initialize the jobs here because in New(), GLOB.command_positions may not be inited yet
|
||||
if(!bold_jobs)
|
||||
bold_jobs = list()
|
||||
bold_jobs += GLOB.command_positions
|
||||
bold_jobs += get_all_centcom_jobs()
|
||||
bold_jobs += list("Nanotrasen Representative", "Blueshield", "Magistrate")
|
||||
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
var/obj/item/clothing/under/C = H.w_uniform
|
||||
@@ -32,11 +42,13 @@ GLOBAL_DATUM_INIT(crew_repository, /datum/repository/crew, new())
|
||||
crewmemberData["name"] = H.get_authentification_name(if_no_id="Unknown")
|
||||
crewmemberData["rank"] = H.get_authentification_rank(if_no_id="Unknown", if_no_job="No Job")
|
||||
crewmemberData["assignment"] = H.get_assignment(if_no_id="Unknown", if_no_job="No Job")
|
||||
crewmemberData["is_command"] = (crewmemberData["assignment"] in bold_jobs)
|
||||
|
||||
if(C.sensor_mode >= SUIT_SENSOR_BINARY)
|
||||
crewmemberData["dead"] = H.stat > UNCONSCIOUS
|
||||
crewmemberData["dead"] = H.stat == DEAD
|
||||
|
||||
if(C.sensor_mode >= SUIT_SENSOR_VITAL)
|
||||
crewmemberData["stat"] = H.stat
|
||||
crewmemberData["oxy"] = round(H.getOxyLoss(), 1)
|
||||
crewmemberData["tox"] = round(H.getToxLoss(), 1)
|
||||
crewmemberData["fire"] = round(H.getFireLoss(), 1)
|
||||
|
||||
@@ -47,23 +47,30 @@
|
||||
return
|
||||
if(!isturf(target))
|
||||
return
|
||||
if(!user.unEquip(I))
|
||||
return
|
||||
var/turf/source_turf = get_turf(I)
|
||||
var/turf/target_turf = target
|
||||
var/list/clickparams = params2list(params)
|
||||
var/x_offset = text2num(clickparams["icon-x"]) - 16
|
||||
var/y_offset = text2num(clickparams["icon-y"]) - 16
|
||||
var/x_offset
|
||||
var/y_offset
|
||||
if(target_turf != get_turf(I)) //Trying to stick it on a wall, don't move it to the actual wall or you can move the item through it. Instead set the pixels as appropriate
|
||||
var/target_direction = get_dir(source_turf, target_turf)//The direction we clicked
|
||||
// Snowflake diagonal handling
|
||||
if(target_direction in GLOB.diagonals)
|
||||
to_chat(user, "<span class='warning'>You cant reach [target_turf].</span>")
|
||||
return
|
||||
if(target_direction & EAST)
|
||||
x_offset += 32
|
||||
x_offset = 16
|
||||
y_offset = rand(-12, 12)
|
||||
else if(target_direction & WEST)
|
||||
x_offset -= 32
|
||||
if(target_direction & NORTH)
|
||||
y_offset += 32
|
||||
x_offset = -16
|
||||
y_offset = rand(-12, 12)
|
||||
else if(target_direction & NORTH)
|
||||
x_offset = rand(-12, 12)
|
||||
y_offset = 16
|
||||
else if(target_direction & SOUTH)
|
||||
y_offset -= 32
|
||||
x_offset = rand(-12, 12)
|
||||
y_offset = -16
|
||||
if(!user.unEquip(I))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You stick [I] to [target_turf].</span>")
|
||||
I.pixel_x = x_offset
|
||||
I.pixel_y = y_offset
|
||||
|
||||
@@ -191,6 +191,10 @@
|
||||
..()
|
||||
desc = "That's Definitely Not [M.real_name]."
|
||||
|
||||
/datum/dog_fashion/head/cone
|
||||
name = "REAL_NAME"
|
||||
desc = "Omnicone's Chosen Champion"
|
||||
|
||||
/datum/dog_fashion/back/hardsuit
|
||||
name = "Space Explorer REAL_NAME"
|
||||
desc = "That's one small step for a corgi. One giant yap for corgikind."
|
||||
@@ -200,3 +204,7 @@
|
||||
D.mutations.Add(BREATHLESS)
|
||||
D.atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
D.minbodytemp = 0
|
||||
|
||||
/datum/dog_fashion/head/fried_vox_empty
|
||||
name = "Colonel REAL_NAME"
|
||||
desc = "Keep away from live vox."
|
||||
|
||||
@@ -152,13 +152,11 @@
|
||||
return doTeleport()
|
||||
return 0
|
||||
|
||||
/datum/teleport/instant //teleports when datum is created
|
||||
|
||||
start(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null)
|
||||
if(..())
|
||||
if(teleport())
|
||||
return 1
|
||||
return 0
|
||||
/datum/teleport/instant/start(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null)
|
||||
if(..())
|
||||
if(teleport())
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
/datum/teleport/instant/science
|
||||
|
||||
+5
-4
@@ -35,6 +35,7 @@
|
||||
var/list/restricted_roles = list()
|
||||
|
||||
var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button.
|
||||
var/datum/martial_art/martial_art
|
||||
|
||||
var/role_alt_title
|
||||
|
||||
@@ -914,7 +915,7 @@
|
||||
log_admin("[key_name(usr)] has equipped [key_name(current)] as a wizard")
|
||||
message_admins("[key_name_admin(usr)] has equipped [key_name_admin(current)] as a wizard")
|
||||
if("name")
|
||||
SSticker.mode.name_wizard(current)
|
||||
INVOKE_ASYNC(SSticker.mode, /datum/game_mode/wizard.proc/name_wizard, current)
|
||||
log_admin("[key_name(usr)] has allowed wizard [key_name(current)] to name themselves")
|
||||
message_admins("[key_name_admin(usr)] has allowed wizard [key_name_admin(current)] to name themselves")
|
||||
if("autoobjectives")
|
||||
@@ -1102,8 +1103,8 @@
|
||||
special_role = null
|
||||
to_chat(current,"<span class='userdanger'>Your infernal link has been severed! You are no longer a devil!</span>")
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/infernal_jaunt)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/fireball/hellish)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/summon_contract)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/click/fireball/hellish)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/click/summon_contract)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork/greater)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork/ascended)
|
||||
@@ -1501,7 +1502,7 @@
|
||||
SSticker.mode.equip_wizard(current)
|
||||
for(var/obj/item/spellbook/S in current.contents)
|
||||
S.op = 0
|
||||
SSticker.mode.name_wizard(current)
|
||||
INVOKE_ASYNC(SSticker.mode, /datum/game_mode/wizard.proc/name_wizard, current)
|
||||
SSticker.mode.forge_wizard_objectives(src)
|
||||
SSticker.mode.greet_wizard(src)
|
||||
SSticker.mode.update_wiz_icons_added(src)
|
||||
|
||||
@@ -242,7 +242,7 @@
|
||||
/obj/item/organ/internal/cyberimp/eyes/shield,
|
||||
/obj/item/organ/internal/cyberimp/eyes/hud/security,
|
||||
/obj/item/organ/internal/cyberimp/eyes/xray,
|
||||
/obj/item/organ/internal/cyberimp/brain/anti_stun,
|
||||
/obj/item/organ/internal/cyberimp/brain/anti_stun/hardened,
|
||||
/obj/item/organ/internal/cyberimp/chest/nutriment/plus,
|
||||
/obj/item/organ/internal/cyberimp/arm/combat/centcom
|
||||
)
|
||||
|
||||
@@ -351,16 +351,6 @@ GLOBAL_LIST_EMPTY(rpd_pipe_list) //Some pipes we don't want to be dispensable
|
||||
pipe_id = PIPE_CIRCULATOR
|
||||
pipe_icon = "circ"
|
||||
|
||||
/datum/pipes/atmospheric/omni_filter
|
||||
pipe_name = "omni filter"
|
||||
pipe_id = PIPE_OMNI_FILTER
|
||||
pipe_icon = "omni_filter"
|
||||
|
||||
/datum/pipes/atmospheric/omni_mixer
|
||||
pipe_name = "omni mixer"
|
||||
pipe_id = PIPE_OMNI_MIXER
|
||||
pipe_icon = "omni_mixer"
|
||||
|
||||
/datum/pipes/atmospheric/insulated
|
||||
pipe_name = "insulated pipe"
|
||||
pipe_id = PIPE_INSULATED_STRAIGHT
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
name = "Biodome Winter"
|
||||
id = "biodome-winter"
|
||||
description = "For those getaways where you want to get back to nature, but you don't want to leave the fortified military compound where you spend your days. \
|
||||
Includes a unique(*) laser pistol display case, and the recently introduced I.C.E(tm)."
|
||||
Includes the recently introduced I.C.E(tm)."
|
||||
suffix = "lavaland_biodome_winter.dmm"
|
||||
|
||||
/datum/map_template/ruin/lavaland/biodome/clown
|
||||
@@ -42,7 +42,7 @@
|
||||
cost = 10
|
||||
allow_duplicates = FALSE
|
||||
|
||||
datum/map_template/ruin/lavaland/ash_walker
|
||||
/datum/map_template/ruin/lavaland/ash_walker
|
||||
name = "Ash Walker Nest"
|
||||
id = "ash-walker"
|
||||
description = "A race of unbreathing lizards live here, that run faster than a human can, worship a broken dead city, and are capable of reproducing by something involving tentacles? \
|
||||
|
||||
@@ -6,44 +6,47 @@
|
||||
qdel(src)
|
||||
owner = new_owner
|
||||
|
||||
/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = FALSE, datum/topic_state/state = GLOB.ghost_state, datum/nanoui/master_ui = null)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/datum/spawners_menu/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui_state/state = GLOB.tgui_observer_state, datum/tgui/master_ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "spawners_menu.tmpl", "Spawners Menu", 700, 600, master_ui, state = state)
|
||||
ui = new(user, src, ui_key, "SpawnersMenu", "Spawners Menu", 700, 600, master_ui, state = state)
|
||||
ui.open()
|
||||
|
||||
/datum/spawners_menu/ui_data(mob/user)
|
||||
/datum/spawners_menu/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["spawners"] = list()
|
||||
for(var/spawner in GLOB.mob_spawners)
|
||||
var/list/this = list()
|
||||
this["name"] = spawner
|
||||
this["desc"] = ""
|
||||
this["important_info"] = ""
|
||||
this["fluff"] = ""
|
||||
this["uids"] = list()
|
||||
for(var/spawner_obj in GLOB.mob_spawners[spawner])
|
||||
for(var/spawner_obj in GLOB.mob_spawners[spawner])//each spawner can contain multiple actual spawners, we use only one desc/info
|
||||
this["uids"] += "\ref[spawner_obj]"
|
||||
if(!this["desc"])
|
||||
if(!this["desc"]) //haven't set descriptions yet
|
||||
if(istype(spawner_obj, /obj/effect/mob_spawn))
|
||||
var/obj/effect/mob_spawn/MS = spawner_obj
|
||||
this["desc"] = MS.flavour_text
|
||||
this["desc"] = MS.description
|
||||
this["important_info"] = MS.important_info
|
||||
this["fluff"] = MS.flavour_text
|
||||
else
|
||||
var/obj/O = spawner_obj
|
||||
this["desc"] = O.desc
|
||||
this["amount_left"] = LAZYLEN(GLOB.mob_spawners[spawner])
|
||||
data["spawners"] += list(this)
|
||||
|
||||
return data
|
||||
|
||||
/datum/spawners_menu/Topic(href, href_list)
|
||||
/datum/spawners_menu/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
var/spawners = replacetext(href_list["uid"], ",", ";")
|
||||
return
|
||||
var/spawners = replacetext(params["ID"], ",", ";")
|
||||
var/list/possible_spawners = params2list(spawners)
|
||||
var/obj/effect/mob_spawn/MS = locate(pick(possible_spawners))
|
||||
if(!MS || !istype(MS))
|
||||
log_runtime(EXCEPTION("A ghost tried to interact with an invalid spawner, or the spawner didn't exist."))
|
||||
return
|
||||
switch(href_list["action"])
|
||||
switch(action)
|
||||
if("jump")
|
||||
owner.forceMove(get_turf(MS))
|
||||
. = TRUE
|
||||
|
||||
+172
-70
@@ -24,6 +24,20 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
user.face_atom(A)
|
||||
return FALSE
|
||||
|
||||
/datum/click_intercept/proc_holder
|
||||
var/obj/effect/proc_holder/spell
|
||||
|
||||
/datum/click_intercept/proc_holder/New(client/C, obj/effect/proc_holder/spell_to_cast)
|
||||
. = ..()
|
||||
spell = spell_to_cast
|
||||
|
||||
/datum/click_intercept/proc_holder/InterceptClickOn(user, params, atom/object)
|
||||
spell.InterceptClickOn(user, params, object)
|
||||
|
||||
/datum/click_intercept/proc_holder/quit()
|
||||
spell.remove_ranged_ability(spell.ranged_ability_user)
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/proc/add_ranged_ability(mob/living/user, var/msg)
|
||||
if(!user || !user.client)
|
||||
return
|
||||
@@ -32,7 +46,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
user.ranged_ability.remove_ranged_ability(user)
|
||||
user.ranged_ability = src
|
||||
ranged_ability_user = user
|
||||
user.client.click_intercept = user.ranged_ability
|
||||
user.client.click_intercept = new /datum/click_intercept/proc_holder(user.client, user.ranged_ability)
|
||||
add_mousepointer(user.client)
|
||||
active = TRUE
|
||||
if(msg)
|
||||
@@ -48,15 +62,17 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
C.mouse_pointer_icon = initial(C.mouse_pointer_icon)
|
||||
|
||||
/obj/effect/proc_holder/proc/remove_ranged_ability(mob/living/user, var/msg)
|
||||
if(!user || !user.client || (user.ranged_ability && user.ranged_ability != src)) //To avoid removing the wrong ability
|
||||
if(!user || (user.ranged_ability && user.ranged_ability != src)) //To avoid removing the wrong ability
|
||||
return
|
||||
user.ranged_ability = null
|
||||
ranged_ability_user = null
|
||||
user.client.click_intercept = null
|
||||
remove_mousepointer(user.client)
|
||||
active = FALSE
|
||||
if(msg)
|
||||
to_chat(user, msg)
|
||||
if(user.client)
|
||||
qdel(user.client.click_intercept)
|
||||
user.client.click_intercept = null
|
||||
remove_mousepointer(user.client)
|
||||
if(msg)
|
||||
to_chat(user, msg)
|
||||
update_icon()
|
||||
|
||||
/obj/effect/proc_holder/spell
|
||||
@@ -114,10 +130,14 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
|
||||
var/sound = null //The sound the spell makes when it is cast
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0, mob/living/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
|
||||
if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list))
|
||||
to_chat(user, "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>")
|
||||
return 0
|
||||
/* Checks if the user can cast the spell
|
||||
* @param charge_check If the proc should do the cooldown check
|
||||
* @param start_recharge If the proc should set the cooldown
|
||||
* @param user The caster of the spell
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/proc/cast_check(charge_check = TRUE, start_recharge = TRUE, mob/living/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
|
||||
if(!can_cast(user, charge_check, TRUE))
|
||||
return FALSE
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/caster = user
|
||||
@@ -126,49 +146,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
caster.reset_perspective(0)
|
||||
return 0
|
||||
|
||||
if(is_admin_level(user.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
|
||||
return 0
|
||||
|
||||
if(!skipcharge)
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
if(charge_counter < charge_max)
|
||||
to_chat(user, still_recharging_msg)
|
||||
return 0
|
||||
if("charges")
|
||||
if(!charge_counter)
|
||||
to_chat(user, "<span class='notice'>[name] has no charges left.</span>")
|
||||
return 0
|
||||
|
||||
if(!ghost)
|
||||
if(user.stat && !stat_allowed)
|
||||
to_chat(user, "<span class='notice'>You can't cast this spell while incapacitated.</span>")
|
||||
return 0
|
||||
if(ishuman(user) && (invocation_type == "whisper" || invocation_type == "shout") && user.is_muzzled())
|
||||
to_chat(user, "Mmmf mrrfff!")
|
||||
return 0
|
||||
|
||||
var/obj/effect/proc_holder/spell/noclothes/clothes_spell = locate() in (user.mob_spell_list | (user.mind ? user.mind.spell_list : list()))
|
||||
if((ishuman(user) && clothes_req) && !istype(clothes_spell))//clothes check
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/obj/item/clothing/robe = H.wear_suit
|
||||
var/obj/item/clothing/hat = H.head
|
||||
var/obj/item/clothing/shoes = H.shoes
|
||||
if(!robe || !hat || !shoes)
|
||||
to_chat(user, "<span class='notice'>Your outfit isn't complete, you should put on your robe and wizard hat, as well as sandals.</span>")
|
||||
return 0
|
||||
if(!robe.magical || !hat.magical || !shoes.magical)
|
||||
to_chat(user, "<span class='notice'>Your outfit isn't magical enough, you should put on your robe and wizard hat, as well as your sandals.</span>")
|
||||
return 0
|
||||
else if(!ishuman(user))
|
||||
if(clothes_req || human_req)
|
||||
to_chat(user, "<span class='notice'>This spell can only be cast by humans!</span>")
|
||||
return 0
|
||||
if(nonabstract_req && (isbrain(user) || ispAI(user)))
|
||||
to_chat(user, "<span class='notice'>This spell can only be cast by physical beings!</span>")
|
||||
return 0
|
||||
|
||||
if(!skipcharge)
|
||||
if(start_recharge)
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
charge_counter = 0 //doesn't start recharging until the targets selecting ends
|
||||
@@ -230,12 +208,12 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
|
||||
/obj/effect/proc_holder/spell/process()
|
||||
charge_counter += 2
|
||||
if(action)
|
||||
action.UpdateButtonIcon()
|
||||
if(charge_counter < charge_max)
|
||||
return
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
charge_counter = charge_max
|
||||
if(action)
|
||||
action.UpdateButtonIcon()
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1, mob/user = usr, make_attack_logs = TRUE) //if recharge is started is important for the trigger spells
|
||||
before_cast(targets)
|
||||
@@ -339,6 +317,19 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
target.vars[type] += amount //I bear no responsibility for the runtimes that'll happen if you try to adjust non-numeric or even non-existant vars
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/get_availability_percentage()
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
if(charge_counter == 0)
|
||||
return 0
|
||||
return charge_counter / charge_max
|
||||
if("charges")
|
||||
if(charge_counter)
|
||||
return 1
|
||||
return 0
|
||||
if("holdervar")
|
||||
return 1
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob
|
||||
var/max_targets = 1 //leave 0 for unlimited targets in range, 1 for one selectable target in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range
|
||||
var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast
|
||||
@@ -429,6 +420,100 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click
|
||||
var/click_radius = 1 // How big the radius around the clicked atom is to find a suitable target. -1 is only the selected atom is considered
|
||||
var/selection_activated_message = "<span class='notice'>Click on a target to cast the spell.</span>"
|
||||
var/selection_deactivated_message = "<span class='notice'>You choose to not cast this spell.</span>"
|
||||
var/allowed_type = /mob/living // Which type the targets have to be
|
||||
var/auto_target_single = TRUE // If the spell should auto select a target if only one is found
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/Click()
|
||||
var/mob/living/user = usr
|
||||
if(!istype(user))
|
||||
return
|
||||
|
||||
if(active)
|
||||
remove_ranged_ability(user, selection_deactivated_message)
|
||||
else
|
||||
if(cast_check(TRUE, FALSE, user))
|
||||
if(auto_target_single && attempt_auto_target(user))
|
||||
return
|
||||
|
||||
add_ranged_ability(user, selection_activated_message)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] is not ready to be used yet.</span>")
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/proc/attempt_auto_target(mob/user)
|
||||
var/atom/target
|
||||
for(var/atom/A in view_or_range(range, user, selection_type))
|
||||
if(valid_target(A, user))
|
||||
if(target)
|
||||
return FALSE // Two targets found. ABORT
|
||||
target = A
|
||||
|
||||
if(target && cast_check(TRUE, TRUE, user)) // Singular target found. Cast it instantly
|
||||
to_chat(user, "<span class='warning'>Only one target found. Casting [src] on [target]!</span>")
|
||||
perform(list(target), user = user)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/InterceptClickOn(mob/living/user, params, atom/A)
|
||||
if(..() || !cast_check(TRUE, TRUE, user))
|
||||
remove_ranged_ability(user)
|
||||
revert_cast(user)
|
||||
return TRUE
|
||||
|
||||
var/list/targets = list()
|
||||
if(valid_target(A, user))
|
||||
targets.Add(A)
|
||||
|
||||
if((!max_targets || max_targets > targets.len) && click_radius >= 0)
|
||||
var/list/found_others = list()
|
||||
for(var/atom/target in range(click_radius, A))
|
||||
if(valid_target(target, user))
|
||||
found_others |= target
|
||||
if(!max_targets)
|
||||
targets.Add(found_others)
|
||||
else
|
||||
if(max_targets <= found_others.len + targets.len)
|
||||
targets.Add(found_others)
|
||||
else
|
||||
switch(random_target_priority) //Add in the rest
|
||||
if(TARGET_RANDOM)
|
||||
while(targets.len < max_targets && found_others.len) // Add the others
|
||||
targets.Add(pick_n_take(found_others))
|
||||
if(TARGET_CLOSEST)
|
||||
var/list/distances = list()
|
||||
for(var/target in found_others)
|
||||
distances[target] = get_dist(user, target)
|
||||
sortTim(distances, /proc/cmp_numeric_asc, TRUE) // Sort on distance
|
||||
for(var/target in distances)
|
||||
targets.Add(target)
|
||||
if(targets.len >= max_targets)
|
||||
break
|
||||
|
||||
|
||||
if(!targets.len)
|
||||
to_chat(user, "<span class='warning'>No suitable target found.</span>")
|
||||
revert_cast(user)
|
||||
return FALSE
|
||||
|
||||
perform(targets, user = user)
|
||||
remove_ranged_ability(user)
|
||||
return TRUE
|
||||
|
||||
/* Checks if a target is valid
|
||||
* Should not include to_chats or other types of messages since this is used often on tons of targets.
|
||||
* @param target The target to check
|
||||
* @param user The user of the spell
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/targeted/click/proc/valid_target(target, user)
|
||||
return istype(target, allowed_type) && (include_user || target != user) && \
|
||||
(target in view_or_range(range, user, selection_type))
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/choose_targets(mob/living/user, atom/A) // Not used
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/choose_targets(mob/user = usr)
|
||||
var/list/targets = list()
|
||||
|
||||
@@ -462,30 +547,39 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
qdel(dummy)
|
||||
return 1
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list))
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>")
|
||||
return 0
|
||||
|
||||
if(is_admin_level(user.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
|
||||
return 0
|
||||
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
if(charge_counter < charge_max)
|
||||
return 0
|
||||
if("charges")
|
||||
if(!charge_counter)
|
||||
return 0
|
||||
|
||||
if(user.stat && !stat_allowed)
|
||||
return 0
|
||||
if(charge_check)
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
if(charge_counter < charge_max)
|
||||
if(show_message)
|
||||
to_chat(user, still_recharging_msg)
|
||||
return 0
|
||||
if("charges")
|
||||
if(!charge_counter)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>[name] has no charges left.</span>")
|
||||
return 0
|
||||
if(!ghost)
|
||||
if(user.stat && !stat_allowed)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>You can't cast this spell while incapacitated.</span>")
|
||||
return 0
|
||||
if(ishuman(user) && (invocation_type == "whisper" || invocation_type == "shout") && user.is_muzzled())
|
||||
if(show_message)
|
||||
to_chat(user, "Mmmf mrrfff!")
|
||||
return 0
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
|
||||
if((invocation_type == "whisper" || invocation_type == "shout") && H.is_muzzled())
|
||||
return 0
|
||||
|
||||
var/clothcheck = locate(/obj/effect/proc_holder/spell/noclothes) in user.mob_spell_list
|
||||
var/clothcheck2 = user.mind && (locate(/obj/effect/proc_holder/spell/noclothes) in user.mind.spell_list)
|
||||
if(clothes_req && !clothcheck && !clothcheck2) //clothes check
|
||||
@@ -493,12 +587,20 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
var/obj/item/clothing/hat = H.head
|
||||
var/obj/item/clothing/shoes = H.shoes
|
||||
if(!robe || !hat || !shoes)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>Your outfit isn't complete, you should put on your robe and wizard hat, as well as sandals.</span>")
|
||||
return 0
|
||||
if(!robe.magical || !hat.magical || !shoes.magical)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>Your outfit isn't magical enough, you should put on your robe and wizard hat, as well as your sandals.</span>")
|
||||
return 0
|
||||
else
|
||||
if(clothes_req || human_req)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>This spell can only be cast by humans!</span>")
|
||||
return 0
|
||||
if(nonabstract_req && (isbrain(user) || ispAI(user)))
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>This spell can only be cast by physical beings!</span>")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1, mob/living/user = usr)
|
||||
var/thearea = before_cast(targets)
|
||||
if(!thearea || !cast_check(1))
|
||||
if(!thearea || !cast_check(TRUE, FALSE, user))
|
||||
revert_cast()
|
||||
return
|
||||
invocation(thearea)
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/chaplain_bless
|
||||
/obj/effect/proc_holder/spell/targeted/click/chaplain_bless
|
||||
name = "Bless"
|
||||
desc = "Blesses a single person."
|
||||
|
||||
school = "transmutation"
|
||||
charge_max = 60
|
||||
clothes_req = 0
|
||||
clothes_req = FALSE
|
||||
invocation = "none"
|
||||
invocation_type = "none"
|
||||
|
||||
max_targets = 1
|
||||
include_user = 0
|
||||
humans_only = 1
|
||||
|
||||
include_user = FALSE
|
||||
allowed_type = /mob/living/carbon/human
|
||||
selection_activated_message = "<span class='notice'>You prepare a blessing. Click on a target to start blessing.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>The crew will be blessed another time.</span>"
|
||||
range = 1
|
||||
click_radius = -1 // Only precision clicking
|
||||
cooldown_min = 20
|
||||
action_icon_state = "shield"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/chaplain_bless/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/chaplain_bless/cast(list/targets, mob/living/user = usr, distanceoverride)
|
||||
return target.mind && target.ckey && !target.stat
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/chaplain_bless/cast(list/targets, mob/living/user = usr)
|
||||
if(!istype(user))
|
||||
to_chat(user, "Somehow, you are not a living mob. This should never happen. Report this bug.")
|
||||
revert_cast()
|
||||
@@ -35,32 +41,7 @@
|
||||
revert_cast()
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/target = targets[range]
|
||||
|
||||
if(!istype(target))
|
||||
to_chat(user, "No target.")
|
||||
revert_cast()
|
||||
return
|
||||
|
||||
if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
|
||||
to_chat(user, "[target] is too far away!")
|
||||
revert_cast()
|
||||
return
|
||||
|
||||
if(!target.mind)
|
||||
to_chat(user, "[target] appears to be catatonic. Your blessing would have no effect.")
|
||||
revert_cast()
|
||||
return
|
||||
|
||||
if(!target.ckey)
|
||||
to_chat(user, "[target] appears to be too out of it to benefit from this.")
|
||||
revert_cast()
|
||||
return
|
||||
|
||||
if(target.stat == DEAD)
|
||||
to_chat(user, "[target] is already dead. There is no point.")
|
||||
revert_cast()
|
||||
return
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
|
||||
spawn(0) // allows cast to complete even if recipient ignores the prompt
|
||||
if(alert(target, "[user] wants to bless you, in the name of [user.p_their()] religion. Accept?", "Accept Blessing?", "Yes", "No") == "Yes") // prevents forced conversions
|
||||
|
||||
@@ -21,13 +21,18 @@
|
||||
action_background_icon_state = "bg_demon"
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/summon_contract
|
||||
/obj/effect/proc_holder/spell/targeted/click/summon_contract
|
||||
name = "Summon infernal contract"
|
||||
desc = "Skip making a contract by hand, just do it by magic."
|
||||
invocation_type = "whisper"
|
||||
invocation = "Just sign on the dotted line."
|
||||
include_user = 0
|
||||
selection_activated_message = "<span class='notice'>You prepare a detailed contract. Click on a target to summon the contract in his hands.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>You archive the contract for later use.</span>"
|
||||
include_user = FALSE
|
||||
range = 5
|
||||
auto_target_single = FALSE // Prevent an accidental contract from summoning
|
||||
click_radius = -1 // Precision clicking required
|
||||
allowed_type = /mob/living/carbon
|
||||
clothes_req = FALSE
|
||||
school = "conjuration"
|
||||
charge_max = 150
|
||||
@@ -35,8 +40,9 @@
|
||||
action_icon_state = "spell_default"
|
||||
action_background_icon_state = "bg_demon"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/summon_contract/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/carbon/C in targets)
|
||||
/obj/effect/proc_holder/spell/targeted/click/summon_contract/cast(list/targets, mob/user = usr)
|
||||
for(var/target in targets)
|
||||
var/mob/living/carbon/C = target
|
||||
if(C.mind && user.mind)
|
||||
if(C.stat == DEAD)
|
||||
if(user.drop_item())
|
||||
@@ -63,7 +69,7 @@
|
||||
to_chat(user,"<span class='notice'>[C] seems to not be sentient. You are unable to summon a contract for them.</span>")
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/hellish
|
||||
/obj/effect/proc_holder/spell/targeted/click/fireball/hellish
|
||||
name = "Hellfire"
|
||||
desc = "This spell launches hellfire at the target."
|
||||
school = "evocation"
|
||||
@@ -74,8 +80,8 @@
|
||||
fireball_type = /obj/item/projectile/magic/fireball/infernal
|
||||
action_background_icon_state = "bg_demon"
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/hellish/cast(list/targets, mob/living/user = usr)
|
||||
msg_admin_attack("[key_name_admin(usr)] has fired a fireball.", ATKLOG_FEW)
|
||||
/obj/effect/proc_holder/spell/targeted/click/fireball/hellish/cast(list/targets, mob/living/user = usr)
|
||||
add_attack_logs(user, targets, "has fired a Hellfire ball", ATKLOG_FEW)
|
||||
.=..()
|
||||
|
||||
|
||||
|
||||
@@ -1,39 +1,31 @@
|
||||
/obj/effect/proc_holder/spell/targeted/horsemask
|
||||
/obj/effect/proc_holder/spell/targeted/click/horsemask
|
||||
name = "Curse of the Horseman"
|
||||
desc = "This spell triggers a curse on a target, causing them to wield an unremovable horse head mask. They will speak like a horse! Any masks they are wearing will be disintegrated. This spell does not require robes."
|
||||
school = "transmutation"
|
||||
charge_type = "recharge"
|
||||
charge_max = 150
|
||||
charge_counter = 0
|
||||
clothes_req = 0
|
||||
stat_allowed = 0
|
||||
clothes_req = FALSE
|
||||
stat_allowed = FALSE
|
||||
invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
|
||||
invocation_type = "shout"
|
||||
range = 7
|
||||
cooldown_min = 30 //30 deciseconds reduction per rank
|
||||
selection_type = "range"
|
||||
|
||||
selection_activated_message = "<span class='notice'>You start to quietly neigh an incantation. Click on or near a target to cast the spell.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>You stop neighing to yourself.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
action_icon_state = "barn"
|
||||
sound = 'sound/magic/HorseHead_curse.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/horsemask/cast(list/targets, mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/click/horsemask/cast(list/targets, mob/user = usr)
|
||||
if(!targets.len)
|
||||
to_chat(user, "<span class='notice'>No target found in range.</span>")
|
||||
return
|
||||
|
||||
var/mob/living/carbon/target = targets[1]
|
||||
|
||||
if(!target)
|
||||
return
|
||||
|
||||
|
||||
if(!ishuman(target))
|
||||
to_chat(user, "<span class='notice'>It'd be stupid to curse [target] with a horse's head!</span>")
|
||||
return
|
||||
|
||||
if(!(target in oview(range)))//If they are not in overview after selection.
|
||||
to_chat(user, "<span class='notice'>They are too far away!</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
|
||||
var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
|
||||
magichead.flags |= NODROP | DROPDEL //curses!
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/lightning/Click()
|
||||
if(!ready && start_time == 0)
|
||||
if(cast_check())
|
||||
if(cast_check(TRUE, FALSE, usr))
|
||||
StartChargeup()
|
||||
else
|
||||
if(ready && cast_check(skipcharge=1))
|
||||
if(ready && cast_check(TRUE, TRUE, usr))
|
||||
choose_targets()
|
||||
return 1
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
if(ready)
|
||||
Discharge()
|
||||
|
||||
obj/effect/proc_holder/spell/targeted/lightning/proc/Reset(mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/lightning/proc/Reset(mob/user = usr)
|
||||
ready = 0
|
||||
start_time = 0
|
||||
if(halo)
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/magnet/Click()
|
||||
if(!ready && start_time == 0)
|
||||
if(cast_check())
|
||||
if(cast_check(TRUE, FALSE, usr))
|
||||
StartChargeup()
|
||||
else
|
||||
if(ready && cast_check(skipcharge=1))
|
||||
if(ready && cast_check(TRUE, TRUE, usr))
|
||||
choose_targets()
|
||||
return 1
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
if(ready)
|
||||
Discharge()
|
||||
|
||||
obj/effect/proc_holder/spell/targeted/magnet/proc/Reset(mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/magnet/proc/Reset(mob/user = usr)
|
||||
ready = 0
|
||||
energy = 0
|
||||
start_time = 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/obj/effect/proc_holder/spell/targeted/mind_transfer
|
||||
/obj/effect/proc_holder/spell/targeted/click/mind_transfer
|
||||
name = "Mind Transfer"
|
||||
desc = "This spell allows the user to switch bodies with a target."
|
||||
|
||||
@@ -8,33 +8,29 @@
|
||||
invocation = "GIN'YU CAPAN"
|
||||
invocation_type = "whisper"
|
||||
range = 1
|
||||
click_radius = 0 // Still gotta be pretty accurate
|
||||
selection_activated_message = "<span class='notice'>You prepare to transfer your mind. Click on a target to cast the spell.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>You decide that your current form is good enough.</span>"
|
||||
cooldown_min = 200 //100 deciseconds reduction per rank
|
||||
var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell
|
||||
var/paralysis_amount_caster = 20 //how much the caster is paralysed for after the spell
|
||||
var/paralysis_amount_victim = 20 //how much the victim is paralysed for after the spell
|
||||
action_icon_state = "mindswap"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mind_transfer/valid_target(mob/living/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return target.stat != DEAD && target.key && target.mind
|
||||
|
||||
/*
|
||||
Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do.
|
||||
Make sure spells that are removed from spell_list are actually removed and deleted when mind transfering.
|
||||
Also, you never added distance checking after target is selected. I've went ahead and did that.
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets, mob/user = usr, distanceoverride)
|
||||
/obj/effect/proc_holder/spell/targeted/click/mind_transfer/cast(list/targets, mob/user = usr)
|
||||
|
||||
var/mob/living/target = targets[range]
|
||||
|
||||
if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
|
||||
to_chat(user, "They are too far away!")
|
||||
return
|
||||
|
||||
if(target.stat == DEAD)
|
||||
to_chat(user, "You don't particularly want to be dead.")
|
||||
return
|
||||
|
||||
if(!target.key || !target.mind)
|
||||
to_chat(user, "[target.p_they(TRUE)] appear[target.p_s()] to be catatonic. Not even magic can affect [target.p_their()] vacant mind.")
|
||||
return
|
||||
|
||||
if(user.suiciding)
|
||||
to_chat(user, "<span class='warning'>You're killing yourself! You can't concentrate enough to do this!</span>")
|
||||
return
|
||||
|
||||
@@ -308,76 +308,50 @@
|
||||
duration = 300
|
||||
sound = 'sound/magic/blind.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball
|
||||
/obj/effect/proc_holder/spell/targeted/click/fireball
|
||||
name = "Fireball"
|
||||
desc = "This spell fires a fireball at a target and does not require wizard garb."
|
||||
|
||||
school = "evocation"
|
||||
charge_max = 60
|
||||
clothes_req = 0
|
||||
clothes_req = FALSE
|
||||
invocation = "ONI SOMA"
|
||||
invocation_type = "shout"
|
||||
auto_target_single = FALSE // Having this true won't ever find a single target and is just lost processing power
|
||||
range = 20
|
||||
cooldown_min = 20 //10 deciseconds reduction per rank
|
||||
|
||||
click_radius = -1
|
||||
selection_activated_message = "<span class='notice'>Your prepare to cast your fireball spell! <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>You extinguish your fireball...for now.</span>"
|
||||
allowed_type = /atom // FIRE AT EVERYTHING
|
||||
|
||||
var/fireball_type = /obj/item/projectile/magic/fireball
|
||||
action_icon_state = "fireball0"
|
||||
sound = 'sound/magic/fireball.ogg'
|
||||
|
||||
active = FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/Click()
|
||||
var/mob/living/user = usr
|
||||
if(!istype(user))
|
||||
return
|
||||
|
||||
var/msg
|
||||
|
||||
if(!can_cast(user))
|
||||
msg = "<span class='warning'>You can no longer cast Fireball.</span>"
|
||||
remove_ranged_ability(user, msg)
|
||||
return
|
||||
|
||||
if(active)
|
||||
msg = "<span class='notice'>You extinguish your fireball...for now.</span>"
|
||||
remove_ranged_ability(user, msg)
|
||||
else
|
||||
msg = "<span class='notice'>Your prepare to cast your fireball spell! <B>Left-click to cast at a target!</B></span>"
|
||||
add_ranged_ability(user, msg)
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/update_icon()
|
||||
/obj/effect/proc_holder/spell/targeted/click/fireball/update_icon()
|
||||
if(!action)
|
||||
return
|
||||
action.button_icon_state = "fireball[active]"
|
||||
action.UpdateButtonIcon()
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/InterceptClickOn(mob/living/user, params, atom/target)
|
||||
if(..())
|
||||
return FALSE
|
||||
|
||||
if(!cast_check(0, user))
|
||||
remove_ranged_ability(user)
|
||||
return FALSE
|
||||
|
||||
var/list/targets = list(target)
|
||||
perform(targets, user = user)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/cast(list/targets, mob/living/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/click/fireball/cast(list/targets, mob/living/user = usr)
|
||||
var/target = targets[1] //There is only ever one target for fireball
|
||||
var/turf/T = user.loc
|
||||
var/turf/U = get_step(user, user.dir) // Get the tile infront of the move, based on their direction
|
||||
if(!isturf(U) || !isturf(T))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/obj/item/projectile/magic/fireball/FB = new fireball_type(user.loc)
|
||||
FB.current = get_turf(user)
|
||||
FB.preparePixelProjectile(target, get_turf(target), user)
|
||||
FB.fire()
|
||||
user.newtonian_move(get_dir(U, T))
|
||||
remove_ranged_ability(user)
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse
|
||||
name = "Repulse"
|
||||
|
||||
@@ -344,6 +344,14 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
|
||||
cost = 15
|
||||
containername = "tactical armor crate"
|
||||
|
||||
/datum/supply_packs/security/armory/webbing
|
||||
name = "Webbing Crate"
|
||||
contains = list(/obj/item/storage/belt/security/webbing,
|
||||
/obj/item/storage/belt/security/webbing,
|
||||
/obj/item/storage/belt/security/webbing)
|
||||
cost = 15
|
||||
containername = "tactical webbing crate"
|
||||
|
||||
/datum/supply_packs/security/armory/swat
|
||||
name = "SWAT gear crate"
|
||||
contains = list(/obj/item/clothing/head/helmet/swat,
|
||||
@@ -980,12 +988,6 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
|
||||
containername = "shield generators crate"
|
||||
access = ACCESS_TELEPORTER
|
||||
|
||||
/datum/supply_packs/science/modularpc
|
||||
name = "Deluxe Silicate Selections restocking unit"
|
||||
cost = 15
|
||||
contains = list(/obj/item/vending_refill/modularpc)
|
||||
containername = "computer supply crate"
|
||||
|
||||
/datum/supply_packs/science/transfer_valves
|
||||
name = "Tank Transfer Valves Crate"
|
||||
contains = list(/obj/item/transfer_valve,
|
||||
|
||||
@@ -412,9 +412,9 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
|
||||
/datum/uplink_item/jobspecific/energizedfireaxe
|
||||
name = "Energized Fire Axe"
|
||||
desc = "A fire axe with a massive electrical charge built into it. It can release this charge on its first victim and will be rather plain after that."
|
||||
desc = "A fire axe with a massive energy charge built into it. Upon striking someone while charged it will throw them backwards while stunning them briefly, but will take some time to charge up again. It is also much sharper than a regular axe and can pierce light armor."
|
||||
reference = "EFA"
|
||||
item = /obj/item/twohanded/energizedfireaxe
|
||||
item = /obj/item/twohanded/fireaxe/energized
|
||||
cost = 10
|
||||
job = list("Life Support Specialist")
|
||||
|
||||
@@ -1563,11 +1563,11 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
cost = 10
|
||||
|
||||
/datum/uplink_item/cyber_implants/antistun
|
||||
name = "CNS Rebooter Implant"
|
||||
desc = "This implant will help you get back up on your feet faster after being stunned. \
|
||||
name = "Hardened CNS Rebooter Implant"
|
||||
desc = "This implant will help you get back up on your feet faster after being stunned. It is invulnerable to EMPs. \
|
||||
Comes with an automated implanting tool."
|
||||
reference = "CIAS"
|
||||
item = /obj/item/organ/internal/cyberimp/brain/anti_stun
|
||||
item = /obj/item/organ/internal/cyberimp/brain/anti_stun/hardened
|
||||
cost = 12
|
||||
|
||||
/datum/uplink_item/cyber_implants/reviver
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
. += "The green light is [A.shocked ? "on" : "off"]."
|
||||
. += "The UV display shows [A.uv_super ? "15 nm" : "185 nm"]."
|
||||
|
||||
datum/wires/suitstorage/interactable(mob/user)
|
||||
/datum/wires/suitstorage/interactable(mob/user)
|
||||
var/obj/machinery/suit_storage_unit/A = holder
|
||||
if(iscarbon(user) && A.Adjacent(user) && A.shocked)
|
||||
return A.shock(user, 100)
|
||||
@@ -42,7 +42,7 @@ datum/wires/suitstorage/interactable(mob/user)
|
||||
A.uv_super = !mend
|
||||
..()
|
||||
|
||||
datum/wires/suitstorage/on_pulse(wire)
|
||||
/datum/wires/suitstorage/on_pulse(wire)
|
||||
var/obj/machinery/suit_storage_unit/A = holder
|
||||
if(is_cut(wire))
|
||||
return
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
* In the `colors` list, the name of the color is the key, and the wire is the value.
|
||||
* For example: `colors["red"] = WIRE_ELECTRIFY`. This will look like `list("red" = WIRE_ELECTRIFY)` internally.
|
||||
*/
|
||||
datum/wires/proc/randomize()
|
||||
/datum/wires/proc/randomize()
|
||||
var/static/list/possible_colors = list("red", "blue", "green", "silver", "orange", "brown", "gold", "white", "cyan", "magenta", "purple", "pink")
|
||||
var/list/my_possible_colors = possible_colors.Copy()
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#define BLOB 14
|
||||
// TODO: Investigate more recent type additions and see if I can handle them. - Nadrew
|
||||
|
||||
DBConnection
|
||||
/DBConnection
|
||||
var/_db_con // This variable contains a reference to the actual database connection.
|
||||
var/dbi // This variable is a string containing the DBI MySQL requires.
|
||||
var/user // This variable contains the username data.
|
||||
@@ -39,14 +39,14 @@ DBConnection
|
||||
var/server = ""
|
||||
var/port = 3306
|
||||
|
||||
DBConnection/New(dbi_handler,username,password_handler,cursor_handler)
|
||||
/DBConnection/New(dbi_handler,username,password_handler,cursor_handler)
|
||||
src.dbi = dbi_handler
|
||||
src.user = username
|
||||
src.password = password_handler
|
||||
src.default_cursor = cursor_handler
|
||||
_db_con = _dm_db_new_con()
|
||||
|
||||
DBConnection/proc/Connect(dbi_handler=src.dbi,user_handler=src.user,password_handler=src.password,cursor_handler)
|
||||
/DBConnection/proc/Connect(dbi_handler=src.dbi,user_handler=src.user,password_handler=src.password,cursor_handler)
|
||||
if(!config.sql_enabled)
|
||||
return 0
|
||||
if(!src) return 0
|
||||
@@ -54,24 +54,24 @@ DBConnection/proc/Connect(dbi_handler=src.dbi,user_handler=src.user,password_han
|
||||
if(!cursor_handler) cursor_handler = Default_Cursor
|
||||
return _dm_db_connect(_db_con,dbi_handler,user_handler,password_handler,cursor_handler,null)
|
||||
|
||||
DBConnection/proc/Disconnect() return _dm_db_close(_db_con)
|
||||
/DBConnection/proc/Disconnect() return _dm_db_close(_db_con)
|
||||
|
||||
DBConnection/proc/IsConnected()
|
||||
/DBConnection/proc/IsConnected()
|
||||
if(!config.sql_enabled) return 0
|
||||
var/success = _dm_db_is_connected(_db_con)
|
||||
return success
|
||||
|
||||
DBConnection/proc/Quote(str) return _dm_db_quote(_db_con,str)
|
||||
/DBConnection/proc/Quote(str) return _dm_db_quote(_db_con,str)
|
||||
|
||||
DBConnection/proc/ErrorMsg() return _dm_db_error_msg(_db_con)
|
||||
DBConnection/proc/SelectDB(database_name,dbi)
|
||||
/DBConnection/proc/ErrorMsg() return _dm_db_error_msg(_db_con)
|
||||
/DBConnection/proc/SelectDB(database_name,dbi)
|
||||
if(IsConnected()) Disconnect()
|
||||
//return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[DB_SERVER]:[DB_PORT]"]",user,password)
|
||||
return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[sqladdress]:[sqlport]"]",user,password)
|
||||
DBConnection/proc/NewQuery(sql_query,cursor_handler=src.default_cursor) return new/DBQuery(sql_query,src,cursor_handler)
|
||||
/DBConnection/proc/NewQuery(sql_query,cursor_handler=src.default_cursor) return new/DBQuery(sql_query,src,cursor_handler)
|
||||
|
||||
|
||||
DBQuery/New(sql_query,DBConnection/connection_handler,cursor_handler)
|
||||
/DBQuery/New(sql_query,DBConnection/connection_handler,cursor_handler)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='boldannounce'>DB query blocked: Advanced ProcCall detected.</span>")
|
||||
message_admins("[key_name(usr)] attempted to create a DB query via advanced proc-call")
|
||||
@@ -83,12 +83,12 @@ DBQuery/New(sql_query,DBConnection/connection_handler,cursor_handler)
|
||||
_db_query = _dm_db_new_query()
|
||||
return ..()
|
||||
|
||||
DBQuery/CanProcCall()
|
||||
/DBQuery/CanProcCall()
|
||||
// dont even try it
|
||||
return FALSE
|
||||
|
||||
|
||||
DBQuery
|
||||
/DBQuery
|
||||
var/sql // The sql query being executed.
|
||||
var/default_cursor
|
||||
var/list/columns //list of DB Columns populated by Columns()
|
||||
@@ -98,26 +98,26 @@ DBQuery
|
||||
var/DBConnection/db_connection
|
||||
var/_db_query
|
||||
|
||||
DBQuery/proc/Connect(DBConnection/connection_handler) src.db_connection = connection_handler
|
||||
/DBQuery/proc/Connect(DBConnection/connection_handler) src.db_connection = connection_handler
|
||||
|
||||
DBQuery/proc/Execute(sql_query=src.sql,cursor_handler=default_cursor)
|
||||
/DBQuery/proc/Execute(sql_query=src.sql,cursor_handler=default_cursor)
|
||||
Close()
|
||||
return _dm_db_execute(_db_query,sql_query,db_connection._db_con,cursor_handler,null)
|
||||
|
||||
DBQuery/proc/NextRow() return _dm_db_next_row(_db_query,item,conversions)
|
||||
/DBQuery/proc/NextRow() return _dm_db_next_row(_db_query,item,conversions)
|
||||
|
||||
DBQuery/proc/RowsAffected() return _dm_db_rows_affected(_db_query)
|
||||
/DBQuery/proc/RowsAffected() return _dm_db_rows_affected(_db_query)
|
||||
|
||||
DBQuery/proc/RowCount() return _dm_db_row_count(_db_query)
|
||||
/DBQuery/proc/RowCount() return _dm_db_row_count(_db_query)
|
||||
|
||||
DBQuery/proc/ErrorMsg() return _dm_db_error_msg(_db_query)
|
||||
/DBQuery/proc/ErrorMsg() return _dm_db_error_msg(_db_query)
|
||||
|
||||
DBQuery/proc/Columns()
|
||||
/DBQuery/proc/Columns()
|
||||
if(!columns)
|
||||
columns = _dm_db_columns(_db_query,/DBColumn)
|
||||
return columns
|
||||
|
||||
DBQuery/proc/GetRowData()
|
||||
/DBQuery/proc/GetRowData()
|
||||
var/list/columns = Columns()
|
||||
var/list/results
|
||||
if(columns.len)
|
||||
@@ -128,23 +128,23 @@ DBQuery/proc/GetRowData()
|
||||
results[C] = src.item[(cur_col.position+1)]
|
||||
return results
|
||||
|
||||
DBQuery/proc/Close()
|
||||
/DBQuery/proc/Close()
|
||||
item.len = 0
|
||||
columns = null
|
||||
conversions = null
|
||||
return _dm_db_close(_db_query)
|
||||
|
||||
DBQuery/proc/Quote(str)
|
||||
/DBQuery/proc/Quote(str)
|
||||
return db_connection.Quote(str)
|
||||
|
||||
DBQuery/proc/SetConversion(column,conversion)
|
||||
/DBQuery/proc/SetConversion(column,conversion)
|
||||
if(istext(column)) column = columns.Find(column)
|
||||
if(!conversions) conversions = new/list(column)
|
||||
else if(conversions.len < column) conversions.len = column
|
||||
conversions[column] = conversion
|
||||
|
||||
|
||||
DBColumn
|
||||
/DBColumn
|
||||
var/name
|
||||
var/table
|
||||
var/position //1-based index into item data
|
||||
@@ -153,7 +153,7 @@ DBColumn
|
||||
var/length
|
||||
var/max_length
|
||||
|
||||
DBColumn/New(name_handler,table_handler,position_handler,type_handler,flag_handler,length_handler,max_length_handler)
|
||||
/DBColumn/New(name_handler,table_handler,position_handler,type_handler,flag_handler,length_handler,max_length_handler)
|
||||
src.name = name_handler
|
||||
src.table = table_handler
|
||||
src.position = position_handler
|
||||
@@ -164,7 +164,7 @@ DBColumn/New(name_handler,table_handler,position_handler,type_handler,flag_handl
|
||||
return ..()
|
||||
|
||||
|
||||
DBColumn/proc/SqlTypeName(type_handler=src.sql_type)
|
||||
/DBColumn/proc/SqlTypeName(type_handler=src.sql_type)
|
||||
switch(type_handler)
|
||||
if(TINYINT) return "TINYINT"
|
||||
if(SMALLINT) return "SMALLINT"
|
||||
|
||||
@@ -570,7 +570,7 @@
|
||||
|
||||
/area/proc/prison_break()
|
||||
for(var/obj/machinery/power/apc/temp_apc in src)
|
||||
temp_apc.overload_lighting(70)
|
||||
INVOKE_ASYNC(temp_apc, /obj/machinery/power/apc.proc/overload_lighting, 70)
|
||||
for(var/obj/machinery/door/airlock/temp_airlock in src)
|
||||
temp_airlock.prison_open()
|
||||
for(var/obj/machinery/door/window/temp_windoor in src)
|
||||
|
||||
+2
-2
@@ -231,7 +231,7 @@
|
||||
/atom/proc/on_reagent_change()
|
||||
return
|
||||
|
||||
/atom/proc/Bumped(AM as mob|obj)
|
||||
/atom/proc/Bumped(atom/movable/AM)
|
||||
return
|
||||
|
||||
/// Convenience proc to see if a container is open for chemistry handling
|
||||
@@ -257,7 +257,7 @@
|
||||
/atom/proc/CheckExit()
|
||||
return TRUE
|
||||
|
||||
/atom/proc/HasProximity(atom/movable/AM as mob|obj)
|
||||
/atom/proc/HasProximity(atom/movable/AM)
|
||||
return
|
||||
|
||||
/atom/proc/emp_act(severity)
|
||||
|
||||
@@ -123,13 +123,13 @@
|
||||
instability = GENE_INSTABILITY_MODERATE
|
||||
mutation = CRYO
|
||||
|
||||
spelltype = /obj/effect/proc_holder/spell/targeted/cryokinesis
|
||||
spelltype = /obj/effect/proc_holder/spell/targeted/click/cryokinesis
|
||||
|
||||
/datum/dna/gene/basic/grant_spell/cryo/New()
|
||||
..()
|
||||
block = GLOB.cryoblock
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/cryokinesis
|
||||
/obj/effect/proc_holder/spell/targeted/click/cryokinesis
|
||||
name = "Cryokinesis"
|
||||
desc = "Drops the bodytemperature of another person."
|
||||
panel = "Abilities"
|
||||
@@ -137,45 +137,44 @@
|
||||
charge_type = "recharge"
|
||||
charge_max = 1200
|
||||
|
||||
clothes_req = 0
|
||||
stat_allowed = 0
|
||||
clothes_req = FALSE
|
||||
stat_allowed = FALSE
|
||||
|
||||
click_radius = 0
|
||||
auto_target_single = FALSE // Give the clueless geneticists a way out and to have them not target themselves
|
||||
selection_activated_message = "<span class='notice'>Your mind grow cold. Click on a target to cast the spell.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind returns to normal.</span>"
|
||||
allowed_type = /mob/living/carbon
|
||||
invocation_type = "none"
|
||||
range = 7
|
||||
selection_type = "range"
|
||||
include_user = 1
|
||||
include_user = TRUE
|
||||
var/list/compatible_mobs = list(/mob/living/carbon/human)
|
||||
|
||||
action_icon_state = "genetic_cryo"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/cryokinesis/cast(list/targets, mob/user = usr)
|
||||
if(!targets.len)
|
||||
to_chat(user, "<span class='notice'>No target found in range.</span>")
|
||||
return
|
||||
/obj/effect/proc_holder/spell/targeted/click/cryokinesis/cast(list/targets, mob/user = usr)
|
||||
|
||||
var/mob/living/carbon/C = targets[1]
|
||||
|
||||
if(!iscarbon(C))
|
||||
to_chat(user, "<span class='warning'>This will only work on normal organic beings.</span>")
|
||||
return
|
||||
|
||||
if(COLDRES in C.mutations)
|
||||
C.visible_message("<span class='warning'>A cloud of fine ice crystals engulfs [C.name], but disappears almost instantly!</span>")
|
||||
return
|
||||
var/handle_suit = 0
|
||||
var/handle_suit = FALSE
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(istype(H.head, /obj/item/clothing/head/helmet/space))
|
||||
if(istype(H.wear_suit, /obj/item/clothing/suit/space))
|
||||
handle_suit = 1
|
||||
handle_suit = TRUE
|
||||
if(H.internal)
|
||||
H.visible_message("<span class='warning'>[user] sprays a cloud of fine ice crystals, engulfing [H]!</span>",
|
||||
"<span class='notice'>[user] sprays a cloud of fine ice crystals over your [H.head]'s visor.</span>")
|
||||
add_attack_logs(user, C, "Cryokinesis")
|
||||
else
|
||||
H.visible_message("<span class='warning'>[user] sprays a cloud of fine ice crystals engulfing, [H]!</span>",
|
||||
"<span class='warning'>[user] sprays a cloud of fine ice crystals cover your [H.head]'s visor and make it into your air vents!.</span>")
|
||||
add_attack_logs(user, C, "Cryokinesis")
|
||||
|
||||
H.bodytemperature = max(0, H.bodytemperature - 100)
|
||||
add_attack_logs(user, C, "Cryokinesis")
|
||||
if(!handle_suit)
|
||||
C.bodytemperature = max(0, C.bodytemperature - 200)
|
||||
C.ExtinguishMob()
|
||||
@@ -454,7 +453,7 @@
|
||||
name = "Polymorphism"
|
||||
desc = "Enables the subject to reconfigure their appearance to mimic that of others."
|
||||
|
||||
spelltype =/obj/effect/proc_holder/spell/targeted/polymorph
|
||||
spelltype =/obj/effect/proc_holder/spell/targeted/click/polymorph
|
||||
//cooldown = 1800
|
||||
activation_messages = list("You don't feel entirely like yourself somehow.")
|
||||
deactivation_messages = list("You feel secure in your identity.")
|
||||
@@ -465,34 +464,36 @@
|
||||
..()
|
||||
block = GLOB.polymorphblock
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/polymorph
|
||||
/obj/effect/proc_holder/spell/targeted/click/polymorph
|
||||
name = "Polymorph"
|
||||
desc = "Mimic the appearance of others!"
|
||||
panel = "Abilities"
|
||||
charge_max = 1800
|
||||
|
||||
clothes_req = 0
|
||||
human_req = 1
|
||||
stat_allowed = 0
|
||||
clothes_req = FALSE
|
||||
stat_allowed = FALSE
|
||||
|
||||
click_radius = -1 // Precision required
|
||||
auto_target_single = FALSE // Safety to not turn into monkey (420)
|
||||
selection_activated_message = "<span class='notice'>You body becomes unstable. Click on a target to cast transform into them.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your body calms down again.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
invocation_type = "none"
|
||||
range = 1
|
||||
selection_type = "range"
|
||||
|
||||
action_icon_state = "genetic_poly"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/polymorph/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/M = targets[1]
|
||||
if(!ishuman(M))
|
||||
to_chat(usr, "<span class='warning'>You can only change your appearance to that of another human.</span>")
|
||||
return
|
||||
/obj/effect/proc_holder/spell/targeted/click/polymorph/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
|
||||
user.visible_message("<span class='warning'>[user]'s body shifts and contorts.</span>")
|
||||
|
||||
spawn(10)
|
||||
if(M && user)
|
||||
if(target && user)
|
||||
playsound(user.loc, 'sound/goonstation/effects/gib.ogg', 50, 1)
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/mob/living/carbon/human/target = M
|
||||
H.UpdateAppearance(target.dna.UI)
|
||||
H.real_name = target.real_name
|
||||
H.name = target.name
|
||||
|
||||
@@ -214,25 +214,21 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/remotetalk/choose_targets(mob/user = usr)
|
||||
var/list/targets = new /list()
|
||||
var/list/validtargets = new /list()
|
||||
var/turf/T = get_turf(user)
|
||||
for(var/mob/living/M in range(14, T))
|
||||
if(M && M.mind)
|
||||
if(M == user)
|
||||
continue
|
||||
validtargets += M
|
||||
var/list/validtargets = user.get_telepathic_targets()
|
||||
|
||||
if(!validtargets.len)
|
||||
if(!length(validtargets))
|
||||
to_chat(user, "<span class='warning'>There are no valid targets!</span>")
|
||||
start_recharge()
|
||||
return
|
||||
|
||||
targets += input("Choose the target to talk to.", "Targeting") as null|mob in validtargets
|
||||
var/target_name = input("Choose the target to talk to.", "Targeting") as null|anything in validtargets
|
||||
|
||||
if(!targets.len || !targets[1]) //doesn't waste the spell
|
||||
var/mob/living/target
|
||||
if(!target_name || !(target = validtargets[target_name]))
|
||||
revert_cast(user)
|
||||
return
|
||||
|
||||
targets += target
|
||||
perform(targets, user = user)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/remotetalk/cast(list/targets, mob/user = usr)
|
||||
@@ -249,7 +245,7 @@
|
||||
target.show_message("<span class='abductor'>You hear [user.real_name]'s voice: [say]</span>")
|
||||
else
|
||||
target.show_message("<span class='abductor'>You hear a voice that seems to echo around the room: [say]</span>")
|
||||
user.show_message("<span class='abductor'>You project your mind into [target.name]: [say]</span>")
|
||||
user.show_message("<span class='abductor'>You project your mind into [(target in user.get_visible_mobs()) ? target.name : "the unknown entity"]: [say]</span>")
|
||||
for(var/mob/dead/observer/G in GLOB.player_list)
|
||||
G.show_message("<i>Telepathic message from <b>[user]</b> ([ghost_follow_link(user, ghost=G)]) to <b>[target]</b> ([ghost_follow_link(target, ghost=G)]): [say]</i>")
|
||||
|
||||
@@ -266,26 +262,22 @@
|
||||
var/list/available_targets = list()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/mindscan/choose_targets(mob/user = usr)
|
||||
var/list/targets = new /list()
|
||||
var/list/validtargets = new /list()
|
||||
var/turf/T = get_turf(user)
|
||||
for(var/mob/living/M in range(14, T))
|
||||
if(M && M.mind)
|
||||
if(M == user)
|
||||
continue
|
||||
validtargets += M
|
||||
var/list/targets = list()
|
||||
var/list/validtargets = user.get_telepathic_targets()
|
||||
|
||||
if(!validtargets.len)
|
||||
if(!length(validtargets))
|
||||
to_chat(user, "<span class='warning'>There are no valid targets!</span>")
|
||||
start_recharge()
|
||||
return
|
||||
|
||||
targets += input("Choose the target to listen to.", "Targeting") as null|mob in validtargets
|
||||
var/target_name = input("Choose the target to listen to.", "Targeting") as null|anything in validtargets
|
||||
|
||||
if(!targets.len || !targets[1]) //doesn't waste the spell
|
||||
var/mob/living/target
|
||||
if(!target_name || !(target = validtargets[target_name]))
|
||||
revert_cast(user)
|
||||
return
|
||||
|
||||
targets += target
|
||||
perform(targets, user = user)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/mindscan/cast(list/targets, mob/user = usr)
|
||||
@@ -295,7 +287,7 @@
|
||||
var/message = "You feel your mind expand briefly... (Click to send a message.)"
|
||||
if(REMOTE_TALK in target.mutations)
|
||||
message = "You feel [user.real_name] request a response from you... (Click here to project mind.)"
|
||||
user.show_message("<span class='abductor'>You offer your mind to [target.name].</span>")
|
||||
user.show_message("<span class='abductor'>You offer your mind to [(target in user.get_visible_mobs()) ? target.name : "the unknown entity"].</span>")
|
||||
target.show_message("<span class='abductor'><A href='?src=[UID()];target=[target.UID()];user=[user.UID()]'>[message]</a></span>")
|
||||
available_targets += target
|
||||
addtimer(CALLBACK(src, .proc/removeAvailability, target), 100)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
intercepttext += "<BR>Note in the event of a quarantine breach or uncontrolled spread of the biohazard, the directive 7-10 may be upgraded to a directive 7-12.<BR>"
|
||||
intercepttext += "Message ends."
|
||||
if(2)
|
||||
var/nukecode = "[rand(10000, 99999)]"
|
||||
var/nukecode = rand(10000, 99999)
|
||||
for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
|
||||
if(bomb && bomb.r_code)
|
||||
if(is_station_level(bomb.z))
|
||||
@@ -40,7 +40,7 @@
|
||||
aiPlayer.set_zeroth_law(law)
|
||||
to_chat(aiPlayer, "Laws Updated: [law]")
|
||||
|
||||
print_command_report(intercepttext, interceptname)
|
||||
print_command_report(intercepttext, interceptname, FALSE)
|
||||
GLOB.event_announcement.Announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg', from = "[command_name()] Update")
|
||||
|
||||
/datum/station_state
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
feedback_add_details("changeling_powers","TS")
|
||||
return TRUE
|
||||
|
||||
datum/action/changeling/sting/extract_dna
|
||||
/datum/action/changeling/sting/extract_dna
|
||||
name = "Extract DNA Sting"
|
||||
desc = "We stealthily sting a target and extract their DNA. Costs 25 chemicals."
|
||||
helptext = "Will give you the DNA of your target, allowing you to transform into them."
|
||||
@@ -132,7 +132,7 @@ datum/action/changeling/sting/extract_dna
|
||||
feedback_add_details("changeling_powers","ED")
|
||||
return 1
|
||||
|
||||
datum/action/changeling/sting/mute
|
||||
/datum/action/changeling/sting/mute
|
||||
name = "Mute Sting"
|
||||
desc = "We silently sting a human, completely silencing them for a short time. Costs 20 chemicals."
|
||||
helptext = "Does not provide a warning to the victim that they have been stung, until they try to speak and cannot."
|
||||
@@ -147,7 +147,7 @@ datum/action/changeling/sting/mute
|
||||
feedback_add_details("changeling_powers","MS")
|
||||
return 1
|
||||
|
||||
datum/action/changeling/sting/blind
|
||||
/datum/action/changeling/sting/blind
|
||||
name = "Blind Sting"
|
||||
desc = "We temporarily blind our victim. Costs 25 chemicals."
|
||||
helptext = "This sting completely blinds a target for a short time, and leaves them with blurred vision for a long time."
|
||||
@@ -165,7 +165,7 @@ datum/action/changeling/sting/blind
|
||||
feedback_add_details("changeling_powers","BS")
|
||||
return 1
|
||||
|
||||
datum/action/changeling/sting/LSD
|
||||
/datum/action/changeling/sting/LSD
|
||||
name = "Hallucination Sting"
|
||||
desc = "We cause mass terror to our victim. Costs 10 chemicals."
|
||||
helptext = "We evolve the ability to sting a target with a powerful hallucinogenic chemical. The target does not notice they have been stung, and the effect occurs after 30 to 60 seconds."
|
||||
@@ -182,7 +182,7 @@ datum/action/changeling/sting/LSD
|
||||
feedback_add_details("changeling_powers","HS")
|
||||
return 1
|
||||
|
||||
datum/action/changeling/sting/cryo //Enable when mob cooling is fixed so that frostoil actually makes you cold, instead of mostly just hungry.
|
||||
/datum/action/changeling/sting/cryo //Enable when mob cooling is fixed so that frostoil actually makes you cold, instead of mostly just hungry.
|
||||
name = "Cryogenic Sting"
|
||||
desc = "We silently sting our victim with a cocktail of chemicals that freezes them from the inside. Costs 15 chemicals."
|
||||
helptext = "Does not provide a warning to the victim, though they will likely realize they are suddenly freezing."
|
||||
|
||||
@@ -270,14 +270,10 @@ GLOBAL_LIST_INIT(blacklisted_pylon_turfs, typecacheof(list(
|
||||
/obj/effect/gateway/singularity_pull()
|
||||
return
|
||||
|
||||
/obj/effect/gateway/Bumped(mob/M as mob|obj)
|
||||
spawn(0)
|
||||
return
|
||||
/obj/effect/gateway/Bumped(atom/movable/AM)
|
||||
return
|
||||
|
||||
/obj/effect/gateway/Crossed(AM as mob|obj, oldloc)
|
||||
spawn(0)
|
||||
return
|
||||
/obj/effect/gateway/Crossed(atom/movable/AM, oldloc)
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
/obj/effect/mob_spawn/human/demonic_friend/Initialize(mapload, datum/mind/owner_mind, obj/effect/proc_holder/spell/targeted/summon_friend/summoning_spell)
|
||||
. = ..()
|
||||
owner = owner_mind
|
||||
flavour_text = "<span class='big bold'>You have been given a reprieve from your eternity of torment, to be [owner.name]'s friend for [owner.p_their()] short mortal coil.</span><b> Be aware that if you do not live up to [owner.name]'s expectations, [owner.p_they()] can send you back to hell with a single thought. [owner.name]'s death will also return you to hell.</b>"
|
||||
description = "Be someone's loyal friend/slave. If they die, you die as well." //best I could think of in the moment, not sure how this role plays in practise, have never seen it.
|
||||
flavour_text = "You have been given a reprieve from your eternity of torment, to be [owner.name]'s friend for [owner.p_their()] short mortal coil. Be aware that if you do not live up to [owner.name]'s expectations, [owner.p_they()] can send you back to hell with a single thought. [owner.name]'s death will also return you to hell."
|
||||
var/area/A = get_area(src)
|
||||
if(!mapload && A)
|
||||
notify_ghosts("\A friendship shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = TRUE)
|
||||
|
||||
@@ -92,7 +92,7 @@ GLOBAL_LIST_INIT(lawlorify, list (
|
||||
var/form = BASIC_DEVIL
|
||||
var/exists = 0
|
||||
var/static/list/dont_remove_spells = list(
|
||||
/obj/effect/proc_holder/spell/targeted/summon_contract,
|
||||
/obj/effect/proc_holder/spell/targeted/click/summon_contract,
|
||||
/obj/effect/proc_holder/spell/targeted/conjure_item/violin,
|
||||
/obj/effect/proc_holder/spell/targeted/summon_dancefloor)
|
||||
var/ascendable = FALSE
|
||||
@@ -326,12 +326,12 @@ GLOBAL_LIST_INIT(lawlorify, list (
|
||||
owner.RemoveSpell(S)
|
||||
|
||||
/datum/devilinfo/proc/give_summon_contract()
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/summon_contract(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/summon_contract(null))
|
||||
|
||||
|
||||
/datum/devilinfo/proc/give_base_spells(give_summon_contract = 0)
|
||||
remove_spells()
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork(null))
|
||||
if(give_summon_contract)
|
||||
give_summon_contract()
|
||||
@@ -343,13 +343,13 @@ GLOBAL_LIST_INIT(lawlorify, list (
|
||||
/datum/devilinfo/proc/give_lizard_spells()
|
||||
remove_spells()
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/infernal_jaunt(null))
|
||||
|
||||
/datum/devilinfo/proc/give_true_spells()
|
||||
remove_spells()
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork/greater(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/infernal_jaunt(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/sintouch(null))
|
||||
|
||||
|
||||
@@ -337,7 +337,7 @@
|
||||
//////////////////////////
|
||||
//Reports player logouts//
|
||||
//////////////////////////
|
||||
proc/display_roundstart_logout_report()
|
||||
/proc/display_roundstart_logout_report()
|
||||
var/msg = "<span class='notice'>Roundstart logout report</span>\n\n"
|
||||
for(var/mob/living/L in GLOB.mob_list)
|
||||
|
||||
@@ -507,7 +507,7 @@ proc/display_roundstart_logout_report()
|
||||
message_text += G.get_report()
|
||||
message_text += "<hr>"
|
||||
|
||||
print_command_report(message_text, "[command_name()] Orders")
|
||||
print_command_report(message_text, "[command_name()] Orders", FALSE)
|
||||
|
||||
/datum/game_mode/proc/declare_station_goal_completion()
|
||||
for(var/V in station_goals)
|
||||
|
||||
@@ -250,7 +250,7 @@ GLOBAL_LIST_EMPTY(cortical_stacks) //Stacks for 'leave nobody behind' objective.
|
||||
|
||||
..()
|
||||
|
||||
datum/game_mode/proc/auto_declare_completion_heist()
|
||||
/datum/game_mode/proc/auto_declare_completion_heist()
|
||||
if(raiders.len)
|
||||
var/check_return = 0
|
||||
if(GAMEMODE_IS_HEIST)
|
||||
|
||||
@@ -679,7 +679,7 @@
|
||||
for(var/thing in GLOB.apcs)
|
||||
var/obj/machinery/power/apc/apc
|
||||
if(prob(30 * apc.overload))
|
||||
apc.overload_lighting()
|
||||
INVOKE_ASYNC(apc, /obj/machinery/power/apc.proc/overload_lighting)
|
||||
else
|
||||
apc.overload++
|
||||
to_chat(owner, "<span class='notice'>Overcurrent applied to the powernet.</span>")
|
||||
|
||||
@@ -19,15 +19,13 @@
|
||||
mob_name = "a swarmer"
|
||||
death = FALSE
|
||||
roundstart = FALSE
|
||||
flavour_text = {"
|
||||
<b>You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate.</b>
|
||||
<b>Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful.</b>
|
||||
<b>Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage.</b>
|
||||
<b>Objectives:</b>
|
||||
important_info = "Follow your objectives, do not make the station inhospitable or try and kill crew."
|
||||
flavour_text = "You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate."
|
||||
description = {" Your goal is to create more of yourself by consuming the station. Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful. Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage.
|
||||
Objectives:
|
||||
1. Consume resources and replicate until there are no more resources left.
|
||||
2. Ensure that this location is fit for invasion at a later date; do not perform actions that would render it dangerous or inhospitable.
|
||||
3. Biological resources will be harvested at a later date; do not harm them.
|
||||
"}
|
||||
3. Biological resources will be harvested at a later date; do not harm them."}
|
||||
|
||||
/obj/effect/mob_spawn/swarmer/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
var/swarmer_report = "<font size=3><b>[command_name()] High-Priority Update</b></span>"
|
||||
swarmer_report += "<br><br>Our long-range sensors have detected an odd signal emanating from your station's gateway. We recommend immediate investigation of your gateway, as something may have come \
|
||||
through."
|
||||
print_command_report(swarmer_report, "Classified [command_name()] Update")
|
||||
print_command_report(swarmer_report, "Classified [command_name()] Update", FALSE)
|
||||
GLOB.event_announcement.Announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg')
|
||||
|
||||
/datum/event/spawn_swarmer/start()
|
||||
|
||||
@@ -363,7 +363,7 @@
|
||||
if("Protector")
|
||||
pickedtype = /mob/living/simple_animal/hostile/guardian/protector
|
||||
|
||||
var/mob/living/simple_animal/hostile/guardian/G = new pickedtype(user)
|
||||
var/mob/living/simple_animal/hostile/guardian/G = new pickedtype(user, user)
|
||||
G.summoner = user
|
||||
G.summoned = TRUE
|
||||
G.key = key
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
layer = LYING_MOB_LAYER
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam
|
||||
melee_damage_lower = 7
|
||||
melee_damage_upper = 7
|
||||
melee_damage_lower = 12
|
||||
melee_damage_upper = 12
|
||||
attacktext = "shocks"
|
||||
melee_damage_type = BURN
|
||||
attack_sound = 'sound/machines/defib_zap.ogg'
|
||||
damage_transfer = 0.7
|
||||
damage_transfer = 0.6
|
||||
range = 7
|
||||
playstyle_string = "As a <b>Lightning</b> type, you will apply lightning chains to targets on attack and have a lightning chain to your summoner. Lightning chains will shock anyone near them."
|
||||
magic_fluff_string = "..And draw the Tesla, a shocking, lethal source of power."
|
||||
@@ -18,6 +18,17 @@
|
||||
var/list/enemychains = list()
|
||||
var/successfulshocks = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam/New(loc, mob/living/user)
|
||||
. = ..()
|
||||
if(!user)
|
||||
return
|
||||
summoner = user
|
||||
if(!(NO_SHOCK in summoner.mutations))
|
||||
summoner.mutations.Add(NO_SHOCK)
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
|
||||
return FALSE //You are lightning, you should not be hurt by such things.
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam/AttackingTarget()
|
||||
. = ..()
|
||||
if(. && isliving(target) && target != src && target != summoner)
|
||||
@@ -106,3 +117,8 @@
|
||||
)
|
||||
L.adjustFireLoss(1.2) //adds up very rapidly
|
||||
. = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam/death(gibbed)
|
||||
if(summoner && (NO_SHOCK in summoner.mutations))
|
||||
summoner.mutations.Remove(NO_SHOCK)
|
||||
return ..()
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
overlays.Cut()
|
||||
melee_damage_lower = initial(melee_damage_lower)
|
||||
melee_damage_upper = initial(melee_damage_upper)
|
||||
obj_damage = initial(obj_damage)
|
||||
speed = initial(speed)
|
||||
damage_transfer = 0.4
|
||||
to_chat(src, "<span class='danger'>You switch to combat mode.</span>")
|
||||
@@ -35,6 +36,7 @@
|
||||
overlays.Add(shield_overlay)
|
||||
melee_damage_lower = 2
|
||||
melee_damage_upper = 2
|
||||
obj_damage = 6 //40/7.5 rounded up, we don't want a protector guardian 2 shotting blob tiles while taking 5% damage, thats just silly.
|
||||
speed = 1
|
||||
damage_transfer = 0.05 //damage? what's damage?
|
||||
to_chat(src, "<span class='danger'>You switch to protection mode.</span>")
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
else
|
||||
name = "[initial(name)] ([cast_amount]E)"
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/revenant/can_cast(mob/living/simple_animal/revenant/user = usr)
|
||||
/obj/effect/proc_holder/spell/aoe_turf/revenant/can_cast(mob/living/simple_animal/revenant/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(user.inhibited)
|
||||
return 0
|
||||
if(charge_counter < charge_max)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/syndicates = list()
|
||||
|
||||
proc/issyndicate(mob/living/M as mob)
|
||||
/proc/issyndicate(mob/living/M as mob)
|
||||
return istype(M) && M.mind && SSticker && SSticker.mode && (M.mind in SSticker.mode.syndicates)
|
||||
|
||||
/datum/game_mode/nuclear
|
||||
@@ -103,7 +103,7 @@ proc/issyndicate(mob/living/M as mob)
|
||||
|
||||
var/obj/effect/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb")
|
||||
|
||||
var/nuke_code = "[rand(10000, 99999)]"
|
||||
var/nuke_code = rand(10000, 99999)
|
||||
var/leader_selected = 0
|
||||
var/agent_number = 1
|
||||
var/spawnpos = 1
|
||||
|
||||
@@ -14,29 +14,29 @@ GLOBAL_VAR(bomb_set)
|
||||
icon_state = "nuclearbomb0"
|
||||
density = 1
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/deployable = 0
|
||||
var/extended = 0
|
||||
var/lighthack = 0
|
||||
var/extended = FALSE
|
||||
var/lighthack = FALSE
|
||||
var/timeleft = 120
|
||||
var/timing = 0
|
||||
var/timing = FALSE
|
||||
var/exploded = FALSE
|
||||
var/r_code = "ADMIN"
|
||||
var/code = ""
|
||||
var/yes_code = 0
|
||||
var/safety = 1
|
||||
var/code
|
||||
var/yes_code = FALSE
|
||||
var/safety = TRUE
|
||||
var/obj/item/disk/nuclear/auth = null
|
||||
var/removal_stage = NUKE_INTACT
|
||||
var/lastentered
|
||||
var/is_syndicate = 0
|
||||
var/is_syndicate = FALSE
|
||||
use_power = NO_POWER_USE
|
||||
var/previous_level = ""
|
||||
var/datum/wires/nuclearbomb/wires = null
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate
|
||||
is_syndicate = 1
|
||||
is_syndicate = TRUE
|
||||
|
||||
/obj/machinery/nuclearbomb/New()
|
||||
..()
|
||||
r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn.
|
||||
r_code = rand(10000, 99999.0) // Creates a random code upon object spawn.
|
||||
wires = new/datum/wires/nuclearbomb(src)
|
||||
previous_level = get_security_level()
|
||||
GLOB.poi_list |= src
|
||||
@@ -49,25 +49,24 @@ GLOBAL_VAR(bomb_set)
|
||||
|
||||
/obj/machinery/nuclearbomb/process()
|
||||
if(timing)
|
||||
GLOB.bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed.
|
||||
GLOB.bomb_set = TRUE // So long as there is one nuke timing, it means one nuke is armed.
|
||||
timeleft = max(timeleft - 2, 0) // 2 seconds per process()
|
||||
if(timeleft <= 0)
|
||||
INVOKE_ASYNC(src, .proc/explode)
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
|
||||
/obj/machinery/nuclearbomb/attackby(obj/item/O as obj, mob/user as mob, params)
|
||||
if(istype(O, /obj/item/disk/nuclear))
|
||||
if(extended)
|
||||
if(!user.drop_item())
|
||||
to_chat(user, "<span class='notice'>\The [O] is stuck to your hand!</span>")
|
||||
to_chat(user, "<span class='notice'>[O] is stuck to your hand!</span>")
|
||||
return
|
||||
O.forceMove(src)
|
||||
auth = O
|
||||
add_fingerprint(user)
|
||||
return attack_hand(user)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You need to deploy \the [src] first. Right click on the sprite, select 'Make Deployable' then click on \the [src] with an empty hand.</span>")
|
||||
to_chat(user, "<span class='notice'>You need to deploy [src] first.</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -171,181 +170,157 @@ GLOBAL_VAR(bomb_set)
|
||||
removal_stage = NUKE_SEALANT_OPEN
|
||||
|
||||
/obj/machinery/nuclearbomb/attack_ghost(mob/user as mob)
|
||||
if(extended)
|
||||
attack_hand(user)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/nuclearbomb/attack_hand(mob/user as mob)
|
||||
if(extended)
|
||||
if(panel_open)
|
||||
wires.Interact(user)
|
||||
else
|
||||
ui_interact(user)
|
||||
else if(deployable)
|
||||
if(removal_stage != NUKE_MOBILE)
|
||||
anchored = 1
|
||||
visible_message("<span class='warning'>With a steely snap, bolts slide out of [src] and anchor it to the flooring!</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>\The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.</span>")
|
||||
if(!lighthack)
|
||||
flick("nuclearbombc", src)
|
||||
icon_state = "nuclearbomb1"
|
||||
extended = 1
|
||||
return
|
||||
|
||||
/obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "nuclear_bomb.tmpl", "Nuke Control Panel", 450, 550, state = GLOB.physical_state)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/nuclearbomb/ui_data(mob/user, datum/topic_state/state)
|
||||
var/data[0]
|
||||
data["is_syndicate"] = is_syndicate
|
||||
data["hacking"] = 0
|
||||
data["auth"] = is_auth(user)
|
||||
if(is_auth(user))
|
||||
if(yes_code)
|
||||
data["authstatus"] = timing ? "Functional/Set" : "Functional"
|
||||
else
|
||||
data["authstatus"] = "Auth. S2"
|
||||
if(panel_open)
|
||||
wires.Interact(user)
|
||||
else
|
||||
if(timing)
|
||||
data["authstatus"] = "Set"
|
||||
else
|
||||
data["authstatus"] = "Auth. S1"
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/nuclearbomb/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "NuclearBomb", name, 450, 300, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/nuclearbomb/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["extended"] = extended
|
||||
data["authdisk"] = is_auth(user)
|
||||
data["diskname"] = auth ? auth.name : FALSE
|
||||
data["authcode"] = yes_code
|
||||
data["authfull"] = data["authdisk"] && data["authcode"]
|
||||
data["safe"] = safety ? "Safe" : "Engaged"
|
||||
data["time"] = timeleft
|
||||
data["timer"] = timing
|
||||
data["safety"] = safety
|
||||
data["anchored"] = anchored
|
||||
data["yescode"] = yes_code
|
||||
data["message"] = "AUTH"
|
||||
if(is_auth(user))
|
||||
data["message"] = code
|
||||
if(yes_code)
|
||||
data["message"] = "*****"
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/nuclearbomb/verb/make_deployable()
|
||||
set category = "Object"
|
||||
set name = "Make Deployable"
|
||||
set src in oview(1)
|
||||
|
||||
if(usr.stat || !usr.canmove || usr.restrained())
|
||||
return
|
||||
|
||||
if(deployable)
|
||||
to_chat(usr, "<span class='warning'>You close several panels to make [src] undeployable.</span>")
|
||||
deployable = 0
|
||||
data["codemsg"] = "CLEAR CODE"
|
||||
else if(code)
|
||||
data["codemsg"] = "RE-ENTER CODE"
|
||||
else
|
||||
data["codemsg"] = "ENTER CODE"
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You adjust some panels to make [src] deployable.</span>")
|
||||
deployable = 1
|
||||
return
|
||||
data["codemsg"] = "-----"
|
||||
return data
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/is_auth(var/mob/user)
|
||||
if(auth)
|
||||
return 1
|
||||
return TRUE
|
||||
else if(user.can_admin_interact())
|
||||
return 1
|
||||
return TRUE
|
||||
else
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/nuclearbomb/Topic(href, href_list)
|
||||
/obj/machinery/nuclearbomb/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["auth"])
|
||||
if(auth)
|
||||
auth.loc = loc
|
||||
yes_code = 0
|
||||
auth = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if(istype(I, /obj/item/disk/nuclear))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
auth = I
|
||||
if(is_auth(usr))
|
||||
if(href_list["type"])
|
||||
if(href_list["type"] == "E")
|
||||
return
|
||||
. = TRUE
|
||||
if(exploded)
|
||||
return
|
||||
switch(action)
|
||||
if("deploy")
|
||||
if(removal_stage != NUKE_MOBILE)
|
||||
anchored = TRUE
|
||||
visible_message("<span class='warning'>With a steely snap, bolts slide out of [src] and anchor it to the flooring!</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>[src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.</span>")
|
||||
if(!lighthack)
|
||||
flick("nuclearbombc", src)
|
||||
icon_state = "nuclearbomb1"
|
||||
extended = TRUE
|
||||
return
|
||||
if("auth")
|
||||
if(auth)
|
||||
if(!usr.get_active_hand() && Adjacent(usr))
|
||||
usr.put_in_hands(auth)
|
||||
else
|
||||
auth.forceMove(get_turf(src))
|
||||
yes_code = FALSE
|
||||
auth = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if(istype(I, /obj/item/disk/nuclear))
|
||||
usr.drop_item()
|
||||
I.forceMove(src)
|
||||
auth = I
|
||||
return
|
||||
if(!is_auth(usr)) // All requests below here require NAD inserted.
|
||||
return FALSE
|
||||
switch(action)
|
||||
if("code")
|
||||
if(yes_code) // Clear code
|
||||
code = null
|
||||
yes_code = FALSE
|
||||
return
|
||||
// If no code set, enter new one
|
||||
var/tempcode = input(usr, "Code", "Input Code", null) as num|null
|
||||
if(tempcode)
|
||||
code = min(max(round(tempcode), 0), 999999)
|
||||
if(code == r_code)
|
||||
yes_code = 1
|
||||
yes_code = TRUE
|
||||
code = null
|
||||
else
|
||||
code = "ERROR"
|
||||
return
|
||||
|
||||
if(!yes_code) // All requests below here require both NAD inserted AND code correct
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("toggle_anchor")
|
||||
if(removal_stage == NUKE_MOBILE)
|
||||
anchored = FALSE
|
||||
visible_message("<span class='warning'>[src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.</span>")
|
||||
else if(isinspace())
|
||||
to_chat(usr, "<span class='warning'>There is nothing to anchor to!</span>")
|
||||
return FALSE
|
||||
else
|
||||
if(href_list["type"] == "R")
|
||||
yes_code = 0
|
||||
code = null
|
||||
else
|
||||
lastentered = text("[]", href_list["type"])
|
||||
if(text2num(lastentered) == null)
|
||||
var/turf/LOC = get_turf(usr)
|
||||
message_admins("[key_name_admin(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: <a href='?_src_=vars;Vars=[UID()]'>[lastentered]</a>! ([LOC ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[LOC.x];Y=[LOC.y];Z=[LOC.z]'>JMP</a>" : "null"])", 0)
|
||||
log_admin("EXPLOIT: [key_name(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: [lastentered]!")
|
||||
else
|
||||
code += lastentered
|
||||
if(length(code) > 5)
|
||||
code = "ERROR"
|
||||
if(yes_code)
|
||||
if(href_list["time"])
|
||||
var/time = text2num(href_list["time"])
|
||||
timeleft += time
|
||||
timeleft = min(max(round(src.timeleft), 120), 600)
|
||||
if(href_list["timer"])
|
||||
if(timing == -1.0)
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
if(safety)
|
||||
to_chat(usr, "<span class='warning'>The safety is still on.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
timing = !(timing)
|
||||
if(timing)
|
||||
if(!lighthack)
|
||||
icon_state = "nuclearbomb2"
|
||||
if(!safety)
|
||||
message_admins("[key_name_admin(usr)] engaged a nuclear bomb (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
if(!is_syndicate)
|
||||
set_security_level("delta")
|
||||
GLOB.bomb_set = 1 //There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke/N
|
||||
else
|
||||
GLOB.bomb_set = 0
|
||||
anchored = !(anchored)
|
||||
if(anchored)
|
||||
visible_message("<span class='warning'>With a steely snap, bolts slide out of [src] and anchor it to the flooring.</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>The anchoring bolts slide back into the depths of [src].</span>")
|
||||
return
|
||||
if("set_time")
|
||||
var/time = input(usr, "Detonation time (seconds, min 120, max 600)", "Input Time", 120) as num|null
|
||||
if(time)
|
||||
timeleft = min(max(round(time), 120), 600)
|
||||
if("toggle_safety")
|
||||
safety = !(safety)
|
||||
if(safety)
|
||||
if(!is_syndicate)
|
||||
set_security_level(previous_level)
|
||||
timing = FALSE
|
||||
GLOB.bomb_set = FALSE
|
||||
if("toggle_armed")
|
||||
if(safety)
|
||||
to_chat(usr, "<span class='notice'>The safety is still on.</span>")
|
||||
return
|
||||
timing = !(timing)
|
||||
if(timing)
|
||||
if(!lighthack)
|
||||
icon_state = "nuclearbomb2"
|
||||
if(!safety)
|
||||
message_admins("[key_name_admin(usr)] engaged a nuclear bomb [ADMIN_JMP(src)]")
|
||||
if(!is_syndicate)
|
||||
set_security_level(previous_level)
|
||||
GLOB.bomb_set = 0
|
||||
if(!lighthack)
|
||||
icon_state = "nuclearbomb1"
|
||||
if(href_list["safety"])
|
||||
safety = !(safety)
|
||||
if(safety)
|
||||
if(!is_syndicate)
|
||||
set_security_level(previous_level)
|
||||
timing = 0
|
||||
GLOB.bomb_set = 0
|
||||
if(href_list["anchor"])
|
||||
if(removal_stage == NUKE_MOBILE)
|
||||
anchored = 0
|
||||
visible_message("<span class='warning'>\The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
|
||||
if(!isinspace())
|
||||
anchored = !(anchored)
|
||||
if(anchored)
|
||||
visible_message("<span class='warning'>With a steely snap, bolts slide out of [src] and anchor it to the flooring.</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>The anchoring bolts slide back into the depths of [src].</span>")
|
||||
set_security_level("delta")
|
||||
GLOB.bomb_set = TRUE // There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>There is nothing to anchor to!</span>")
|
||||
GLOB.bomb_set = TRUE
|
||||
else
|
||||
if(!is_syndicate)
|
||||
set_security_level(previous_level)
|
||||
GLOB.bomb_set = FALSE
|
||||
if(!lighthack)
|
||||
icon_state = "nuclearbomb1"
|
||||
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
/obj/machinery/nuclearbomb/blob_act(obj/structure/blob/B)
|
||||
if(timing == -1.0)
|
||||
if(exploded)
|
||||
return
|
||||
if(timing) //boom
|
||||
INVOKE_ASYNC(src, .proc/explode)
|
||||
@@ -360,11 +335,11 @@ GLOBAL_VAR(bomb_set)
|
||||
#define NUKERANGE 80
|
||||
/obj/machinery/nuclearbomb/proc/explode()
|
||||
if(safety)
|
||||
timing = 0
|
||||
timing = FALSE
|
||||
return
|
||||
timing = -1.0
|
||||
yes_code = 0
|
||||
safety = 1
|
||||
exploded = TRUE
|
||||
yes_code = FALSE
|
||||
safety = TRUE
|
||||
if(!lighthack)
|
||||
icon_state = "nuclearbomb3"
|
||||
playsound(src,'sound/machines/alarm.ogg',100,0,5)
|
||||
|
||||
@@ -18,80 +18,56 @@
|
||||
return 0
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/glare //Stuns and mutes a human target, depending on the distance relative to the shadowling
|
||||
/obj/effect/proc_holder/spell/targeted/click/glare //Stuns and mutes a human target, depending on the distance relative to the shadowling
|
||||
name = "Glare"
|
||||
desc = "Stuns and mutes a target for a decent duration. Duration depends on the proximity to the target."
|
||||
panel = "Shadowling Abilities"
|
||||
charge_max = 300
|
||||
clothes_req = 0
|
||||
clothes_req = FALSE
|
||||
range = 10 //has no effect beyond this range, so setting this makes invalid/useless targets not show up in popup
|
||||
action_icon_state = "glare"
|
||||
humans_only = 1 //useless since we override chose_targets, but might be used for other code later??? Might remove, idk
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/glare/choose_targets(mob/user)
|
||||
var/list/possible_targets = list()
|
||||
for(var/mob/living/carbon/human/target in view_or_range(range, user, "view"))
|
||||
if(target.stat)
|
||||
continue
|
||||
if(is_shadow_or_thrall(target))
|
||||
continue
|
||||
possible_targets += target
|
||||
var/mob/living/carbon/human/M
|
||||
var/list/targets = list()
|
||||
if(possible_targets.len == 1)//no choice involved
|
||||
targets = possible_targets
|
||||
else
|
||||
M = input("Choose the target for the spell.", "Targeting") as mob in possible_targets
|
||||
if(M in view_or_range(range, user, "view"))
|
||||
targets += M
|
||||
selection_activated_message = "<span class='notice'>Your prepare to your eyes for a stunning glare! <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your eyes relax... for now.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/glare/cast_check(charge_check = TRUE, start_recharge = TRUE, mob/living/user = usr)
|
||||
if(!shadowling_check(user))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
if(!targets.len) //doesn't waste the spell
|
||||
revert_cast(user)
|
||||
/obj/effect/proc_holder/spell/targeted/click/glare/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return !target.stat && !is_shadow_or_thrall(target)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/glare/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/H = targets[1]
|
||||
|
||||
user.visible_message("<span class='warning'><b>[user]'s eyes flash a blinding red!</b></span>")
|
||||
var/distance = get_dist(H, user)
|
||||
if (distance <= 1) //Melee glare
|
||||
H.visible_message("<span class='danger'>[H] freezes in place, [H.p_their()] eyes glazing over...</span>", \
|
||||
"<span class='userdanger'>Your gaze is forcibly drawn into [user]'s eyes, and you are mesmerized by [user.p_their()] heavenly beauty...</span>")
|
||||
H.Stun(10)
|
||||
H.AdjustSilence(10)
|
||||
else //Distant glare
|
||||
var/loss = 10 - distance
|
||||
var/duration = 10 - loss
|
||||
if(loss <= 0)
|
||||
to_chat(user, "<span class='danger'>Your glare had no effect over a such long distance!</span>")
|
||||
return
|
||||
H.slowed = duration
|
||||
H.AdjustSilence(10)
|
||||
to_chat(H, "<span class='userdanger'>A red light flashes across your vision, and your mind tries to resist them.. you are exhausted.. you are not able to speak..</span>")
|
||||
addtimer(CALLBACK(src, .proc/do_stun, H, user, loss), duration SECONDS)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/glare/proc/do_stun(mob/living/carbon/human/target, user, stun_time)
|
||||
if(!istype(target) || target.stat)
|
||||
return
|
||||
|
||||
perform(targets, user = user)
|
||||
return
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/glare/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/carbon/human/target in targets)
|
||||
if(!ishuman(target))
|
||||
to_chat(user, "<span class='warning'>You may only glare at humans!</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!shadowling_check(user))
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(target.stat)
|
||||
to_chat(user, "<span class='warning'>[target] must be conscious!</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(is_shadow_or_thrall(target))
|
||||
to_chat(user, "<span class='danger'>You don't see why you would want to paralyze an ally.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
var/mob/living/carbon/human/M = target
|
||||
user.visible_message("<span class='warning'><b>[user]'s eyes flash a blinding red!</b></span>")
|
||||
var/distance = get_dist(target, user)
|
||||
if (distance <= 1) //Melee glare
|
||||
target.visible_message("<span class='danger'>[target] freezes in place, [target.p_their()] eyes glazing over...</span>")
|
||||
to_chat(target, "<span class='userdanger'>Your gaze is forcibly drawn into [user]'s eyes, and you are mesmerized by [user.p_their()] heavenly beauty...</span>")
|
||||
target.Stun(10)
|
||||
M.AdjustSilence(10)
|
||||
else //Distant glare
|
||||
var/loss = 10 - distance
|
||||
var/duration = 10 - loss
|
||||
if(loss <= 0)
|
||||
to_chat(user, "<span class='danger'>Your glare had no effect over a such long distance!</span>")
|
||||
return
|
||||
target.slowed = duration
|
||||
M.AdjustSilence(10)
|
||||
to_chat(target, "<span class='userdanger'>A red light flashes across your vision, and your mind tries to resist them.. you are exhausted.. you are not able to speak..</span>")
|
||||
sleep(duration*10)
|
||||
target.Stun(loss)
|
||||
target.visible_message("<span class='danger'>[target] freezes in place, [target.p_their()] eyes glazing over...</span>")
|
||||
to_chat(target, "<span class='userdanger'>Red lights suddenly dance in your vision, and you are mesmerized by the heavenly lights...</span>")
|
||||
target.Stun(stun_time)
|
||||
target.visible_message("<span class='danger'>[target] freezes in place, [target.p_their()] eyes glazing over...</span>",\
|
||||
"<span class='userdanger'>Red lights suddenly dance in your vision, and you are mesmerized by the heavenly lights...</span>")
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/veil
|
||||
name = "Veil"
|
||||
@@ -109,9 +85,10 @@
|
||||
return
|
||||
to_chat(user, "<span class='shadowling'>You silently disable all nearby lights.</span>")
|
||||
for(var/obj/structure/glowshroom/G in orange(2, user)) //Why the fuck was this in the loop below?
|
||||
G.visible_message("<span class='warning'>\The [G] withers away!</span>")
|
||||
G.visible_message("<span class='warning'>[G] withers away!</span>")
|
||||
qdel(G)
|
||||
for(var/turf/T in targets)
|
||||
T.extinguish_light()
|
||||
for(var/atom/A in T.contents)
|
||||
A.extinguish_light()
|
||||
|
||||
@@ -227,96 +204,80 @@
|
||||
M.reagents.add_reagent("frostoil", 15) //Half of a cryosting
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/enthrall //Turns a target into the shadowling's slave. This overrides all previous loyalties
|
||||
/obj/effect/proc_holder/spell/targeted/click/enthrall //Turns a target into the shadowling's slave. This overrides all previous loyalties
|
||||
name = "Enthrall"
|
||||
desc = "Allows you to enslave a conscious, non-braindead, non-catatonic human to your will. This takes some time to cast."
|
||||
panel = "Shadowling Abilities"
|
||||
charge_max = 0
|
||||
clothes_req = 0
|
||||
clothes_req = FALSE
|
||||
range = 1 //Adjacent to user
|
||||
var/enthralling = 0
|
||||
var/enthralling = FALSE
|
||||
action_icon_state = "enthrall"
|
||||
humans_only = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/enthrall/cast(list/targets, mob/user = usr)
|
||||
click_radius = -1 // Precision baby
|
||||
selection_activated_message = "<span class='notice'>Your prepare your mind to entrall a mortal. <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind relaxes.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/enthrall/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(enthralling || !shadowling_check(user))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/enthrall/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return target.key && target.mind && !target.stat && !is_shadow_or_thrall(target) && target.client
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/enthrall/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/ling = user
|
||||
listclearnulls(SSticker.mode.shadowling_thralls)
|
||||
if(!(ling.mind in SSticker.mode.shadows))
|
||||
return
|
||||
if(!isshadowling(ling))
|
||||
if(SSticker.mode.shadowling_thralls.len >= 5)
|
||||
charge_counter = charge_max
|
||||
return
|
||||
for(var/mob/living/carbon/human/target in targets)
|
||||
if(!in_range(user, target))
|
||||
to_chat(user, "<span class='warning'>You need to be closer to enthrall [target].</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!target.key || !target.mind)
|
||||
to_chat(user, "<span class='warning'>The target has no mind.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(target.stat)
|
||||
to_chat(user, "<span class='warning'>The target must be conscious.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(is_shadow_or_thrall(target))
|
||||
to_chat(user, "<span class='warning'>You can not enthrall allies.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!ishuman(target))
|
||||
to_chat(user, "<span class='warning'>You can only enthrall humans.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(enthralling)
|
||||
to_chat(user, "<span class='warning'>You are already enthralling!</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!target.client)
|
||||
to_chat(user, "<span class='warning'>[target]'s mind is vacant of activity.</span>")
|
||||
enthralling = 1
|
||||
to_chat(user, "<span class='danger'>This target is valid. You begin the enthralling.</span>")
|
||||
to_chat(target, "<span class='userdanger'>[user] stares at you. You feel your head begin to pulse.</span>")
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
enthralling = TRUE
|
||||
to_chat(user, "<span class='danger'>This target is valid. You begin the enthralling.</span>")
|
||||
to_chat(target, "<span class='userdanger'>[user] stares at you. You feel your head begin to pulse.</span>")
|
||||
|
||||
for(var/progress = 0, progress <= 3, progress++)
|
||||
switch(progress)
|
||||
if(1)
|
||||
to_chat(user, "<span class='notice'>You place your hands to [target]'s head...</span>")
|
||||
user.visible_message("<span class='warning'>[user] places [user.p_their()] hands onto the sides of [target]'s head!</span>")
|
||||
if(2)
|
||||
to_chat(user, "<span class='notice'>You begin preparing [target]'s mind as a blank slate...</span>")
|
||||
user.visible_message("<span class='warning'>[user]'s palms flare a bright red against [target]'s temples!</span>")
|
||||
to_chat(target, "<span class='danger'>A terrible red light floods your mind. You collapse as conscious thought is wiped away.</span>")
|
||||
target.Weaken(12)
|
||||
sleep(20)
|
||||
if(ismindshielded(target))
|
||||
to_chat(user, "<span class='notice'>They have a mindshield implant. You begin to deactivate it - this will take some time.</span>")
|
||||
user.visible_message("<span class='warning'>[user] pauses, then dips [user.p_their()] head in concentration!</span>")
|
||||
to_chat(target, "<span class='boldannounce'>Your mindshield implant becomes hot as it comes under attack!</span>")
|
||||
sleep(100) //10 seconds - not spawn() so the enthralling takes longer
|
||||
to_chat(user, "<span class='notice'>The nanobots composing the mindshield implant have been rendered inert. Now to continue.</span>")
|
||||
user.visible_message("<span class='warning'>[user] relaxes again.</span>")
|
||||
for(var/obj/item/implant/mindshield/L in target)
|
||||
if(L && L.implanted)
|
||||
qdel(L)
|
||||
to_chat(target, "<span class='boldannounce'>Your mental protection implant unexpectedly falters, dims, dies.</span>")
|
||||
if(3)
|
||||
to_chat(user, "<span class='notice'>You begin planting the tumor that will control the new thrall...</span>")
|
||||
user.visible_message("<span class='warning'>A strange energy passes from [user]'s hands into [target]'s head!</span>")
|
||||
to_chat(target, "<span class='boldannounce'>You feel your memories twisting, morphing. A sense of horror dominates your mind.</span>")
|
||||
if(!do_mob(user, target, 70)) //around 21 seconds total for enthralling, 31 for someone with a mindshield implant
|
||||
to_chat(user, "<span class='warning'>The enthralling has been interrupted - your target's mind returns to its previous state.</span>")
|
||||
to_chat(target, "<span class='userdanger'>You wrest yourself away from [user]'s hands and compose yourself</span>")
|
||||
enthralling = 0
|
||||
return
|
||||
for(var/progress = 0, progress <= 3, progress++)
|
||||
switch(progress)
|
||||
if(1)
|
||||
to_chat(user, "<span class='notice'>You place your hands to [target]'s head...</span>")
|
||||
user.visible_message("<span class='warning'>[user] places [user.p_their()] hands onto the sides of [target]'s head!</span>")
|
||||
if(2)
|
||||
to_chat(user, "<span class='notice'>You begin preparing [target]'s mind as a blank slate...</span>")
|
||||
user.visible_message("<span class='warning'>[user]'s palms flare a bright red against [target]'s temples!</span>")
|
||||
to_chat(target, "<span class='danger'>A terrible red light floods your mind. You collapse as conscious thought is wiped away.</span>")
|
||||
target.Weaken(12)
|
||||
sleep(20)
|
||||
if(ismindshielded(target))
|
||||
to_chat(user, "<span class='notice'>They have a mindshield implant. You begin to deactivate it - this will take some time.</span>")
|
||||
user.visible_message("<span class='warning'>[user] pauses, then dips [user.p_their()] head in concentration!</span>")
|
||||
to_chat(target, "<span class='boldannounce'>Your mindshield implant becomes hot as it comes under attack!</span>")
|
||||
sleep(100) //10 seconds - not spawn() so the enthralling takes longer
|
||||
to_chat(user, "<span class='notice'>The nanobots composing the mindshield implant have been rendered inert. Now to continue.</span>")
|
||||
user.visible_message("<span class='warning'>[user] relaxes again.</span>")
|
||||
for(var/obj/item/implant/mindshield/L in target)
|
||||
if(L && L.implanted)
|
||||
qdel(L)
|
||||
to_chat(target, "<span class='boldannounce'>Your mental protection implant unexpectedly falters, dims, dies.</span>")
|
||||
if(3)
|
||||
to_chat(user, "<span class='notice'>You begin planting the tumor that will control the new thrall...</span>")
|
||||
user.visible_message("<span class='warning'>A strange energy passes from [user]'s hands into [target]'s head!</span>")
|
||||
to_chat(target, "<span class='boldannounce'>You feel your memories twisting, morphing. A sense of horror dominates your mind.</span>")
|
||||
if(!do_mob(user, target, 70)) //around 21 seconds total for enthralling, 31 for someone with a mindshield implant
|
||||
to_chat(user, "<span class='warning'>The enthralling has been interrupted - your target's mind returns to its previous state.</span>")
|
||||
to_chat(target, "<span class='userdanger'>You wrest yourself away from [user]'s hands and compose yourself</span>")
|
||||
enthralling = FALSE
|
||||
return
|
||||
|
||||
enthralling = 0
|
||||
to_chat(user, "<span class='shadowling'>You have enthralled <b>[target]</b>!</span>")
|
||||
target.visible_message("<span class='big'>[target] looks to have experienced a revelation!</span>", \
|
||||
"<span class='warning'>False faces all d<b>ark not real not real not--</b></span>")
|
||||
target.setOxyLoss(0) //In case the shadowling was choking them out
|
||||
SSticker.mode.add_thrall(target.mind)
|
||||
target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL
|
||||
enthralling = FALSE
|
||||
to_chat(user, "<span class='shadowling'>You have enthralled <b>[target]</b>!</span>")
|
||||
target.visible_message("<span class='big'>[target] looks to have experienced a revelation!</span>", \
|
||||
"<span class='warning'>False faces all d<b>ark not real not real not--</b></span>")
|
||||
target.setOxyLoss(0) //In case the shadowling was choking them out
|
||||
SSticker.mode.add_thrall(target.mind)
|
||||
target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shadowling_regenarmor //Resets a shadowling's species to normal, removes genetic defects, and re-equips their armor
|
||||
name = "Rapid Re-Hatch"
|
||||
@@ -404,7 +365,7 @@
|
||||
reviveThrallAcquired = 1
|
||||
to_chat(target, "<span class='shadowling'><i>The power of your thralls has granted you the <b>Black Recuperation</b> ability. \
|
||||
This will, after a short time, bring a dead thrall completely back to life with no bodily defects.</i></span>")
|
||||
target.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/reviveThrall(null))
|
||||
target.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/reviveThrall(null))
|
||||
|
||||
if(thralls < victory_threshold)
|
||||
to_chat(target, "<span class='shadowling'>You do not have the power to ascend. You require [victory_threshold] thralls, but only [thralls] living thralls are present.</span>")
|
||||
@@ -570,169 +531,170 @@
|
||||
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/reviveThrall
|
||||
/obj/effect/proc_holder/spell/targeted/click/reviveThrall
|
||||
name = "Black Recuperation"
|
||||
desc = "Revives or empowers a thrall."
|
||||
panel = "Shadowling Abilities"
|
||||
range = 1
|
||||
charge_max = 600
|
||||
clothes_req = 0
|
||||
include_user = 0
|
||||
clothes_req = FALSE
|
||||
include_user = FALSE
|
||||
action_icon_state = "revive_thrall"
|
||||
humans_only = 1
|
||||
click_radius = -1 // Precision baby
|
||||
selection_activated_message = "<span class='notice'>You start focusing your powers on mending wounds of allies. <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind relaxes.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/reviveThrall/cast(list/targets, mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/click/reviveThrall/can_cast(mob/user = usr)
|
||||
if(!shadowling_check(user))
|
||||
charge_counter = charge_max
|
||||
return
|
||||
for(var/mob/living/carbon/human/thrallToRevive in targets)
|
||||
var/choice = alert(user,"Empower a living thrall or revive a dead one?",,"Empower","Revive","Cancel")
|
||||
switch(choice)
|
||||
if("Empower")
|
||||
if(!is_thrall(thrallToRevive))
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] is not a thrall.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(thrallToRevive.stat != CONSCIOUS)
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] must be conscious to become empowered.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(isshadowlinglesser(thrallToRevive))
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] is already empowered.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
var/empowered_thralls = 0
|
||||
for(var/datum/mind/M in SSticker.mode.shadowling_thralls)
|
||||
if(!ishuman(M.current))
|
||||
return
|
||||
var/mob/living/carbon/human/H = M.current
|
||||
if(isshadowlinglesser(H))
|
||||
empowered_thralls++
|
||||
if(empowered_thralls >= EMPOWERED_THRALL_LIMIT)
|
||||
to_chat(user, "<span class='warning'>You cannot spare this much energy. There are too many empowered thralls.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
user.visible_message("<span class='danger'>[user] places [user.p_their()] hands over [thrallToRevive]'s face, red light shining from beneath.</span>", \
|
||||
"<span class='shadowling'>You place your hands on [thrallToRevive]'s face and begin gathering energy...</span>")
|
||||
to_chat(thrallToRevive, "<span class='userdanger'>[user] places [user.p_their()] hands over your face. You feel energy gathering. Stand still...</span>")
|
||||
if(!do_mob(user, thrallToRevive, 80))
|
||||
to_chat(user, "<span class='warning'>Your concentration snaps. The flow of energy ebbs.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
to_chat(user, "<span class='shadowling'><b><i>You release a massive surge of power into [thrallToRevive]!</b></i></span>")
|
||||
user.visible_message("<span class='boldannounce'><i>Red lightning surges into [thrallToRevive]'s face!</i></span>")
|
||||
playsound(thrallToRevive, 'sound/weapons/egloves.ogg', 50, 1)
|
||||
playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
|
||||
user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
|
||||
thrallToRevive.Weaken(5)
|
||||
thrallToRevive.visible_message("<span class='warning'><b>[thrallToRevive] collapses, [thrallToRevive.p_their()] skin and face distorting!</span>", \
|
||||
"<span class='userdanger'><i>AAAAAAAAAAAAAAAAAAAGH-</i></span>")
|
||||
sleep(20)
|
||||
thrallToRevive.visible_message("<span class='warning'>[thrallToRevive] slowly rises, no longer recognizable as human.</span>", \
|
||||
"<span class='shadowling'><b>You feel new power flow into you. You have been gifted by your masters. You now closely resemble them. You are empowered in \
|
||||
darkness but wither slowly in light. In addition, you now have glare and true shadow walk.</b></span>")
|
||||
thrallToRevive.set_species(/datum/species/shadow/ling/lesser)
|
||||
thrallToRevive.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk)
|
||||
thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare(null))
|
||||
thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk(null))
|
||||
if("Revive")
|
||||
if(!is_thrall(thrallToRevive))
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] is not a thrall.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(thrallToRevive.stat != DEAD)
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] is not dead.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
user.visible_message("<span class='danger'>[user] kneels over [thrallToRevive], placing [user.p_their()] hands on [thrallToRevive.p_their()] chest.</span>", \
|
||||
"<span class='shadowling'>You crouch over the body of your thrall and begin gathering energy...</span>")
|
||||
thrallToRevive.notify_ghost_cloning("Your masters are resuscitating you! Re-enter your corpse if you wish to be brought to life.", source = thrallToRevive)
|
||||
if(!do_mob(user, thrallToRevive, 30))
|
||||
to_chat(user, "<span class='warning'>Your concentration snaps. The flow of energy ebbs.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
to_chat(user, "<span class='shadowling'><b><i>You release a massive surge of power into [thrallToRevive]!</b></i></span>")
|
||||
user.visible_message("<span class='boldannounce'><i>Red lightning surges from [user]'s hands into [thrallToRevive]'s chest!</i></span>")
|
||||
playsound(thrallToRevive, 'sound/weapons/egloves.ogg', 50, 1)
|
||||
playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
|
||||
user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
|
||||
sleep(10)
|
||||
if(thrallToRevive.revive())
|
||||
thrallToRevive.visible_message("<span class='boldannounce'>[thrallToRevive] heaves in breath, dim red light shining in [thrallToRevive.p_their()] eyes.</span>", \
|
||||
"<span class='shadowling'><b><i>You have returned. One of your masters has brought you from the darkness beyond.</b></i></span>")
|
||||
thrallToRevive.Weaken(4)
|
||||
thrallToRevive.emote("gasp")
|
||||
playsound(thrallToRevive, "bodyfall", 50, 1)
|
||||
else
|
||||
charge_counter = charge_max
|
||||
return
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle
|
||||
/obj/effect/proc_holder/spell/targeted/click/reviveThrall/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
return is_thrall(target)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/reviveThrall/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/thrallToRevive = targets[1]
|
||||
if(thrallToRevive.stat == CONSCIOUS)
|
||||
if(isshadowlinglesser(thrallToRevive))
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] is already empowered.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
var/empowered_thralls = 0
|
||||
for(var/datum/mind/M in SSticker.mode.shadowling_thralls)
|
||||
if(!ishuman(M.current))
|
||||
return
|
||||
var/mob/living/carbon/human/H = M.current
|
||||
if(isshadowlinglesser(H))
|
||||
empowered_thralls++
|
||||
if(empowered_thralls >= EMPOWERED_THRALL_LIMIT)
|
||||
to_chat(user, "<span class='warning'>You cannot spare this much energy. There are too many empowered thralls.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
user.visible_message("<span class='danger'>[user] places [user.p_their()] hands over [thrallToRevive]'s face, red light shining from beneath.</span>", \
|
||||
"<span class='shadowling'>You place your hands on [thrallToRevive]'s face and begin gathering energy...</span>")
|
||||
to_chat(thrallToRevive, "<span class='userdanger'>[user] places [user.p_their()] hands over your face. You feel energy gathering. Stand still...</span>")
|
||||
if(!do_mob(user, thrallToRevive, 80))
|
||||
to_chat(user, "<span class='warning'>Your concentration snaps. The flow of energy ebbs.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
to_chat(user, "<span class='shadowling'><b><i>You release a massive surge of power into [thrallToRevive]!</b></i></span>")
|
||||
user.visible_message("<span class='boldannounce'><i>Red lightning surges into [thrallToRevive]'s face!</i></span>")
|
||||
playsound(thrallToRevive, 'sound/weapons/egloves.ogg', 50, 1)
|
||||
playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
|
||||
user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
|
||||
thrallToRevive.Weaken(5)
|
||||
thrallToRevive.visible_message("<span class='warning'><b>[thrallToRevive] collapses, [thrallToRevive.p_their()] skin and face distorting!</span>", \
|
||||
"<span class='userdanger'><i>AAAAAAAAAAAAAAAAAAAGH-</i></span>")
|
||||
sleep(20)
|
||||
thrallToRevive.visible_message("<span class='warning'>[thrallToRevive] slowly rises, no longer recognizable as human.</span>", \
|
||||
"<span class='shadowling'><b>You feel new power flow into you. You have been gifted by your masters. You now closely resemble them. You are empowered in \
|
||||
darkness but wither slowly in light. In addition, you now have glare and true shadow walk.</b></span>")
|
||||
thrallToRevive.set_species(/datum/species/shadow/ling/lesser)
|
||||
thrallToRevive.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk)
|
||||
thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/glare(null))
|
||||
thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk(null))
|
||||
else if(thrallToRevive.stat == DEAD)
|
||||
user.visible_message("<span class='danger'>[user] kneels over [thrallToRevive], placing [user.p_their()] hands on [thrallToRevive.p_their()] chest.</span>", \
|
||||
"<span class='shadowling'>You crouch over the body of your thrall and begin gathering energy...</span>")
|
||||
thrallToRevive.notify_ghost_cloning("Your masters are resuscitating you! Re-enter your corpse if you wish to be brought to life.", source = thrallToRevive)
|
||||
if(!do_mob(user, thrallToRevive, 30))
|
||||
to_chat(user, "<span class='warning'>Your concentration snaps. The flow of energy ebbs.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
to_chat(user, "<span class='shadowling'><b><i>You release a massive surge of power into [thrallToRevive]!</b></i></span>")
|
||||
user.visible_message("<span class='boldannounce'><i>Red lightning surges from [user]'s hands into [thrallToRevive]'s chest!</i></span>")
|
||||
playsound(thrallToRevive, 'sound/weapons/egloves.ogg', 50, 1)
|
||||
playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
|
||||
user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
|
||||
sleep(10)
|
||||
if(thrallToRevive.revive())
|
||||
thrallToRevive.visible_message("<span class='boldannounce'>[thrallToRevive] heaves in breath, dim red light shining in [thrallToRevive.p_their()] eyes.</span>", \
|
||||
"<span class='shadowling'><b><i>You have returned. One of your masters has brought you from the darkness beyond.</b></i></span>")
|
||||
thrallToRevive.Weaken(4)
|
||||
thrallToRevive.emote("gasp")
|
||||
playsound(thrallToRevive, "bodyfall", 50, 1)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The target must be awake to empower or dead to revive.</span>")
|
||||
revert_cast(user)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/shadowling_extend_shuttle
|
||||
name = "Destroy Engines"
|
||||
desc = "Extends the time of the emergency shuttle's arrival by ten minutes using a life force of our enemy. Shuttle will be unable to be recalled. This can only be used once."
|
||||
panel = "Shadowling Abilities"
|
||||
range = 1
|
||||
clothes_req = 0
|
||||
clothes_req = FALSE
|
||||
charge_max = 600
|
||||
click_radius = -1 // Precision baby
|
||||
selection_activated_message = "<span class='notice'>You start gathering destructive powers to delay the shuttle. <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind relaxes.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
action_icon_state = "extend_shuttle"
|
||||
var/global/extendlimit = 0
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle/cast(list/targets, mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/click/shadowling_extend_shuttle/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(!shadowling_check(user))
|
||||
charge_counter = charge_max
|
||||
return
|
||||
return FALSE
|
||||
if(extendlimit == 1)
|
||||
to_chat(user, "<span class='warning'>Shuttle was already delayed.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
for(var/mob/living/carbon/human/target in targets)
|
||||
if(target.stat)
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(is_shadow_or_thrall(target))
|
||||
to_chat(user, "<span class='warning'>[target] must not be an ally.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_CALL)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='warning'>Shuttle was already delayed.</span>")
|
||||
return FALSE
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_CALL)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='warning'>The shuttle must be inbound only to the station.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
var/mob/living/carbon/human/M = target
|
||||
user.visible_message("<span class='warning'>[user]'s eyes flash a bright red!</span>", \
|
||||
"<span class='notice'>You begin to draw [M]'s life force.</span>")
|
||||
M.visible_message("<span class='warning'>[M]'s face falls slack, [M.p_their()] jaw slightly distending.</span>", \
|
||||
"<span class='boldannounce'>You are suddenly transported... far, far away...</span>")
|
||||
extendlimit = 1
|
||||
if(!do_after(user, 150, target = M))
|
||||
extendlimit = 0
|
||||
to_chat(M, "<span class='warning'>You are snapped back to reality, your haze dissipating!</span>")
|
||||
to_chat(user, "<span class='warning'>You have been interrupted. The draw has failed.</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You project [M]'s life force toward the approaching shuttle, extending its arrival duration!</span>")
|
||||
M.visible_message("<span class='warning'>[M]'s eyes suddenly flare red. They proceed to collapse on the floor, not breathing.</span>", \
|
||||
"<span class='warning'><b>...speeding by... ...pretty blue glow... ...touch it... ...no glow now... ...no light... ...nothing at all...</span>")
|
||||
M.death()
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
|
||||
var/more_minutes = 6000
|
||||
var/timer = SSshuttle.emergency.timeLeft(1) + more_minutes
|
||||
GLOB.event_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 10 minutes and the shuttle is unable to be recalled.", "System Failure", 'sound/misc/notice1.ogg')
|
||||
SSshuttle.emergency.setTimer(timer)
|
||||
SSshuttle.emergency.canRecall = FALSE
|
||||
user.mind.spell_list.Remove(src) //Can only be used once!
|
||||
qdel(src)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/shadowling_extend_shuttle/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return !target.stat && !is_shadow_or_thrall(target)
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/shadowling_extend_shuttle/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
|
||||
user.visible_message("<span class='warning'>[user]'s eyes flash a bright red!</span>", \
|
||||
"<span class='notice'>You begin to draw [target]'s life force.</span>")
|
||||
target.visible_message("<span class='warning'>[target]'s face falls slack, [target.p_their()] jaw slightly distending.</span>", \
|
||||
"<span class='boldannounce'>You are suddenly transported... far, far away...</span>")
|
||||
extendlimit = 1
|
||||
if(!do_after(user, 150, target = target))
|
||||
extendlimit = 0
|
||||
to_chat(target, "<span class='warning'>You are snapped back to reality, your haze dissipating!</span>")
|
||||
to_chat(user, "<span class='warning'>You have been interrupted. The draw has failed.</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You project [target]'s life force toward the approaching shuttle, extending its arrival duration!</span>")
|
||||
target.visible_message("<span class='warning'>[target]'s eyes suddenly flare red. They proceed to collapse on the floor, not breathing.</span>", \
|
||||
"<span class='warning'><b>...speeding by... ...pretty blue glow... ...touch it... ...no glow now... ...no light... ...nothing at all...</span>")
|
||||
target.death()
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
|
||||
var/more_minutes = 6000
|
||||
var/timer = SSshuttle.emergency.timeLeft(1) + more_minutes
|
||||
GLOB.event_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 10 minutes and the shuttle is unable to be recalled.", "System Failure", 'sound/misc/notice1.ogg')
|
||||
SSshuttle.emergency.setTimer(timer)
|
||||
SSshuttle.emergency.canRecall = FALSE
|
||||
user.mind.spell_list.Remove(src) //Can only be used once!
|
||||
qdel(src)
|
||||
|
||||
// ASCENDANT ABILITIES BEYOND THIS POINT //
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/annihilate
|
||||
/obj/effect/proc_holder/spell/targeted/click/annihilate
|
||||
name = "Annihilate"
|
||||
desc = "Gibs someone instantly."
|
||||
panel = "Ascendant"
|
||||
range = 7
|
||||
charge_max = 0
|
||||
clothes_req = 0
|
||||
charge_max = FALSE
|
||||
clothes_req = FALSE
|
||||
action_icon_state = "annihilate"
|
||||
selection_activated_message = "<span class='notice'>You start thinking about gibs. <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind relaxes.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/annihilate/cast(list/targets, mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/click/annihilate/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/simple_animal/ascendant_shadowling/SHA = user
|
||||
if(SHA.phasing)
|
||||
to_chat(user, "<span class='warning'>You are not in the same plane of existence. Unphase first.</span>")
|
||||
@@ -755,45 +717,42 @@
|
||||
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/hypnosis
|
||||
/obj/effect/proc_holder/spell/targeted/click/hypnosis
|
||||
name = "Hypnosis"
|
||||
desc = "Instantly enthralls a human."
|
||||
panel = "Ascendant"
|
||||
range = 7
|
||||
charge_max = 0
|
||||
clothes_req = 0
|
||||
charge_max = FALSE
|
||||
clothes_req = FALSE
|
||||
action_icon_state = "enthrall"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/hypnosis/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/simple_animal/ascendant_shadowling/SHA = user
|
||||
if(SHA.phasing)
|
||||
charge_counter = charge_max
|
||||
to_chat(user, "<span class='warning'>You are not in the same plane of existence. Unphase first.</span>")
|
||||
return
|
||||
click_radius = -1
|
||||
selection_activated_message = "<span class='notice'>You start preparing to mindwash over a mortal mind. <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind relaxes.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
for(var/mob/living/carbon/human/target in targets)
|
||||
if(is_shadow_or_thrall(target))
|
||||
to_chat(user, "<span class='warning'>You cannot enthrall an ally.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!target.ckey || !target.mind)
|
||||
to_chat(user, "<span class='warning'>The target has no mind.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(target.stat)
|
||||
to_chat(user, "<span class='warning'>The target must be conscious.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!ishuman(target))
|
||||
to_chat(user, "<span class='warning'>You can only enthrall humans.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
/obj/effect/proc_holder/spell/targeted/click/hypnosis/can_cast(mob/living/simple_animal/ascendant_shadowling/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
if(user.phasing)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='warning'>You are not in the same plane of existence. Unphase first.</span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
to_chat(user, "<span class='shadowling'>You instantly rearrange <b>[target]</b>'s memories, hyptonitizing [target.p_them()] into a thrall.</span>")
|
||||
to_chat(target, "<span class='userdanger'><font size=3>An agonizing spike of pain drives into your mind, and--</font></span>")
|
||||
SSticker.mode.add_thrall(target.mind)
|
||||
target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL
|
||||
target.add_language("Shadowling Hivemind")
|
||||
/obj/effect/proc_holder/spell/targeted/click/hypnosis/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return !is_shadow_or_thrall(target) && target.ckey && target.mind && !target.stat
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/hypnosis/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
|
||||
to_chat(user, "<span class='shadowling'>You instantly rearrange <b>[target]</b>'s memories, hyptonitizing [target.p_them()] into a thrall.</span>")
|
||||
to_chat(target, "<span class='userdanger'><font size=3>An agonizing spike of pain drives into your mind, and--</font></span>")
|
||||
SSticker.mode.add_thrall(target.mind)
|
||||
target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL
|
||||
target.add_language("Shadowling Hivemind")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -99,14 +99,14 @@ GLOBAL_LIST_INIT(possibleShadowlingNames, list("U'ruan", "Y`shej", "Nex", "Hel-u
|
||||
to_chat(H, "<span class='shadowling'><b><i>Your powers are awoken. You may now live to your fullest extent. Remember your goal. Cooperate with your thralls and allies.</b></i></span>")
|
||||
H.ExtinguishMob()
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_vision(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/enthrall(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/enthrall(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/glare(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/veil(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/collective_mind(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_regenarmor(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/shadowling_extend_shuttle(null))
|
||||
|
||||
QDEL_NULL(H.hud_used)
|
||||
H.hud_used = new /datum/hud/human(H, ui_style2icon(H.client.prefs.UI_style), H.client.prefs.UI_style_color, H.client.prefs.UI_style_alpha)
|
||||
@@ -163,7 +163,7 @@ GLOBAL_LIST_INIT(possibleShadowlingNames, list("U'ruan", "Y`shej", "Nex", "Hel-u
|
||||
to_chat(M, "<span class='userdanger'>An immense pressure slams you onto the ground!</span>")
|
||||
for(var/thing in GLOB.apcs)
|
||||
var/obj/machinery/power/apc/A = thing
|
||||
A.overload_lighting()
|
||||
INVOKE_ASYNC(A, /obj/machinery/power/apc.proc/overload_lighting)
|
||||
var/mob/living/simple_animal/ascendant_shadowling/A = new /mob/living/simple_animal/ascendant_shadowling(H.loc)
|
||||
A.announce("VYSHA NERADA YEKHEZET U'RUU!!", 5, 'sound/hallucinations/veryfar_noise.ogg')
|
||||
for(var/obj/effect/proc_holder/spell/S in H.mind.spell_list)
|
||||
@@ -172,8 +172,8 @@ GLOBAL_LIST_INIT(possibleShadowlingNames, list("U'ruan", "Y`shej", "Nex", "Hel-u
|
||||
H.mind.transfer_to(A)
|
||||
A.name = H.real_name
|
||||
A.languages = H.languages
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/annihilate(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/hypnosis(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/annihilate(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/hypnosis(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_phase_shift(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/ascendant_storm(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowlingAscendantTransmit(null))
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
typepath = /obj/item/aicard
|
||||
location_override = "AI Satellite. An intellicard for transportation can be found in Tech Storage, Science Department or manufactured"
|
||||
|
||||
datum/theft_objective/ai/check_special_completion(var/obj/item/aicard/C)
|
||||
/datum/theft_objective/ai/check_special_completion(var/obj/item/aicard/C)
|
||||
if(..())
|
||||
for(var/mob/living/silicon/ai/A in C)
|
||||
if(istype(A, /mob/living/silicon/ai) && A.stat != 2) //See if any AI's are alive inside that card.
|
||||
|
||||
@@ -82,22 +82,10 @@
|
||||
|
||||
/datum/game_mode/proc/auto_declare_completion_traitor()
|
||||
if(traitors.len)
|
||||
var/text = "<FONT size = 2><B>The traitors were:</B></FONT>"
|
||||
var/text = "<FONT size = 2><B>The traitors were:</B></FONT><br>"
|
||||
for(var/datum/mind/traitor in traitors)
|
||||
var/traitorwin = 1
|
||||
|
||||
text += "<br>[traitor.key] was [traitor.name] ("
|
||||
if(traitor.current)
|
||||
if(traitor.current.stat == DEAD)
|
||||
text += "died"
|
||||
else
|
||||
text += "survived"
|
||||
if(traitor.current.real_name != traitor.name)
|
||||
text += " as [traitor.current.real_name]"
|
||||
else
|
||||
text += "body destroyed"
|
||||
text += ")"
|
||||
|
||||
text += printplayer(traitor)
|
||||
|
||||
var/TC_uses = 0
|
||||
var/uplink_true = 0
|
||||
@@ -131,12 +119,20 @@
|
||||
|
||||
|
||||
if(traitorwin)
|
||||
text += "<br><font color='green'><B>The [special_role_text] was successful!</B></font>"
|
||||
text += "<br><font color='green'><B>The [special_role_text] was successful!</B></font><br>"
|
||||
feedback_add_details("traitor_success","SUCCESS")
|
||||
else
|
||||
text += "<br><font color='red'><B>The [special_role_text] has failed!</B></font>"
|
||||
text += "<br><font color='red'><B>The [special_role_text] has failed!</B></font><br>"
|
||||
feedback_add_details("traitor_success","FAIL")
|
||||
|
||||
if(length(SSticker.mode.implanted))
|
||||
text += "<br><br><FONT size = 2><B>The mindslaves were:</B></FONT><br>"
|
||||
for(var/datum/mind/mindslave in SSticker.mode.implanted)
|
||||
text += printplayer(mindslave)
|
||||
var/datum/mind/master_mind = SSticker.mode.implanted[mindslave]
|
||||
var/mob/living/carbon/human/master = master_mind.current
|
||||
text += " (slaved by: <b>[master]</b>)<br>"
|
||||
|
||||
var/phrases = jointext(GLOB.syndicate_code_phrase, ", ")
|
||||
var/responses = jointext(GLOB.syndicate_code_response, ", ")
|
||||
|
||||
|
||||
@@ -279,6 +279,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
|
||||
var/blood = 0
|
||||
var/old_bloodtotal = 0 //used to see if we increased our blood total
|
||||
var/old_bloodusable = 0 //used to see if we increased our blood usable
|
||||
var/blood_volume_warning = 9999 //Blood volume threshold for warnings
|
||||
if(owner.is_muzzled())
|
||||
to_chat(owner, "<span class='warning'>[owner.wear_mask] prevents you from biting [H]!</span>")
|
||||
draining = null
|
||||
@@ -291,13 +292,10 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
|
||||
H.LAssailant = owner
|
||||
while(do_mob(owner, H, 50))
|
||||
if(!(owner.mind in SSticker.mode.vampires))
|
||||
to_chat(owner, "<span class='warning'>Your fangs have disappeared!</span>")
|
||||
to_chat(owner, "<span class='userdanger'>Your fangs have disappeared!</span>")
|
||||
return
|
||||
old_bloodtotal = bloodtotal
|
||||
old_bloodusable = bloodusable
|
||||
if(!H.blood_volume)
|
||||
to_chat(owner, "<span class='warning'>They've got no blood left to give.</span>")
|
||||
break
|
||||
if(H.stat < DEAD)
|
||||
if(H.ckey || H.player_ghosted) //Requires ckey regardless if monkey or humanoid, or the body has been ghosted before it died
|
||||
blood = min(20, H.blood_volume) // if they have less than 20 blood, give them the remnant else they get 20 blood
|
||||
@@ -312,6 +310,17 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
|
||||
to_chat(owner, "<span class='notice'><b>You have accumulated [bloodtotal] [bloodtotal > 1 ? "units" : "unit"] of blood[bloodusable != old_bloodusable ? ", and have [bloodusable] left to use" : ""].</b></span>")
|
||||
check_vampire_upgrade()
|
||||
H.blood_volume = max(H.blood_volume - 25, 0)
|
||||
//Blood level warnings (Code 'borrowed' from Fulp)
|
||||
if(H.blood_volume)
|
||||
if(H.blood_volume <= BLOOD_VOLUME_BAD && blood_volume_warning > BLOOD_VOLUME_BAD)
|
||||
to_chat(owner, "<span class='danger'>Your victim's blood volume is dangerously low.</span>")
|
||||
else if(H.blood_volume <= BLOOD_VOLUME_OKAY && blood_volume_warning > BLOOD_VOLUME_OKAY)
|
||||
to_chat(owner, "<span class='warning'>Your victim's blood is at an unsafe level.</span>")
|
||||
blood_volume_warning = H.blood_volume //Set to blood volume, so that you only get the message once
|
||||
else
|
||||
to_chat(owner, "<span class='warning'>You have bled your victim dry!</span>")
|
||||
break
|
||||
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/V = owner
|
||||
if(!H.ckey && !H.player_ghosted)//Only runs if there is no ckey and the body has not being ghosted while alive
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
if(!gain_desc)
|
||||
gain_desc = "You have gained \the [src] ability."
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/cast_check(skipcharge = 0, mob/living/user = usr)
|
||||
/obj/effect/proc_holder/spell/vampire/cast_check(charge_check = TRUE, start_recharge = TRUE, mob/living/user = usr)
|
||||
if(!user.mind)
|
||||
return 0
|
||||
if(!ishuman(user))
|
||||
@@ -45,7 +45,7 @@
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/can_cast(mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/vampire/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(!user.mind)
|
||||
return 0
|
||||
if(!ishuman(user))
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
switch(href_list["school"])
|
||||
if("destruction")
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(null))
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/fireball(null))
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/fireball(null))
|
||||
to_chat(M, "<B>Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned powerful, destructive spells. You are able to cast magic missile and fireball.")
|
||||
if("bluespace")
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null))
|
||||
@@ -74,7 +74,7 @@
|
||||
to_chat(M, "<B>Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall.")
|
||||
if("robeless")
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null))
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mind_transfer(null))
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/mind_transfer(null))
|
||||
to_chat(M, "<B>Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap.")
|
||||
|
||||
M.equip_to_slot_or_del(new /obj/item/radio/headset(M), slot_l_ear)
|
||||
@@ -836,6 +836,10 @@ GLOBAL_LIST_EMPTY(multiverse)
|
||||
var/wgw = sanitize(input(user, "What would you like the victim to say", "Voodoo", null) as text)
|
||||
target.say(wgw)
|
||||
log_game("[user][user.key] made [target][target.key] say [wgw] with a voodoo doll.")
|
||||
log_say("Wicker doll say to [target][target.key]: [wgw]", user)
|
||||
log_admin("[user][user.key] made [target][target.key] say [wgw] with a voodoo doll.")
|
||||
user.create_log(SAY_LOG, "forced [target] to say [wgw] through [src].", target)
|
||||
target.create_log(SAY_LOG, "was forced to say [wgw] through [src] by [user].", user)
|
||||
if("eyes")
|
||||
user.set_machine(src)
|
||||
user.reset_perspective(target)
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
/datum/spellbook_entry/horseman
|
||||
name = "Curse of the Horseman"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/horsemask
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/click/horsemask
|
||||
log_name = "HH"
|
||||
category = "Offensive"
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
|
||||
/datum/spellbook_entry/fireball
|
||||
name = "Fireball"
|
||||
spell_type = /obj/effect/proc_holder/spell/fireball
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/click/fireball
|
||||
log_name = "FB"
|
||||
category = "Offensive"
|
||||
|
||||
@@ -257,7 +257,7 @@
|
||||
|
||||
/datum/spellbook_entry/mindswap
|
||||
name = "Mindswap"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/click/mind_transfer
|
||||
log_name = "MT"
|
||||
category = "Mobility"
|
||||
|
||||
@@ -877,7 +877,7 @@
|
||||
return
|
||||
|
||||
/obj/item/spellbook/oneuse/fireball
|
||||
spell = /obj/effect/proc_holder/spell/fireball
|
||||
spell = /obj/effect/proc_holder/spell/targeted/click/fireball
|
||||
spellname = "fireball"
|
||||
icon_state = "bookfireball"
|
||||
desc = "This book feels warm to the touch."
|
||||
@@ -910,7 +910,7 @@
|
||||
user.EyeBlind(10)
|
||||
|
||||
/obj/item/spellbook/oneuse/mindswap
|
||||
spell = /obj/effect/proc_holder/spell/targeted/mind_transfer
|
||||
spell = /obj/effect/proc_holder/spell/targeted/click/mind_transfer
|
||||
spellname = "mindswap"
|
||||
icon_state = "bookmindswap"
|
||||
desc = "This book's cover is pristine, though its pages look ragged and torn."
|
||||
@@ -934,8 +934,8 @@
|
||||
to_chat(user, "<span class='notice'>You stare at the book some more, but there doesn't seem to be anything else to learn...</span>")
|
||||
return
|
||||
|
||||
var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new
|
||||
swapper.cast(user, stored_swap, 1)
|
||||
var/obj/effect/proc_holder/spell/targeted/click/mind_transfer/swapper = new
|
||||
swapper.cast(user, stored_swap)
|
||||
|
||||
to_chat(stored_swap, "<span class='warning'>You're suddenly somewhere else... and someone else?!</span>")
|
||||
to_chat(user, "<span class='warning'>Suddenly you're staring at [src] again... where are you, who are you?!</span>")
|
||||
@@ -966,7 +966,7 @@
|
||||
user.Weaken(20)
|
||||
|
||||
/obj/item/spellbook/oneuse/horsemask
|
||||
spell = /obj/effect/proc_holder/spell/targeted/horsemask
|
||||
spell = /obj/effect/proc_holder/spell/targeted/click/horsemask
|
||||
spellname = "horses"
|
||||
icon_state = "bookhorses"
|
||||
desc = "This book is more horse than your mind has room for."
|
||||
|
||||
@@ -45,9 +45,8 @@
|
||||
for(var/datum/mind/wizard in wizards)
|
||||
log_game("[key_name(wizard)] has been selected as a Wizard")
|
||||
forge_wizard_objectives(wizard)
|
||||
//learn_basic_spells(wizard.current)
|
||||
equip_wizard(wizard.current)
|
||||
name_wizard(wizard.current)
|
||||
INVOKE_ASYNC(src, .proc/name_wizard, wizard.current)
|
||||
greet_wizard(wizard)
|
||||
if(use_huds)
|
||||
update_wiz_icons_added(wizard)
|
||||
@@ -89,17 +88,15 @@
|
||||
var/wizard_name_first = pick(GLOB.wizard_first)
|
||||
var/wizard_name_second = pick(GLOB.wizard_second)
|
||||
var/randomname = "[wizard_name_first] [wizard_name_second]"
|
||||
spawn(0)
|
||||
var/newname = sanitize(copytext(input(wizard_mob, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text,1,MAX_NAME_LEN))
|
||||
var/newname = sanitize(copytext(input(wizard_mob, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text,1,MAX_NAME_LEN))
|
||||
|
||||
if(!newname)
|
||||
newname = randomname
|
||||
if(!newname)
|
||||
newname = randomname
|
||||
|
||||
wizard_mob.real_name = newname
|
||||
wizard_mob.name = newname
|
||||
if(wizard_mob.mind)
|
||||
wizard_mob.mind.name = newname
|
||||
return
|
||||
wizard_mob.real_name = newname
|
||||
wizard_mob.name = newname
|
||||
if(wizard_mob.mind)
|
||||
wizard_mob.mind.name = newname
|
||||
|
||||
/datum/game_mode/proc/greet_wizard(var/datum/mind/wizard, var/you_are=1)
|
||||
addtimer(CALLBACK(wizard.current, /mob/.proc/playsound_local, null, 'sound/ambience/antag/ragesmages.ogg', 100, 0), 30)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
Care should be taken in hiding the item you choose as your phylactery after using Bind Soul, as you cannot revive if it destroyed or too far from your body! <br><br> \
|
||||
</i>Provides Bind Soul, Ethereal Jaunt, Fireball, Rod Form, Disable Tech, and Greater Forcewall.<i>"
|
||||
log_name = "DL"
|
||||
spells_path = list(/obj/effect/proc_holder/spell/targeted/lichdom, /obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/fireball, \
|
||||
spells_path = list(/obj/effect/proc_holder/spell/targeted/lichdom, /obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/targeted/click/fireball, \
|
||||
/obj/effect/proc_holder/spell/targeted/rod_form, /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech, /obj/effect/proc_holder/spell/targeted/forcewall/greater)
|
||||
is_ragin_restricted = TRUE
|
||||
|
||||
|
||||
@@ -426,6 +426,7 @@
|
||||
|
||||
//gets the alt title, failing that the actual job rank
|
||||
//this is unused
|
||||
// THEN WHY IS IT STILL HERE?? -AA07, 2020-07-31
|
||||
/obj/proc/sdsdsd() //GetJobDisplayName
|
||||
if(!istype(src, /obj/item/pda) && !istype(src,/obj/item/card/id))
|
||||
return
|
||||
@@ -442,7 +443,7 @@
|
||||
|
||||
return "Unknown"
|
||||
|
||||
proc/GetIdCard(var/mob/living/carbon/human/H)
|
||||
/proc/GetIdCard(var/mob/living/carbon/human/H)
|
||||
if(H.wear_id)
|
||||
var/id = H.wear_id.GetID()
|
||||
if(id)
|
||||
@@ -451,7 +452,7 @@ proc/GetIdCard(var/mob/living/carbon/human/H)
|
||||
var/obj/item/I = H.get_active_hand()
|
||||
return I.GetID()
|
||||
|
||||
proc/FindNameFromID(var/mob/living/carbon/human/H)
|
||||
/proc/FindNameFromID(var/mob/living/carbon/human/H)
|
||||
ASSERT(istype(H))
|
||||
var/obj/item/card/id/C = H.get_active_hand()
|
||||
if( istype(C) || istype(C, /obj/item/pda) )
|
||||
@@ -480,7 +481,7 @@ proc/FindNameFromID(var/mob/living/carbon/human/H)
|
||||
if(ID)
|
||||
return ID.registered_name
|
||||
|
||||
proc/get_all_job_icons() //For all existing HUD icons
|
||||
/proc/get_all_job_icons() //For all existing HUD icons
|
||||
return GLOB.joblist + list("Prisoner")
|
||||
|
||||
/obj/proc/GetJobName() //Used in secHUD icon generation
|
||||
@@ -511,7 +512,7 @@ proc/get_all_job_icons() //For all existing HUD icons
|
||||
|
||||
return "Unknown" //Return unknown if none of the above apply
|
||||
|
||||
proc/get_accesslist_static_data(num_min_region = REGION_GENERAL, num_max_region = REGION_COMMAND)
|
||||
/proc/get_accesslist_static_data(num_min_region = REGION_GENERAL, num_max_region = REGION_COMMAND)
|
||||
var/list/retval
|
||||
for(var/i in num_min_region to num_max_region)
|
||||
var/list/accesses = list()
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
)
|
||||
cybernetic_implants = list(
|
||||
/obj/item/organ/internal/cyberimp/eyes/xray,
|
||||
/obj/item/organ/internal/cyberimp/brain/anti_stun,
|
||||
/obj/item/organ/internal/cyberimp/brain/anti_stun/hardened,
|
||||
/obj/item/organ/internal/cyberimp/chest/nutriment/plus,
|
||||
/obj/item/organ/internal/cyberimp/arm/combat/centcom
|
||||
)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
ACCESS_HEADS, ACCESS_CONSTRUCTION, ACCESS_SEC_DOORS,
|
||||
ACCESS_CE, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_MINISAT, ACCESS_MECHANIC, ACCESS_MINERAL_STOREROOM)
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_ENGINEERING
|
||||
outfit = /datum/outfit/job/chief_engineer
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_SURGERY, ACCESS_RC_ANNOUNCE,
|
||||
ACCESS_KEYCARD_AUTH, ACCESS_SEC_DOORS, ACCESS_PSYCHIATRIST, ACCESS_MAINT_TUNNELS, ACCESS_PARAMEDIC, ACCESS_MINERAL_STOREROOM)
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_MEDICAL
|
||||
outfit = /datum/outfit/job/cmo
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
ACCESS_RESEARCH, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY, ACCESS_AI_UPLOAD,
|
||||
ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_GATEWAY, ACCESS_XENOARCH, ACCESS_MINISAT, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM, ACCESS_NETWORK)
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_SCIENCE
|
||||
// All science-y guys get bonuses for maxing out their tech.
|
||||
required_objectives = list(
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
ACCESS_RESEARCH, ACCESS_ENGINE, ACCESS_MINING, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING,
|
||||
ACCESS_HEADS, ACCESS_HOS, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_PILOT, ACCESS_WEAPONS)
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_SECURITY
|
||||
disabilities_allowed = 0
|
||||
outfit = /datum/outfit/job/hos
|
||||
@@ -64,7 +64,7 @@
|
||||
minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_WEAPONS)
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 600
|
||||
exp_type = EXP_TYPE_CREW
|
||||
exp_type = EXP_TYPE_SECURITY
|
||||
outfit = /datum/outfit/job/warden
|
||||
|
||||
/datum/outfit/job/warden
|
||||
|
||||
@@ -13,7 +13,7 @@ GLOBAL_DATUM_INIT(captain_announcement, /datum/announcement/minor, new(do_newsca
|
||||
access = list() //See get_access()
|
||||
minimal_access = list() //See get_access()
|
||||
minimal_player_age = 30
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_COMMAND
|
||||
disabilities_allowed = 0
|
||||
outfit = /datum/outfit/job/captain
|
||||
@@ -67,7 +67,7 @@ GLOBAL_DATUM_INIT(captain_announcement, /datum/announcement/minor, new(do_newsca
|
||||
req_admin_notify = 1
|
||||
is_command = 1
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 300
|
||||
exp_requirements = 1200
|
||||
exp_type = EXP_TYPE_COMMAND
|
||||
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_FORENSICS_LOCKERS,
|
||||
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user