Merge pull request #12229 from Arturlang/TGUI-3.0

[READY]TGUI 3.0
This commit is contained in:
silicons
2020-07-16 17:28:42 -07:00
committed by GitHub
921 changed files with 33028 additions and 40339 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ TGS3.json
cfg
data
SQL
tgui/node_modules
node_modules
tgstation.dmb
tgstation.int
tgstation.rsc
+12 -2
View File
@@ -257,6 +257,12 @@ This prevents nesting levels from getting deeper then they need to be.
* Please attempt to clean out any dirty variables that may be contained within items you alter through var-editing. For example, due to how DM functions, changing the `pixel_x` variable from 23 to 0 will leave a dirty record in the map's code of `pixel_x = 0`. Likewise this can happen when changing an item's icon to something else and then back. This can lead to some issues where an item's icon has changed within the code, but becomes broken on the map due to it still attempting to use the old entry.
* Areas should not be var-edited on a map to change it's name or attributes. All areas of a single type and it's altered instances are considered the same area within the code, and editing their variables on a map can lead to issues with powernets and event subsystems which are difficult to debug.
### User Interfaces
* All new player-facing user interfaces must use TGUI.
* Raw HTML is permitted for admin and debug UIs.
* Documentation for TGUI can be found at:
* [tgui/README.md](../tgui/README.md)
* [tgui/tutorial-and-examples.md](../tgui/docs/tutorial-and-examples.md)
### Other Notes
* Code should be modular where possible; if you are working on a new addition, then strongly consider putting it in its own file unless it makes sense to put it with similar ones (i.e. a new tool would go in the "tools.dm" file)
@@ -337,7 +343,7 @@ for(var/obj/item/sword/S in bag_of_swords)
if(!best_sword || S.damage > best_sword.damage)
best_sword = S
```
specifies a type for DM to filter by.
specifies a type for DM to filter by.
With the previous example that's perfectly fine, we only want swords, but here the bag only contains swords? Is DM still going to try to filter because we gave it a type to filter by? YES, and here comes the inefficiency. Wherever a list (or other container, such as an atom (in which case you're technically accessing their special contents list, but that's irrelevant)) contains datums of the same datatype or subtypes of the datatype you require for your loop's body,
you can circumvent DM's filtering and automatic ```istype()``` checks by writing the loop as such:
@@ -374,7 +380,7 @@ mob
```
This does NOT mean that you can access it everywhere like a global var. Instead, it means that that var will only exist once for all instances of its type, in this case that var will only exist once for all mobs - it's shared across everything in its type. (Much more like the keyword `static` in other languages like PHP/C++/C#/Java)
Isn't that confusing?
Isn't that confusing?
There is also an undocumented keyword called `static` that has the same behaviour as global but more correctly describes BYOND's behaviour. Therefore, we always use static instead of global where we need it, as it reduces suprise when reading BYOND code.
@@ -394,6 +400,10 @@ There is no strict process when it comes to merging pull requests. Pull requests
* Please explain why you are submitting the pull request, and how you think your change will be beneficial to the game. Failure to do so will be grounds for rejecting the PR.
* If your pull request is not finished make sure it is at least testable in a live environment. Pull requests that do not at least meet this requirement will be closed. You may request a maintainer reopen the pull request when you're ready, or make a new one.
* While we have no issue helping contributors (and especially new contributors) bring reasonably sized contributions up to standards via the pull request review process, larger contributions are expected to pass a higher bar of completeness and code quality *before* you open a pull request. Maintainers may close such pull requests that are deemed to be substantially flawed. You should take some time to discuss with maintainers or other contributors on how to improve the changes.
## Porting features/sprites/sounds/tools from other codebases
If you are porting features/tools from other codebases, you must give them credit where it's due. Typically, crediting them in your pull request and the changelog is the recommended way of doing it. Take note of what license they use though, porting stuff from AGPLv3 and GPLv3 codebases are allowed.
+3 -3
View File
@@ -5,8 +5,8 @@ on:
branches:
- 'master'
paths:
- 'tgui-next/**.js'
- 'tgui-next/**.scss'
- 'tgui/**.js'
- 'tgui/**.scss'
jobs:
build:
@@ -23,7 +23,7 @@ jobs:
node-version: '>=12.13'
- name: Build TGUI
run: bin/tgui --ci
working-directory: ./tgui-next
working-directory: ./tgui
- name: Commit Artifacts
run: |
git config --local user.email "action@github.com"
+1 -1
View File
@@ -23,7 +23,7 @@ matrix:
- tools/travis/check_filedirs.sh tgstation.dme
- tools/travis/check_changelogs.sh
- find . -name "*.php" -print0 | xargs -0 -n1 php -l
- find . -name "*.json" -not -path "./tgui/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py
- find . -name "*.json" -not -path "*/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py
- tools/travis/build_tgui.sh
- tools/travis/check_grep.sh
- python3 tools/travis/check_line_endings.py
@@ -932,7 +932,6 @@
/obj/machinery/airalarm/all_access{
dir = 1;
icon_state = "alarm0";
pixel_x = 0;
pixel_y = -24
},
/turf/open/floor/plasteel/dark,
+12 -58
View File
@@ -3594,36 +3594,12 @@
},
/turf/open/floor/carpet,
/area/awaymission/academy/academygate)
"km" = (
/obj/machinery/gateway{
dir = 9
},
/obj/structure/cable{
icon_state = "1-4"
},
/turf/open/floor/plating,
/area/awaymission/academy/academygate)
"kn" = (
/obj/machinery/gateway{
dir = 1
},
/obj/structure/cable{
icon_state = "2-8"
},
/turf/open/floor/plating,
/area/awaymission/academy/academygate)
"ko" = (
/obj/machinery/gateway{
dir = 5
},
/turf/open/floor/plating,
/area/awaymission/academy/academygate)
"kp" = (
/obj/machinery/gateway{
dir = 8
},
/turf/open/floor/plating,
/area/awaymission/academy/academygate)
"kq" = (
/mob/living/simple_animal/hostile/wizard,
/obj/effect/turf_decal/tile/yellow{
@@ -3634,28 +3610,6 @@
},
/turf/open/floor/plasteel,
/area/awaymission/academy/classrooms)
"kr" = (
/obj/machinery/gateway{
dir = 4
},
/turf/open/floor/plating,
/area/awaymission/academy/academygate)
"ks" = (
/obj/machinery/gateway{
dir = 10
},
/turf/open/floor/plating,
/area/awaymission/academy/academygate)
"kt" = (
/obj/machinery/gateway,
/turf/open/floor/plating,
/area/awaymission/academy/academygate)
"ku" = (
/obj/machinery/gateway{
dir = 6
},
/turf/open/floor/plating,
/area/awaymission/academy/academygate)
"kv" = (
/obj/machinery/light,
/turf/open/floor/carpet,
@@ -3737,7 +3691,7 @@
/area/awaymission/academy/academyaft)
"kI" = (
/obj/structure/cable,
/obj/machinery/gateway/centeraway,
/obj/machinery/gateway/away,
/turf/open/floor/plating,
/area/awaymission/academy/academygate)
"kJ" = (
@@ -13173,10 +13127,10 @@ jZ
kb
ke
kj
km
kp
ks
Ao
kk
kf
kf
kf
kf
ky
kf
@@ -13305,8 +13259,8 @@ jW
Ao
kn
kI
kt
Ao
kf
kf
kf
ky
mF
@@ -13432,11 +13386,11 @@ jV
jY
kc
jW
Ao
ko
kr
ku
Ao
kf
kf
kf
kf
kf
kf
ky
kf
+9 -56
View File
@@ -633,24 +633,6 @@
/obj/machinery/processor,
/turf/open/floor/plasteel/freezer,
/area/awaymission/cabin)
"cb" = (
/obj/machinery/gateway{
dir = 9
},
/turf/open/floor/wood,
/area/awaymission/cabin)
"cc" = (
/obj/machinery/gateway{
dir = 1
},
/turf/open/floor/wood,
/area/awaymission/cabin)
"cd" = (
/obj/machinery/gateway{
dir = 5
},
/turf/open/floor/wood,
/area/awaymission/cabin)
"ce" = (
/obj/structure/chair/wood{
dir = 4
@@ -733,20 +715,8 @@
"cn" = (
/turf/open/lava,
/area/awaymission/cabin/caves/mountain)
"co" = (
/obj/machinery/gateway{
dir = 8
},
/turf/open/floor/wood,
/area/awaymission/cabin)
"cp" = (
/obj/machinery/gateway/centeraway,
/turf/open/floor/wood,
/area/awaymission/cabin)
"cq" = (
/obj/machinery/gateway{
dir = 4
},
/obj/machinery/gateway/away,
/turf/open/floor/wood,
/area/awaymission/cabin)
"cr" = (
@@ -787,23 +757,6 @@
},
/turf/open/floor/plasteel/white,
/area/awaymission/cabin)
"cw" = (
/obj/machinery/gateway{
dir = 10
},
/turf/open/floor/wood,
/area/awaymission/cabin)
"cx" = (
/obj/machinery/gateway,
/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
/turf/open/floor/wood,
/area/awaymission/cabin)
"cy" = (
/obj/machinery/gateway{
dir = 6
},
/turf/open/floor/wood,
/area/awaymission/cabin)
"cz" = (
/obj/machinery/light{
dir = 1
@@ -35769,9 +35722,9 @@ an
bk
bJ
an
cb
co
cw
aq
aq
aq
aq
cH
cQ
@@ -36026,9 +35979,9 @@ an
nU
an
an
cc
aq
cp
cx
eg
eg
eg
cQ
@@ -36283,9 +36236,9 @@ an
jf
ay
an
cd
cq
cy
aq
aq
aq
aq
cH
hH
+9 -85
View File
@@ -224,63 +224,13 @@
/mob/living/simple_animal/crab,
/turf/open/floor/plating/beach/sand,
/area/awaymission/beach)
"aL" = (
/obj/machinery/gateway{
dir = 9
},
/obj/effect/turf_decal/sand,
/obj/effect/turf_decal/stripes/asteroid/line{
dir = 9
},
/turf/open/floor/plating/beach/sand,
/area/awaymission/beach)
"aM" = (
/obj/machinery/gateway{
dir = 1
},
/obj/effect/turf_decal/sand,
/obj/effect/turf_decal/stripes/asteroid/line{
dir = 1
},
/turf/open/floor/plating/beach/sand,
/area/awaymission/beach)
"aN" = (
/obj/machinery/gateway{
dir = 5
},
/obj/effect/turf_decal/sand,
/obj/effect/turf_decal/stripes/asteroid/line{
dir = 5
},
/turf/open/floor/plating/beach/sand,
/area/awaymission/beach)
"aO" = (
/obj/effect/baseturf_helper/beach/sand,
/turf/open/floor/plating/beach/sand,
/area/awaymission/beach)
"aP" = (
/obj/machinery/gateway{
dir = 8
},
/obj/effect/turf_decal/sand,
/obj/effect/turf_decal/stripes/asteroid/line{
dir = 8
},
/turf/open/floor/plating/beach/sand,
/area/awaymission/beach)
"aQ" = (
/obj/machinery/gateway/centeraway,
/obj/effect/turf_decal/sand,
/turf/open/floor/plating/beach/sand,
/area/awaymission/beach)
"aR" = (
/obj/machinery/gateway{
dir = 4
},
/obj/effect/turf_decal/sand,
/obj/effect/turf_decal/stripes/asteroid/line{
dir = 4
},
/obj/machinery/gateway/away,
/turf/open/floor/plating/beach/sand,
/area/awaymission/beach)
"aS" = (
@@ -295,32 +245,6 @@
dir = 8
},
/area/awaymission/beach)
"aU" = (
/obj/machinery/gateway{
dir = 10
},
/obj/effect/turf_decal/sand,
/obj/effect/turf_decal/stripes/asteroid/line{
dir = 10
},
/turf/open/floor/plating/beach/sand,
/area/awaymission/beach)
"aV" = (
/obj/machinery/gateway,
/obj/effect/turf_decal/sand,
/obj/effect/turf_decal/stripes/asteroid/line,
/turf/open/floor/plating/beach/sand,
/area/awaymission/beach)
"aW" = (
/obj/machinery/gateway{
dir = 6
},
/obj/effect/turf_decal/sand,
/obj/effect/turf_decal/stripes/asteroid/line{
dir = 6
},
/turf/open/floor/plating/beach/sand,
/area/awaymission/beach)
"aX" = (
/turf/closed/wall/mineral/sandstone,
/area/awaymission/beach)
@@ -6896,9 +6820,9 @@ ak
ak
ak
ak
aL
aP
aU
bf
bp
bx
ak
ak
ba
@@ -7003,9 +6927,9 @@ ak
ak
ak
ak
aM
bg
aQ
aV
by
ba
ba
ba
@@ -7110,9 +7034,9 @@ ak
ak
ak
ak
aN
aR
aW
bh
br
bz
ak
ak
ak
File diff suppressed because it is too large Load Diff
+5 -38
View File
@@ -866,21 +866,10 @@
},
/area/awaymission/challenge/start)
"cS" = (
/obj/machinery/gateway{
dir = 9
},
/turf/open/floor/bluespace,
/area/awaymission/challenge/start)
"cT" = (
/obj/machinery/gateway{
dir = 1
},
/obj/machinery/gateway/away,
/turf/open/floor/bluespace,
/area/awaymission/challenge/start)
"cV" = (
/obj/machinery/gateway{
dir = 5
},
/obj/structure/cable{
icon_state = "1-2"
},
@@ -894,24 +883,12 @@
/turf/open/floor/plasteel/dark,
/area/awaymission/challenge/end)
"cX" = (
/obj/machinery/gateway{
dir = 8
},
/obj/machinery/light{
dir = 8
},
/turf/open/floor/bluespace,
/area/awaymission/challenge/start)
"cY" = (
/obj/machinery/gateway/centeraway{
calibrated = 0
},
/turf/open/floor/bluespace,
/area/awaymission/challenge/start)
"cZ" = (
/obj/machinery/gateway{
dir = 4
},
/obj/structure/cable{
icon_state = "1-2"
},
@@ -920,18 +897,11 @@
},
/turf/open/floor/bluespace,
/area/awaymission/challenge/start)
"da" = (
/obj/machinery/gateway{
dir = 10
},
/turf/open/floor/bluespace,
/area/awaymission/challenge/start)
"db" = (
/obj/structure/window/reinforced,
/turf/open/floor/circuit,
/area/awaymission/challenge/end)
"dc" = (
/obj/machinery/gateway,
/obj/structure/cable{
icon_state = "0-4"
},
@@ -996,9 +966,6 @@
/turf/open/floor/plasteel/dark,
/area/awaymission/challenge/end)
"dn" = (
/obj/machinery/gateway{
dir = 6
},
/obj/structure/cable{
icon_state = "1-8"
},
@@ -28109,9 +28076,9 @@ aa
ab
ab
ab
cS
dq
cX
da
dq
ab
ab
at
@@ -28366,8 +28333,8 @@ aa
ab
aB
ab
cT
cY
dq
cS
dc
dq
dq
@@ -191,60 +191,6 @@
heat_capacity = 1e+006
},
/area/awaymission/moonoutpost19/syndicate)
"aG" = (
/obj/machinery/gateway{
dir = 9
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
/area/awaymission/moonoutpost19/syndicate)
"aH" = (
/obj/machinery/gateway{
dir = 1
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
/area/awaymission/moonoutpost19/syndicate)
"aI" = (
/obj/machinery/gateway{
dir = 5
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
/area/awaymission/moonoutpost19/syndicate)
"aJ" = (
/obj/structure/alien/weeds,
/obj/structure/alien/weeds{
@@ -291,46 +237,8 @@
heat_capacity = 1e+006
},
/area/awaymission/moonoutpost19/syndicate)
"aO" = (
/obj/machinery/gateway{
dir = 8
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
/area/awaymission/moonoutpost19/syndicate)
"aP" = (
/obj/machinery/gateway/centeraway{
calibrated = 0
},
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
/area/awaymission/moonoutpost19/syndicate)
"aQ" = (
/obj/machinery/gateway{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/obj/machinery/gateway/away,
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
@@ -377,9 +285,6 @@
},
/area/awaymission/moonoutpost19/syndicate)
"aW" = (
/obj/machinery/gateway{
dir = 10
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -395,7 +300,6 @@
},
/area/awaymission/moonoutpost19/syndicate)
"aX" = (
/obj/machinery/gateway,
/obj/structure/cable{
icon_state = "0-2"
},
@@ -414,9 +318,6 @@
},
/area/awaymission/moonoutpost19/syndicate)
"aY" = (
/obj/machinery/gateway{
dir = 6
},
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -41927,8 +41828,8 @@ ac
ac
at
az
aG
aO
aW
aW
aW
aV
br
@@ -42184,7 +42085,7 @@ ac
ac
at
aA
aH
aW
aP
aX
bg
@@ -42441,8 +42342,8 @@ ac
ac
at
aB
aI
aQ
aW
aW
aY
bh
bt
+1 -25
View File
@@ -592,27 +592,18 @@
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/gateway)
"bA" = (
/obj/machinery/gateway{
dir = 9
},
/obj/effect/turf_decal/stripes/line{
dir = 9
},
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/gateway)
"bB" = (
/obj/machinery/gateway{
dir = 1
},
/obj/effect/turf_decal/stripes/line{
dir = 1
},
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/gateway)
"bC" = (
/obj/machinery/gateway{
dir = 5
},
/obj/effect/turf_decal/stripes/line{
dir = 5
},
@@ -764,24 +755,16 @@
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/gateway)
"bS" = (
/obj/machinery/gateway{
dir = 8
},
/obj/effect/turf_decal/stripes/line{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/gateway)
"bT" = (
/obj/machinery/gateway/centeraway{
calibrated = 0
},
/obj/machinery/gateway/away,
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/gateway)
"bU" = (
/obj/machinery/gateway{
dir = 4
},
/obj/effect/turf_decal/stripes/line{
dir = 4
},
@@ -830,24 +813,17 @@
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior/engineering)
"bY" = (
/obj/machinery/gateway{
dir = 10
},
/obj/effect/turf_decal/stripes/line{
dir = 10
},
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/gateway)
"bZ" = (
/obj/machinery/gateway,
/obj/effect/landmark/awaystart,
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/gateway)
"ca" = (
/obj/machinery/gateway{
dir = 6
},
/obj/effect/turf_decal/stripes/line{
dir = 6
},
+5 -46
View File
@@ -2514,27 +2514,6 @@
"fF" = (
/turf/open/floor/plasteel,
/area/awaymission/snowdin/post/gateway)
"fG" = (
/obj/machinery/gateway{
dir = 9
},
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
/area/awaymission/snowdin/post/gateway)
"fH" = (
/obj/machinery/gateway{
dir = 1
},
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
/area/awaymission/snowdin/post/gateway)
"fI" = (
/obj/machinery/gateway{
dir = 5
},
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
/area/awaymission/snowdin/post/gateway)
"fJ" = (
/obj/structure/table/reinforced,
/obj/effect/turf_decal/tile/bar,
@@ -2894,29 +2873,16 @@
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel,
/area/awaymission/snowdin/post/gateway)
"gw" = (
/obj/machinery/gateway{
dir = 8
},
/obj/effect/turf_decal/bot,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel,
/area/awaymission/snowdin/post/gateway)
"gx" = (
/obj/machinery/gateway/centeraway{
calibrated = 0
},
/obj/effect/turf_decal/bot,
/obj/structure/cable/yellow{
icon_state = "0-2"
},
/obj/effect/decal/cleanable/dirt,
/obj/machinery/gateway/away,
/turf/open/floor/plasteel,
/area/awaymission/snowdin/post/gateway)
"gy" = (
/obj/machinery/gateway{
dir = 4
},
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
/area/awaymission/snowdin/post/gateway)
@@ -3263,15 +3229,11 @@
/turf/open/floor/plasteel,
/area/awaymission/snowdin/post/gateway)
"hl" = (
/obj/machinery/gateway{
dir = 10
},
/obj/effect/turf_decal/bot,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel,
/area/awaymission/snowdin/post/gateway)
"hm" = (
/obj/machinery/gateway,
/obj/effect/turf_decal/bot,
/obj/structure/cable/yellow{
icon_state = "0-2"
@@ -3283,9 +3245,6 @@
/turf/open/floor/plasteel,
/area/awaymission/snowdin/post/gateway)
"hn" = (
/obj/machinery/gateway{
dir = 6
},
/obj/effect/turf_decal/bot,
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
@@ -26601,8 +26560,8 @@ bE
az
en
fh
fG
gw
gy
hl
hl
hR
iA
@@ -26858,7 +26817,7 @@ bE
dK
eo
fh
fH
gy
gx
hm
hS
@@ -27115,7 +27074,7 @@ dk
dK
ep
fh
fI
gy
gy
hn
hT
@@ -3324,60 +3324,6 @@
icon_state = "platingdmg1"
},
/area/awaymission/undergroundoutpost45/central)
"gR" = (
/obj/machinery/gateway{
dir = 9
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
/area/awaymission/undergroundoutpost45/gateway)
"gS" = (
/obj/machinery/gateway{
dir = 1
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
/area/awaymission/undergroundoutpost45/gateway)
"gT" = (
/obj/machinery/gateway{
dir = 5
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
/area/awaymission/undergroundoutpost45/gateway)
"gU" = (
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating{
@@ -3634,46 +3580,8 @@
heat_capacity = 1e+006
},
/area/awaymission/undergroundoutpost45/crew_quarters)
"ht" = (
/obj/machinery/gateway{
dir = 8
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
/area/awaymission/undergroundoutpost45/gateway)
"hu" = (
/obj/machinery/gateway/centeraway{
calibrated = 0
},
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
/area/awaymission/undergroundoutpost45/gateway)
"hv" = (
/obj/machinery/gateway{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/obj/machinery/gateway/away,
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
@@ -3958,26 +3866,7 @@
heat_capacity = 1e+006
},
/area/awaymission/undergroundoutpost45/central)
"hY" = (
/obj/machinery/gateway{
dir = 10
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark{
heat_capacity = 1e+006
},
/area/awaymission/undergroundoutpost45/gateway)
"hZ" = (
/obj/machinery/gateway,
/obj/structure/cable{
icon_state = "0-2"
},
@@ -3996,9 +3885,6 @@
},
/area/awaymission/undergroundoutpost45/gateway)
"ia" = (
/obj/machinery/gateway{
dir = 6
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -33198,9 +33084,9 @@ ad
ad
gv
gJ
gR
ht
hY
ia
ia
ia
it
iO
jh
@@ -33455,7 +33341,7 @@ ad
ad
gv
gJ
gS
ia
hu
hZ
iu
@@ -33712,8 +33598,8 @@ ad
ad
gw
gJ
gT
hv
ia
ia
ia
iv
iQ
+8 -69
View File
@@ -63,72 +63,11 @@
/obj/structure/destructible/cult/pylon,
/turf/open/floor/circuit/green/off,
/area/awaymission/wildwest/vault)
"ar" = (
/obj/machinery/gateway{
dir = 9
},
/turf/open/floor/plating/ironsand{
icon_state = "ironsand1"
},
/area/awaymission/wildwest/mines)
"as" = (
/obj/machinery/gateway{
dir = 1
},
/turf/open/floor/plating/ironsand{
icon_state = "ironsand1"
},
/area/awaymission/wildwest/mines)
"at" = (
/obj/machinery/gateway{
dir = 5
},
/turf/open/floor/plating/ironsand{
icon_state = "ironsand1"
},
/area/awaymission/wildwest/mines)
"au" = (
/obj/machinery/gateway{
dir = 8
},
/turf/open/floor/plating/ironsand{
icon_state = "ironsand1"
},
/area/awaymission/wildwest/mines)
"av" = (
/obj/machinery/gateway/centeraway{
calibrated = 0
},
/turf/open/floor/plating/ironsand{
icon_state = "ironsand1"
},
/area/awaymission/wildwest/mines)
"aw" = (
/obj/machinery/gateway{
dir = 4
},
/turf/open/floor/plating/ironsand{
icon_state = "ironsand1"
},
/area/awaymission/wildwest/mines)
"ax" = (
/obj/machinery/gateway{
dir = 10
},
/turf/open/floor/plating/ironsand{
icon_state = "ironsand1"
},
/area/awaymission/wildwest/mines)
"ay" = (
/obj/machinery/gateway,
/turf/open/floor/plating/ironsand{
icon_state = "ironsand1"
},
/area/awaymission/wildwest/mines)
})
"az" = (
/obj/machinery/gateway{
dir = 6
},
/turf/open/floor/plating/ironsand{
icon_state = "ironsand1"
},
@@ -32745,9 +32684,9 @@ aT
aN
aN
aT
ar
au
ax
aT
aT
aT
aT
aT
aT
@@ -33002,9 +32941,9 @@ aT
aN
aN
aT
as
av
ay
aT
aT
aT
aT
aT
aT
@@ -33259,7 +33198,7 @@ aT
aN
aN
aT
at
aT
aw
az
aT
+5 -84
View File
@@ -11788,63 +11788,12 @@
/obj/item/instrument/eguitar,
/turf/open/floor/wood,
/area/crew_quarters/theatre)
"azJ" = (
/obj/machinery/gateway{
dir = 9
},
/obj/effect/turf_decal/bot_white/right,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"azK" = (
/obj/machinery/light{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"azL" = (
/obj/machinery/gateway{
dir = 5
},
/obj/effect/turf_decal/bot_white/left,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"azM" = (
/obj/machinery/gateway{
dir = 1
},
/obj/effect/turf_decal/bot_white,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"azN" = (
/obj/machinery/light{
dir = 4
@@ -12316,30 +12265,10 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/closed/wall/r_wall,
/area/ai_monitored/nuke_storage)
"aBd" = (
/obj/machinery/gateway{
dir = 8
},
/obj/effect/turf_decal/bot_white,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"aBe" = (
/turf/open/floor/plasteel/dark,
/area/gateway)
"aBf" = (
/obj/machinery/gateway{
dir = 4
},
/obj/effect/turf_decal/bot_white,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -12692,9 +12621,6 @@
/turf/open/floor/plasteel/dark,
/area/ai_monitored/nuke_storage)
"aBX" = (
/obj/machinery/gateway{
dir = 10
},
/obj/effect/turf_decal/bot_white/left,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -12709,9 +12635,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"aBY" = (
/obj/machinery/gateway{
dir = 6
},
/obj/effect/turf_decal/bot_white/right,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -12726,7 +12649,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"aBZ" = (
/obj/machinery/gateway,
/obj/structure/cable{
icon_state = "0-2"
},
@@ -13795,8 +13717,7 @@
/turf/open/floor/plasteel/dark,
/area/ai_monitored/nuke_storage)
"aEQ" = (
/obj/structure/table,
/obj/item/paper/pamphlet/gateway,
/obj/machinery/computer/gateway_control,
/turf/open/floor/plasteel,
/area/gateway)
"aER" = (
@@ -84053,8 +83974,8 @@ esK
awb
axt
ayG
azJ
aBd
aBY
aBf
aBX
aDi
aEQ
@@ -84310,7 +84231,7 @@ arP
awb
axt
ayG
azM
aBf
aBg
aBZ
aDx
@@ -84567,7 +84488,7 @@ arP
vgJ
hSl
ayG
azL
aBX
aBf
aBY
aDw
+10 -51
View File
@@ -22362,6 +22362,9 @@
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
/obj/machinery/computer/gateway_control{
dir = 8
},
/turf/open/floor/plasteel/dark/side{
dir = 4
},
@@ -22381,12 +22384,6 @@
/obj/effect/spawner/lootdrop/maintenance,
/turf/open/floor/plating,
/area/maintenance/department/eva)
"aWr" = (
/obj/machinery/gateway{
dir = 10
},
/turf/open/floor/engine,
/area/gateway)
"aWs" = (
/obj/machinery/light{
dir = 8;
@@ -22840,10 +22837,6 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/central)
"aXm" = (
/obj/machinery/gateway,
/turf/open/floor/engine,
/area/gateway)
"aXn" = (
/obj/effect/turf_decal/tile/bar,
/obj/effect/turf_decal/tile/bar{
@@ -22883,12 +22876,6 @@
"aXr" = (
/turf/open/floor/plasteel,
/area/ai_monitored/storage/eva)
"aXs" = (
/obj/machinery/gateway{
dir = 6
},
/turf/open/floor/engine,
/area/gateway)
"aXt" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/structure/sign/warning/securearea,
@@ -30329,12 +30316,6 @@
},
/turf/open/floor/plasteel,
/area/science/mixing)
"bnl" = (
/obj/machinery/gateway{
dir = 9
},
/turf/open/floor/engine,
/area/gateway)
"bnm" = (
/obj/machinery/atmospherics/pipe/manifold/orange/hidden{
dir = 4
@@ -34660,9 +34641,6 @@
c_tag = "Research - Gateway Chamber";
network = list("ss13","rd")
},
/obj/machinery/gateway{
dir = 1
},
/turf/open/floor/engine,
/area/gateway)
"bwL" = (
@@ -34672,12 +34650,6 @@
},
/turf/open/floor/plating,
/area/router)
"bwM" = (
/obj/machinery/gateway{
dir = 5
},
/turf/open/floor/engine,
/area/gateway)
"bwN" = (
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 4
@@ -36403,12 +36375,6 @@
/area/medical/medbay/zone2{
name = "Medbay Treatment Center"
})
"bAz" = (
/obj/machinery/gateway{
dir = 8
},
/turf/open/floor/engine,
/area/gateway)
"bAA" = (
/obj/structure/lattice,
/obj/structure/cable{
@@ -36566,12 +36532,6 @@
/area/medical/medbay/zone2{
name = "Medbay Treatment Center"
})
"bAN" = (
/obj/machinery/gateway{
dir = 4
},
/turf/open/floor/engine,
/area/gateway)
"bAO" = (
/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{
dir = 4
@@ -62112,7 +62072,6 @@
departmentType = 2;
name = "Chemistry RC";
pixel_x = 30;
pixel_y = 0;
receive_ore_updates = 1
},
/turf/open/floor/plasteel/white,
@@ -99510,9 +99469,9 @@ aaa
aaa
aaa
aUk
bnl
bAz
aWr
bmG
bmG
bmG
cDN
bmG
aUk
@@ -99769,7 +99728,7 @@ aaa
aUk
bwK
bAF
aXm
bmG
cDN
bmG
aUk
@@ -100024,9 +99983,9 @@ aaa
aaa
aaa
aUk
bwM
bAN
aXs
bmG
bmG
bmG
cDN
bmG
aUk
+7 -41
View File
@@ -64841,7 +64841,6 @@
pixel_x = -26
},
/obj/structure/sign/painting/library{
pixel_x = 0;
pixel_y = -32
},
/turf/open/floor/wood,
@@ -75577,9 +75576,6 @@
/turf/open/floor/plating,
/area/gateway)
"cyE" = (
/obj/machinery/gateway{
dir = 9
},
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/bot_white/right,
/obj/effect/turf_decal/tile/neutral{
@@ -75595,9 +75591,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"cyF" = (
/obj/machinery/gateway{
dir = 1
},
/obj/machinery/status_display/evac{
pixel_y = 32
},
@@ -75616,9 +75609,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"cyG" = (
/obj/machinery/gateway{
dir = 5
},
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/bot_white/left,
/obj/effect/turf_decal/tile/neutral{
@@ -76575,26 +76565,10 @@
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/gateway)
"cAi" = (
/obj/machinery/gateway{
dir = 8
},
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/bot_white,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"cAj" = (
/obj/machinery/gateway/centerstation,
/obj/machinery/gateway/centerstation{
dir = 0
},
/obj/structure/cable/white{
icon_state = "0-2"
},
@@ -76602,9 +76576,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"cAk" = (
/obj/machinery/gateway{
dir = 4
},
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/bot_white,
/obj/effect/turf_decal/tile/neutral{
@@ -77428,9 +77399,6 @@
/turf/closed/wall,
/area/gateway)
"cBD" = (
/obj/machinery/gateway{
dir = 10
},
/obj/machinery/light{
dir = 8
},
@@ -77449,7 +77417,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"cBE" = (
/obj/machinery/gateway,
/obj/structure/cable/white{
icon_state = "0-2"
},
@@ -77471,9 +77438,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"cBF" = (
/obj/machinery/gateway{
dir = 6
},
/obj/effect/decal/cleanable/dirt,
/obj/machinery/camera{
c_tag = "Bridge - Gateway Chamber";
@@ -78596,6 +78560,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 5
},
/obj/machinery/computer/gateway_control{
dir = 8
},
/turf/open/floor/plasteel,
/area/gateway)
"cDj" = (
@@ -125456,7 +125423,6 @@
/area/chapel/office)
"iNK" = (
/obj/structure/sign/painting/library{
pixel_x = 0;
pixel_y = -32
},
/turf/open/floor/wood,
@@ -169589,7 +169555,7 @@ cur
cvC
cvz
cyE
cAi
cAk
cBD
cDk
cEY
+3 -26
View File
@@ -7205,9 +7205,6 @@
/turf/open/floor/plasteel/dark,
/area/tcommsat/computer)
"amk" = (
/obj/machinery/gateway{
dir = 1
},
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -13604,9 +13601,6 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/obj/machinery/gateway{
dir = 10
},
/obj/effect/decal/cleanable/dirt,
/obj/machinery/airalarm{
dir = 4;
@@ -13851,7 +13845,6 @@
/obj/item/lighter,
/obj/item/clothing/mask/cigarette/cigar/cohiba,
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/suit_storage_unit/ce,
/turf/open/floor/plasteel,
/area/crew_quarters/heads/chief)
"axi" = (
@@ -76334,9 +76327,6 @@
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/machinery/gateway{
dir = 9
},
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/box/corners{
dir = 4
@@ -76403,9 +76393,6 @@
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/machinery/gateway{
dir = 5
},
/obj/effect/decal/cleanable/dirt,
/obj/machinery/camera{
c_tag = "Gateway";
@@ -77551,9 +77538,6 @@
dir = 8
},
/obj/effect/decal/cleanable/greenglow,
/obj/machinery/gateway{
dir = 8
},
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel/dark,
/area/gateway)
@@ -77573,9 +77557,6 @@
dir = 4
},
/obj/effect/decal/cleanable/greenglow,
/obj/machinery/gateway{
dir = 4
},
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel/dark,
/area/gateway)
@@ -77588,8 +77569,6 @@
/turf/open/floor/plasteel/dark,
/area/maintenance/disposal)
"cvQ" = (
/obj/effect/turf_decal/bot,
/obj/structure/closet/cardboard,
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
/obj/machinery/light/small{
@@ -77599,6 +77578,9 @@
dir = 8;
pixel_x = 32
},
/obj/machinery/computer/gateway_control{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"cvR" = (
@@ -77635,7 +77617,6 @@
dir = 8
},
/obj/effect/decal/cleanable/greenglow,
/obj/machinery/gateway,
/obj/effect/decal/cleanable/dirt,
/obj/structure/cable{
icon_state = "0-2"
@@ -77652,9 +77633,6 @@
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/machinery/gateway{
dir = 6
},
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel/dark,
/area/gateway)
@@ -85287,7 +85265,6 @@
icon_state = "1-2"
},
/obj/structure/table/wood,
/obj/item/folder/paperwork,
/turf/open/floor/wood,
/area/security/vacantoffice)
"ppP" = (
+10 -70
View File
@@ -44580,27 +44580,7 @@
},
/turf/open/floor/plating,
/area/gateway)
"bJY" = (
/obj/machinery/gateway{
dir = 9
},
/obj/effect/turf_decal/bot_white/right,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"bJZ" = (
/obj/machinery/gateway{
dir = 1
},
/obj/machinery/status_display/evac{
pixel_y = 32
},
@@ -44617,23 +44597,6 @@
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"bKa" = (
/obj/machinery/gateway{
dir = 5
},
/obj/effect/turf_decal/bot_white/left,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"bKb" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
@@ -45306,31 +45269,13 @@
/obj/structure/cable/yellow,
/turf/open/floor/plating,
/area/gateway)
"bLD" = (
/obj/machinery/gateway{
dir = 8
},
/obj/effect/turf_decal/bot_white,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"bLE" = (
/obj/machinery/gateway/centerstation,
/obj/machinery/gateway/centerstation{
dir = 0
},
/turf/open/floor/plasteel/dark,
/area/gateway)
"bLF" = (
/obj/machinery/gateway{
dir = 4
},
/obj/effect/turf_decal/bot_white,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -46196,9 +46141,6 @@
},
/area/gateway)
"bNp" = (
/obj/machinery/gateway{
dir = 10
},
/obj/effect/turf_decal/bot_white/left,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -46213,7 +46155,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"bNq" = (
/obj/machinery/gateway,
/obj/structure/cable/yellow{
icon_state = "0-2"
},
@@ -46231,9 +46172,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"bNr" = (
/obj/machinery/gateway{
dir = 6
},
/obj/effect/turf_decal/bot_white/right,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -46829,6 +46767,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 5
},
/obj/machinery/computer/gateway_control{
dir = 8
},
/turf/open/floor/plasteel,
/area/gateway)
"bOJ" = (
@@ -67172,8 +67113,7 @@
layer = 4;
name = "Test Chamber Telescreen";
network = list("toxins");
pixel_x = -32;
pixel_y = 0
pixel_x = -32
},
/turf/open/floor/plasteel,
/area/science/mixing)
@@ -113599,8 +113539,8 @@ bDj
bFb
bGQ
bGM
bJY
bLD
bNr
bLF
bNp
bOK
bQu
@@ -114113,7 +114053,7 @@ bDw
bFd
bGS
bGM
bKa
bNp
bLF
bNr
bOM
@@ -4294,8 +4294,7 @@
department = "Head of Security's Desk";
departmentType = 5;
name = "Head of Security RC";
pixel_x = 30;
pixel_y = 0
pixel_x = 30
},
/obj/machinery/computer/security/hos{
icon_state = "computer";
@@ -7141,8 +7140,7 @@
},
/obj/effect/turf_decal/tile/red,
/obj/machinery/status_display{
pixel_x = 32;
pixel_y = 0
pixel_x = 32
},
/turf/open/floor/plasteel,
/area/security/brig)
@@ -13298,7 +13296,6 @@
dir = 9
},
/obj/machinery/computer/security/wooden_tv{
pixel_x = 0;
pixel_y = 4
},
/turf/open/floor/wood,
+19 -46
View File
@@ -3545,8 +3545,8 @@
name = "supply dock loading door"
},
/obj/machinery/conveyor{
id = "QMLoad2";
dir = 1
dir = 1;
id = "QMLoad2"
},
/turf/open/floor/plating,
/area/quartermaster/storage)
@@ -11666,6 +11666,9 @@
/obj/structure/disposalpipe/segment{
dir = 9
},
/obj/machinery/computer/gateway_control{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/teleporter)
"eFy" = (
@@ -12398,8 +12401,8 @@
/area/bridge/meeting_room)
"eZU" = (
/obj/machinery/conveyor{
id = "QMLoad2";
dir = 1
dir = 1;
id = "QMLoad2"
},
/turf/open/floor/plating,
/area/quartermaster/storage)
@@ -19924,7 +19927,6 @@
/obj/structure/cable{
icon_state = "0-2"
},
/obj/machinery/gateway,
/obj/effect/turf_decal/bot_white,
/turf/open/floor/plasteel/dark,
/area/teleporter)
@@ -20693,13 +20695,6 @@
},
/turf/open/floor/plasteel,
/area/hallway/secondary/exit/departure_lounge)
"jPP" = (
/obj/machinery/gateway{
dir = 8
},
/obj/effect/turf_decal/bot_white,
/turf/open/floor/plasteel/dark,
/area/teleporter)
"jQj" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/structure/cable{
@@ -21094,8 +21089,8 @@
"kdM" = (
/obj/effect/turf_decal/stripes,
/obj/machinery/conveyor{
id = "QMLoad2";
dir = 1
dir = 1;
id = "QMLoad2"
},
/turf/open/floor/plasteel,
/area/quartermaster/storage)
@@ -27641,9 +27636,6 @@
/turf/closed/wall,
/area/quartermaster/sorting)
"ohf" = (
/obj/machinery/gateway{
dir = 5
},
/obj/effect/turf_decal/bot_white/left,
/turf/open/floor/plasteel/dark,
/area/teleporter)
@@ -32098,8 +32090,8 @@
/area/hallway/secondary/exit/departure_lounge)
"qGt" = (
/obj/structure/bodycontainer/crematorium{
id = "crematoriumChapel";
dir = 8
dir = 8;
id = "crematoriumChapel"
},
/obj/machinery/button/crematorium{
id = "crematoriumChapel";
@@ -35403,9 +35395,6 @@
/turf/open/floor/plating,
/area/hallway/secondary/exit/departure_lounge)
"sLr" = (
/obj/machinery/gateway{
dir = 6
},
/obj/effect/turf_decal/bot_white/right,
/obj/effect/turf_decal/stripes/corner{
dir = 1
@@ -36573,9 +36562,9 @@
/obj/effect/turf_decal/delivery,
/obj/structure/table/reinforced,
/obj/machinery/door/window/eastleft{
dir = 8;
name = "Hydroponics Desk";
req_access_txt = "35";
dir = 8
req_access_txt = "35"
},
/obj/machinery/door/firedoor/border_only{
dir = 8;
@@ -39247,8 +39236,8 @@
name = "supply dock loading door"
},
/obj/machinery/conveyor{
id = "QMLoad2";
dir = 1
dir = 1;
id = "QMLoad2"
},
/turf/open/floor/plating,
/area/quartermaster/storage)
@@ -39695,8 +39684,8 @@
/area/security/checkpoint/supply)
"vgX" = (
/obj/machinery/conveyor{
id = "QMLoad2";
dir = 1
dir = 1;
id = "QMLoad2"
},
/turf/open/floor/plasteel,
/area/quartermaster/storage)
@@ -40096,9 +40085,6 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"vse" = (
/obj/machinery/gateway{
dir = 10
},
/obj/machinery/light{
dir = 8
},
@@ -41638,13 +41624,6 @@
},
/turf/open/floor/engine,
/area/engine/engineering)
"wie" = (
/obj/machinery/gateway{
dir = 1
},
/obj/effect/turf_decal/bot_white,
/turf/open/floor/plasteel/dark,
/area/teleporter)
"wje" = (
/turf/open/floor/plasteel,
/area/hallway/primary/port)
@@ -42940,9 +42919,6 @@
/turf/open/floor/plating/snowed/smoothed/icemoon,
/area/icemoon/surface/outdoors)
"xcd" = (
/obj/machinery/gateway{
dir = 4
},
/obj/effect/turf_decal/bot_white,
/turf/open/floor/plasteel/dark,
/area/teleporter)
@@ -43874,9 +43850,6 @@
/turf/open/floor/plating/snowed/smoothed/icemoon,
/area/engine/atmos)
"xHk" = (
/obj/machinery/gateway{
dir = 9
},
/obj/effect/turf_decal/bot_white/right,
/turf/open/floor/plasteel/dark,
/area/teleporter)
@@ -56913,7 +56886,7 @@ avT
avT
gLH
xHk
jPP
xcd
vse
mSs
qQH
@@ -57169,7 +57142,7 @@ bBh
avT
avT
gLH
wie
xcd
ePa
jrR
nTQ
+3 -1
View File
@@ -108,6 +108,8 @@
#define TR_KEEPSE (1<<5) // changelings shouldn't edit the DNA's SE when turning into a monkey
#define TR_DEFAULTMSG (1<<6)
#define TR_KEEPORGANS (1<<8)
#define TR_KEEPREAGENTS (1<<10)
#define TR_KEEPSTUNS (1<<9)
#define CLONER_FRESH_CLONE "fresh"
@@ -184,4 +186,4 @@
#define G_MALE 1
#define G_FEMALE 2
#define G_PLURAL 3
#define G_NEUTER 4
#define G_NEUTER 4
+2
View File
@@ -32,6 +32,8 @@
#define COMSIG_ELEMENT_DETACH "element_detach"
// /atom signals
//from base of atom/proc/Initialize(): sent any time a new atom is created
#define COMSIG_ATOM_CREATED "atom_created"
#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params)
#define COMPONENT_NO_AFTERATTACK 1 //Return this in response if you don't want afterattack to be called
#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human)
+1
View File
@@ -38,6 +38,7 @@
#define LOG_ADMIN_PRIVATE (1 << 14)
#define LOG_ASAY (1 << 15)
#define LOG_VIRUS (1 << 16)
#define LOG_SHUTTLE (1 << 18)
//Individual logging panel pages
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK)
+2
View File
@@ -534,3 +534,5 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define LOOT_RESTRICTION_CKEY 2
#define LOOT_RESTRICTION_MIND_PILE 3 //limited to the current pile.
#define LOOT_RESTRICTION_CKEY_PILE 4 //Idem
#define WANTED_FILE "wanted_message.json"
+7
View File
@@ -118,6 +118,9 @@
//reusing the PDA option because I really don't think news comments are worth a config option
WRITE_LOG(GLOB.world_pda_log, "COMMENT: [text]")
/proc/log_paper(text)
WRITE_LOG(GLOB.world_paper_log, "PAPER: [text]")
/proc/log_telecomms(text)
if (CONFIG_GET(flag/log_telecomms))
WRITE_LOG(GLOB.world_telecomms_log, "TCOMMS: [text]")
@@ -131,6 +134,10 @@
if (CONFIG_GET(flag/log_vote))
WRITE_LOG(GLOB.world_game_log, "VOTE: [text]")
/proc/log_shuttle(text)
if (CONFIG_GET(flag/log_shuttle))
WRITE_LOG(GLOB.world_shuttle_log, "SHUTTLE: [text]")
/proc/log_craft(text)
if (CONFIG_GET(flag/log_craft))
WRITE_LOG(GLOB.world_crafting_log, "CRAFT: [text]")
+1
View File
@@ -1,4 +1,5 @@
#define pick_list(FILE, KEY) (pick(strings(FILE, KEY)))
#define pick_list_weighted(FILE, KEY) (pickweight(strings(FILE, KEY)))
#define pick_list_replacements(FILE, KEY) (strings_replacement(FILE, KEY))
#define json_load(FILE) (json_decode(file2text(FILE)))
+2 -1
View File
@@ -5,8 +5,9 @@
#define GET_INITIALIZED_MUTATION(A) GLOB.all_mutations[A]
#define GET_GENE_STRING(A, B) (B.mutation_index[A])
#define GET_SEQUENCE(A) (GLOB.full_sequences[A])
#define GET_MUTATION_TYPE_FROM_ALIAS(A) (GLOB.alias_mutations[A])
#define GET_MUTATION_STABILIZER(A) ((A.stabilizer_coeff < 0) ? 1 : A.stabilizer_coeff)
#define GET_MUTATION_SYNCHRONIZER(A) ((A.synchronizer_coeff < 0) ? 1 : A.synchronizer_coeff)
#define GET_MUTATION_POWER(A) ((A.power_coeff < 0) ? 1 : A.power_coeff)
#define GET_MUTATION_ENERGY(A) ((A.energy_coeff < 0) ? 1 : A.energy_coeff)
#define GET_MUTATION_ENERGY(A) ((A.energy_coeff < 0) ? 1 : A.energy_coeff)
+21
View File
@@ -53,6 +53,27 @@
for(var/I in adjacent_turfs)
. |= get_area(I)
/**
* Get a bounding box of a list of atoms.
*
* Arguments:
* - atoms - List of atoms. Can accept output of view() and range() procs.
*
* Returns: list(x1, y1, x2, y2)
*/
/proc/get_bbox_of_atoms(list/atoms)
var/list/list_x = list()
var/list/list_y = list()
for(var/_a in atoms)
var/atom/a = _a
list_x += a.x
list_y += a.y
return list(
min(list_x),
min(list_y),
max(list_x),
max(list_y))
// Like view but bypasses luminosity check
/proc/get_hear(range, atom/source)
-22
View File
@@ -90,7 +90,6 @@
init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
INVOKE_ASYNC(GLOBAL_PROC, /proc/init_ref_coin_values) //so the current procedure doesn't sleep because of UNTIL()
INVOKE_ASYNC(GLOBAL_PROC, /proc/setupGenetics)
//creates every subtype of prototype (excluding prototype) and adds it to list L.
//if no list/L is provided, one is created.
@@ -117,24 +116,3 @@
GLOB.coin_values[path] = C.value
qdel(C)
/proc/setupGenetics()
var/list/mutations = subtypesof(/datum/mutation/human)
shuffle_inplace(mutations)
for(var/A in subtypesof(/datum/generecipe))
var/datum/generecipe/GR = A
GLOB.mutation_recipes[initial(GR.required)] = initial(GR.result)
for(var/i in 1 to LAZYLEN(mutations))
var/path = mutations[i] //byond gets pissy when we do it in one line
var/datum/mutation/human/B = new path ()
B.alias = "Mutation #[i]"
GLOB.all_mutations[B.type] = B
GLOB.full_sequences[B.type] = generate_gene_sequence(B.blocks)
if(B.locked)
continue
if(B.quality == POSITIVE)
GLOB.good_mutations |= B
else if(B.quality == NEGATIVE)
GLOB.bad_mutations |= B
else if(B.quality == MINOR_NEGATIVE)
GLOB.not_good_mutations |= B
CHECK_TICK
+2
View File
@@ -1509,6 +1509,8 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
set waitfor = FALSE
return call(source, proctype)(arglist(arguments))
#define TURF_FROM_COORDS_LIST(List) (locate(List[1], List[2], List[3]))
/proc/num2sign(numeric)
if(numeric > 0)
return 1
+2 -1
View File
@@ -27,5 +27,6 @@ GLOBAL_LIST_EMPTY(full_sequences)
GLOBAL_LIST_EMPTY(bad_mutations)
GLOBAL_LIST_EMPTY(good_mutations)
GLOBAL_LIST_EMPTY(not_good_mutations)
GLOBAL_LIST_EMPTY(alias_mutations) //alias = type
GLOBAL_LIST_EMPTY(mutation_recipes)
GLOBAL_LIST_EMPTY(mutation_recipes)
+1 -2
View File
@@ -38,8 +38,7 @@ GLOBAL_LIST_EMPTY(servant_spawns) //Servants of Ratvar spawn here
GLOBAL_LIST_EMPTY(city_of_cogs_spawns) //Anyone entering the City of Cogs spawns here
GLOBAL_LIST_EMPTY(ruin_landmarks)
//away missions
GLOBAL_LIST_EMPTY(awaydestinations) //a list of landmarks that the warpgate can take you to
//away missions
GLOBAL_LIST_EMPTY(vr_spawnpoints)
//used by jump-to-area etc. Updated by area/updateName()
+1
View File
@@ -23,6 +23,7 @@ GLOBAL_LIST_EMPTY(joined_player_list) //all clients that have joined the game a
GLOBAL_LIST_EMPTY(silicon_mobs) //all silicon mobs
GLOBAL_LIST_EMPTY(mob_living_list) //all instances of /mob/living and subtypes
GLOBAL_LIST_EMPTY(carbon_list) //all instances of /mob/living/carbon and subtypes, notably does not contain brains or simple animals
GLOBAL_LIST_EMPTY(human_list) //all instances of /mob/living/carbon/human and subtypes
GLOBAL_LIST_EMPTY(ai_list)
GLOBAL_LIST_EMPTY(pai_list)
GLOBAL_LIST_EMPTY(available_ai_shells)
+4 -2
View File
@@ -32,6 +32,8 @@ GLOBAL_VAR(world_asset_log)
GLOBAL_PROTECT(world_asset_log)
GLOBAL_VAR(world_map_error_log)
GLOBAL_PROTECT(world_map_error_log)
GLOBAL_VAR(world_paper_log)
GLOBAL_PROTECT(world_paper_log)
GLOBAL_VAR(subsystem_log)
GLOBAL_PROTECT(subsystem_log)
GLOBAL_VAR(reagent_log)
@@ -49,10 +51,10 @@ GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src]
GLOBAL_PROTECT(lastsignalers)
GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was
GLOBAL_PROTECT(lawchanges)
GLOBAL_VAR(tgui_log)
GLOBAL_PROTECT(tgui_log)
GLOBAL_VAR(world_shuttle_log)
GLOBAL_PROTECT(world_shuttle_log)
GLOBAL_LIST_EMPTY(combatlog)
GLOBAL_PROTECT(combatlog)
GLOBAL_LIST_EMPTY(IClog)
+165
View File
@@ -0,0 +1,165 @@
/client
/**
* Assoc list with all the active maps - when a screen obj is added to
* a map, it's put in here as well.
*
* Format: list(<mapname> = list(/obj/screen))
*/
var/list/screen_maps = list()
/**
* A screen object, which acts as a container for turfs and other things
* you want to show on the map, which you usually attach to "vis_contents".
*/
/obj/screen
/**
* Map name assigned to this object.
* Automatically set by /client/proc/add_obj_to_map.
*/
var/assigned_map
/**
* Mark this object as garbage-collectible after you clean the map
* it was registered on.
*
* This could probably be changed to be a proc, for conditional removal.
* But for now, this works.
*/
var/del_on_map_removal = TRUE
/**
* A generic background object.
* It is also implicitly used to allocate a rectangle on the map, which will
* be used for auto-scaling the map.
*/
/obj/screen/background
name = "background"
icon = 'icons/mob/map_backgrounds.dmi'
icon_state = "clear"
layer = GAME_PLANE
plane = GAME_PLANE
/**
* Sets screen_loc of this screen object, in form of point coordinates,
* with optional pixel offset (px, py).
*
* If applicable, "assigned_map" has to be assigned before this proc call.
*/
/obj/screen/proc/set_position(x, y, px = 0, py = 0)
if(assigned_map)
screen_loc = "[assigned_map]:[x]:[px],[y]:[py]"
else
screen_loc = "[x]:[px],[y]:[py]"
/**
* Sets screen_loc to fill a rectangular area of the map.
*
* If applicable, "assigned_map" has to be assigned before this proc call.
*/
/obj/screen/proc/fill_rect(x1, y1, x2, y2)
if(assigned_map)
screen_loc = "[assigned_map]:[x1],[y1] to [x2],[y2]"
else
screen_loc = "[x1],[y1] to [x2],[y2]"
/**
* Registers screen obj with the client, which makes it visible on the
* assigned map, and becomes a part of the assigned map's lifecycle.
*/
/client/proc/register_map_obj(obj/screen/screen_obj)
if(!screen_obj.assigned_map)
CRASH("Can't register [screen_obj] without 'assigned_map' property.")
if(!screen_maps[screen_obj.assigned_map])
screen_maps[screen_obj.assigned_map] = list()
// NOTE: Possibly an expensive operation
var/list/screen_map = screen_maps[screen_obj.assigned_map]
if(!screen_map.Find(screen_obj))
screen_map += screen_obj
if(!screen.Find(screen_obj))
screen += screen_obj
/**
* Clears the map of registered screen objects.
*
* Not really needed most of the time, as the client's screen list gets reset
* on relog. any of the buttons are going to get caught by garbage collection
* anyway. they're effectively qdel'd.
*/
/client/proc/clear_map(map_name)
if(!map_name || !(map_name in screen_maps))
return FALSE
for(var/obj/screen/screen_obj in screen_maps[map_name])
screen_maps[map_name] -= screen_obj
if(screen_obj.del_on_map_removal)
qdel(screen_obj)
screen_maps -= map_name
/**
* Clears all the maps of registered screen objects.
*/
/client/proc/clear_all_maps()
for(var/map_name in screen_maps)
clear_map(map_name)
/**
* Creates a popup window with a basic map element in it, without any
* further initialization.
*
* Ratio is how many pixels by how many pixels (keep it simple).
*
* Returns a map name.
*/
/client/proc/create_popup(name, ratiox = 100, ratioy = 100)
winclone(src, "popupwindow", name)
var/list/winparams = list()
winparams["size"] = "[ratiox]x[ratioy]"
winparams["on-close"] = "handle-popup-close [name]"
winset(src, "[name]", list2params(winparams))
winshow(src, "[name]", 1)
var/list/params = list()
params["parent"] = "[name]"
params["type"] = "map"
params["size"] = "[ratiox]x[ratioy]"
params["anchor1"] = "0,0"
params["anchor2"] = "[ratiox],[ratioy]"
winset(src, "[name]_map", list2params(params))
return "[name]_map"
/**
* Create the popup, and get it ready for generic use by giving
* it a background.
*
* Width and height are multiplied by 64 by default.
*/
/client/proc/setup_popup(popup_name, width = 9, height = 9, \
tilesize = 2, bg_icon)
if(!popup_name)
return
clear_map("[popup_name]_map")
var/x_value = world.icon_size * tilesize * width
var/y_value = world.icon_size * tilesize * height
var/map_name = create_popup(popup_name, x_value, y_value)
var/obj/screen/background/background = new
background.assigned_map = map_name
background.fill_rect(1, 1, width, height)
if(bg_icon)
background.icon_state = bg_icon
register_map_obj(background)
return map_name
/**
* Closes a popup.
*/
/client/proc/close_popup(popup)
winshow(src, popup, 0)
handle_popup_close(popup)
/**
* When the popup closes in any way (player or proc call) it calls this.
*/
/client/verb/handle_popup_close(window_id as text)
set hidden = TRUE
clear_map("[window_id]_map")
+3 -12
View File
@@ -63,18 +63,9 @@
// And here are some good things for free:
// Now you can click through portals, wormholes, gateways, and teleporters while observing. -Sayu
/obj/machinery/gateway/centerstation/attack_ghost(mob/user)
if(awaygate)
user.forceMove(awaygate.loc)
else
to_chat(user, "[src] has no destination.")
return ..()
/obj/machinery/gateway/centeraway/attack_ghost(mob/user)
if(stationgate)
user.forceMove(stationgate.loc)
else
to_chat(user, "[src] has no destination.")
/obj/effect/gateway_portal_bumper/attack_ghost(mob/user)
if(gateway)
gateway.Transfer(user)
return ..()
/obj/machinery/teleport/hub/attack_ghost(mob/user)
@@ -56,6 +56,8 @@
/datum/config_entry/flag/log_adminchat // log admin chat messages
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_shuttle // log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
/datum/config_entry/flag/log_pda // log pda messages
/datum/config_entry/flag/log_telecomms // log telecomms messages
+24
View File
@@ -16,6 +16,7 @@ SUBSYSTEM_DEF(atoms)
/datum/controller/subsystem/atoms/Initialize(timeofday)
GLOB.fire_overlay.appearance_flags = RESET_COLOR
setupGenetics()
initialized = INITIALIZATION_INNEW_MAPLOAD
InitializeAtoms()
return ..()
@@ -106,6 +107,29 @@ SUBSYSTEM_DEF(atoms)
old_initialized = SSatoms.old_initialized
BadInitializeCalls = SSatoms.BadInitializeCalls
/datum/controller/subsystem/atoms/proc/setupGenetics()
var/list/mutations = subtypesof(/datum/mutation/human)
shuffle_inplace(mutations)
for(var/A in subtypesof(/datum/generecipe))
var/datum/generecipe/GR = A
GLOB.mutation_recipes[initial(GR.required)] = initial(GR.result)
for(var/i in 1 to LAZYLEN(mutations))
var/path = mutations[i] //byond gets pissy when we do it in one line
var/datum/mutation/human/B = new path ()
B.alias = "Mutation [i]"
GLOB.all_mutations[B.type] = B
GLOB.full_sequences[B.type] = generate_gene_sequence(B.blocks)
GLOB.alias_mutations[B.alias] = B.type
if(B.locked)
continue
if(B.quality == POSITIVE)
GLOB.good_mutations |= B
else if(B.quality == NEGATIVE)
GLOB.bad_mutations |= B
else if(B.quality == MINOR_NEGATIVE)
GLOB.not_good_mutations |= B
CHECK_TICK
/datum/controller/subsystem/atoms/proc/InitLog()
. = ""
for(var/path in BadInitializeCalls)
+15 -26
View File
@@ -334,6 +334,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
for (var/map in mapvotes)
if (!map)
mapvotes.Remove(map)
continue
if (!(map in global.config.maplist))
mapvotes.Remove(map)
continue
@@ -468,9 +469,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
else
return
possible_options += "Custom"
var/lvl_name
var/datum/space_level/level
possible_options = "Custom"
var/away_name
var/datum/space_level/away_level
var/answer = input("What kind ? ","Away/VR") as null|anything in possible_options
switch(answer)
@@ -480,34 +481,22 @@ GLOBAL_LIST_EMPTY(the_station_areas)
var/mapfile = input("Pick file:", "File") as null|file
if(!mapfile)
return
lvl_name = "[mapfile] custom"
to_chat(usr,"<span class='notice'>Loading [lvl_name]...</span>")
away_name = "[mapfile] custom"
to_chat(usr,"<span class='notice'>Loading [away_name]...</span>")
var/datum/map_template/template = new(mapfile, choice, ztraits)
level = template.load_new_z(ztraits)
away_level = template.load_new_z(ztraits)
else
lvl_name = answer
to_chat(usr,"<span class='notice'>Loading [lvl_name]...</span>")
var/datum/map_template/template = new(lvl_name, choice)
level = template.load_new_z(ztraits)
away_name = answer
to_chat(usr,"<span class='notice'>Loading [away_name]...</span>")
var/datum/map_template/template = new(away_name, choice)
away_level = template.load_new_z(ztraits)
message_admins("Admin [key_name_admin(usr)] has loaded [lvl_name] [choice].")
log_admin("Admin [key_name(usr)] has loaded [lvl_name] [choice].")
if(!level)
message_admins("Loading [lvl_name] failed!")
message_admins("Admin [key_name_admin(usr)] has loaded [away_name] away mission.")
log_admin("Admin [key_name(usr)] has loaded [away_name] away mission.")
if(!away_level)
message_admins("Loading [away_name] failed!")
return
if(choice == AWAY_MISSION_NAME && GLOB.the_gateway)
//Link any found away gate with station gate
var/obj/machinery/gateway/centeraway/new_gate
for(var/obj/machinery/gateway/centeraway/G in GLOB.machines)
if(G.z == level.z_value) //I'll have to refactor gateway shitcode before multi-away support.
new_gate = G
break
//Link station gate with away gate and remove wait time.
GLOB.the_gateway.awaygate = new_gate
GLOB.the_gateway.wait = world.time
/datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override, border_type_override)
UNTIL((!z || reservation_ready["[z]"]) && !clearing_reserved_turfs)
var/datum/turf_reservation/reserve = new type
+310 -39
View File
@@ -7,10 +7,9 @@ SUBSYSTEM_DEF(shuttle)
flags = SS_KEEP_TIMING|SS_NO_TICK_CHECK
runlevels = RUNLEVEL_SETUP | RUNLEVEL_GAME
var/obj/machinery/shuttle_manipulator/manipulator
var/list/mobile = list()
var/list/stationary = list()
var/list/beacons = list()
var/list/transit = list()
var/list/transit_requesters = list()
@@ -57,6 +56,15 @@ SUBSYSTEM_DEF(shuttle)
var/realtimeofstart = 0
var/datum/map_template/shuttle/selected
var/obj/docking_port/mobile/existing_shuttle
var/obj/docking_port/mobile/preview_shuttle
var/datum/map_template/shuttle/preview_template
var/datum/turf_reservation/preview_reservation
/datum/controller/subsystem/shuttle/Initialize(timeofday)
ordernum = rand(1, 9000)
@@ -76,13 +84,10 @@ SUBSYSTEM_DEF(shuttle)
WARNING("No /obj/docking_port/mobile/emergency/backup placed on the map!")
if(!supply)
WARNING("No /obj/docking_port/mobile/supply placed on the map!")
realtimeofstart = world.realtime
realtimeofstart = world.realtime
return ..()
/datum/controller/subsystem/shuttle/proc/initial_load()
if(!istype(manipulator))
CRASH("No shuttle manipulator found.")
for(var/s in stationary)
var/obj/docking_port/stationary/S = s
S.load_roundstart()
@@ -143,11 +148,13 @@ SUBSYSTEM_DEF(shuttle)
++alive
var/total = GLOB.joined_player_list.len
if(total <= 0)
return //no players no autoevac
if(alive / total <= threshold)
var/msg = "Automatically dispatching shuttle due to crew death."
var/msg = "Automatically dispatching emergency shuttle due to crew death."
message_admins(msg)
log_game("[msg] Alive: [alive], Roundstart: [total], Threshold: [threshold]")
log_shuttle("[msg] Alive: [alive], Roundstart: [total], Threshold: [threshold]")
emergencyNoRecall = TRUE
priority_announce("Catastrophic casualties detected: crisis shuttle protocols activated - jamming recall signals across all frequencies.")
if(emergency.timeLeft(1) > emergencyCallTime * 0.4)
@@ -172,6 +179,34 @@ SUBSYSTEM_DEF(shuttle)
return S
WARNING("couldn't find dock with id: [id]")
/datum/controller/subsystem/shuttle/proc/canEvac(mob/user)
var/srd = CONFIG_GET(number/shuttle_refuel_delay)
if(world.time - SSticker.round_start_time < srd)
to_chat(user, "<span class='alert'>The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before trying again.</span>")
return FALSE
switch(emergency.mode)
if(SHUTTLE_RECALL)
to_chat(user, "<span class='alert'>The emergency shuttle may not be called while returning to CentCom.</span>")
return FALSE
if(SHUTTLE_CALL)
to_chat(user, "<span class='alert'>The emergency shuttle is already on its way.</span>")
return FALSE
if(SHUTTLE_DOCKED)
to_chat(user, "<span class='alert'>The emergency shuttle is already here.</span>")
return FALSE
if(SHUTTLE_IGNITING)
to_chat(user, "<span class='alert'>The emergency shuttle is firing its engines to leave.</span>")
return FALSE
if(SHUTTLE_ESCAPE)
to_chat(user, "<span class='alert'>The emergency shuttle is moving away to a safe distance.</span>")
return FALSE
if(SHUTTLE_STRANDED)
to_chat(user, "<span class='alert'>The emergency shuttle has been disabled by CentCom.</span>")
return FALSE
return TRUE
/datum/controller/subsystem/shuttle/proc/requestEvac(mob/user, call_reason)
if(!emergency)
WARNING("requestEvac(): There is no emergency shuttle, but the \
@@ -185,35 +220,14 @@ SUBSYSTEM_DEF(shuttle)
manually, and then calling register() on the mobile docking port. \
Good luck.")
emergency = backup_shuttle
var/srd = CONFIG_GET(number/shuttle_refuel_delay)
if(world.time - SSticker.round_start_time < srd)
to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before trying again.")
return
switch(emergency.mode)
if(SHUTTLE_RECALL)
to_chat(user, "The emergency shuttle may not be called while returning to CentCom.")
return
if(SHUTTLE_CALL)
to_chat(user, "The emergency shuttle is already on its way.")
return
if(SHUTTLE_DOCKED)
to_chat(user, "The emergency shuttle is already here.")
return
if(SHUTTLE_IGNITING)
to_chat(user, "The emergency shuttle is firing its engines to leave.")
return
if(SHUTTLE_ESCAPE)
to_chat(user, "The emergency shuttle is moving away to a safe distance.")
return
if(SHUTTLE_STRANDED)
to_chat(user, "The emergency shuttle has been disabled by CentCom.")
return
if(!canEvac(user))
return
call_reason = trim(html_encode(call_reason))
if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH && GLOB.security_level > SEC_LEVEL_GREEN)
to_chat(user, "You must provide a reason.")
to_chat(user, "<span class='alert'>You must provide a reason.</span>")
return
var/area/signal_origin = get_area(user)
@@ -235,11 +249,11 @@ SUBSYSTEM_DEF(shuttle)
var/area/A = get_area(user)
log_game("[key_name(user)] has called the shuttle.")
deadchat_broadcast("<span class='deadsay'><span class='name'>[user.real_name]</span> has called the shuttle at <span class='name'>[A.name]</span>.</span>", user)
log_shuttle("[key_name(user)] has called the emergency shuttle.")
deadchat_broadcast(" has called the shuttle at <span class='name'>[A.name]</span>.", "<span class='name'>[user.real_name]</span>", user)
if(call_reason)
SSblackbox.record_feedback("text", "shuttle_reason", 1, "[call_reason]")
log_game("Shuttle call reason: [call_reason]")
log_shuttle("Shuttle call reason: [call_reason]")
message_admins("[ADMIN_LOOKUPFLW(user)] has called the shuttle. (<A HREF='?_src_=holder;[HrefToken()];trigger_centcom_recall=1'>TRIGGER CENTCOM RECALL</A>)")
/datum/controller/subsystem/shuttle/proc/centcom_recall(old_timer, admiral_message)
@@ -272,9 +286,9 @@ SUBSYSTEM_DEF(shuttle)
/datum/controller/subsystem/shuttle/proc/cancelEvac(mob/user)
if(canRecall())
emergency.cancel(get_area(user))
log_game("[key_name(user)] has recalled the shuttle.")
log_shuttle("[key_name(user)] has recalled the shuttle.")
message_admins("[ADMIN_LOOKUPFLW(user)] has recalled the shuttle.")
deadchat_broadcast("<span class='deadsay'><span class='name'>[user.real_name]</span> has recalled the shuttle from <span class='name'>[get_area_name(user, TRUE)]</span>.</span>", user)
deadchat_broadcast(" has recalled the shuttle from <span class='name'>[get_area_name(user, TRUE)]</span>.", "<span class='name'>[user.real_name]</span>", user)
return 1
/datum/controller/subsystem/shuttle/proc/canRecall()
@@ -294,7 +308,7 @@ SUBSYSTEM_DEF(shuttle)
else
if(emergency.timeLeft(1) < emergencyCallTime * 0.25)
return
return 1
return TRUE
/datum/controller/subsystem/shuttle/proc/autoEvac()
if (!SSticker.IsRoundInProgress())
@@ -322,7 +336,7 @@ SUBSYSTEM_DEF(shuttle)
if(callShuttle)
if(EMERGENCY_IDLE_OR_RECALLED)
emergency.request(null, set_coefficient = 2.5)
log_game("There is no means of calling the shuttle anymore. Shuttle automatically called.")
log_shuttle("There is no means of calling the emergency shuttle anymore. Shuttle automatically called.")
message_admins("All the communications consoles were destroyed and all AIs are inactive. Shuttle called.")
/datum/controller/subsystem/shuttle/proc/registerHostileEnvironment(datum/bad)
@@ -559,6 +573,14 @@ SUBSYSTEM_DEF(shuttle)
shuttle_purchased = SSshuttle.shuttle_purchased
lockdown = SSshuttle.lockdown
selected = SSshuttle.selected
existing_shuttle = SSshuttle.existing_shuttle
preview_shuttle = SSshuttle.preview_shuttle
preview_template = SSshuttle.preview_template
preview_reservation = SSshuttle.preview_reservation
/datum/controller/subsystem/shuttle/proc/is_in_shuttle_bounds(atom/A)
var/area/current = get_area(A)
@@ -641,3 +663,252 @@ SUBSYSTEM_DEF(shuttle)
message_admins("Round end vote passed. Shuttle has been auto-called.")
emergencyNoRecall = TRUE
endvote_passed = TRUE
/datum/controller/subsystem/shuttle/proc/action_load(datum/map_template/shuttle/loading_template, obj/docking_port/stationary/destination_port)
// Check for an existing preview
if(preview_shuttle && (loading_template != preview_template))
preview_shuttle.jumpToNullSpace()
preview_shuttle = null
preview_template = null
QDEL_NULL(preview_reservation)
if(!preview_shuttle)
if(load_template(loading_template))
preview_shuttle.linkup(loading_template, destination_port)
preview_template = loading_template
// get the existing shuttle information, if any
var/timer = 0
var/mode = SHUTTLE_IDLE
var/obj/docking_port/stationary/D
if(istype(destination_port))
D = destination_port
else if(existing_shuttle)
timer = existing_shuttle.timer
mode = existing_shuttle.mode
D = existing_shuttle.get_docked()
if(!D)
D = generate_transit_dock(preview_shuttle)
if(!D)
CRASH("No dock found for preview shuttle ([preview_template.name]), aborting.")
var/result = preview_shuttle.canDock(D)
// truthy value means that it cannot dock for some reason
// but we can ignore the someone else docked error because we'll
// be moving into their place shortly
if((result != SHUTTLE_CAN_DOCK) && (result != SHUTTLE_SOMEONE_ELSE_DOCKED))
WARNING("Template shuttle [preview_shuttle] cannot dock at [D] ([result]).")
return
if(existing_shuttle)
existing_shuttle.jumpToNullSpace()
var/list/force_memory = preview_shuttle.movement_force
preview_shuttle.movement_force = list("KNOCKDOWN" = 0, "THROW" = 0)
preview_shuttle.initiate_docking(D)
preview_shuttle.movement_force = force_memory
. = preview_shuttle
// Shuttle state involves a mode and a timer based on world.time, so
// plugging the existing shuttles old values in works fine.
preview_shuttle.timer = timer
preview_shuttle.mode = mode
preview_shuttle.register()
// TODO indicate to the user that success happened, rather than just
// blanking the modification tab
preview_shuttle = null
preview_template = null
existing_shuttle = null
selected = null
QDEL_NULL(preview_reservation)
/datum/controller/subsystem/shuttle/proc/load_template(datum/map_template/shuttle/S)
. = FALSE
// load shuttle template, centred at shuttle import landmark,
preview_reservation = SSmapping.RequestBlockReservation(S.width, S.height, SSmapping.transit.z_value, /datum/turf_reservation/transit)
if(!preview_reservation)
CRASH("failed to reserve an area for shuttle template loading")
var/turf/BL = TURF_FROM_COORDS_LIST(preview_reservation.bottom_left_coords)
S.load(BL, centered = FALSE, register = FALSE)
var/affected = S.get_affected_turfs(BL, centered=FALSE)
var/found = 0
// Search the turfs for docking ports
// - We need to find the mobile docking port because that is the heart of
// the shuttle.
// - We need to check that no additional ports have slipped in from the
// template, because that causes unintended behaviour.
for(var/T in affected)
for(var/obj/docking_port/P in T)
if(istype(P, /obj/docking_port/mobile))
found++
if(found > 1)
qdel(P, force=TRUE)
log_world("Map warning: Shuttle Template [S.mappath] has multiple mobile docking ports.")
else
preview_shuttle = P
if(istype(P, /obj/docking_port/stationary))
log_world("Map warning: Shuttle Template [S.mappath] has a stationary docking port.")
if(!found)
var/msg = "load_template(): Shuttle Template [S.mappath] has no mobile docking port. Aborting import."
for(var/T in affected)
var/turf/T0 = T
T0.empty()
message_admins(msg)
WARNING(msg)
return
//Everything fine
S.post_load(preview_shuttle)
return TRUE
/datum/controller/subsystem/shuttle/proc/unload_preview()
if(preview_shuttle)
preview_shuttle.jumpToNullSpace()
preview_shuttle = null
/datum/controller/subsystem/shuttle/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ShuttleManipulator", name, 800, 600, master_ui, state)
ui.open()
/datum/controller/subsystem/shuttle/ui_data(mob/user)
var/list/data = list()
data["tabs"] = list("Status", "Templates", "Modification")
// Templates panel
data["templates"] = list()
var/list/templates = data["templates"]
data["templates_tabs"] = list()
data["selected"] = list()
for(var/shuttle_id in SSmapping.shuttle_templates)
var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id]
if(!templates[S.port_id])
data["templates_tabs"] += S.port_id
templates[S.port_id] = list(
"port_id" = S.port_id,
"templates" = list())
var/list/L = list()
L["name"] = S.name
L["shuttle_id"] = S.shuttle_id
L["port_id"] = S.port_id
L["description"] = S.description
L["admin_notes"] = S.admin_notes
if(selected == S)
data["selected"] = L
templates[S.port_id]["templates"] += list(L)
data["templates_tabs"] = sortList(data["templates_tabs"])
data["existing_shuttle"] = null
// Status panel
data["shuttles"] = list()
for(var/i in mobile)
var/obj/docking_port/mobile/M = i
var/timeleft = M.timeLeft(1)
var/list/L = list()
L["name"] = M.name
L["id"] = M.id
L["timer"] = M.timer
L["timeleft"] = M.getTimerStr()
if (timeleft > 1 HOURS)
L["timeleft"] = "Infinity"
L["can_fast_travel"] = M.timer && timeleft >= 50
L["can_fly"] = TRUE
if(istype(M, /obj/docking_port/mobile/emergency))
L["can_fly"] = FALSE
else if(!M.destination)
L["can_fast_travel"] = FALSE
if (M.mode != SHUTTLE_IDLE)
L["mode"] = capitalize(M.mode)
L["status"] = M.getDbgStatusText()
if(M == existing_shuttle)
data["existing_shuttle"] = L
data["shuttles"] += list(L)
return data
/datum/controller/subsystem/shuttle/ui_act(action, params)
if(..())
return
var/mob/user = usr
// Preload some common parameters
var/shuttle_id = params["shuttle_id"]
var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id]
switch(action)
if("select_template")
if(S)
existing_shuttle = getShuttle(S.port_id)
selected = S
. = TRUE
if("jump_to")
if(params["type"] == "mobile")
for(var/i in mobile)
var/obj/docking_port/mobile/M = i
if(M.id == params["id"])
user.forceMove(get_turf(M))
. = TRUE
break
if("fly")
for(var/i in mobile)
var/obj/docking_port/mobile/M = i
if(M.id == params["id"])
. = TRUE
M.admin_fly_shuttle(user)
break
if("fast_travel")
for(var/i in mobile)
var/obj/docking_port/mobile/M = i
if(M.id == params["id"] && M.timer && M.timeLeft(1) >= 50)
M.setTimer(50)
. = TRUE
message_admins("[key_name_admin(usr)] fast travelled [M]")
log_admin("[key_name(usr)] fast travelled [M]")
SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[M.name]")
break
if("preview")
if(S)
. = TRUE
unload_preview()
load_template(S)
if(preview_shuttle)
preview_template = S
user.forceMove(get_turf(preview_shuttle))
if("load")
if(existing_shuttle == backup_shuttle)
// TODO make the load button disabled
WARNING("The shuttle that the selected shuttle will replace \
is the backup shuttle. Backup shuttle is required to be \
intact for round sanity.")
else if(S)
. = TRUE
// If successful, returns the mobile docking port
var/obj/docking_port/mobile/mdp = action_load(S)
if(mdp)
user.forceMove(get_turf(mdp))
message_admins("[key_name_admin(usr)] loaded [mdp] with the shuttle manipulator.")
log_admin("[key_name(usr)] loaded [mdp] with the shuttle manipulator.</span>")
SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[mdp.name]")
+1 -1
View File
@@ -11,7 +11,7 @@ SUBSYSTEM_DEF(tgui)
var/basehtml // The HTML base used for all UIs.
/datum/controller/subsystem/tgui/PreInit()
basehtml = file2text('tgui-next/packages/tgui/public/tgui-main.html')
basehtml = file2text('tgui/packages/tgui/public/tgui.html')
/datum/controller/subsystem/tgui/Shutdown()
close_all_uis()
+463
View File
@@ -0,0 +1,463 @@
/datum/component/personal_crafting/Initialize()
if(ismob(parent))
RegisterSignal(parent, COMSIG_MOB_CLIENT_LOGIN, .proc/create_mob_button)
/datum/component/personal_crafting/proc/create_mob_button(mob/user, client/CL)
var/datum/hud/H = user.hud_used
var/obj/screen/craft/C = new()
C.icon = H.ui_style
H.static_inventory += C
CL.screen += C
RegisterSignal(C, COMSIG_CLICK, .proc/component_ui_interact)
/datum/component/personal_crafting
var/busy
var/viewing_category = 1 //typical powergamer starting on the Weapons tab
var/viewing_subcategory = 1
var/list/categories = list(
CAT_WEAPONRY = list(
CAT_WEAPON,
CAT_AMMO,
),
CAT_ROBOT = CAT_NONE,
CAT_MISC = list(
CAT_MISCELLANEOUS,
CAT_TOOL,
CAT_FURNITURE,
),
CAT_PRIMAL = CAT_NONE,
CAT_FOOD = list(
CAT_BREAD,
CAT_BURGER,
CAT_CAKE,
CAT_DONUT,
CAT_EGG,
CAT_ICE,
CAT_MEAT,
CAT_MEXICAN,
CAT_MISCFOOD,
CAT_PASTRY,
CAT_PIE,
CAT_PIZZA,
CAT_SEAFOOD,
CAT_SALAD,
CAT_SANDWICH,
CAT_SOUP,
CAT_SPAGHETTI,
),
CAT_DRINK = CAT_NONE,
CAT_CLOTHING = CAT_NONE,
)
var/cur_category = CAT_NONE
var/cur_subcategory = CAT_NONE
var/datum/action/innate/crafting/button
var/display_craftable_only = FALSE
var/display_compact = TRUE
/* This is what procs do:
get_environment - gets a list of things accessable for crafting by user
get_surroundings - takes a list of things and makes a list of key-types to values-amounts of said type in the list
check_contents - takes a recipe and a key-type list and checks if said recipe can be done with available stuff
check_tools - takes recipe, a key-type list, and a user and checks if there are enough tools to do the stuff, checks bugs one level deep
construct_item - takes a recipe and a user, call all the checking procs, calls do_after, checks all the things again, calls del_reqs, creates result, calls CheckParts of said result with argument being list returned by deel_reqs
del_reqs - takes recipe and a user, loops over the recipes reqs var and tries to find everything in the list make by get_environment and delete it/add to parts list, then returns the said list
*/
/**
* Check that the contents of the recipe meet the requirements.
*
* user: The /mob that initated the crafting.
* R: The /datum/crafting_recipe being attempted.
* contents: List of items to search for R's reqs.
*/
/datum/component/personal_crafting/proc/check_contents(atom/a, datum/crafting_recipe/R, list/contents)
var/list/item_instances = contents["instances"]
contents = contents["other"]
var/list/requirements_list = list()
// Process all requirements
for(var/requirement_path in R.reqs)
// Check we have the appropriate amount available in the contents list
var/needed_amount = R.reqs[requirement_path]
for(var/content_item_path in contents)
// Right path and not blacklisted
if(!ispath(content_item_path, requirement_path) || R.blacklist.Find(content_item_path))
continue
needed_amount -= contents[content_item_path]
if(needed_amount <= 0)
break
if(needed_amount > 0)
return FALSE
// Store the instances of what we will use for R.check_requirements() for requirement_path
var/list/instances_list = list()
for(var/instance_path in item_instances)
if(ispath(instance_path, requirement_path))
instances_list += item_instances[instance_path]
requirements_list[requirement_path] = instances_list
for(var/requirement_path in R.chem_catalysts)
if(contents[requirement_path] < R.chem_catalysts[requirement_path])
return FALSE
return R.check_requirements(a, requirements_list)
/datum/component/personal_crafting/proc/get_environment(atom/a, list/blacklist = null, radius_range = 1)
. = list()
if(!isturf(a.loc))
return
for(var/atom/movable/AM in range(radius_range, a))
if(AM.flags_1 & HOLOGRAM_1)
continue
. += AM
/datum/component/personal_crafting/proc/get_surroundings(atom/a)
. = list()
.["tool_behaviour"] = list()
.["other"] = list()
.["instances"] = list()
for(var/obj/item/I in get_environment(a))
if(I.flags_1 & HOLOGRAM_1)
continue
if(.["instances"][I.type])
.["instances"][I.type] += I
else
.["instances"][I.type] = list(I)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
.["other"][I.type] += S.amount
else if(I.tool_behaviour)
.["tool_behaviour"] += I.tool_behaviour
.["other"][I.type] += 1
else
if(istype(I, /obj/item/reagent_containers))
var/obj/item/reagent_containers/RC = I
if(RC.is_drainable())
for(var/datum/reagent/A in RC.reagents.reagent_list)
.["other"][A.type] += A.volume
.["other"][I.type] += 1
/datum/component/personal_crafting/proc/check_tools(atom/a, datum/crafting_recipe/R, list/contents)
if(!R.tools.len)
return TRUE
var/list/possible_tools = list()
var/list/present_qualities = list()
present_qualities |= contents["tool_behaviour"]
for(var/obj/item/I in a.contents)
if(istype(I, /obj/item/storage))
for(var/obj/item/SI in I.contents)
possible_tools += SI.type
if(SI.tool_behaviour)
present_qualities.Add(SI.tool_behaviour)
possible_tools += I.type
if(I.tool_behaviour)
present_qualities.Add(I.tool_behaviour)
possible_tools |= contents["other"]
main_loop:
for(var/A in R.tools)
if(A in present_qualities)
continue
else
for(var/I in possible_tools)
if(ispath(I, A))
continue main_loop
return FALSE
return TRUE
/datum/component/personal_crafting/proc/construct_item(atom/a, datum/crafting_recipe/R)
var/list/contents = get_surroundings(a)
var/send_feedback = 1
if(check_contents(a, R, contents))
if(check_tools(a, R, contents))
//If we're a mob we'll try a do_after; non mobs will instead instantly construct the item
if(ismob(a) && !do_after(a, R.time, target = a))
return "."
contents = get_surroundings(a)
if(!check_contents(a, R, contents))
return ", missing component."
if(!check_tools(a, R, contents))
return ", missing tool."
var/list/parts = del_reqs(R, a)
var/atom/movable/I = new R.result (get_turf(a.loc))
I.CheckParts(parts, R)
if(send_feedback)
SSblackbox.record_feedback("tally", "object_crafted", 1, I.type)
return I //Send the item back to whatever called this proc so it can handle whatever it wants to do with the new item
return ", missing tool."
return ", missing component."
/*Del reqs works like this:
Loop over reqs var of the recipe
Set var amt to the value current cycle req is pointing to, its amount of type we need to delete
Get var/surroundings list of things accessable to crafting by get_environment()
Check the type of the current cycle req
If its reagent then do a while loop, inside it try to locate() reagent containers, inside such containers try to locate needed reagent, if there isnt remove thing from surroundings
If there is enough reagent in the search result then delete the needed amount, create the same type of reagent with the same data var and put it into deletion list
If there isnt enough take all of that reagent from the container, put into deletion list, substract the amt var by the volume of reagent, remove the container from surroundings list and keep searching
While doing above stuff check deletion list if it already has such reagnet, if yes merge instead of adding second one
If its stack check if it has enough amount
If yes create new stack with the needed amount and put in into deletion list, substract taken amount from the stack
If no put all of the stack in the deletion list, substract its amount from amt and keep searching
While doing above stuff check deletion list if it already has such stack type, if yes try to merge them instead of adding new one
If its anything else just locate() in in the list in a while loop, each find --s the amt var and puts the found stuff in deletion loop
Then do a loop over parts var of the recipe
Do similar stuff to what we have done above, but now in deletion list, until the parts conditions are satisfied keep taking from the deletion list and putting it into parts list for return
After its done loop over deletion list and delete all the shit that wasnt taken by parts loop
del_reqs return the list of parts resulting object will receive as argument of CheckParts proc, on the atom level it will add them all to the contents, on all other levels it calls ..() and does whatever is needed afterwards but from contents list already
*/
/datum/component/personal_crafting/proc/del_reqs(datum/crafting_recipe/R, atom/a)
var/list/surroundings
var/list/Deletion = list()
. = list()
var/data
var/amt
main_loop:
for(var/A in R.reqs)
amt = R.reqs[A]
surroundings = get_environment(a, R.blacklist)
surroundings -= Deletion
if(ispath(A, /datum/reagent))
var/datum/reagent/RG = new A
var/datum/reagent/RGNT
while(amt > 0)
var/obj/item/reagent_containers/RC = locate() in surroundings
RG = RC.reagents.get_reagent(A)
if(RG)
if(!locate(RG.type) in Deletion)
Deletion += new RG.type()
if(RG.volume > amt)
RG.volume -= amt
data = RG.data
RC.reagents.conditional_update(RC)
RG = locate(RG.type) in Deletion
RG.volume = amt
RG.data += data
continue main_loop
else
surroundings -= RC
amt -= RG.volume
RC.reagents.reagent_list -= RG
RC.reagents.conditional_update(RC)
RGNT = locate(RG.type) in Deletion
RGNT.volume += RG.volume
RGNT.data += RG.data
qdel(RG)
RC.on_reagent_change()
else
surroundings -= RC
else if(ispath(A, /obj/item/stack))
var/obj/item/stack/S
var/obj/item/stack/SD
while(amt > 0)
S = locate(A) in surroundings
if(S.amount >= amt)
if(!locate(S.type) in Deletion)
SD = new S.type()
Deletion += SD
S.use(amt)
SD = locate(S.type) in Deletion
SD.amount += amt
continue main_loop
else
amt -= S.amount
if(!locate(S.type) in Deletion)
Deletion += S
else
data = S.amount
S = locate(S.type) in Deletion
S.add(data)
surroundings -= S
else
var/atom/movable/I
while(amt > 0)
I = locate(A) in surroundings
Deletion += I
surroundings -= I
amt--
var/list/partlist = list(R.parts.len)
for(var/M in R.parts)
partlist[M] = R.parts[M]
for(var/A in R.parts)
if(istype(A, /datum/reagent))
var/datum/reagent/RG = locate(A) in Deletion
if(RG.volume > partlist[A])
RG.volume = partlist[A]
. += RG
Deletion -= RG
continue
else if(istype(A, /obj/item/stack))
var/obj/item/stack/ST = locate(A) in Deletion
if(ST.amount > partlist[A])
ST.amount = partlist[A]
. += ST
Deletion -= ST
continue
else
while(partlist[A] > 0)
var/atom/movable/AM = locate(A) in Deletion
. += AM
Deletion -= AM
partlist[A] -= 1
while(Deletion.len)
var/DL = Deletion[Deletion.len]
Deletion.Cut(Deletion.len)
qdel(DL)
/datum/component/personal_crafting/proc/component_ui_interact(obj/screen/craft/image, location, control, params, user)
if(user == parent)
ui_interact(user)
//For the UI related things we're going to assume the user is a mob rather than typesetting it to an atom as the UI isn't generated if the parent is an atom
/datum/component/personal_crafting/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_turf_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
cur_category = categories[1]
if(islist(categories[cur_category]))
var/list/subcats = categories[cur_category]
cur_subcategory = subcats[1]
else
cur_subcategory = CAT_NONE
ui = new(user, src, ui_key, "PersonalCrafting", "Crafting Menu", 700, 800, master_ui, state)
ui.open()
/datum/component/personal_crafting/ui_data(mob/user)
var/list/data = list()
data["busy"] = busy
data["category"] = cur_category
data["subcategory"] = cur_subcategory
data["display_craftable_only"] = display_craftable_only
data["display_compact"] = display_compact
var/list/surroundings = get_surroundings(user)
var/list/craftability = list()
for(var/rec in GLOB.crafting_recipes)
var/datum/crafting_recipe/R = rec
if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
continue
if((R.category != cur_category) || (R.subcategory != cur_subcategory))
continue
craftability["[REF(R)]"] = check_contents(user, R, surroundings)
data["craftability"] = craftability
return data
/datum/component/personal_crafting/ui_static_data(mob/user)
var/list/data = list()
var/list/crafting_recipes = list()
for(var/rec in GLOB.crafting_recipes)
var/datum/crafting_recipe/R = rec
if(R.name == "") //This is one of the invalid parents that sneaks in
continue
if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
continue
if(isnull(crafting_recipes[R.category]))
crafting_recipes[R.category] = list()
if(R.subcategory == CAT_NONE)
crafting_recipes[R.category] += list(build_recipe_data(R))
else
if(isnull(crafting_recipes[R.category][R.subcategory]))
crafting_recipes[R.category][R.subcategory] = list()
crafting_recipes[R.category]["has_subcats"] = TRUE
crafting_recipes[R.category][R.subcategory] += list(build_recipe_data(R))
data["crafting_recipes"] = crafting_recipes
return data
/datum/component/personal_crafting/ui_act(action, params)
if(..())
return
switch(action)
if("make")
var/mob/user = usr
var/datum/crafting_recipe/TR = locate(params["recipe"]) in GLOB.crafting_recipes
busy = TRUE
ui_interact(user)
var/atom/movable/result = construct_item(user, TR)
if(!istext(result)) //We made an item and didn't get a fail message
if(ismob(user) && isitem(result)) //In case the user is actually possessing a non mob like a machine
user.put_in_hands(result)
else
result.forceMove(user.drop_location())
to_chat(user, "<span class='notice'>[TR.name] constructed.</span>")
else
to_chat(user, "<span class='warning'>Construction failed[result]</span>")
busy = FALSE
if("toggle_recipes")
display_craftable_only = !display_craftable_only
. = TRUE
if("toggle_compact")
display_compact = !display_compact
. = TRUE
if("set_category")
if(!isnull(params["category"]))
cur_category = params["category"]
if(!isnull(params["subcategory"]))
if(params["subcategory"] == "0")
cur_subcategory = ""
else
cur_subcategory = params["subcategory"]
. = TRUE
/datum/component/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R)
var/list/data = list()
data["name"] = R.name
data["ref"] = "[REF(R)]"
var/req_text = ""
var/tool_text = ""
var/catalyst_text = ""
for(var/a in R.reqs)
//We just need the name, so cheat-typecast to /atom for speed (even tho Reagents are /datum they DO have a "name" var)
//Also these are typepaths so sadly we can't just do "[a]"
var/atom/A = a
req_text += " [R.reqs[A]] [initial(A.name)],"
req_text = replacetext(req_text,",","",-1)
data["req_text"] = req_text
for(var/a in R.chem_catalysts)
var/atom/A = a //cheat-typecast
catalyst_text += " [R.chem_catalysts[A]] [initial(A.name)],"
catalyst_text = replacetext(catalyst_text,",","",-1)
data["catalyst_text"] = catalyst_text
for(var/a in R.tools)
if(ispath(a, /obj/item))
var/obj/item/b = a
tool_text += " [initial(b.name)],"
else
tool_text += " [a],"
tool_text = replacetext(tool_text,",","",-1)
data["tool_text"] = tool_text
return data
//Mind helpers
/datum/mind/proc/teach_crafting_recipe(R)
if(!learned_recipes)
learned_recipes = list()
learned_recipes |= R
+153
View File
@@ -0,0 +1,153 @@
///Global GPS_list. All GPS components get saved in here for easy reference.
GLOBAL_LIST_EMPTY(GPS_list)
///GPS component. Atoms that have this show up on gps. Pretty simple stuff.
/datum/component/gps
var/gpstag = "COM0"
var/tracking = TRUE
var/emped = FALSE
/datum/component/gps/Initialize(_gpstag = "COM0")
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
gpstag = _gpstag
GLOB.GPS_list += src
/datum/component/gps/Destroy()
GLOB.GPS_list -= src
return ..()
///GPS component subtype. Only gps/item's can be used to open the UI.
/datum/component/gps/item
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
/datum/component/gps/item/Initialize(_gpstag = "COM0", emp_proof = FALSE)
. = ..()
if(. == COMPONENT_INCOMPATIBLE || !isitem(parent))
return COMPONENT_INCOMPATIBLE
var/atom/A = parent
A.add_overlay("working")
A.name = "[initial(A.name)] ([gpstag])"
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/interact)
if(!emp_proof)
RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/on_emp_act)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/on_AltClick)
///Called on COMSIG_ITEM_ATTACK_SELF
/datum/component/gps/item/proc/interact(datum/source, mob/user)
if(user)
ui_interact(user)
///Called on COMSIG_PARENT_EXAMINE
/datum/component/gps/item/proc/on_examine(datum/source, mob/user, list/examine_list)
examine_list += "<span class='notice'>Alt-click to switch it [tracking ? "off":"on"].</span>"
///Called on COMSIG_ATOM_EMP_ACT
/datum/component/gps/item/proc/on_emp_act(datum/source, severity)
emped = TRUE
var/atom/A = parent
A.cut_overlay("working")
A.add_overlay("emp")
addtimer(CALLBACK(src, .proc/reboot), 300, TIMER_UNIQUE|TIMER_OVERRIDE) //if a new EMP happens, remove the old timer so it doesn't reactivate early
SStgui.close_uis(src) //Close the UI control if it is open.
///Restarts the GPS after getting turned off by an EMP.
/datum/component/gps/item/proc/reboot()
emped = FALSE
var/atom/A = parent
A.cut_overlay("emp")
A.add_overlay("working")
///Calls toggletracking
/datum/component/gps/item/proc/on_AltClick(datum/source, mob/user)
toggletracking(user)
///Toggles the tracking for the gps
/datum/component/gps/item/proc/toggletracking(mob/user)
if(!user.canUseTopic(parent, BE_CLOSE))
return //user not valid to use gps
if(emped)
to_chat(user, "<span class='warning'>It's busted!</span>")
return
var/atom/A = parent
if(tracking)
A.cut_overlay("working")
to_chat(user, "<span class='notice'>[parent] is no longer tracking, or visible to other GPS devices.</span>")
tracking = FALSE
else
A.add_overlay("working")
to_chat(user, "<span class='notice'>[parent] is now tracking, and visible to other GPS devices.</span>")
tracking = TRUE
/datum/component/gps/item/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
if(emped)
to_chat(user, "<span class='hear'>[parent] fizzles weakly.</span>")
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
// Variable window height, depending on how many GPS units there are
// to show, clamped to relatively safe range.
var/gps_window_height = clamp(325 + GLOB.GPS_list.len * 14, 325, 700)
ui = new(user, src, ui_key, "Gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height
ui.open()
ui.set_autoupdate(state = updating)
/datum/component/gps/item/ui_data(mob/user)
var/list/data = list()
data["power"] = tracking
data["tag"] = gpstag
data["updating"] = updating
data["globalmode"] = global_mode
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
return data
var/turf/curr = get_turf(parent)
data["currentArea"] = "[get_area_name(curr, TRUE)]"
data["currentCoords"] = "[curr.x], [curr.y], [curr.z]"
var/list/signals = list()
data["signals"] = list()
for(var/gps in GLOB.GPS_list)
var/datum/component/gps/G = gps
if(G.emped || !G.tracking || G == src)
continue
var/turf/pos = get_turf(G.parent)
if(!pos || !global_mode && pos.z != curr.z)
continue
var/list/signal = list()
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
signal["coords"] = "[pos.x], [pos.y], [pos.z]"
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
return data
/datum/component/gps/item/ui_act(action, params)
if(..())
return
switch(action)
if("rename")
var/atom/parentasatom = parent
var/a = stripped_input(usr, "Please enter desired tag.", parentasatom.name, gpstag, 20)
if (!a)
return
gpstag = a
. = TRUE
parentasatom.name = "global positioning system ([gpstag])"
if("power")
toggletracking(usr)
. = TRUE
if("updating")
updating = !updating
. = TRUE
if("globalmode")
global_mode = !global_mode
. = TRUE
+21 -24
View File
@@ -24,16 +24,17 @@ GLOBAL_LIST_EMPTY(uplinks)
var/unlock_note
var/unlock_code
var/failsafe_code
var/datum/ui_state/checkstate
var/compact_mode = FALSE
var/debug = FALSE
var/saved_player_population = 0
var/list/filters = list()
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate, datum/traitor_class/traitor_class)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/interact)
if(istype(parent, /obj/item/implant))
@@ -65,7 +66,6 @@ GLOBAL_LIST_EMPTY(uplinks)
active = _enabled
gamemode = _gamemode
telecrystals = starting_tc
checkstate = _checkstate
if(!lockable)
active = TRUE
locked = FALSE
@@ -136,13 +136,13 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
state = checkstate ? checkstate : state
active = TRUE
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "uplink", name, 620, 580, master_ui, state)
ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input.
ui.set_style("syndicate")
ui = new(user, src, ui_key, "Uplink", name, 620, 580, master_ui, state)
// This UI is only ever opened by one person,
// and never is updated outside of user input.
ui.set_autoupdate(FALSE)
ui.open()
/datum/component/uplink/ui_host(mob/user)
@@ -157,8 +157,7 @@ GLOBAL_LIST_EMPTY(uplinks)
var/list/data = list()
data["telecrystals"] = telecrystals
data["lockable"] = lockable
data["compact_mode"] = compact_mode
data["compactMode"] = compact_mode
return data
/datum/component/uplink/ui_static_data(mob/user)
@@ -192,21 +191,16 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/ui_act(action, params)
if(!active)
return
switch(action)
if("buy")
var/item = params["item"]
var/item_name = params["name"]
var/list/buyable_items = list()
for(var/category in uplink_items)
buyable_items += uplink_items[category]
if(item in buyable_items)
var/datum/uplink_item/I = buyable_items[item]
//check to make sure people cannot buy items when the player pop is below the requirement
if(GLOB.joined_player_list.len >= I.player_minimum)
MakePurchase(usr, I)
. = TRUE
if(item_name in buyable_items)
var/datum/uplink_item/I = buyable_items[item_name]
MakePurchase(usr, I)
return TRUE
if("lock")
active = FALSE
locked = TRUE
@@ -215,9 +209,10 @@ GLOBAL_LIST_EMPTY(uplinks)
SStgui.close_uis(src)
if("select")
selected_cat = params["category"]
return TRUE
if("compact_toggle")
compact_mode = !compact_mode
return TRUE
return TRUE
/datum/component/uplink/proc/MakePurchase(mob/user, datum/uplink_item/U)
if(!istype(U))
@@ -262,12 +257,12 @@ GLOBAL_LIST_EMPTY(uplinks)
var/obj/item/pda/master = parent
if(trim(lowertext(new_ring_text)) != trim(lowertext(unlock_code)))
if(trim(lowertext(new_ring_text)) == trim(lowertext(failsafe_code)))
failsafe()
failsafe(user)
return COMPONENT_STOP_RINGTONE_CHANGE
return
locked = FALSE
interact(null, user)
to_chat(user, "The PDA softly beeps.")
to_chat(user, "<span class='hear'>The PDA softly beeps.</span>")
user << browse(null, "window=pda")
master.mode = 0
return COMPONENT_STOP_RINGTONE_CHANGE
@@ -279,7 +274,7 @@ GLOBAL_LIST_EMPTY(uplinks)
var/frequency = arguments[1]
if(frequency != unlock_code)
if(frequency == failsafe_code)
failsafe()
failsafe(master.loc)
return
locked = FALSE
if(ismob(master.loc))
@@ -306,7 +301,7 @@ GLOBAL_LIST_EMPTY(uplinks)
else if(istype(parent,/obj/item/radio))
unlock_note = "<B>Radio Frequency:</B> [format_frequency(unlock_code)] ([P.name])."
else if(istype(parent,/obj/item/pen))
unlock_note = "<B>Uplink Degrees:</B> [unlock_code] ([P.name])."
unlock_note = "<B>Uplink Degrees:</B> [english_list(unlock_code)] ([P.name])."
/datum/component/uplink/proc/generate_code()
if(istype(parent,/obj/item/pda))
@@ -316,11 +311,13 @@ GLOBAL_LIST_EMPTY(uplinks)
else if(istype(parent,/obj/item/pen))
return rand(1, 360)
/datum/component/uplink/proc/failsafe()
/datum/component/uplink/proc/failsafe(mob/living/carbon/user)
if(!parent)
return
var/turf/T = get_turf(parent)
if(!T)
return
message_admins("[ADMIN_LOOKUPFLW(user)] has triggered an uplink failsafe explosion at [AREACOORD(T)] The owner of the uplink was [ADMIN_LOOKUPFLW(owner)].")
log_game("[key_name(user)] triggered an uplink failsafe explosion. The owner of the uplink was [key_name(owner)].")
explosion(T,1,2,3)
qdel(parent) //Alternatively could brick the uplink.
+15 -2
View File
@@ -15,6 +15,7 @@
var/mob/living/holder
var/delete_species = TRUE //Set to FALSE when a body is scanned by a cloner to fix #38875
var/mutation_index[DNA_MUTATION_BLOCKS] //List of which mutations this carbon has and its assigned block
var/default_mutation_genes[DNA_MUTATION_BLOCKS] //List of the default genes from this mutation to allow DNA Scanner highlighting
var/stability = 100
var/scrambled = FALSE //Did we take something like mutagen? In that case we cant get our genes scanned to instantly cheese all the powers.
var/skin_tone_override //because custom skin tones are not found in the skin_tones global list.
@@ -58,6 +59,7 @@
H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA
if(transfer_SE)
destination.dna.mutation_index = mutation_index
destination.dna.default_mutation_genes = default_mutation_genes
destination.dna.update_body_size(old_size)
@@ -66,6 +68,7 @@
/datum/dna/proc/copy_dna(datum/dna/new_dna)
new_dna.unique_enzymes = unique_enzymes
new_dna.mutation_index = mutation_index
new_dna.default_mutation_genes = default_mutation_genes
new_dna.uni_identity = uni_identity
new_dna.blood_type = blood_type
new_dna.skin_tone_override = skin_tone_override
@@ -160,15 +163,18 @@
if(!LAZYLEN(mutations_temp))
return
mutation_index.Cut()
default_mutation_genes.Cut()
shuffle_inplace(mutations_temp)
if(ismonkey(holder))
mutations |= new RACEMUT(MUT_NORMAL)
mutation_index[RACEMUT] = GET_SEQUENCE(RACEMUT)
else
mutation_index[RACEMUT] = create_sequence(RACEMUT, FALSE)
default_mutation_genes[RACEMUT] = mutation_index[RACEMUT]
for(var/i in 2 to DNA_MUTATION_BLOCKS)
var/datum/mutation/human/M = mutations_temp[i]
mutation_index[M.type] = create_sequence(M.type, FALSE,M.difficulty)
mutation_index[M.type] = create_sequence(M.type, FALSE, M.difficulty)
default_mutation_genes[M.type] = mutation_index[M.type]
shuffle_inplace(mutation_index)
//Used to generate original gene sequences for every mutation
@@ -389,7 +395,7 @@
return dna
/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, newreal_name, newblood_type, datum/species/mrace, newfeatures)
/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, newreal_name, newblood_type, datum/species/mrace, newfeatures, list/default_mutation_genes)
if(newreal_name)
real_name = newreal_name
@@ -414,6 +420,10 @@
if(LAZYLEN(mutation_index))
dna.mutation_index = mutation_index.Copy()
if(LAZYLEN(default_mutation_genes))
dna.default_mutation_genes = default_mutation_genes.Copy()
else
dna.default_mutation_genes = mutation_index.Copy()
domutcheck()
SEND_SIGNAL(src, COMSIG_HUMAN_HARDSET_DNA, ui, mutation_index, newreal_name, newblood_type, mrace, newfeatures)
@@ -505,8 +515,11 @@
. = TRUE
if(on)
mutation_index[HM.type] = GET_SEQUENCE(HM.type)
default_mutation_genes[HM.type] = mutation_index[HM.type]
else if(GET_SEQUENCE(HM.type) == mutation_index[HM.type])
mutation_index[HM.type] = create_sequence(HM.type, FALSE, HM.difficulty)
default_mutation_genes[HM.type] = mutation_index[HM.type]
/datum/dna/proc/activate_mutation(mutation) //note that this returns a boolean and not a new mob
if(!mutation)
+22
View File
@@ -42,6 +42,7 @@
var/synchronizer_coeff = -1 //makes the mutation hurt the user less
var/power_coeff = -1 //boosts mutation strength
var/energy_coeff = -1 //lowers mutation cooldown
var/list/valid_chrom_list = list() //List of strings of valid chromosomes this mutation can accept.
/datum/mutation/human/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
. = ..()
@@ -167,6 +168,7 @@
energy_coeff = HM.energy_coeff
mutadone_proof = HM.mutadone_proof
can_chromosome = HM.can_chromosome
valid_chrom_list = HM.valid_chrom_list
/datum/mutation/human/proc/remove_chromosome()
stabilizer_coeff = initial(stabilizer_coeff)
@@ -192,3 +194,23 @@
power.panel = "Genetic"
owner.AddSpell(power)
return TRUE
// Runs through all the coefficients and uses this to determine which chromosomes the
// mutation can take. Stores these as text strings in a list.
/datum/mutation/human/proc/update_valid_chromosome_list()
valid_chrom_list.Cut()
if(can_chromosome == CHROMOSOME_NEVER)
valid_chrom_list += "none"
return
valid_chrom_list += "Reinforcement"
if(stabilizer_coeff != -1)
valid_chrom_list += "Stabilizer"
if(synchronizer_coeff != -1)
valid_chrom_list += "Synchronizer"
if(power_coeff != -1)
valid_chrom_list += "Power"
if(energy_coeff != -1)
valid_chrom_list += "Energetic"
+1 -1
View File
@@ -14,7 +14,7 @@
/datum/mutation/human/wacky
name = "Wacky"
desc = "<span class='sans'>Unknown.</span>"
desc = "Unknown."
quality = MINOR_NEGATIVE
text_gain_indication = "<span class='sans'>You feel an off sensation in your voicebox.</span>"
text_lose_indication = "<span class='notice'>The off sensation passes.</span>"
+3
View File
@@ -104,6 +104,9 @@
rack.AddComponent(/datum/component/magnetic_catch)
//Whatever special stuff you want
/datum/map_template/shuttle/proc/post_load(obj/docking_port/mobile/M)
return
/datum/map_template/shuttle/proc/on_bought()
return
+1 -1
View File
@@ -17,7 +17,7 @@
/datum/skill_holder/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "skillpanel", "[owner.name]'s Skills", 620, 580, master_ui, state)
ui = new(user, src, ui_key, "SkillPanel", "[owner.name]'s Skills", 620, 580, master_ui, state)
ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input.
ui.open()
else if(need_static_data_update)
+1 -1
View File
@@ -9,7 +9,7 @@
/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "spawners_menu", "Spawners Menu", 700, 600, master_ui, state)
ui = new(user, src, ui_key, "SpawnersMenu", "Spawners Menu", 700, 600, master_ui, state)
ui.open()
/datum/spawners_menu/ui_data(mob/user)
+2 -2
View File
@@ -242,8 +242,8 @@
/datum/wires/ui_interact(mob/user, ui_key = "wires", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "wires", "[holder.name] Wires", 350, 150 + wires.len * 30, master_ui, state)
if (!ui)
ui = new(user, src, ui_key, "Wires", "[holder.name] Wires", 350, 150 + wires.len * 30, master_ui, state)
ui.open()
/datum/wires/ui_data(mob/user)
+4
View File
@@ -101,6 +101,8 @@
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
if(loc)
SEND_SIGNAL(loc, COMSIG_ATOM_CREATED, src) /// Sends a signal that the new atom `src`, has been created at `loc`
//atom color stuff
if(color)
add_atom_colour(color, FIXED_COLOUR_PRIORITY)
@@ -930,6 +932,8 @@
log_game(log_text)
if(LOG_GAME)
log_game(log_text)
if(LOG_SHUTTLE)
log_shuttle(log_text)
else
stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).")
log_game(log_text)
+2 -1
View File
@@ -350,8 +350,9 @@ Credit where due:
for(var/entry in changelog)
changelog_contents += "<li>[entry]</li>"
info = replacetext(info, "CLOCKCULTCHANGELOG", changelog_contents)
/*
/obj/item/paper/servant_primer/oui_getcontent(mob/target)
if(!is_servant_of_ratvar(target) && !isobserver(target))
return "<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)]<HR>[stamps]</BODY></HTML>"
return ..()
*/
+3 -2
View File
@@ -209,7 +209,7 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "sleeper", name, 550, 700, master_ui, state)
ui = new(user, src, ui_key, "Sleeper", name, 550, 700, master_ui, state)
ui.open()
/obj/machinery/sleeper/process()
@@ -421,7 +421,8 @@
desc = "A large cryogenics unit built from brass. Its surface is pleasantly cool the touch."
icon_state = "sleeper_clockwork"
enter_message = "<span class='bold inathneq_small'>You hear the gentle hum and click of machinery, and are lulled into a sense of peace.</span>"
possible_chems = list(list("epinephrine", "salbutamol", "bicaridine", "kelotane", "oculine", "inacusiate", "mannitol"))
possible_chems = list(list(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/salbutamol, /datum/reagent/medicine/bicaridine,
/datum/reagent/medicine/kelotane, /datum/reagent/medicine/oculine, /datum/reagent/medicine/inacusiate, /datum/reagent/medicine/mannitol))
/obj/machinery/sleeper/clockwork/process()
if(occupant && isliving(occupant))
+2 -2
View File
@@ -121,7 +121,7 @@ Class Procs:
var/ui_style // ID of custom TGUI style (optional)
var/ui_x
var/ui_y
var/init_process = TRUE //Stop processing from starting on init
var/interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE
var/fair_market_price = 69
@@ -138,7 +138,7 @@ Class Procs:
circuit = new circuit
circuit.apply_default_parts(src)
if(!speed_process)
if(!speed_process && init_process)
START_PROCESSING(SSmachines, src)
else
START_PROCESSING(SSfastprocess, src)
+48 -60
View File
@@ -39,7 +39,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
icon_state = (panel_open ? "AAS_Off_Open" : "AAS_Off")
/obj/machinery/announcement_system/update_overlays()
. =..()
. = ..()
if(arrivalToggle)
. += greenlight
@@ -54,19 +54,15 @@ GLOBAL_LIST_EMPTY(announcement_systems)
GLOB.announcement_systems -= src //"OH GOD WHY ARE THERE 100,000 LISTED ANNOUNCEMENT SYSTEMS?!!"
return ..()
/obj/machinery/announcement_system/power_change()
..()
update_icon()
/obj/machinery/announcement_system/attackby(obj/item/P, mob/user, params)
if(istype(P, /obj/item/screwdriver))
if(P.tool_behaviour == TOOL_SCREWDRIVER)
P.play_tool_sound(src)
panel_open = !panel_open
to_chat(user, "<span class='notice'>You [panel_open ? "open" : "close"] the maintenance hatch of [src].</span>")
update_icon()
else if(default_deconstruction_crowbar(P))
return
else if(istype(P, /obj/item/multitool) && panel_open && (stat & BROKEN))
else if(P.tool_behaviour == TOOL_MULTITOOL && panel_open && (stat & BROKEN))
to_chat(user, "<span class='notice'>You reset [src]'s firmware.</span>")
stat &= ~BROKEN
update_icon()
@@ -88,10 +84,6 @@ GLOBAL_LIST_EMPTY(announcement_systems)
message = CompileText(arrival, user, rank)
else if(message_type == "NEWHEAD" && newheadToggle)
message = CompileText(newhead, user, rank)
//CITADEL EDIT for cryopods
else if(message_type == "CRYOSTORAGE")
message = CompileText("%PERSON, %RANK has been moved to cryo storage.", user, rank)
//END EDIT
else if(message_type == "ARRIVALS_BROKEN")
message = "The arrivals shuttle has been damaged. Docking for repairs..."
@@ -103,61 +95,59 @@ GLOBAL_LIST_EMPTY(announcement_systems)
//config stuff
/obj/machinery/announcement_system/ui_interact(mob/user)
/obj/machinery/announcement_system/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
. = ..()
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "AutomatedAnnouncement", "Automated Announcement System", 500, 225, master_ui, state)
ui.open()
/obj/machinery/announcement_system/ui_data()
var/list/data = list()
data["arrival"] = arrival
data["arrivalToggle"] = arrivalToggle
data["newhead"] = newhead
data["newheadToggle"] = newheadToggle
return data
/obj/machinery/announcement_system/ui_act(action, param)
. = ..()
if(.)
return
if(!usr.canUseTopic(src, !issilicon(usr)))
return
if(stat & BROKEN)
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='italics'>You hear a faint buzz.</span>")
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 1)
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='hear'>You hear a faint buzz.</span>")
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, TRUE)
return
var/contents = "Arrival Announcement: <A href='?src=[REF(src)];ArrivalT-Topic=1'>([(arrivalToggle ? "On" : "Off")])</a><br>\n<A href='?src=[REF(src)];ArrivalTopic=1'>[arrival]</a><br><br>\n"
contents += "Departmental Head Announcement: <A href='?src=[REF(src)];NewheadT-Topic=1'>([(newheadToggle ? "On" : "Off")])</a><br>\n<A href='?src=[REF(src)];NewheadTopic=1'>[newhead]</a><br><br>\n"
var/datum/browser/popup = new(user, "announcement_config", "Automated Announcement Configuration", 370, 220)
popup.set_content(contents)
popup.open()
/obj/machinery/announcement_system/Topic(href, href_list)
if(..())
return
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
return
if(stat & BROKEN)
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='italics'>You hear a faint buzz.</span>")
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 1)
return
if(href_list["ArrivalTopic"])
var/NewMessage = stripped_input(usr, "Enter in the arrivals announcement configuration.", "Arrivals Announcement Config", arrival)
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
return
if(NewMessage)
arrival = NewMessage
else if(href_list["NewheadTopic"])
var/NewMessage = stripped_input(usr, "Enter in the departmental head announcement configuration.", "Head Departmental Announcement Config", newhead)
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
return
if(NewMessage)
newhead = NewMessage
else if(href_list["NewheadT-Topic"])
newheadToggle = !newheadToggle
update_icon()
else if(href_list["ArrivalT-Topic"])
arrivalToggle = !arrivalToggle
update_icon()
switch(action)
if("ArrivalText")
var/NewMessage = trim(html_encode(param["newText"]), MAX_MESSAGE_LEN)
if(!usr.canUseTopic(src, !issilicon(usr)))
return
if(NewMessage)
arrival = NewMessage
log_game("The arrivals announcement was updated: [NewMessage] by:[key_name(usr)]")
if("NewheadText")
var/NewMessage = trim(html_encode(param["newText"]), MAX_MESSAGE_LEN)
if(!usr.canUseTopic(src, !issilicon(usr)))
return
if(NewMessage)
newhead = NewMessage
log_game("The head announcement was updated: [NewMessage] by:[key_name(usr)]")
if("NewheadToggle")
newheadToggle = !newheadToggle
update_icon()
if("ArrivalToggle")
arrivalToggle = !arrivalToggle
update_icon()
add_fingerprint(usr)
interact(usr)
/obj/machinery/announcement_system/attack_robot(mob/living/silicon/user)
. = attack_ai(user)
/obj/machinery/announcement_system/attack_ai(mob/user)
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
if(!user.canUseTopic(src, !issilicon(user)))
return
if(stat & BROKEN)
to_chat(user, "<span class='warning'>[src]'s firmware appears to be malfunctioning!</span>")
@@ -165,8 +155,8 @@ GLOBAL_LIST_EMPTY(announcement_systems)
interact(user)
/obj/machinery/announcement_system/proc/act_up() //does funny breakage stuff
stat |= BROKEN
update_icon()
if(!obj_break()) // if badmins flag this unbreakable or its already broken
return
arrival = pick("#!@%ERR-34%2 CANNOT LOCAT@# JO# F*LE!", "CRITICAL ERROR 99.", "ERR)#: DA#AB@#E NOT F(*ND!")
newhead = pick("OV#RL()D: \[UNKNOWN??\] DET*#CT)D!", "ER)#R - B*@ TEXT F*O(ND!", "AAS.exe is not responding. NanoOS is searching for a solution to the problem.")
@@ -177,9 +167,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
act_up()
/obj/machinery/announcement_system/emag_act()
. = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
act_up()
return TRUE
+1 -1
View File
@@ -64,7 +64,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "bank_machine", name, 320, 165, master_ui, state)
ui = new(user, src, ui_key, "BankMachine", name, 320, 165, master_ui, state)
ui.open()
/obj/machinery/computer/bank_machine/ui_data(mob/user)
+10 -1
View File
@@ -43,7 +43,11 @@
board.one_access = 1
board.accesses = req_one_access
/obj/machinery/button/update_icon_state()
setup_device()
/obj/machinery/button/update_icon()
cut_overlays()
if(panel_open)
icon_state = "button-open"
else if(stat & (NOPOWER|BROKEN))
@@ -129,6 +133,11 @@
A.id = id
initialized_button = 1
/obj/machinery/button/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
if(id && istype(device, /obj/item/assembly/control))
var/obj/item/assembly/control/A = device
A.id = "[idnum][id]"
/obj/machinery/button/attack_hand(mob/user)
. = ..()
if(.)
+5
View File
@@ -72,6 +72,11 @@
if(mapload && is_station_level(z) && prob(3) && !start_active)
toggle_cam()
/obj/machinery/camera/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
for(var/i in network)
network -= i
network += "[idnum][i]"
/obj/machinery/camera/Destroy()
if(can_use())
toggle_cam(null, 0) //kick anyone viewing out and remove from the camera chunks
-25
View File
@@ -75,31 +75,6 @@
speed_coeff = max(1, speed_coeff)
heal_level = clamp((efficiency * 10) + 10, MINIMUM_HEAL_LEVEL, 100)
//The return of data disks?? Just for transferring between genetics machine/cloning machine.
//TO-DO: Make the genetics machine accept them.
/obj/item/disk/data
name = "cloning data disk"
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
var/list/fields = list()
var/list/mutations = list()
var/max_mutations = 6
var/read_only = 0 //Well,it's still a floppy disk
//Disk stuff.
/obj/item/disk/data/Initialize()
. = ..()
icon_state = "datadisk[rand(0,6)]"
add_overlay("datadisk_gene")
/obj/item/disk/data/attack_self(mob/user)
read_only = !read_only
to_chat(user, "<span class='notice'>You flip the write-protect tab to [read_only ? "protected" : "unprotected"].</span>")
/obj/item/disk/data/examine(mob/user)
. = ..()
. += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]."
//Clonepod
/obj/machinery/clonepod/examine(mob/user)
+44 -1
View File
@@ -46,7 +46,7 @@
/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "operating_computer", name, 350, 470, master_ui, state)
ui = new(user, src, ui_key, "OperatingComputer", name, 350, 470, master_ui, state)
ui.open()
/obj/machinery/computer/operating/ui_data(mob/user)
@@ -108,6 +108,49 @@
))
else
data["patient"] = null
return data
switch(patient.stat)
if(CONSCIOUS)
data["patient"]["stat"] = "Conscious"
data["patient"]["statstate"] = "good"
if(SOFT_CRIT)
data["patient"]["stat"] = "Conscious"
data["patient"]["statstate"] = "average"
if(UNCONSCIOUS)
data["patient"]["stat"] = "Unconscious"
data["patient"]["statstate"] = "average"
if(DEAD)
data["patient"]["stat"] = "Dead"
data["patient"]["statstate"] = "bad"
data["patient"]["health"] = patient.health
data["patient"]["blood_type"] = patient.dna.blood_type
data["patient"]["maxHealth"] = patient.maxHealth
data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD
data["patient"]["bruteLoss"] = patient.getBruteLoss()
data["patient"]["fireLoss"] = patient.getFireLoss()
data["patient"]["toxLoss"] = patient.getToxLoss()
data["patient"]["oxyLoss"] = patient.getOxyLoss()
data["procedures"] = list()
if(patient.surgeries.len)
for(var/datum/surgery/procedure in patient.surgeries)
var/datum/surgery_step/surgery_step = procedure.get_surgery_step()
var/chems_needed = surgery_step.get_chem_list()
var/alternative_step
var/alt_chems_needed = ""
if(surgery_step.repeatable)
var/datum/surgery_step/next_step = procedure.get_surgery_next_step()
if(next_step)
alternative_step = capitalize(next_step.name)
alt_chems_needed = next_step.get_chem_list()
else
alternative_step = "Finish operation"
data["procedures"] += list(list(
"name" = capitalize("[parse_zone(procedure.location)] [procedure.name]"),
"next_step" = capitalize(surgery_step.name),
"chems_needed" = chems_needed,
"alternative_step" = alternative_step,
"alt_chems_needed" = alt_chems_needed
))
return data
/obj/machinery/computer/operating/ui_act(action, params)
+8 -2
View File
@@ -8,6 +8,8 @@
icon_keyboard = "tech_key"
icon_screen = "ai-fixer"
light_color = LIGHT_COLOR_PINK
ui_x = 370
ui_y = 360
/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params)
if(occupier && istype(I, /obj/item/screwdriver))
@@ -18,8 +20,12 @@
else
return ..()
/obj/machinery/computer/aifixer/ui_interact(mob/user)
. = ..()
/obj/machinery/computer/aifixer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "AiRestorer", name, ui_x, ui_y, master_ui, state)
ui.open()
var/dat = ""
+14
View File
@@ -136,3 +136,17 @@
empprize = pickweight(prizes)
new empprize(loc)
explosion(loc, -1, 0, 1+num_of_prizes, flame_range = 1+num_of_prizes)
/obj/machinery/computer/arcade/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/stack/arcadeticket))
var/obj/item/stack/arcadeticket/T = O
var/amount = T.get_amount()
if(amount <2)
to_chat(user, "<span class='warning'>You need 2 tickets to claim a prize!</span>")
return
prizevend(user)
T.pay_tickets()
T.update_icon()
O = T
to_chat(user, "<span class='notice'>You turn in 2 tickets to the [src] and claim a prize!</span>")
return
+1 -1
View File
@@ -23,7 +23,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_alert", name, 350, 300, master_ui, state)
ui = new(user, src, ui_key, "AtmosAlertConsole", name, 350, 300, master_ui, state)
ui.open()
/obj/machinery/computer/atmos_alert/ui_data(mob/user)
@@ -127,7 +127,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_control", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "AtmosControlConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/atmos_control/ui_data(mob/user)
@@ -269,7 +269,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_control", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "AtmosControlConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/atmos_control/tank/ui_data(mob/user)
+172 -93
View File
@@ -4,109 +4,166 @@
icon_screen = "cameras"
icon_keyboard = "security_key"
circuit = /obj/item/circuitboard/computer/security
var/last_pic = 1
var/list/network = list("ss13")
var/list/watchers = list() //who's using the console, associated with the camera they're on.
light_color = LIGHT_COLOR_RED
ui_x = 870
ui_y = 708
var/list/network = list("ss13")
var/obj/machinery/camera/active_camera
var/list/concurrent_users = list()
// Stuff needed to render the map
var/map_name
var/const/default_map_size = 15
var/obj/screen/cam_screen
var/obj/screen/plane_master/lighting/cam_plane_master
var/obj/screen/background/cam_background
/obj/machinery/computer/security/Initialize()
. = ..()
// Map name has to start and end with an A-Z character,
// and definitely NOT with a square bracket or even a number.
// I wasted 6 hours on this. :agony:
map_name = "camera_console_[REF(src)]_map"
// Convert networks to lowercase
for(var/i in network)
network -= i
network += lowertext(i)
/obj/machinery/computer/security/check_eye(mob/user)
if(!can_interact(user) || !(user in watchers) || !watchers[user])
user.unset_machine()
return
var/obj/machinery/camera/C = watchers[user]
if(!C.can_use())
user.unset_machine()
return
/obj/machinery/computer/security/on_unset_machine(mob/user)
watchers.Remove(user)
user.reset_perspective(null)
// Initialize map objects
cam_screen = new
cam_screen.name = "screen"
cam_screen.assigned_map = map_name
cam_screen.del_on_map_removal = FALSE
cam_screen.screen_loc = "[map_name]:1,1"
cam_plane_master = new
cam_plane_master.name = "plane_master"
cam_plane_master.assigned_map = map_name
cam_plane_master.del_on_map_removal = FALSE
cam_plane_master.screen_loc = "[map_name]:CENTER"
cam_background = new
cam_background.assigned_map = map_name
cam_background.del_on_map_removal = FALSE
/obj/machinery/computer/security/Destroy()
if(watchers.len)
for(var/mob/M in watchers)
M.unset_machine() //to properly reset the view of the users if the console is deleted.
qdel(cam_screen)
qdel(cam_plane_master)
qdel(cam_background)
return ..()
/obj/machinery/computer/security/can_interact(mob/user)
if((!hasSiliconAccessInArea(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
return FALSE
return ..()
/obj/machinery/computer/security/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
for(var/i in network)
network -= i
network += "[idnum][i]"
/obj/machinery/computer/security/interact(mob/user, special_state)
/obj/machinery/computer/security/ui_interact(\
mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
// Update UI
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
if(!ui)
var/user_ref = REF(user)
var/is_living = isliving(user)
// Ghosts shouldn't count towards concurrent users, which produces
// an audible terminal_on click.
if(is_living)
concurrent_users += user_ref
// Turn on the console
if(length(concurrent_users) == 1 && is_living)
playsound(src, 'sound/machines/terminal_on.ogg', 25, FALSE)
use_power(active_power_usage)
// Register map objects
user.client.register_map_obj(cam_screen)
user.client.register_map_obj(cam_plane_master)
user.client.register_map_obj(cam_background)
// Open UI
ui = new(user, src, ui_key, "CameraConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/security/ui_data()
var/list/data = list()
data["network"] = network
data["activeCamera"] = null
if(active_camera)
data["activeCamera"] = list(
name = active_camera.c_tag,
status = active_camera.status,
)
return data
/obj/machinery/computer/security/ui_static_data()
var/list/data = list()
data["mapRef"] = map_name
var/list/cameras = get_available_cameras()
data["cameras"] = list()
for(var/i in cameras)
var/obj/machinery/camera/C = cameras[i]
data["cameras"] += list(list(
name = C.c_tag,
))
return data
/obj/machinery/computer/security/ui_act(action, params)
. = ..()
if (ismob(user) && !isliving(user)) // ghosts don't need cameras
return
if (!network)
stack_trace("No camera network")
user.unset_machine()
return FALSE
if (!(islist(network)))
stack_trace("Camera network is not a list")
user.unset_machine()
return FALSE
var/list/camera_list = get_available_cameras()
if(!(user in watchers))
for(var/Num in camera_list)
var/obj/machinery/camera/CAM = camera_list[Num]
if(istype(CAM) && CAM.can_use())
watchers[user] = CAM //let's give the user the first usable camera, and then let him change to the camera he wants.
break
if(!(user in watchers))
user.unset_machine() // no usable camera on the network, we disconnect the user from the computer.
return FALSE
playsound(src, 'sound/machines/terminal_prompt.ogg', 25, 0)
use_camera_console(user)
/obj/machinery/computer/security/proc/use_camera_console(mob/user)
var/list/camera_list = get_available_cameras()
var/t = input(user, "Which camera should you change to?") as null|anything in camera_list
if(!src || user.machine != src) //while we were choosing we got disconnected from our computer or are using another machine.
return
if(!t || t == "Cancel")
user.unset_machine()
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
if(.)
return
var/obj/machinery/camera/C = camera_list[t]
if(action == "switch_camera")
var/c_tag = params["name"]
var/list/cameras = get_available_cameras()
var/obj/machinery/camera/C = cameras[c_tag]
active_camera = C
playsound(src, get_sfx("terminal_type"), 25, FALSE)
if(!C || !C.can_use() || !can_interact(user))
user.unset_machine()
return FALSE
// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
return TRUE
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
if(isAI(user))
var/mob/living/silicon/ai/A = user
A.eyeobj.setLoc(get_turf(C))
A.client.eye = A.eyeobj
else
user.reset_perspective(C)
user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
user.clear_fullscreen("flash", 5)
watchers[user] = C
use_power(50)
addtimer(CALLBACK(src, .proc/use_camera_console, user), 5)
var/list/visible_turfs = list()
for(var/turf/T in (C.isXRay() \
? range(C.view_range, C) \
: view(C.view_range, C)))
visible_turfs += T
//returns the list of cameras accessible from this computer
var/list/bbox = get_bbox_of_atoms(visible_turfs)
var/size_x = bbox[3] - bbox[1] + 1
var/size_y = bbox[4] - bbox[2] + 1
cam_screen.vis_contents = visible_turfs
cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, size_x, size_y)
return TRUE
/obj/machinery/computer/security/ui_close(mob/user)
var/user_ref = REF(user)
var/is_living = isliving(user)
// Living creature or not, we remove you anyway.
concurrent_users -= user_ref
// Unregister map objects
user.client.clear_map(map_name)
// Turn off the console
if(length(concurrent_users) == 0 && is_living)
active_camera = null
playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE)
use_power(0)
/obj/machinery/computer/security/proc/show_camera_static()
cam_screen.vis_contents.Cut()
cam_background.icon_state = "scanline2"
cam_background.fill_rect(1, 1, default_map_size, default_map_size)
// Returns the list of cameras accessible from this computer
/obj/machinery/computer/security/proc/get_available_cameras()
var/list/L = list()
for (var/obj/machinery/camera/C in GLOB.cameranet.cameras)
if((is_away_level(z) || is_away_level(C.z)) && (C.z != z))//if on away mission, can only receive feed from same z_level cameras
continue
L.Add(C)
camera_sort(L)
var/list/D = list()
D["Cancel"] = "Cancel"
for(var/obj/machinery/camera/C in L)
if(!C.network)
stack_trace("Camera in a cameranet has no camera network")
@@ -114,9 +171,9 @@
if(!(islist(C.network)))
stack_trace("Camera in a cameranet has a non-list camera network")
continue
var/list/tempnetwork = C.network&network
var/list/tempnetwork = C.network & network
if(tempnetwork.len)
D["[C.c_tag][(C.status ? null : " (Deactivated)")]"] = C
D["[C.c_tag]"] = C
return D
// SECURITY MONITORS
@@ -127,7 +184,6 @@
icon_state = "television"
icon_keyboard = null
icon_screen = "detective_tv"
clockwork = TRUE //it'd look weird
pass_flags = PASSTABLE
/obj/machinery/computer/security/mining
@@ -145,7 +201,7 @@
circuit = /obj/item/circuitboard/computer/research
/obj/machinery/computer/security/hos
name = "Head of Security's camera console"
name = "\improper Head of Security's camera console"
desc = "A custom security console with added access to the labor camp network."
network = list("ss13", "labor")
circuit = null
@@ -157,7 +213,7 @@
circuit = null
/obj/machinery/computer/security/qm
name = "Quartermaster's camera console"
name = "\improper Quartermaster's camera console"
desc = "A console with access to the mining, auxillary base and vault camera networks."
network = list("mine", "auxbase", "vault")
circuit = null
@@ -172,7 +228,6 @@
network = list("thunder")
density = FALSE
circuit = null
clockwork = TRUE //it'd look very weird
light_power = 0
/obj/machinery/computer/security/telescreen/Initialize()
@@ -190,11 +245,35 @@
name = "entertainment monitor"
desc = "Damn, they better have the /tg/ channel on these things."
icon = 'icons/obj/status_display.dmi'
icon_state = "entertainment"
icon_state = "entertainment_blank"
network = list("thunder")
density = FALSE
circuit = null
interaction_flags_atom = NONE // interact() is called by BigClick()
var/icon_state_off = "entertainment_blank"
var/icon_state_on = "entertainment"
/obj/machinery/computer/security/telescreen/entertainment/Initialize()
. = ..()
RegisterSignal(src, COMSIG_CLICK, .proc/BigClick)
// Bypass clickchain to allow humans to use the telescreen from a distance
/obj/machinery/computer/security/telescreen/entertainment/proc/BigClick()
interact(usr)
/obj/machinery/computer/security/telescreen/entertainment/proc/notify(on)
if(on && icon_state == icon_state_off)
say(pick(
"Feats of bravery live now at the thunderdome!",
"Two enter, one leaves! Tune in now!",
"Violence like you've never seen it before!",
"Spears! Camera! Action! LIVE NOW!"))
icon_state = icon_state_on
else
icon_state = icon_state_off
/obj/machinery/computer/security/telescreen/rd
name = "Research Director's telescreen"
name = "\improper Research Director's telescreen"
desc = "Used for watching the AI and the RD's goons from the safety of his office."
network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test")
@@ -202,26 +281,26 @@
name = "circuitry telescreen"
desc = "Used for watching the other eggheads from the safety of the circuitry lab."
network = list("rd")
/obj/machinery/computer/security/telescreen/ce
name = "Chief Engineer's telescreen"
name = "\improper Chief Engineer's telescreen"
desc = "Used for watching the engine, telecommunications and the minisat."
network = list("engine", "singularity", "tcomms", "minisat")
/obj/machinery/computer/security/telescreen/cmo
name = "Chief Medical Officer's telescreen"
name = "\improper Chief Medical Officer's telescreen"
desc = "A telescreen with access to the medbay's camera network."
network = list("medbay")
/obj/machinery/computer/security/telescreen/vault
name = "Vault monitor"
name = "vault monitor"
desc = "A telescreen that connects to the vault's camera network."
network = list("vault")
/obj/machinery/computer/security/telescreen/toxins
name = "Bomb test site monitor"
name = "bomb test site monitor"
desc = "A telescreen that connects to the bomb test site's camera."
network = list("toxin")
network = list("toxins")
/obj/machinery/computer/security/telescreen/engine
name = "engine monitor"
@@ -254,7 +333,7 @@
network = list("minisat")
/obj/machinery/computer/security/telescreen/aiupload
name = "AI upload monitor"
name = "\improper AI upload monitor"
desc = "A telescreen that connects to the AI upload's camera network."
network = list("aiupload")
@@ -29,9 +29,17 @@
if(lock_override & CAMERA_LOCK_REEBE)
z_lock |= SSmapping.levels_by_trait(ZTRAIT_REEBE)
/obj/machinery/computer/camera_advanced/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
for(var/i in networks)
networks -= i
networks += "[idnum][i]"
/obj/machinery/computer/camera_advanced/syndie
icon_keyboard = "syndie_key"
/obj/machinery/computer/camera_advanced/syndie/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
return //For syndie nuke shuttle, to spy for station.
/obj/machinery/computer/camera_advanced/proc/CreateEye()
eyeobj = new()
eyeobj.origin = src
+36 -40
View File
@@ -61,7 +61,7 @@
// main interface
if("main")
state = STATE_DEFAULT
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
if("login")
var/mob/M = usr
@@ -73,19 +73,19 @@
auth_id = "[I.registered_name] ([I.assignment])"
if((ACCESS_CAPTAIN in I.access))
authenticated = 2
playsound(src, 'sound/machines/terminal_on.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
if(obj_flags & EMAGGED)
authenticated = 2
auth_id = "Unknown"
to_chat(M, "<span class='warning'>[src] lets out a quiet alarm as its login is overridden.</span>")
playsound(src, 'sound/machines/terminal_on.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_alert.ogg', 25, 0)
playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
playsound(src, 'sound/machines/terminal_alert.ogg', 25, FALSE)
if(prob(25))
for(var/mob/living/silicon/ai/AI in active_ais())
SEND_SOUND(AI, sound('sound/machines/terminal_alert.ogg', volume = 10)) //Very quiet for balance reasons
if("logout")
authenticated = 0
playsound(src, 'sound/machines/terminal_off.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
if("swipeidseclevel")
var/mob/M = usr
@@ -109,7 +109,7 @@
security_level_cd = world.time + 15 SECONDS
if(GLOB.security_level != old_level)
to_chat(usr, "<span class='notice'>Authorization confirmed. Modifying security level.</span>")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
//Only notify people if an actual change happened
var/security_level = NUM2SECLEVEL(GLOB.security_level)
log_game("[key_name(usr)] has changed the security level to [security_level] with [src] at [AREACOORD(usr)].")
@@ -118,28 +118,28 @@
tmp_alertlevel = 0
else
to_chat(usr, "<span class='warning'>You are not authorized to do this!</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
tmp_alertlevel = 0
state = STATE_DEFAULT
else
to_chat(usr, "<span class='warning'>You need to swipe your ID!</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
if("announce")
if(authenticated==2)
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
make_announcement(usr)
if("crossserver")
if(authenticated==2)
if(!checkCCcooldown())
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
return
var/input = stripped_multiline_input(usr, "Please choose a message to transmit to allied stations. Please be aware that this process is very expensive, and abuse will lead to... termination.", "Send a message to an allied station.", "")
if(!input || !(usr in view(1,src)) || !checkCCcooldown())
return
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
send2otherserver("[station_name()]", input,"Comms_Console")
minor_announce(input, title = "Outgoing message to allied station")
usr.log_talk(input, LOG_SAY, tag="message to the other server")
@@ -168,22 +168,18 @@
if(D)
points_to_check = D.account_balance
if(points_to_check >= S.credit_cost)
var/obj/machinery/shuttle_manipulator/M = locate() in GLOB.machines
if(M)
SSshuttle.shuttle_purchased = TRUE
D.adjust_money(-S.credit_cost)
minor_announce("[usr.real_name] has purchased [S.name] for [S.credit_cost] credits." , "Shuttle Purchase")
message_admins("[ADMIN_LOOKUPFLW(usr)] purchased [S.name].")
SSblackbox.record_feedback("text", "shuttle_purchase", 1, "[S.name]")
M.unload_preview()
M.load_template(S)
M.existing_shuttle = SSshuttle.emergency
M.action_load(S)
message_admins("[S.name] loaded, purchased by [usr]")
else
to_chat(usr, "Something went wrong! The shuttle exchange system seems to be down.")
SSshuttle.shuttle_purchased = TRUE
SSshuttle.unload_preview()
SSshuttle.load_template(S)
SSshuttle.existing_shuttle = SSshuttle.emergency
SSshuttle.action_load(S)
D.adjust_money(-S.credit_cost)
minor_announce("[usr.real_name] has purchased [S.name] for [S.credit_cost] credits." , "Shuttle Purchase")
message_admins("[ADMIN_LOOKUPFLW(usr)] purchased [S.name].")
log_shuttle("[key_name(usr)] has purchased [S.name].")
SSblackbox.record_feedback("text", "shuttle_purchase", 1, "[S.name]")
else
to_chat(usr, "Not enough credits.")
to_chat(usr, "<span class='alert'>Insufficient credits.</span>")
if("callshuttle")
state = STATE_DEFAULT
@@ -268,7 +264,7 @@
// Status display stuff
if("setstat")
playsound(src, "terminal_type", 50, 0)
playsound(src, "terminal_type", 50, FALSE)
switch(href_list["statdisp"])
if("message")
post_status("message", stat_msg1, stat_msg2)
@@ -308,13 +304,13 @@
if("MessageSyndicate")
if((authenticated==2) && (obj_flags & EMAGGED))
if(!checkCCcooldown())
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
return
var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING COORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send a message to /??????/.", "")
if(!input || !(usr in view(1,src)) || !checkCCcooldown())
return
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
Syndicate_announce(input, usr)
to_chat(usr, "<span class='danger'>SYSERR @l(19833)of(transmit.dm): !@$ MESSAGE TRANSMITTED TO SYNDICATE COMMAND.</span>")
for(var/client/X in GLOB.admins)
@@ -327,7 +323,7 @@
if("RestoreBackup")
to_chat(usr, "<span class='notice'>Backup routing data restored!</span>")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
obj_flags &= ~EMAGGED
updateDialog()
@@ -341,7 +337,7 @@
return
Nuke_request(input, usr)
to_chat(usr, "<span class='notice'>Request sent.</span>")
usr.log_message("has requested the nuclear codes from CentCom", LOG_SAY)
usr.log_message("has requested the nuclear codes from CentCom with reason \"[input]\"", LOG_SAY)
priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested","commandreport")
CM.lastTimeUsed = world.time
@@ -448,7 +444,7 @@
if(authenticated == 1)
authenticated = 2
to_chat(user, "<span class='danger'>You scramble the communication routing circuits!</span>")
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_alert.ogg', 50, FALSE)
return TRUE
/obj/machinery/computer/communications/ui_interact(mob/user)
@@ -514,16 +510,16 @@
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=login'>Log In</A> \]"
if(STATE_CALLSHUTTLE)
dat += get_call_shuttle_form()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
if(STATE_CANCELSHUTTLE)
dat += get_cancel_shuttle_form()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
if(STATE_MESSAGELIST)
dat += "Messages:"
for(var/i in 1 to messages.len)
var/datum/comm_message/M = messages[i]
dat += "<BR><A HREF='?src=[REF(src)];operation=viewmessage;message-num=[i]'>[M.title]</A>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if(STATE_VIEWMESSAGE)
if (currmsg)
dat += "<B>[currmsg.title]</B><BR><BR>[currmsg.content]"
@@ -557,7 +553,7 @@
dat += " <A HREF='?src=[REF(src)];operation=setstat;statdisp=alert;alert=redalert'>Red Alert</A> |"
dat += " <A HREF='?src=[REF(src)];operation=setstat;statdisp=alert;alert=lockdown'>Lockdown</A> |"
dat += " <A HREF='?src=[REF(src)];operation=setstat;statdisp=alert;alert=biohazard'>Biohazard</A> \]<BR><HR>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if(STATE_ALERT_LEVEL)
dat += "Current alert level: [NUM2SECLEVEL(GLOB.security_level)]<BR>"
if(GLOB.security_level == SEC_LEVEL_DELTA)
@@ -571,7 +567,7 @@
dat += "Confirm the change to: [NUM2SECLEVEL(tmp_alertlevel)]<BR>"
dat += "<A HREF='?src=[REF(src)];operation=swipeidseclevel'>Swipe ID</A> to confirm change.<BR>"
if(STATE_TOGGLE_EMERGENCY)
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
if(GLOB.emergency_access == 1)
dat += "<b>Emergency Maintenance Access is currently <font color='red'>ENABLED</font></b>"
dat += "<BR>Restore maintenance access restrictions? <BR>\[ <A HREF='?src=[REF(src)];operation=disableemergency'>OK</A> | <A HREF='?src=[REF(src)];operation=viewmessage'>Cancel</A> \]"
@@ -722,7 +718,7 @@
/obj/machinery/computer/communications/proc/make_announcement(mob/living/user, is_silicon)
if(!SScommunications.can_announce(user, is_silicon))
to_chat(user, "Intercomms recharging. Please stand by.")
to_chat(user, "<span class='alert'>Intercomms recharging. Please stand by.</span>")
return
var/input = stripped_input(user, "Please choose a message to announce to the station crew.", "What?")
if(!input || !user.canUseTopic(src))
+1 -1
View File
@@ -80,7 +80,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if (!ui)
ui = new(user, src, ui_key, "crew", "crew monitor", 800, 600 , master_ui, state)
ui = new(user, src, ui_key, "CrewConsole", "crew monitor", 800, 600 , master_ui, state)
ui.open()
/datum/crewmonitor/proc/show(mob/M, source)
File diff suppressed because it is too large Load Diff
@@ -56,7 +56,7 @@
/obj/machinery/computer/launchpad/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "launchpad_console", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "LaunchpadConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/launchpad/ui_data(mob/user)
@@ -25,7 +25,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "gulag_console", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "GulagTeleporterConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user)
+87 -127
View File
@@ -5,163 +5,123 @@
icon_keyboard = "rd_key"
req_access = list(ACCESS_ROBOTICS)
circuit = /obj/item/circuitboard/computer/robotics
var/temp = null
light_color = LIGHT_COLOR_PINK
ui_x = 500
ui_y = 460
/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R)
. = FALSE
if(!istype(R))
return FALSE
return
if(isAI(user))
if (R.connected_ai != user)
return FALSE
if(R.connected_ai != user)
return
if(iscyborg(user))
if (R != user)
return FALSE
if(R != user)
return
if(R.scrambledcodes)
return FALSE
if (hasSiliconAccessInArea(user) && !issilicon(user))
if (!Adjacent(user))
return FALSE
return
return TRUE
/obj/machinery/computer/robotics/ui_interact(mob/user)
. = ..()
if (src.z > 6)
to_chat(user, "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!")
return
user.set_machine(src)
var/dat
var/robots = 0
/obj/machinery/computer/robotics/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "RoboticsControlConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/robotics/ui_data(mob/user)
var/list/data = list()
data["can_hack"] = FALSE
if(issilicon(user))
var/mob/living/silicon/S = user
if(S.hack_software)
data["can_hack"] = TRUE
else if(IsAdminGhost(user))
data["can_hack"] = TRUE
data["cyborgs"] = list()
for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs)
if(!can_control(user, R))
continue
robots++
dat += "[R.name] |"
if(R.stat)
dat += " Not Responding |"
else if(R.locked_down)
dat += " Locked Down |"
else
dat += " Operating Normally |"
if(R.cell)
dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |"
else
dat += " No Cell Installed |"
if(R.module)
dat += " Module Installed ([R.module.name]) |"
else
dat += " No Module Installed |"
if(R.connected_ai)
dat += " Slaved to [R.connected_ai.name] |"
else
dat += " Independent from AI |"
if(issilicon(user) && user != R)
var/mob/living/silicon/S = user
if(is_servant_of_ratvar(S))
dat += "<A href='?src=[REF(src)];convert=[REF(R)]'>(<font color=#BE8700><i>Convert</i></font>)</A> "
else if(S.hack_software && !R.emagged)
dat += "<A href='?src=[REF(src)];magbot=[REF(R)]'>(<font color=blue><i>Hack</i></font>)</A> "
else if(IsAdminGhost(user) && !R.emagged)
dat += "<A href='?src=[REF(src)];magbot=[REF(R)]'>(<font color=blue><i>Hack</i></font>)</A> "
dat += "<A href='?src=[REF(src)];stopbot=[REF(R)]'>(<font color=green><i>[R.locked_down? "Lockdown" : "Release"]</i></font>)</A> "
dat += "<A href='?src=[REF(src)];killbot=[REF(R)]'>(<font color=red><i>Destroy</i></font>)</A>"
dat += "<BR>"
if(z != (get_turf(R)).z)
continue
var/list/cyborg_data = list(
name = R.name,
locked_down = R.locked_down,
status = R.stat,
charge = R.cell ? round(R.cell.percent()) : null,
module = R.module ? "[R.module.name] Module" : "No Module Detected",
synchronization = R.connected_ai,
emagged = R.emagged,
ref = REF(R)
)
data["cyborgs"] += list(cyborg_data)
if(!robots)
dat += "No Cyborg Units detected within access parameters."
dat += "<BR>"
var/drones = 0
data["drones"] = list()
for(var/mob/living/simple_animal/drone/D in GLOB.drones_list)
if(D.hacked)
continue
drones++
dat += "[D.name] |"
if(D.stat)
dat += " Not Responding |"
dat += "<A href='?src=[REF(src)];killdrone=[REF(D)]'>(<font color=red><i>Destroy</i></font>)</A>"
dat += "<BR>"
if(z != (get_turf(D)).z)
continue
var/list/drone_data = list(
name = D.name,
status = D.stat,
ref = REF(D)
)
data["drones"] += list(drone_data)
if(!drones)
dat += "No Drone Units detected within access parameters."
return data
var/datum/browser/popup = new(user, "computer", "Cyborg Control Console", 400, 500)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
return
/obj/machinery/computer/robotics/Topic(href, href_list)
/obj/machinery/computer/robotics/ui_act(action, params)
if(..())
return
if (href_list["temp"])
src.temp = null
else if (href_list["killbot"])
if(src.allowed(usr))
var/mob/living/silicon/robot/R = locate(href_list["killbot"]) in GLOB.silicon_mobs
if(can_control(usr, R))
var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm" && can_control(usr, R) && !..())
switch(action)
if("killbot")
if(allowed(usr))
var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs
if(can_control(usr, R) && !..())
var/turf/T = get_turf(R)
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(R, R.client)] at [ADMIN_VERBOSEJMP(T)]!</span>")
log_game("\<span class='notice'>[key_name(usr)] detonated [key_name(R)]!</span>")
if(R.connected_ai)
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
R.self_destruct()
else
to_chat(usr, "<span class='danger'>Access Denied.</span>")
else if (href_list["stopbot"])
if(src.allowed(usr))
var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) in GLOB.silicon_mobs
if(can_control(usr, R))
var/choice = input("Are you certain you wish to [!R.locked_down ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm" && can_control(usr, R) && !..())
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
else
to_chat(usr, "<span class='danger'>Access Denied.</span>")
if("stopbot")
if(allowed(usr))
var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs
if(can_control(usr, R) && !..())
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [!R.locked_down ? "locked down" : "released"] [ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R)]!")
R.SetLockdown(!R.locked_down)
to_chat(R, "[!R.locked_down ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
if(R.connected_ai)
to_chat(R.connected_ai, "[!R.locked_down ? "<span class='notice'>NOTICE - Cyborg lockdown lifted" : "<span class='alert'>ALERT - Cyborg lockdown detected"]: <a href='?src=[REF(R.connected_ai)];track=[html_encode(R.name)]'>[R.name]</a></span><br>")
else
to_chat(usr, "<span class='danger'>Access Denied.</span>")
else if (href_list["magbot"])
var/mob/living/silicon/S = usr
if((istype(S) && S.hack_software) || IsAdminGhost(usr))
var/mob/living/silicon/robot/R = locate(href_list["magbot"]) in GLOB.silicon_mobs
if(istype(R) && !R.emagged && (R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R))
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!")
R.SetEmagged(1)
else if(href_list["convert"])
if(isAI(usr) && is_servant_of_ratvar(usr))
var/mob/living/silicon/robot/R = locate(href_list["convert"]) in GLOB.silicon_mobs
if(istype(R) && !is_servant_of_ratvar(R) && R.connected_ai == usr)
log_game("[key_name(usr)] converted [key_name(R)] using robotic console!")
message_admins("[ADMIN_LOOKUPFLW(usr)] converted cyborg [key_name_admin(R)] using robotic console!")
add_servant_of_ratvar(R)
else if (href_list["killdrone"])
if(src.allowed(usr))
var/mob/living/simple_animal/drone/D = locate(href_list["killdrone"]) in GLOB.mob_list
if(D.hacked)
to_chat(usr, "<span class='danger'>ERROR: [D] is not responding to external commands.</span>")
else
var/turf/T = get_turf(D)
message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(D)] at [ADMIN_VERBOSEJMP(T)]!")
log_game("[key_name(usr)] detonated [key_name(D)]!")
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, D)
s.start()
D.visible_message("<span class='danger'>\the [D] self destructs!</span>")
D.gib()
src.updateUsrDialog()
return
to_chat(usr, "<span class='danger'>Access Denied.</span>")
if("magbot")
var/mob/living/silicon/S = usr
if((istype(S) && S.hack_software) || IsAdminGhost(usr))
var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs
if(istype(R) && !R.emagged && (R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R))
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!")
R.SetEmagged(TRUE)
if("killdrone")
if(allowed(usr))
var/mob/living/simple_animal/drone/D = locate(params["ref"]) in GLOB.mob_list
if(D.hacked)
to_chat(usr, "<span class='danger'>ERROR: [D] is not responding to external commands.</span>")
else
var/turf/T = get_turf(D)
message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(D)] at [ADMIN_VERBOSEJMP(T)]!")
log_game("[key_name(usr)] detonated [key_name(D)]!")
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, TRUE, D)
s.start()
D.visible_message("<span class='danger'>\the [D] self destructs!</span>")
D.gib()
@@ -20,7 +20,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "station_alert", name, 325, 500, master_ui, state)
ui = new(user, src, ui_key, "StationAlertConsole", name, 325, 500, master_ui, state)
ui.open()
/obj/machinery/computer/station_alert/ui_data(mob/user)
+1 -1
View File
@@ -38,7 +38,7 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "teleporter", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "Teleporter", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/teleporter/ui_data(mob/user)
+48 -61
View File
@@ -15,6 +15,7 @@
var/precision_coeff
var/message_cooldown
var/breakout_time = 1200
var/obj/machinery/computer/scan_consolenew/linked_console = null
/obj/machinery/dna_scannernew/RefreshParts()
scan_level = 0
@@ -22,8 +23,8 @@
precision_coeff = 0
for(var/obj/item/stock_parts/scanning_module/P in component_parts)
scan_level += P.rating
for(var/obj/item/stock_parts/matter_bin/P in component_parts)
precision_coeff = P.rating
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
precision_coeff = M.rating
for(var/obj/item/stock_parts/micro_laser/P in component_parts)
damage_coeff = P.rating
@@ -31,11 +32,8 @@
. = ..()
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Radiation pulse accuracy increased by factor <b>[precision_coeff**2]</b>.<br>Radiation pulse damage decreased by factor <b>[damage_coeff**2]</b>.</span>"
if(scan_level >= 3)
. += "<span class='notice'>Scanner has been upgraded to support autoprocessing.<span>"
/obj/machinery/dna_scannernew/update_icon_state()
//no power or maintenance
if(stat & (NOPOWER|BROKEN))
icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_unpowered"
@@ -53,10 +51,6 @@
//running
icon_state = initial(icon_state)+ (state_open ? "_open" : "")
/obj/machinery/dna_scannernew/power_change()
..()
update_icon()
/obj/machinery/dna_scannernew/proc/toggle_open(mob/user)
if(panel_open)
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
@@ -80,7 +74,7 @@
user.last_special = world.time + CLICK_CD_BREAKOUT
user.visible_message("<span class='notice'>You see [user] kicking against the door of [src]!</span>", \
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
"<span class='italics'>You hear a metallic creaking from [src].</span>")
"<span class='hear'>You hear a metallic creaking from [src].</span>")
if(do_after(user,(breakout_time), target = src))
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked)
return
@@ -96,33 +90,28 @@
return C
return null
/obj/machinery/dna_scannernew/close_machine(atom/movable/target)
/obj/machinery/dna_scannernew/close_machine(mob/living/carbon/user)
if(!state_open)
return FALSE
..(target)
// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
if(istype(mob_occupant))
if(locate_computer(/obj/machinery/computer/cloning))
if(!mob_occupant.suiciding && !(HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && !mob_occupant.hellbound)
mob_occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!", source = src)
..(user)
// DNA manipulators cannot operate on severed heads or brains
if(isliving(occupant))
var/obj/machinery/computer/scan_consolenew/console = locate_computer(/obj/machinery/computer/scan_consolenew)
if(console)
console.on_scanner_close()
if(iscarbon(occupant))
if(linked_console)
linked_console.on_scanner_close()
return TRUE
/obj/machinery/dna_scannernew/open_machine()
if(state_open || panel_open)
if(state_open)
return FALSE
..()
if(linked_console)
linked_console.on_scanner_open()
return TRUE
/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
@@ -133,51 +122,49 @@
return
open_machine()
/obj/machinery/dna_scannernew/screwdriver_act(mob/living/user, obj/item/I)
. = TRUE
if(..())
return
if(occupant)
to_chat(user, "<span class='warning'>[src] is currently occupied!</span>")
return
if(state_open)
to_chat(user, "<span class='warning'>[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!</span>")
return
if(default_deconstruction_screwdriver(user, icon_state, icon_state, I)) //sent icon_state is irrelevant...
update_icon() //..since we're updating the icon here, since the scanner can be unpowered when opened/closed
return
return FALSE
/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params)
/obj/machinery/dna_scannernew/wrench_act(mob/living/user, obj/item/I)
. = ..()
if(default_change_direction_wrench(user, I))
return TRUE
if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))//sent icon_state is irrelevant...
update_icon()//..since we're updating the icon here, since the scanner can be unpowered when opened/closed
return
/obj/machinery/dna_scannernew/crowbar_act(mob/living/user, obj/item/I)
. = ..()
if(default_pry_open(I))
return TRUE
if(default_deconstruction_crowbar(I))
return TRUE
return
/obj/machinery/dna_scannernew/default_pry_open(obj/item/I) //wew
. = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR
if(.)
I.play_tool_sound(src, 50)
visible_message("<span class='notice'>[usr] pries open [src].</span>", "<span class='notice'>You pry open [src].</span>")
open_machine()
if(default_deconstruction_crowbar(I))
return
return ..()
/obj/machinery/dna_scannernew/interact(mob/user)
toggle_open(user)
/obj/machinery/dna_scannernew/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
interact(user)
return TRUE
/obj/machinery/dna_scannernew/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
var/mob/living/L = user
if(user.stat || (isliving(user) && (!(L.mobility_flags & MOBILITY_STAND) || !(L.mobility_flags & MOBILITY_UI))) || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
return
close_machine(target)
//Just for transferring between genetics machines.
/obj/item/disk/data
name = "DNA data disk"
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
var/list/genetic_makeup_buffer = list()
var/list/fields = list()
var/list/mutations = list()
var/max_mutations = 6
var/read_only = FALSE //Well,it's still a floppy disk
/obj/item/disk/data/Initialize()
. = ..()
icon_state = "datadisk[rand(0,6)]"
add_overlay("datadisk_gene")
/obj/item/disk/data/attack_self(mob/user)
read_only = !read_only
to_chat(user, "<span class='notice'>You flip the write-protect tab to [read_only ? "protected" : "unprotected"].</span>")
/obj/item/disk/data/examine(mob/user)
. = ..()
. += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]."
+5 -1
View File
@@ -157,6 +157,10 @@
. = ..()
AddComponent(/datum/component/ntnet_interface)
/obj/machinery/door/airlock/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
if(id_tag)
id_tag = "[idnum][id_tag]"
/obj/machinery/door/airlock/proc/update_other_id()
for(var/obj/machinery/door/airlock/A in GLOB.airlocks)
if(A.closeOtherId == closeOtherId && A != src)
@@ -1440,7 +1444,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ai_airlock", name, 500, 390, master_ui, state)
ui = new(user, src, ui_key, "AiAirlock", name, 500, 390, master_ui, state)
ui.open()
return TRUE
@@ -2,10 +2,14 @@
name = "airlock electronics"
req_access = list(ACCESS_MAINT_TUNNELS)
custom_price = PRICE_CHEAP
/// A list of all granted accesses
var/list/accesses = list()
/// If the airlock should require ALL or only ONE of the listed accesses
var/one_access = 0
var/unres_sides = 0 //unrestricted sides, or sides of the airlock that will open regardless of access
/// Unrestricted sides, or sides of the airlock that will open regardless of access
var/unres_sides = 0
/// A holder of the electronics, in case of them working as an integrated part
var/holder
/obj/item/electronics/airlock/examine(mob/user)
. = ..()
@@ -13,31 +17,37 @@
/obj/item/electronics/airlock/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "airlock_electronics", name, 420, 485, master_ui, state)
ui = new(user, src, ui_key, "AirlockElectronics", name, 420, 485, master_ui, state)
ui.open()
/obj/item/electronics/airlock/ui_static_data(mob/user)
var/list/data = list()
var/list/regions = list()
for(var/i in 1 to 7)
var/list/accesses = list()
for(var/access in get_region_accesses(i))
if (get_access_desc(access))
accesses += list(list(
"desc" = replacetext(get_access_desc(access), "&nbsp", " "),
"ref" = access,
))
regions += list(list(
"name" = get_region_accesses_name(i),
"regid" = i,
"accesses" = accesses
))
data["regions"] = regions
return data
/obj/item/electronics/airlock/ui_data()
var/list/data = list()
var/list/regions = list()
for(var/i in 1 to 7)
var/list/region = list()
var/list/accesses = list()
for(var/j in get_region_accesses(i))
var/list/access = list()
access["name"] = get_access_desc(j)
access["id"] = j
access["req"] = (j in src.accesses)
accesses[++accesses.len] = access
region["name"] = get_region_accesses_name(i)
region["accesses"] = accesses
regions[++regions.len] = region
data["regions"] = regions
data["accesses"] = accesses
data["oneAccess"] = one_access
data["unres_direction"] = unres_sides
return data
/obj/item/electronics/airlock/ui_act(action, params)
@@ -48,12 +58,12 @@
accesses = list()
one_access = 0
. = TRUE
if("one_access")
one_access = !one_access
. = TRUE
if("grant_all")
accesses = get_all_accesses()
. = TRUE
if("one_access")
one_access = !one_access
. = TRUE
if("set")
var/access = text2num(params["access"])
if (!(access in accesses))
@@ -65,3 +75,20 @@
var/unres_direction = text2num(params["unres_direction"])
unres_sides ^= unres_direction //XOR, toggles only the bit that was clicked
. = TRUE
if("grant_region")
var/region = text2num(params["region"])
if(isnull(region))
return
accesses |= get_region_accesses(region)
. = TRUE
if("deny_region")
var/region = text2num(params["region"])
if(isnull(region))
return
accesses -= get_region_accesses(region)
. = TRUE
/obj/item/electronics/airlock/ui_host()
if(holder)
return holder
return src
+1 -1
View File
@@ -144,7 +144,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "brig_timer", name, 300, 138, master_ui, state)
ui = new(user, src, ui_key, "BrigTimer", name, 300, 138, master_ui, state)
ui.open()
//icon update function
+3
View File
@@ -16,6 +16,9 @@
damage_deflection = 70
poddoor = TRUE
/obj/machinery/door/poddoor/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
id = "[idnum][id]"
/obj/machinery/door/poddoor/preopen
icon_state = "open"
density = FALSE
+3
View File
@@ -36,6 +36,9 @@
else
bulb = new(src)
/obj/machinery/flasher/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
id = "[idnum][id]"
/obj/machinery/flasher/Destroy()
QDEL_NULL(bulb)
return ..()
+1 -1
View File
@@ -31,7 +31,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "gulag_item_reclaimer", name, 300, 400, master_ui, state)
ui = new(user, src, ui_key, "GulagItemReclaimer", name, 300, 400, master_ui, state)
ui.open()
/obj/machinery/gulag_item_reclaimer/ui_data(mob/user)
+1 -1
View File
@@ -37,7 +37,7 @@
/obj/machinery/hypnochair/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "hypnochair", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "HypnoChair", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/hypnochair/ui_data()
+3
View File
@@ -53,6 +53,9 @@
else
icon_state = "igniter0"
/obj/machinery/igniter/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
id = "[idnum][id]"
// Wall mounted remote-control igniter.
/obj/machinery/sparker
+1 -2
View File
@@ -285,8 +285,7 @@
/obj/item/launchpad_remote/ui_interact(mob/user, ui_key = "launchpad_remote", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "launchpad_remote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height
ui.set_style("syndicate")
ui = new(user, src, ui_key, "LaunchpadRemote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height
ui.open()
ui.set_autoupdate(TRUE)
+2
View File
@@ -11,6 +11,8 @@
var/id = 1
var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess.
/obj/machinery/mass_driver/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
id = "[idnum][id]"
/obj/machinery/mass_driver/proc/drive(amount)
if(stat & (BROKEN|NOPOWER))
+1 -1
View File
@@ -225,6 +225,6 @@
/obj/item/paper/guides/recycler
name = "paper - 'garbage duty instructions'"
info = "<h2>New Assignment</h2> You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect the said trash.<br><br>There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!"
info = "_New Assignment_\n\n You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect the said trash.<br><br>There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!"
#undef SAFETY_COOLDOWN
+1 -1
View File
@@ -175,7 +175,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "space_heater", name, 400, 305, master_ui, state)
ui = new(user, src, ui_key, "SpaceHeater", name, 400, 305, master_ui, state)
ui.open()
/obj/machinery/space_heater/ui_data()
+1 -1
View File
@@ -383,7 +383,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "suit_storage_unit", name, 400, 305, master_ui, state)
ui = new(user, src, ui_key, "SuitStorageUnit", name, 400, 305, master_ui, state)
ui.open()
/obj/machinery/suit_storage_unit/ui_data()
@@ -21,7 +21,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "tcommsserver", "Telecomms Server Monitor", 575, 400, master_ui, state)
ui = new(user, src, ui_key, "TelecommsLogBrowser", "Telecomms Server Monitor", 575, 400, master_ui, state)
ui.open()
/obj/machinery/computer/telecomms/server/ui_data(mob/user)
@@ -41,7 +41,7 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "telepdalog", name, 727, 510, master_ui, state)
ui = new(user, src, ui_key, "TelecommsPDALog", name, 727, 510, master_ui, state)
ui.open()
/obj/machinery/computer/message_monitor/ui_static_data(mob/user)
@@ -389,7 +389,6 @@
/obj/item/paper/monitorkey/proc/print(obj/machinery/telecomms/message_server/server)
info = "<center><h2>Daily Key Reset</h2></center><br>The new message monitor key is '[server.decryptkey]'.<br>Please keep this a secret and away from the clown.<br>If necessary, change the password to a more secure one."
info_links = info
add_overlay("paper_words")
/obj/item/paper/monitorkey/LateInitialize()
@@ -22,7 +22,7 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "telemonitor", name, 575, 400, master_ui, state)
ui = new(user, src, ui_key, "TelecommsMonitor", name, 575, 400, master_ui, state)
ui.open()
/obj/machinery/computer/telecomms/monitor/ui_data(mob/user)
@@ -36,7 +36,7 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "teleinteract", "[name] Access", 520, 500, master_ui, state)
ui = new(user, src, ui_key, "TelecommsInteraction", "[name] Access", 520, 500, master_ui, state)
ui.open()
/obj/machinery/telecomms/ui_data(mob/user)
+1 -1
View File
@@ -84,7 +84,7 @@
/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "mech_bay_power_console", "Mech Bay Power Control Console", 400, 200, master_ui, state)
ui = new(user, src, ui_key, "MechBayPowerConsole", "Mech Bay Power Control Console", 400, 200, master_ui, state)
ui.open()
/obj/machinery/computer/mech_bay_power_console/ui_act(action, params)
+105 -87
View File
@@ -5,62 +5,74 @@
icon_keyboard = "tech_key"
req_access = list(ACCESS_ROBOTICS)
circuit = /obj/item/circuitboard/computer/mecha_control
var/list/located = list()
var/screen = 0
var/stored_data
ui_x = 500
ui_y = 500
/obj/machinery/computer/mecha/ui_interact(mob/user)
. = ..()
var/dat = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>[src.name]</title><style>h3 {margin: 0px; padding: 0px;}</style></head><body>"
if(screen == 0)
dat += "<h3>Tracking beacons data</h3>"
var/list/trackerlist = list()
for(var/obj/mecha/MC in GLOB.mechas_list)
trackerlist += MC.trackers
for(var/obj/item/mecha_parts/mecha_tracking/TR in trackerlist)
var/answer = TR.get_mecha_info()
if(answer)
dat += {"<hr>[answer]<br/>
<a href='?src=[REF(src)];send_message=[REF(TR)]'>Send message</a><br/>
<a href='?src=[REF(src)];get_log=[REF(TR)]'>Show exosuit log</a><br/>
[TR.recharging?"Recharging EMP Pulse...<br>":"<a style='color: #f00;' href='?src=[REF(src)];shock=[REF(TR)]'>(EMP Pulse)</a><br>"]"}
/obj/machinery/computer/mecha/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ExosuitControlConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
if(screen==1)
dat += "<h3>Log contents</h3>"
dat += "<a href='?src=[REF(src)];return=1'>Return</a><hr>"
dat += "[stored_data]"
/obj/machinery/computer/mecha/ui_data(mob/user)
var/list/data = list()
dat += "<A href='?src=[REF(src)];refresh=1'>(Refresh)</A><BR>"
dat += "</body></html>"
var/list/trackerlist = list()
for(var/obj/mecha/MC in GLOB.mechas_list)
trackerlist += MC.trackers
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
data["mechs"] = list()
for(var/obj/item/mecha_parts/mecha_tracking/MT in trackerlist)
if(!MT.chassis)
continue
var/obj/mecha/M = MT.chassis
var/list/mech_data = list(
name = M.name,
integrity = round((M.obj_integrity / M.max_integrity) * 100),
charge = M.cell ? round(M.cell.percent()) : null,
airtank = M.internal_tank ? M.return_pressure() : null,
pilot = M.occupant,
location = get_area_name(M, TRUE),
active_equipment = M.selected,
emp_recharging = MT.recharging,
tracker_ref = REF(MT)
)
if(istype(M, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = M
mech_data += list(
cargo_space = round((RM.cargo.len / RM.cargo_capacity) * 100)
)
/obj/machinery/computer/mecha/Topic(href, href_list)
data["mechs"] += list(mech_data)
return data
/obj/machinery/computer/mecha/ui_act(action, params)
if(..())
return
if(href_list["send_message"])
var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["send_message"])
if (!istype(MT))
return
var/message = stripped_input(usr,"Input message","Transmit message")
var/obj/mecha/M = MT.in_mecha()
if(trim(message) && M)
M.occupant_message(message)
return
if(href_list["shock"])
var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["shock"])
if (istype(MT))
MT.shock()
if(href_list["get_log"])
var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["get_log"])
if(istype(MT))
stored_data = MT.get_mecha_log()
screen = 1
if(href_list["return"])
screen = 0
updateUsrDialog()
return
switch(action)
if("send_message")
var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["tracker_ref"])
if(!istype(MT))
return
var/message = stripped_input(usr, "Input message", "Transmit message")
var/obj/mecha/M = MT.chassis
if(trim(message) && M)
M.occupant_message(message)
to_chat(usr, "<span class='notice'>Message sent.</span>")
. = TRUE
if("shock")
var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["tracker_ref"])
if(!istype(MT))
return
var/obj/mecha/M = MT.chassis
if(M)
MT.shock()
log_game("[key_name(usr)] has activated remote EMP on exosuit [M], located at [loc_name(M)], which is currently [M.occupant? "being piloted by [key_name(M.occupant)]." : "without a pilot."] ")
message_admins("[key_name_admin(usr)][ADMIN_FLW(usr)] has activated remote EMP on exosuit [M][ADMIN_JMP(M)], which is currently [M.occupant ? "being piloted by [key_name_admin(M.occupant)][ADMIN_FLW(M.occupant)]." : "without a pilot."] ")
. = TRUE
/obj/item/mecha_parts/mecha_tracking
name = "exosuit tracking beacon"
@@ -68,24 +80,31 @@
icon = 'icons/obj/device.dmi'
icon_state = "motion2"
w_class = WEIGHT_CLASS_SMALL
var/ai_beacon = FALSE //If this beacon allows for AI control. Exists to avoid using istype() on checking.
var/recharging = 0
/// If this beacon allows for AI control. Exists to avoid using istype() on checking
var/ai_beacon = FALSE
/// Cooldown variable for EMP pulsing
var/recharging = FALSE
/// The Mecha that this tracking beacon is attached to
var/obj/mecha/chassis
/**
* Returns a html formatted string describing attached mech status
*/
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info()
if(!in_mecha())
return 0
var/obj/mecha/M = src.loc
var/cell_charge = M.get_charge()
var/answer = {"<b>Name:</b> [M.name]
<b>Integrity:</b> [M.obj_integrity/M.max_integrity*100]%
<b>Cell charge:</b> [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]
<b>Airtank:</b> [M.return_pressure()]kPa
<b>Pilot:</b> [M.occupant||"None"]
<b>Location:</b> [get_area(M)||"Unknown"]
<b>Active equipment:</b> [M.selected||"None"] "}
if(istype(M, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = M
answer += "<b>Used cargo space:</b> [RM.cargo.len/RM.cargo_capacity*100]%<br>"
if(!chassis)
return FALSE
var/cell_charge = chassis.get_charge()
var/answer = {"<b>Name:</b> [chassis.name]<br>
<b>Integrity:</b> [round((chassis.obj_integrity/chassis.max_integrity * 100), 0.01)]%<br>
<b>Cell Charge:</b> [isnull(cell_charge) ? "Not Found":"[chassis.cell.percent()]%"]<br>
<b>Airtank:</b> [chassis.internal_tank ? "[round(chassis.return_pressure(), 0.01)]" : "Not Equipped"] kPa<br>
<b>Pilot:</b> [chassis.occupant || "None"]<br>
<b>Location:</b> [get_area_name(chassis, TRUE) || "Unknown"]<br>
<b>Active Equipment:</b> [chassis.selected || "None"]"}
if(istype(chassis, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = chassis
answer += "<br><b>Used Cargo Space:</b> [round((RM.cargo.len / RM.cargo_capacity * 100), 0.01)]%"
return answer
@@ -95,42 +114,41 @@
qdel(src)
/obj/item/mecha_parts/mecha_tracking/Destroy()
if(ismecha(loc))
var/obj/mecha/M = loc
if(src in M.trackers)
M.trackers -= src
if(chassis)
if(src in chassis.trackers)
chassis.trackers -= src
chassis = null
return ..()
/obj/item/mecha_parts/mecha_tracking/proc/in_mecha()
if(ismecha(loc))
return loc
return 0
/obj/item/mecha_parts/mecha_tracking/try_attach_part(mob/user, obj/mecha/M)
if(!..())
return
M.trackers += src
M.diag_hud_set_mechtracking()
chassis = M
/**
* Attempts to EMP mech that the tracker is attached to, if there is one and tracker is not on cooldown
*/
/obj/item/mecha_parts/mecha_tracking/proc/shock()
if(recharging)
return
var/obj/mecha/M = in_mecha()
if(M)
M.emp_act(EMP_HEAVY)
addtimer(CALLBACK(src, /obj/item/mecha_parts/mecha_tracking/proc/recharge), 15 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
recharging = 1
if(chassis)
chassis.emp_act(EMP_HEAVY)
addtimer(CALLBACK(src, /obj/item/mecha_parts/mecha_tracking/proc/recharge), 5 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
recharging = TRUE
/**
* Resets recharge variable, allowing tracker to be EMP pulsed again
*/
/obj/item/mecha_parts/mecha_tracking/proc/recharge()
recharging = 0
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_log()
if(!ismecha(loc))
return 0
var/obj/mecha/M = src.loc
return M.get_log_html()
recharging = FALSE
/obj/item/mecha_parts/mecha_tracking/ai_control
name = "exosuit AI control beacon"
desc = "A device used to transmit exosuit data. Also allows active AI units to take control of said exosuit."
ai_beacon = TRUE
/obj/item/storage/box/mechabeacons
name = "exosuit tracking beacons"
+7
View File
@@ -9,6 +9,13 @@
w_class = WEIGHT_CLASS_GIGANTIC
flags_1 = CONDUCT_1
/obj/item/mecha_parts/proc/try_attach_part(mob/user, obj/mecha/M) //For attaching parts to a finished mech
if(!user.transferItemToLoc(src, M))
to_chat(user, "<span class='warning'>\The [src] is stuck to your hand, you cannot put it in \the [M]!</span>")
return FALSE
user.visible_message("<span class='notice'>[user] attaches [src] to [M].</span>", "<span class='notice'>You attach [src] to [M].</span>")
return TRUE
/obj/item/mecha_parts/chassis
name = "Mecha Chassis"
icon_state = "backbone"
+1 -1
View File
@@ -249,7 +249,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
assets.send(user)
ui = new(user, src, ui_key, "rpd", name, 425, 472, master_ui, state)
ui = new(user, src, ui_key, "RapidPipeDispenser", name, 425, 515, master_ui, state)
ui.open()
/obj/item/pipe_dispenser/ui_data(mob/user)
+5 -5
View File
@@ -53,32 +53,32 @@
/obj/item/chromosome/stabilizer
name = "stabilizer chromosome"
desc = "A chromosome that adjusts to the body to reduce genetic damage by 20%."
desc = "A chromosome that reduces mutation instability by 20%."
icon_state = "stabilizer"
stabilizer_coeff = 0.8
weight = 1
/obj/item/chromosome/synchronizer
name = "synchronizer chromosome"
desc = "A chromosome that gives the mind more controle over the mutation, reducing knockback and downsides by 50%."
desc = "A chromosome that reduces mutation knockback and downsides by 50%."
icon_state = "synchronizer"
synchronizer_coeff = 0.5
/obj/item/chromosome/power
name = "power chromosome"
desc = "A power chromosome for boosting certain mutation's power by 50%."
desc = "A chromosome that increases mutation power by 50%."
icon_state = "power"
power_coeff = 1.5
/obj/item/chromosome/energy
name = "energetic chromosome"
desc = "A chromosome that reduces cooldown on action based mutations by 50%."
desc = "A chromosome that reduces action based mutation cooldowns by by 50%."
icon_state = "energy"
energy_coeff = 0.5
/obj/item/chromosome/reinforcer
name = "reinforcement chromosome"
desc = "Renders the mutation immune to mutadone."
desc = "A chromosome that renders mutations immune to mutadone."
icon_state = "reinforcer"
weight = 3

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