mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-27 14:07:51 +01:00
Merge remote-tracking branch 'ParadiseSS13/master' into removes-red-cross
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
# GitHub action to autorender nanomaps outside the game
|
||||
# This kills off the awful verb we have that takes a full 50 seconds and hangs the whole server
|
||||
# The file names and locations are VERY important here
|
||||
# DO NOT EDIT THIS UNLESS YOU KNOW WHAT YOU ARE DOING
|
||||
# -aa
|
||||
name: 'Render Nanomaps'
|
||||
on:
|
||||
push:
|
||||
branches: master
|
||||
paths:
|
||||
- '_maps/map_files/**'
|
||||
|
||||
jobs:
|
||||
generate_maps:
|
||||
name: 'Generate NanoMaps'
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: 'Update Branch'
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: 'Generate Maps'
|
||||
run: './tools/github-actions/nanomap-renderer-invoker.sh'
|
||||
|
||||
- name: 'Commit Maps'
|
||||
run: |
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "NanoMap Generation"
|
||||
git pull origin master
|
||||
git commit -m "NanoMap Auto-Update (`date`)" -a || true
|
||||
- name: 'Push Maps'
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
+2
-2
@@ -52,8 +52,6 @@ jobs:
|
||||
- libstdc++6:i386
|
||||
- libssl-dev:i386
|
||||
- gcc-multilib
|
||||
- g++-7
|
||||
- g++-7-multilib
|
||||
- pkg-config:i386
|
||||
- zlib1g-dev:i386
|
||||
cache:
|
||||
@@ -61,6 +59,8 @@ jobs:
|
||||
- $HOME/.cargo
|
||||
- $HOME/.rustup
|
||||
- $HOME/BYOND
|
||||
before_install:
|
||||
- 'sudo apt-get -qq update'
|
||||
install:
|
||||
- tools/travis/install_byond.sh
|
||||
- source $HOME/BYOND/byond/bin/byondsetup
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
[](https://travis-ci.org/ParadiseSS13/Paradise)
|
||||
[](http://isitmaintained.com/project/paradisess13/paradise "Average time to resolve an issue")
|
||||
[](http://isitmaintained.com/project/paradisess13/paradise "Percentage of issues still open")
|
||||
[](http://www.krihelinator.xyz)
|
||||

|
||||
|
||||
[](http://forthebadge.com)
|
||||
[](http://forthebadge.com)
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ z4 = lavaland
|
||||
#define MAP_TRANSITION_CONFIG list(\
|
||||
DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\
|
||||
DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\
|
||||
DECLARE_LEVEL(MINING, SELFLOOPING, list(REACHABLE, STATION_CONTACT, HAS_WEATHER, ORE_LEVEL, AI_OK)))
|
||||
DECLARE_LEVEL(MINING, SELFLOOPING, list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK)))
|
||||
#define USING_MAP_DATUM /datum/map/cyberiad
|
||||
|
||||
#elif !defined(MAP_OVERRIDE)
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ Lovingly ported by Purpose2 to Paradise
|
||||
#define MAP_TRANSITION_CONFIG list(\
|
||||
DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\
|
||||
DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\
|
||||
DECLARE_LEVEL(MINING, SELFLOOPING, list(REACHABLE, STATION_CONTACT, HAS_WEATHER, ORE_LEVEL, AI_OK)))
|
||||
DECLARE_LEVEL(MINING, SELFLOOPING, list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK)))
|
||||
|
||||
#define USING_MAP_DATUM /datum/map/delta
|
||||
|
||||
|
||||
@@ -12820,7 +12820,7 @@
|
||||
/obj/machinery/light/small{
|
||||
dir = 8
|
||||
},
|
||||
/obj/structure/chickenstatue,
|
||||
/obj/structure/statue/chickenstatue,
|
||||
/turf/simulated/floor/wood,
|
||||
/area/crew_quarters/mrchangs)
|
||||
"awO" = (
|
||||
@@ -12828,7 +12828,7 @@
|
||||
/turf/simulated/floor/wood,
|
||||
/area/crew_quarters/mrchangs)
|
||||
"awP" = (
|
||||
/obj/structure/chickenstatue,
|
||||
/obj/structure/statue/chickenstatue,
|
||||
/turf/simulated/floor/wood,
|
||||
/area/crew_quarters/mrchangs)
|
||||
"awQ" = (
|
||||
|
||||
@@ -1205,9 +1205,9 @@
|
||||
/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
|
||||
/area/lavaland/surface/outdoors)
|
||||
"dg" = (
|
||||
/obj/structure/bonfire/dense,
|
||||
/obj/structure/stone_tile/center,
|
||||
/obj/effect/mapping_helpers/no_lava,
|
||||
/obj/structure/bonfire,
|
||||
/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
|
||||
/area/lavaland/surface/outdoors)
|
||||
"di" = (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/simulated/mineral,
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/simulated/mineral,
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -411,17 +411,9 @@
|
||||
/obj/structure/chair,
|
||||
/turf/simulated/floor/plating/airless,
|
||||
/area/ruin/tcommsat)
|
||||
"bu" = (
|
||||
/obj/machinery/door/airlock/maintenance_hatch,
|
||||
/turf/simulated/floor/plating/airless{
|
||||
icon_state = "dark"
|
||||
},
|
||||
/area/ruin/tcommsat)
|
||||
"bv" = (
|
||||
/obj/machinery/door/airlock/hatch,
|
||||
/turf/simulated/floor/plating/airless{
|
||||
icon_state = "dark"
|
||||
},
|
||||
/turf/simulated/floor/plating/airless,
|
||||
/area/ruin/tcommsat)
|
||||
"bw" = (
|
||||
/obj/structure/window/reinforced{
|
||||
@@ -2709,7 +2701,7 @@ aD
|
||||
aC
|
||||
aC
|
||||
ai
|
||||
bu
|
||||
bC
|
||||
ai
|
||||
ak
|
||||
ak
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"aa" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"ab" = (
|
||||
/turf/simulated/mineral/random/low_chance,
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/obj/structure/lattice,
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"c" = (
|
||||
/turf/simulated/wall,
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/obj/structure/window/reinforced{
|
||||
tag = "icon-rwindow (EAST)";
|
||||
icon_state = "rwindow";
|
||||
dir = 4
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"c" = (
|
||||
/obj/machinery/door/airlock/external,
|
||||
@@ -20,7 +20,7 @@
|
||||
icon_state = "rwindow";
|
||||
dir = 8
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"e" = (
|
||||
/obj/structure/window/reinforced{
|
||||
@@ -64,7 +64,7 @@
|
||||
/area/ruin/powered)
|
||||
"k" = (
|
||||
/obj/structure/window/reinforced,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"l" = (
|
||||
/obj/structure/window/reinforced,
|
||||
@@ -112,7 +112,7 @@
|
||||
icon_state = "rwindow";
|
||||
dir = 1
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"q" = (
|
||||
/obj/machinery/light/small{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/simulated/floor/plating/airless,
|
||||
/area/ruin/unpowered)
|
||||
@@ -10,12 +10,12 @@
|
||||
/area/ruin/unpowered)
|
||||
"d" = (
|
||||
/obj/structure/lattice,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"e" = (
|
||||
/obj/structure/lattice,
|
||||
/obj/structure/lattice,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
|
||||
(1,1,1) = {"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/simulated/mineral,
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/simulated/mineral,
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/obj/structure/lattice,
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"c" = (
|
||||
/turf/simulated/wall/r_wall,
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/obj/structure/lattice,
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"c" = (
|
||||
/turf/simulated/wall,
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/turf/simulated/shuttle/wall{
|
||||
dir = 8;
|
||||
icon_state = "diagonalWall3"
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
/area/ruin/powered)
|
||||
"d" = (
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/turf/simulated/shuttle/wall{
|
||||
dir = 2;
|
||||
icon_state = "diagonalWall3"
|
||||
@@ -198,7 +198,7 @@
|
||||
},
|
||||
/area/ruin/powered)
|
||||
"A" = (
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/turf/simulated/shuttle/wall{
|
||||
dir = 1;
|
||||
icon_state = "diagonalWall3"
|
||||
@@ -212,7 +212,7 @@
|
||||
},
|
||||
/area/ruin/powered)
|
||||
"C" = (
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/turf/simulated/shuttle/wall{
|
||||
dir = 4;
|
||||
icon_state = "diagonalWall3"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/simulated/mineral,
|
||||
/area/ruin/powered)
|
||||
@@ -73,8 +73,7 @@
|
||||
},
|
||||
/mob/living/simple_animal/hostile/syndicate{
|
||||
desc = "A weary looking syndicate operative.";
|
||||
environment_smash = 0;
|
||||
faction = "syndicate"
|
||||
environment_smash = 0
|
||||
},
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/ruin/powered)
|
||||
@@ -100,6 +99,12 @@
|
||||
/obj/item/tank/air,
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/ruin/powered)
|
||||
"u" = (
|
||||
/obj/machinery/tcomms/relay/ruskie{
|
||||
network_id = "LISTENINGOUTPOST-RELAY"
|
||||
},
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/ruin/powered)
|
||||
"w" = (
|
||||
/obj/machinery/light/small,
|
||||
/turf/simulated/floor/plasteel,
|
||||
@@ -923,7 +928,7 @@ b
|
||||
f
|
||||
f
|
||||
f
|
||||
c
|
||||
f
|
||||
f
|
||||
D
|
||||
m
|
||||
@@ -965,7 +970,7 @@ f
|
||||
f
|
||||
p
|
||||
Y
|
||||
f
|
||||
u
|
||||
f
|
||||
j
|
||||
i
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/simulated/shuttle/wall{
|
||||
tag = "icon-swall_s6";
|
||||
@@ -168,7 +168,7 @@
|
||||
/area/ruin/powered)
|
||||
"D" = (
|
||||
/obj/structure/lattice,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"E" = (
|
||||
/obj/item/stack/rods,
|
||||
@@ -202,7 +202,7 @@
|
||||
/area/ruin/powered)
|
||||
"K" = (
|
||||
/obj/item/stack/sheet/metal,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"L" = (
|
||||
/obj/structure/mecha_wreckage/gygax,
|
||||
@@ -228,7 +228,7 @@
|
||||
/area/ruin/powered)
|
||||
"P" = (
|
||||
/obj/item/stack/rods,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"Q" = (
|
||||
/turf/simulated/shuttle/wall{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"aa" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"ab" = (
|
||||
/obj/structure/lattice,
|
||||
/obj/structure/cable{
|
||||
@@ -10,7 +10,7 @@
|
||||
icon_state = "2-4";
|
||||
tag = ""
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"ac" = (
|
||||
/obj/structure/lattice,
|
||||
@@ -20,7 +20,7 @@
|
||||
icon_state = "4-8";
|
||||
tag = ""
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"ad" = (
|
||||
/obj/structure/lattice,
|
||||
@@ -29,7 +29,7 @@
|
||||
d2 = 8;
|
||||
icon_state = "2-8"
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"ae" = (
|
||||
/obj/structure/lattice,
|
||||
@@ -38,7 +38,7 @@
|
||||
dir = 2;
|
||||
icon_state = "coil_red2"
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"af" = (
|
||||
/obj/structure/lattice,
|
||||
@@ -48,7 +48,7 @@
|
||||
icon_state = "1-8";
|
||||
tag = ""
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"ag" = (
|
||||
/turf/simulated/wall,
|
||||
@@ -65,7 +65,7 @@
|
||||
d2 = 2;
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"aj" = (
|
||||
/turf/unsimulated/floor/plating/airless,
|
||||
@@ -154,11 +154,11 @@
|
||||
/area/ruin/onehalf/drone_bay)
|
||||
"aw" = (
|
||||
/obj/structure/lattice,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"ax" = (
|
||||
/obj/structure/lattice,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/ruin/onehalf/hallway)
|
||||
"ay" = (
|
||||
/obj/structure/table_frame,
|
||||
@@ -224,7 +224,7 @@
|
||||
/area/ruin/onehalf/drone_bay)
|
||||
"aH" = (
|
||||
/obj/item/stack/rods,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/ruin/onehalf/hallway)
|
||||
"aI" = (
|
||||
/obj/effect/landmark/damageturf,
|
||||
@@ -805,7 +805,7 @@
|
||||
/area/ruin/onehalf/bridge)
|
||||
"bU" = (
|
||||
/obj/item/stack/sheet/metal,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"bV" = (
|
||||
/obj/structure/disposalpipe/segment,
|
||||
@@ -914,7 +914,7 @@
|
||||
dir = 4
|
||||
},
|
||||
/obj/item/stack/rods,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/ruin/onehalf/hallway)
|
||||
"cn" = (
|
||||
/obj/structure/lattice,
|
||||
@@ -925,7 +925,7 @@
|
||||
tag = "icon-small";
|
||||
icon_state = "small"
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"co" = (
|
||||
/obj/structure/grille,
|
||||
@@ -1008,7 +1008,7 @@
|
||||
/area/ruin/onehalf/bridge)
|
||||
"cv" = (
|
||||
/obj/item/stack/rods,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"cw" = (
|
||||
/turf/unsimulated/floor/plating/airless,
|
||||
@@ -1016,7 +1016,7 @@
|
||||
"cx" = (
|
||||
/obj/structure/lattice,
|
||||
/obj/item/stack/sheet/plasteel,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"cy" = (
|
||||
/obj/structure/lattice,
|
||||
@@ -1024,7 +1024,7 @@
|
||||
tag = "icon-medium";
|
||||
icon_state = "medium"
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/ruin/onehalf/hallway)
|
||||
"cz" = (
|
||||
/obj/structure/grille/broken,
|
||||
@@ -1071,10 +1071,10 @@
|
||||
/area/ruin/onehalf/bridge)
|
||||
"cE" = (
|
||||
/obj/item/stack/tile/wood,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"cF" = (
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/ruin/onehalf/hallway)
|
||||
"cG" = (
|
||||
/obj/structure/lattice,
|
||||
@@ -1083,7 +1083,7 @@
|
||||
d2 = 8;
|
||||
icon_state = "2-8"
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/ruin/onehalf/hallway)
|
||||
"cH" = (
|
||||
/obj/structure/lattice,
|
||||
@@ -1097,7 +1097,7 @@
|
||||
icon_state = "pipe-b";
|
||||
dir = 8
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/ruin/onehalf/hallway)
|
||||
"cI" = (
|
||||
/obj/machinery/door/airlock/command/glass{
|
||||
@@ -1149,7 +1149,7 @@
|
||||
dir = 2;
|
||||
icon_state = "coil_red2"
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/ruin/onehalf/hallway)
|
||||
"cQ" = (
|
||||
/obj/machinery/light{
|
||||
@@ -1160,7 +1160,7 @@
|
||||
/area/ruin/onehalf/bridge)
|
||||
"cR" = (
|
||||
/obj/item/stack/sheet/plasteel,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"cS" = (
|
||||
/obj/structure/lattice,
|
||||
@@ -1169,7 +1169,7 @@
|
||||
d2 = 2;
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/ruin/onehalf/hallway)
|
||||
"cU" = (
|
||||
/obj/structure/grille,
|
||||
@@ -1221,7 +1221,7 @@
|
||||
d2 = 8;
|
||||
icon_state = "2-8"
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"db" = (
|
||||
/obj/structure/table,
|
||||
@@ -1256,7 +1256,7 @@
|
||||
d2 = 2;
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"dg" = (
|
||||
/obj/structure/girder/reinforced,
|
||||
@@ -1350,7 +1350,7 @@
|
||||
tag = "icon-medium";
|
||||
icon_state = "medium"
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"dp" = (
|
||||
/obj/structure/lattice,
|
||||
@@ -1366,7 +1366,7 @@
|
||||
icon_state = "1-4"
|
||||
},
|
||||
/obj/item/stack/rods,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"dq" = (
|
||||
/obj/structure/lattice,
|
||||
@@ -1382,7 +1382,7 @@
|
||||
icon_state = "1-8";
|
||||
tag = ""
|
||||
},
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
|
||||
(1,1,1) = {"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"aa" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"ab" = (
|
||||
/turf/simulated/mineral,
|
||||
/area/space/nearstation)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/obj/structure/lattice,
|
||||
/turf/space,
|
||||
/turf/template_noop,
|
||||
/area/space/nearstation)
|
||||
"c" = (
|
||||
/obj/structure/grille,
|
||||
|
||||
@@ -5760,12 +5760,7 @@
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/derelict/arrival)
|
||||
"lw" = (
|
||||
/obj/structure/chickenstatue{
|
||||
desc = "Like a MULEbot, but more Russian and less functional.";
|
||||
icon = 'icons/obj/aibots.dmi';
|
||||
icon_state = "mulebot0";
|
||||
name = "OXENbot"
|
||||
},
|
||||
/obj/structure/statue/russian_mulebot,
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/derelict/arrival)
|
||||
"lx" = (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/simulated/mineral/random,
|
||||
/area/ruin/unpowered/no_grav/way_home)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"aa" = (
|
||||
/turf/space,
|
||||
/area/space)
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"ab" = (
|
||||
/turf/simulated/floor/plating/asteroid/airless,
|
||||
/area/ruin/unpowered)
|
||||
@@ -152,12 +152,7 @@
|
||||
/turf/simulated/floor/wood,
|
||||
/area/ruin/unpowered)
|
||||
"az" = (
|
||||
/obj/item/spellbook/oneuse/charge{
|
||||
desc = "For the technology-hating wizard.";
|
||||
spell = /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech;
|
||||
spellname = "Disable Technology";
|
||||
used = 1
|
||||
},
|
||||
/obj/item/spellbook/oneuse/emp/used,
|
||||
/turf/simulated/floor/wood,
|
||||
/area/ruin/unpowered)
|
||||
"aA" = (
|
||||
|
||||
@@ -32677,7 +32677,7 @@
|
||||
/turf/simulated/floor/carpet,
|
||||
/area/crew_quarters/mrchangs)
|
||||
"biQ" = (
|
||||
/obj/structure/chickenstatue,
|
||||
/obj/structure/statue/chickenstatue,
|
||||
/obj/machinery/camera{
|
||||
c_tag = "Mr. Chang's";
|
||||
dir = 2;
|
||||
@@ -82378,7 +82378,7 @@
|
||||
/turf/simulated/floor/carpet,
|
||||
/area/crew_quarters/mrchangs)
|
||||
"cSW" = (
|
||||
/obj/structure/chickenstatue,
|
||||
/obj/structure/statue/chickenstatue,
|
||||
/obj/machinery/firealarm{
|
||||
dir = 1;
|
||||
pixel_y = -24
|
||||
@@ -82887,14 +82887,14 @@
|
||||
tag = ""
|
||||
},
|
||||
/obj/structure/table,
|
||||
/obj/item/t_scanner,
|
||||
/obj/item/radio/headset/headset_eng,
|
||||
/obj/item/multitool{
|
||||
pixel_x = 5
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
|
||||
dir = 4
|
||||
},
|
||||
/obj/item/airlock_painter,
|
||||
/obj/item/airlock_painter{
|
||||
pixel_x = -4;
|
||||
pixel_y = 4
|
||||
},
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/engine/equipmentstorage)
|
||||
"cTP" = (
|
||||
|
||||
@@ -681,7 +681,7 @@
|
||||
req_access_txt = "2"
|
||||
},
|
||||
/obj/structure/cable{
|
||||
icon_state = "1-10"
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/turf/simulated/floor/plating,
|
||||
/area/mine/laborcamp)
|
||||
@@ -858,18 +858,11 @@
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/mine/laborcamp/security)
|
||||
"ce" = (
|
||||
/obj/structure/cable{
|
||||
icon_state = "2-4"
|
||||
/obj/machinery/power/smes{
|
||||
charge = 5e+006
|
||||
},
|
||||
/obj/structure/cable{
|
||||
icon_state = "5-6"
|
||||
},
|
||||
/turf/simulated/floor/plating,
|
||||
/area/mine/laborcamp)
|
||||
"cf" = (
|
||||
/obj/machinery/power/terminal,
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-8"
|
||||
icon_state = "0-4"
|
||||
},
|
||||
/turf/simulated/floor/plating,
|
||||
/area/mine/laborcamp)
|
||||
@@ -880,6 +873,9 @@
|
||||
/turf/simulated/floor/plating,
|
||||
/area/mine/laborcamp)
|
||||
"ch" = (
|
||||
/obj/structure/cable{
|
||||
icon_state = "1-8"
|
||||
},
|
||||
/turf/simulated/floor/plating,
|
||||
/area/mine/laborcamp)
|
||||
"ci" = (
|
||||
@@ -1033,21 +1029,22 @@
|
||||
/turf/simulated/floor/plasteel,
|
||||
/area/mine/laborcamp)
|
||||
"cz" = (
|
||||
/obj/machinery/power/port_gen/pacman{
|
||||
anchored = 1
|
||||
},
|
||||
/obj/structure/cable,
|
||||
/turf/simulated/floor/plating,
|
||||
/area/mine/laborcamp)
|
||||
"cA" = (
|
||||
/obj/machinery/power/smes{
|
||||
charge = 5e+006
|
||||
/obj/machinery/power/terminal{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-4"
|
||||
},
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/turf/simulated/floor/plating,
|
||||
/area/mine/laborcamp)
|
||||
"cA" = (
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-9"
|
||||
d1 = 4;
|
||||
d2 = 8;
|
||||
icon_state = "4-8";
|
||||
pixel_x = 0;
|
||||
tag = ""
|
||||
},
|
||||
/turf/simulated/floor/plating,
|
||||
/area/mine/laborcamp)
|
||||
@@ -1056,7 +1053,13 @@
|
||||
/turf/simulated/floor/plating,
|
||||
/area/mine/laborcamp)
|
||||
"cC" = (
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/obj/machinery/power/port_gen/pacman{
|
||||
anchored = 1
|
||||
},
|
||||
/obj/structure/cable{
|
||||
d2 = 8;
|
||||
icon_state = "0-8"
|
||||
},
|
||||
/turf/simulated/floor/plating,
|
||||
/area/mine/laborcamp)
|
||||
"cD" = (
|
||||
@@ -11202,7 +11205,7 @@ bm
|
||||
aq
|
||||
bB
|
||||
bM
|
||||
cf
|
||||
ch
|
||||
cA
|
||||
aq
|
||||
aj
|
||||
@@ -11460,7 +11463,7 @@ aq
|
||||
aq
|
||||
aq
|
||||
cg
|
||||
cB
|
||||
cA
|
||||
aq
|
||||
aj
|
||||
cQ
|
||||
@@ -11716,7 +11719,7 @@ aD
|
||||
aD
|
||||
aD
|
||||
aq
|
||||
ch
|
||||
cB
|
||||
cC
|
||||
aq
|
||||
aj
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@ z7 = empty space
|
||||
#define MAP_TRANSITION_CONFIG list(\
|
||||
DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\
|
||||
DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\
|
||||
DECLARE_LEVEL(MINING, SELFLOOPING, list(REACHABLE, STATION_CONTACT, HAS_WEATHER, ORE_LEVEL, AI_OK)))
|
||||
DECLARE_LEVEL(MINING, SELFLOOPING, list(ORE_LEVEL, REACHABLE, STATION_CONTACT, HAS_WEATHER, AI_OK)))
|
||||
|
||||
#define USING_MAP_DATUM /datum/map/metastation
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/datum/stack
|
||||
var/list/stack = list()
|
||||
var/max_elements = 0
|
||||
|
||||
/datum/stack/New(list/elements,max)
|
||||
..()
|
||||
if(elements)
|
||||
stack = elements.Copy()
|
||||
if(max)
|
||||
max_elements = max
|
||||
|
||||
/datum/stack/proc/Pop()
|
||||
if(is_empty())
|
||||
return null
|
||||
. = stack[stack.len]
|
||||
stack.Cut(stack.len,0)
|
||||
|
||||
/datum/stack/proc/Push(element)
|
||||
if(max_elements && (stack.len+1 > max_elements))
|
||||
return null
|
||||
stack += element
|
||||
|
||||
/datum/stack/proc/Top()
|
||||
if(is_empty())
|
||||
return null
|
||||
. = stack[stack.len]
|
||||
|
||||
/datum/stack/proc/is_empty()
|
||||
. = stack.len ? 0 : 1
|
||||
|
||||
//Rotate entire stack left with the leftmost looping around to the right
|
||||
/datum/stack/proc/RotateLeft()
|
||||
if(is_empty())
|
||||
return 0
|
||||
. = stack[1]
|
||||
stack.Cut(1,2)
|
||||
Push(.)
|
||||
|
||||
//Rotate entire stack to the right with the rightmost looping around to the left
|
||||
/datum/stack/proc/RotateRight()
|
||||
if(is_empty())
|
||||
return 0
|
||||
. = stack[stack.len]
|
||||
stack.Cut(stack.len,0)
|
||||
stack.Insert(1,.)
|
||||
|
||||
|
||||
/datum/stack/proc/Copy()
|
||||
var/datum/stack/S=new()
|
||||
S.stack = stack.Copy()
|
||||
S.max_elements = max_elements
|
||||
return S
|
||||
|
||||
|
||||
/datum/stack/proc/Clear()
|
||||
stack.Cut()
|
||||
@@ -15,6 +15,7 @@
|
||||
#define GAMEMODE_IS_NUCLEAR (SSticker && istype(SSticker.mode, /datum/game_mode/nuclear))
|
||||
#define GAMEMODE_IS_REVOLUTION (SSticker && istype(SSticker.mode, /datum/game_mode/revolution))
|
||||
#define GAMEMODE_IS_WIZARD (SSticker && istype(SSticker.mode, /datum/game_mode/wizard))
|
||||
#define GAMEMODE_IS_RAGIN_MAGES (SSticker && istype(SSticker.mode, /datum/game_mode/wizard/raginmages))
|
||||
|
||||
//special roles
|
||||
// Distinct from the ROLE_X defines because some antags have multiple special roles but only one ban type
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define PLANE_SPACE_PARALLAX -90
|
||||
|
||||
#define FLOOR_PLANE -2
|
||||
#define FLOOR_OVERLAY_PLANE -1.5
|
||||
#define GAME_PLANE -1
|
||||
#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals
|
||||
|
||||
|
||||
@@ -4,3 +4,8 @@
|
||||
#define SAY_LOG "Say"
|
||||
#define EMOTE_LOG "Emote"
|
||||
#define MISC_LOG "Misc"
|
||||
#define DEADCHAT_LOG "Deadchat"
|
||||
#define OOC_LOG "OOC"
|
||||
#define LOOC_LOG "LOOC"
|
||||
|
||||
#define ALL_LOGS list(ATTACK_LOG, DEFENSE_LOG, CONVERSION_LOG, SAY_LOG, EMOTE_LOG, DEADCHAT_LOG, OOC_LOG, LOOC_LOG, MISC_LOG)
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
// Subsystem init_order, from highest priority to lowest priority
|
||||
// Subsystems shutdown in the reverse of the order they initialize in
|
||||
// The numbers just define the ordering, they are meaningless otherwise.
|
||||
|
||||
#define INIT_ORDER_TITLE 100 // This **MUST** load first or people will se blank lobby screens
|
||||
#define INIT_ORDER_GARBAGE 19
|
||||
#define INIT_ORDER_DBCORE 18
|
||||
#define INIT_ORDER_BLACKBOX 17
|
||||
|
||||
+2
-60
@@ -425,66 +425,8 @@
|
||||
if(pressure <= LAVALAND_EQUIPMENT_EFFECT_PRESSURE)
|
||||
. = TRUE
|
||||
|
||||
proc/pollCandidates(Question, be_special_type, antag_age_check = FALSE, poll_time = 300, ignore_respawnability = FALSE, min_hours = 0, flashwindow = TRUE, check_antaghud = TRUE)
|
||||
var/roletext = be_special_type ? get_roletext(be_special_type) : null
|
||||
var/list/mob/dead/observer/candidates = list()
|
||||
var/time_passed = world.time
|
||||
if(!Question)
|
||||
Question = "Would you like to be a special role?"
|
||||
|
||||
for(var/mob/dead/observer/G in (ignore_respawnability ? GLOB.player_list : GLOB.respawnable_list))
|
||||
if(!G.key || !G.client)
|
||||
continue
|
||||
if(be_special_type)
|
||||
if(!(be_special_type in G.client.prefs.be_special))
|
||||
continue
|
||||
if(antag_age_check)
|
||||
if(!player_old_enough_antag(G.client, be_special_type))
|
||||
continue
|
||||
if(roletext)
|
||||
if(jobban_isbanned(G, roletext) || jobban_isbanned(G, "Syndicate"))
|
||||
continue
|
||||
if(config.use_exp_restrictions && min_hours)
|
||||
if(G.client.get_exp_type_num(EXP_TYPE_LIVING) < min_hours * 60)
|
||||
continue
|
||||
if(check_antaghud && cannotPossess(G))
|
||||
continue
|
||||
spawn(0)
|
||||
G << 'sound/misc/notice2.ogg'//Alerting them to their consideration
|
||||
if(flashwindow)
|
||||
window_flash(G.client)
|
||||
var/ans = alert(G,Question,"Please answer in [poll_time/10] seconds!","No","Yes","Not This Round")
|
||||
if(!G?.client)
|
||||
return
|
||||
switch(ans)
|
||||
if("Yes")
|
||||
to_chat(G, "<span class='notice'>Choice registered: Yes.</span>")
|
||||
if((world.time-time_passed)>poll_time)//If more than 30 game seconds passed.
|
||||
to_chat(G, "<span class='danger'>Sorry, you were too late for the consideration!</span>")
|
||||
G << 'sound/machines/buzz-sigh.ogg'
|
||||
return
|
||||
candidates += G
|
||||
if("No")
|
||||
to_chat(G, "<span class='danger'>Choice registered: No.</span>")
|
||||
return
|
||||
if("Not This Round")
|
||||
to_chat(G, "<span class='danger'>Choice registered: No.</span>")
|
||||
to_chat(G, "<span class='notice'>You will no longer receive notifications for the role '[roletext]' for the rest of the round.</span>")
|
||||
G.client.prefs.be_special -= be_special_type
|
||||
return
|
||||
else
|
||||
return
|
||||
sleep(poll_time)
|
||||
|
||||
//Check all our candidates, to make sure they didn't log off during the 30 second wait period.
|
||||
for(var/mob/dead/observer/G in candidates)
|
||||
if(!G.key || !G.client)
|
||||
candidates.Remove(G)
|
||||
|
||||
return candidates
|
||||
|
||||
/proc/pollCandidatesWithVeto(adminclient, adminusr, max_slots, Question, be_special_type, antag_age_check = 0, poll_time = 300, ignore_respawnability = 0, min_hours = 0, flashwindow = TRUE, check_antaghud = TRUE)
|
||||
var/list/willing_ghosts = pollCandidates(Question, be_special_type, antag_age_check, poll_time, ignore_respawnability, min_hours, flashwindow, check_antaghud)
|
||||
/proc/pollCandidatesWithVeto(adminclient, adminusr, max_slots, Question, be_special_type, antag_age_check = FALSE, poll_time = 300, ignore_respawnability = FALSE, min_hours = FALSE, flashwindow = TRUE, check_antaghud = TRUE, source)
|
||||
var/list/willing_ghosts = SSghost_spawns.poll_candidates(Question, be_special_type, antag_age_check, poll_time, ignore_respawnability, min_hours, flashwindow, check_antaghud, source)
|
||||
var/list/selected_ghosts = list()
|
||||
if(!willing_ghosts.len)
|
||||
return selected_ghosts
|
||||
|
||||
@@ -23,6 +23,14 @@
|
||||
|
||||
init_subtypes(/datum/surgery_step, GLOB.surgery_steps)
|
||||
|
||||
// Different bodies
|
||||
__init_body_accessory(/datum/body_accessory/body)
|
||||
// Different tails
|
||||
__init_body_accessory(/datum/body_accessory/tail)
|
||||
|
||||
// Setup species:accessory relations
|
||||
initialize_body_accessory_by_species()
|
||||
|
||||
for(var/path in (subtypesof(/datum/surgery)))
|
||||
GLOB.surgeries_list += new path()
|
||||
|
||||
@@ -30,6 +38,7 @@
|
||||
init_datum_subtypes(/datum/superheroes, GLOB.all_superheroes, null, "name")
|
||||
init_datum_subtypes(/datum/language, GLOB.all_languages, null, "name")
|
||||
|
||||
// Setup languages
|
||||
for(var/language_name in GLOB.all_languages)
|
||||
var/datum/language/L = GLOB.all_languages[language_name]
|
||||
if(!(L.flags & NONGLOBAL))
|
||||
@@ -54,7 +63,61 @@
|
||||
var/datum/pipes/P = D
|
||||
if(P.rpd_dispensable)
|
||||
GLOB.rpd_pipe_list += list(list("pipe_name" = P.pipe_name, "pipe_id" = P.pipe_id, "pipe_type" = P.pipe_type, "pipe_category" = P.pipe_category, "orientations" = P.orientations, "pipe_icon" = P.pipe_icon, "bendy" = P.bendy))
|
||||
return 1
|
||||
|
||||
// Setup PAI software
|
||||
for(var/type in subtypesof(/datum/pai_software))
|
||||
var/datum/pai_software/P = new type()
|
||||
if(GLOB.pai_software_by_key[P.id])
|
||||
var/datum/pai_software/O = GLOB.pai_software_by_key[P.id]
|
||||
to_chat(world, "<span class='warning'>pAI software module [P.name] has the same key as [O.name]!</span>")
|
||||
continue
|
||||
GLOB.pai_software_by_key[P.id] = P
|
||||
if(P.default)
|
||||
GLOB.default_pai_software[P.id] = P
|
||||
|
||||
// Setup loadout gear
|
||||
for(var/geartype in subtypesof(/datum/gear))
|
||||
var/datum/gear/G = geartype
|
||||
|
||||
var/use_name = initial(G.display_name)
|
||||
var/use_category = initial(G.sort_category)
|
||||
|
||||
if(G == initial(G.subtype_path))
|
||||
continue
|
||||
|
||||
if(!use_name)
|
||||
error("Loadout - Missing display name: [G]")
|
||||
continue
|
||||
if(!initial(G.cost))
|
||||
error("Loadout - Missing cost: [G]")
|
||||
continue
|
||||
if(!initial(G.path))
|
||||
error("Loadout - Missing path definition: [G]")
|
||||
continue
|
||||
|
||||
if(!GLOB.loadout_categories[use_category])
|
||||
GLOB.loadout_categories[use_category] = new /datum/loadout_category(use_category)
|
||||
var/datum/loadout_category/LC = GLOB.loadout_categories[use_category]
|
||||
GLOB.gear_datums[use_name] = new geartype
|
||||
LC.gear[use_name] = GLOB.gear_datums[use_name]
|
||||
|
||||
GLOB.loadout_categories = sortAssoc(GLOB.loadout_categories)
|
||||
for(var/loadout_category in GLOB.loadout_categories)
|
||||
var/datum/loadout_category/LC = GLOB.loadout_categories[loadout_category]
|
||||
LC.gear = sortAssoc(LC.gear)
|
||||
|
||||
|
||||
// Setup a list of robolimbs
|
||||
GLOB.basic_robolimb = new()
|
||||
for(var/limb_type in typesof(/datum/robolimb))
|
||||
var/datum/robolimb/R = new limb_type()
|
||||
GLOB.all_robolimbs[R.company] = R
|
||||
if(!R.unavailable_at_chargen)
|
||||
if(R != "head" && R != "chest" && R != "groin" ) //Part of the method that ensures only IPCs can access head, chest and groin prosthetics.
|
||||
if(R.has_subtypes) //Ensures solos get added to the list as well be incorporating has_subtypes == 1 and has_subtypes == 2.
|
||||
GLOB.chargen_robolimbs[R.company] = R //List only main brands and solo parts.
|
||||
if(R.selectable)
|
||||
GLOB.selectable_robolimbs[R.company] = R
|
||||
|
||||
/* // Uncomment to debug chemical reaction list.
|
||||
/client/verb/debug_chemical_list()
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
|
||||
//////////////////////
|
||||
//Heap object
|
||||
//datum/heap object
|
||||
//////////////////////
|
||||
|
||||
/Heap
|
||||
/datum/heap
|
||||
var/list/L
|
||||
var/cmp
|
||||
|
||||
/Heap/New(compare)
|
||||
/datum/heap/New(compare)
|
||||
L = new()
|
||||
cmp = compare
|
||||
|
||||
/Heap/proc/IsEmpty()
|
||||
/datum/heap/proc/IsEmpty()
|
||||
return !L.len
|
||||
|
||||
//Insert and place at its position a new node in the heap
|
||||
/Heap/proc/Insert(atom/A)
|
||||
/datum/heap/proc/Insert(atom/A)
|
||||
|
||||
L.Add(A)
|
||||
Swim(L.len)
|
||||
|
||||
//removes and returns the first element of the heap
|
||||
//(i.e the max or the min dependant on the comparison function)
|
||||
/Heap/proc/Pop()
|
||||
/datum/heap/proc/Pop()
|
||||
if(!L.len)
|
||||
return 0
|
||||
. = L[1]
|
||||
@@ -33,7 +33,7 @@
|
||||
Sink(1)
|
||||
|
||||
//Get a node up to its right position in the heap
|
||||
/Heap/proc/Swim(var/index)
|
||||
/datum/heap/proc/Swim(var/index)
|
||||
var/parent = round(index * 0.5)
|
||||
|
||||
while(parent > 0 && (call(cmp)(L[index],L[parent]) > 0))
|
||||
@@ -42,7 +42,7 @@
|
||||
parent = round(index * 0.5)
|
||||
|
||||
//Get a node down to its right position in the heap
|
||||
/Heap/proc/Sink(var/index)
|
||||
/datum/heap/proc/Sink(var/index)
|
||||
var/g_child = GetGreaterChild(index)
|
||||
|
||||
while(g_child > 0 && (call(cmp)(L[index],L[g_child]) < 0))
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
//Returns the greater (relative to the comparison proc) of a node children
|
||||
//or 0 if there's no child
|
||||
/Heap/proc/GetGreaterChild(var/index)
|
||||
/datum/heap/proc/GetGreaterChild(var/index)
|
||||
if(index * 2 > L.len)
|
||||
return 0
|
||||
|
||||
@@ -65,11 +65,11 @@
|
||||
return index * 2
|
||||
|
||||
//Replaces a given node so it verify the heap condition
|
||||
/Heap/proc/ReSort(atom/A)
|
||||
/datum/heap/proc/ReSort(atom/A)
|
||||
var/index = L.Find(A)
|
||||
|
||||
Swim(index)
|
||||
Sink(index)
|
||||
|
||||
/Heap/proc/List()
|
||||
/datum/heap/proc/List()
|
||||
. = L.Copy()
|
||||
@@ -693,6 +693,9 @@ proc/dd_sortedObjectList(list/incoming)
|
||||
// Lazying Episode 3
|
||||
#define LAZYSET(L, K, V) LAZYINITLIST(L); L[K] = V;
|
||||
|
||||
/// Returns whether a numerical index is within a given list's bounds. Faster than isnull(LAZYACCESS(L, I)).
|
||||
#define ISINDEXSAFE(L, I) (I >= 1 && I <= length(L))
|
||||
|
||||
//same, but returns nothing and acts on list in place
|
||||
/proc/shuffle_inplace(list/L)
|
||||
if(!L)
|
||||
|
||||
+40
-2
@@ -289,11 +289,14 @@ This is always put in the attack log.
|
||||
|
||||
var/user_str = key_name_log(user) + COORD(user)
|
||||
var/target_str
|
||||
var/target_info
|
||||
if(isatom(target))
|
||||
var/atom/AT = target
|
||||
target_str = key_name_log(AT) + COORD(AT)
|
||||
target_info = key_name_admin(target)
|
||||
else
|
||||
target_str = target
|
||||
target_info = target
|
||||
var/mob/MU = user
|
||||
var/mob/MT = target
|
||||
if(istype(MU))
|
||||
@@ -317,10 +320,13 @@ This is always put in the attack log.
|
||||
var/area/A = get_area(MT)
|
||||
if(A && A.hide_attacklogs)
|
||||
loglevel = ATKLOG_ALMOSTALL
|
||||
else
|
||||
loglevel = ATKLOG_ALL // Hitting an object. Not a mob
|
||||
if(isLivingSSD(target)) // Attacks on SSDs are shown to admins with any log level except ATKLOG_NONE. Overrides custom level
|
||||
loglevel = ATKLOG_FEW
|
||||
|
||||
msg_admin_attack("[key_name_admin(user)] vs [key_name_admin(target)]: [what_done]", loglevel)
|
||||
|
||||
msg_admin_attack("[key_name_admin(user)] vs [target_info]: [what_done]", loglevel)
|
||||
|
||||
/proc/do_mob(mob/user, mob/target, time = 30, uninterruptible = 0, progress = 1, list/extra_checks = list())
|
||||
if(!user || !target)
|
||||
@@ -579,7 +585,8 @@ GLOBAL_LIST_INIT(do_after_once_tracker, list())
|
||||
LogMouseMacro(".mouse", params)
|
||||
|
||||
/proc/update_all_mob_security_hud()
|
||||
for(var/mob/living/carbon/human/H in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
H.sec_hud_set_security_status()
|
||||
|
||||
/proc/getviewsize(view)
|
||||
@@ -616,3 +623,34 @@ GLOBAL_LIST_INIT(do_after_once_tracker, list())
|
||||
chosen = pick(mob_spawn_meancritters)
|
||||
var/mob/living/simple_animal/C = new chosen(spawn_location)
|
||||
return C
|
||||
|
||||
//determines the job of a mob, taking into account job transfers
|
||||
/proc/determine_role(mob/living/P)
|
||||
var/datum/mind/M = P.mind
|
||||
if(!M)
|
||||
return
|
||||
return M.playtime_role ? M.playtime_role : M.assigned_role //returns current role
|
||||
|
||||
/** checks the security force on station and returns a list of numbers, of the form:
|
||||
* total, active, dead, antag
|
||||
* where active is defined as conscious (STAT = 0) and not an antag
|
||||
*/
|
||||
/proc/check_active_security_force()
|
||||
var/sec_positions = GLOB.security_positions - "Magistrate" - "Brig Physician"
|
||||
var/total = 0
|
||||
var/active = 0
|
||||
var/dead = 0
|
||||
var/antag = 0
|
||||
for(var/p in GLOB.human_list) //contains only human mobs, so no type check needed
|
||||
var/mob/living/carbon/human/player = p //need to tell it what type it is or we can't access stat without the dreaded :
|
||||
if(determine_role(player) in sec_positions)
|
||||
total++
|
||||
if(player.stat == DEAD)
|
||||
dead++
|
||||
continue
|
||||
if(isAntag(player))
|
||||
antag++
|
||||
continue
|
||||
if(player.stat == CONSCIOUS)
|
||||
active++
|
||||
return list(total, active, dead, antag)
|
||||
|
||||
@@ -533,7 +533,7 @@ proc/checkhtml(var/t)
|
||||
text = replacetext(text, "\[/grid\]", "</td></tr></table>")
|
||||
text = replacetext(text, "\[row\]", "</td><tr>")
|
||||
text = replacetext(text, "\[cell\]", "<td>")
|
||||
text = replacetext(text, "\[logo\]", "<img src = ntlogo.png>")
|
||||
text = replacetext(text, "\[logo\]", "​<img src = ntlogo.png>")
|
||||
text = replacetext(text, "\[time\]", "[station_time_timestamp()]") // TO DO
|
||||
if(!no_font)
|
||||
if(P)
|
||||
|
||||
@@ -2017,5 +2017,10 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
set waitfor = FALSE
|
||||
return call(source, proctype)(arglist(arguments))
|
||||
|
||||
/proc/IsFrozen(atom/A)
|
||||
if(A in GLOB.frozen_atom_list)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/// Waits at a line of code until X is true
|
||||
#define UNTIL(X) while(!(X)) stoplag()
|
||||
|
||||
@@ -34,4 +34,6 @@ GLOBAL_PROTECT(IClog)
|
||||
GLOBAL_LIST_EMPTY(OOClog)
|
||||
GLOBAL_PROTECT(OOClog)
|
||||
|
||||
GLOBAL_DATUM_INIT(logging, /datum/logging, new /datum/logging())
|
||||
|
||||
GLOBAL_LIST_INIT(investigate_log_subjects, list("notes", "watchlist", "hrefs"))
|
||||
|
||||
@@ -55,3 +55,7 @@ GLOBAL_LIST_EMPTY(space_ruins_templates)
|
||||
GLOBAL_LIST_EMPTY(lava_ruins_templates)
|
||||
GLOBAL_LIST_EMPTY(shelter_templates)
|
||||
GLOBAL_LIST_EMPTY(shuttle_templates)
|
||||
|
||||
// Teleport locations
|
||||
GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
GLOBAL_LIST_EMPTY(ghostteleportlocs)
|
||||
|
||||
@@ -89,7 +89,7 @@ GLOBAL_VAR_INIT(copier_items_printed_logged, FALSE)
|
||||
|
||||
GLOBAL_VAR(map_name) // Self explanatory
|
||||
|
||||
GLOBAL_DATUM(data_core, /datum/datacore) // Station datacore, manifest, etc
|
||||
GLOBAL_DATUM_INIT(data_core, /datum/datacore, new) // Station datacore, manifest, etc
|
||||
|
||||
GLOBAL_VAR_INIT(panic_bunker_enabled, FALSE) // Is the panic bunker enabled
|
||||
|
||||
|
||||
@@ -73,7 +73,9 @@
|
||||
var/dragged = modifiers["drag"]
|
||||
if(dragged && !modifiers[dragged])
|
||||
return
|
||||
|
||||
if(IsFrozen(A) && !is_admin(usr))
|
||||
to_chat(usr, "<span class='boldannounce'>Interacting with admin-frozen players is not permitted.</span>")
|
||||
return
|
||||
if(modifiers["middle"] && modifiers["shift"] && modifiers["ctrl"])
|
||||
MiddleShiftControlClickOn(A)
|
||||
return
|
||||
|
||||
+90
-20
@@ -3,7 +3,7 @@
|
||||
//PUBLIC - call these wherever you want
|
||||
|
||||
|
||||
/mob/proc/throw_alert(category, type, severity, obj/new_master, override = FALSE)
|
||||
/mob/proc/throw_alert(category, type, severity, obj/new_master, override = FALSE, timeout_override, no_anim)
|
||||
|
||||
/*
|
||||
Proc to create or update an alert. Returns the alert if the alert is new or updated, 0 if it was thrown already
|
||||
@@ -59,14 +59,16 @@
|
||||
LAZYSET(alerts, category, alert) // This also creates the list if it doesn't exist
|
||||
if(client && hud_used)
|
||||
hud_used.reorganize_alerts()
|
||||
alert.transform = matrix(32, 6, MATRIX_TRANSLATE)
|
||||
animate(alert, transform = matrix(), time = 2.5, easing = CUBIC_EASING)
|
||||
|
||||
if(alert.timeout)
|
||||
spawn(alert.timeout)
|
||||
if(alert.timeout && alerts[category] == alert && world.time >= alert.timeout)
|
||||
clear_alert(category)
|
||||
alert.timeout = world.time + alert.timeout - world.tick_lag
|
||||
if(!no_anim)
|
||||
alert.transform = matrix(32, 6, MATRIX_TRANSLATE)
|
||||
animate(alert, transform = matrix(), time = 2.5, easing = CUBIC_EASING)
|
||||
|
||||
var/timeout = timeout_override || alert.timeout
|
||||
if(timeout)
|
||||
addtimer(CALLBACK(alert, /obj/screen/alert/.proc/do_timeout, src, category), timeout)
|
||||
alert.timeout = world.time + timeout - world.tick_lag
|
||||
|
||||
return alert
|
||||
|
||||
// Proc to clear an existing alert.
|
||||
@@ -94,7 +96,6 @@
|
||||
var/alerttooltipstyle = ""
|
||||
var/override_alerts = FALSE //If it is overriding other alerts of the same type
|
||||
|
||||
|
||||
/obj/screen/alert/MouseEntered(location,control,params)
|
||||
openToolTip(usr, src, params, title = name, content = desc, theme = alerttooltipstyle)
|
||||
|
||||
@@ -102,6 +103,12 @@
|
||||
/obj/screen/alert/MouseExited()
|
||||
closeToolTip(usr)
|
||||
|
||||
/obj/screen/alert/proc/do_timeout(mob/M, category)
|
||||
if(!M || !M.alerts)
|
||||
return
|
||||
|
||||
if(timeout && M.alerts[category] == src && world.time >= timeout)
|
||||
M.clear_alert(category)
|
||||
|
||||
//Gas alerts
|
||||
/obj/screen/alert/not_enough_oxy
|
||||
@@ -507,6 +514,34 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
timeout = 300
|
||||
var/atom/target = null
|
||||
var/action = NOTIFY_JUMP
|
||||
var/show_time_left = FALSE // If true you need to call START_PROCESSING manually
|
||||
var/image/time_left_overlay // The last image showing the time left
|
||||
var/datum/candidate_poll/poll // If set, on Click() it'll register the player as a candidate
|
||||
|
||||
/obj/screen/alert/notify_action/process()
|
||||
if(show_time_left)
|
||||
var/timeleft = timeout - world.time
|
||||
if(timeleft <= 0)
|
||||
return PROCESS_KILL
|
||||
|
||||
if(time_left_overlay)
|
||||
overlays -= time_left_overlay
|
||||
|
||||
var/obj/O = new
|
||||
O.maptext = "<span style='font-family: \"Small Fonts\"; font-weight: bold; font-size: 32px; color: [(timeleft <= 10 SECONDS) ? "red" : "white"];'>[CEILING(timeleft / 10, 1)]</span>"
|
||||
O.maptext_width = O.maptext_height = 128
|
||||
var/matrix/M = new
|
||||
M.Translate(4, 16)
|
||||
O.transform = M
|
||||
|
||||
var/image/I = image(O)
|
||||
I.layer = FLOAT_LAYER
|
||||
I.plane = FLOAT_PLANE + 1
|
||||
overlays += I
|
||||
|
||||
time_left_overlay = I
|
||||
qdel(O)
|
||||
..()
|
||||
|
||||
/obj/screen/alert/notify_action/Destroy()
|
||||
target = null
|
||||
@@ -515,20 +550,55 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
/obj/screen/alert/notify_action/Click()
|
||||
if(!usr || !usr.client)
|
||||
return
|
||||
if(!target)
|
||||
return
|
||||
var/mob/dead/observer/G = usr
|
||||
if(!istype(G))
|
||||
return
|
||||
switch(action)
|
||||
if(NOTIFY_ATTACK)
|
||||
target.attack_ghost(G)
|
||||
if(NOTIFY_JUMP)
|
||||
var/turf/T = get_turf(target)
|
||||
if(T && isturf(T))
|
||||
G.loc = T
|
||||
if(NOTIFY_FOLLOW)
|
||||
G.ManualFollow(target)
|
||||
|
||||
if(poll)
|
||||
if(poll.sign_up(G))
|
||||
// Add a small overlay to indicate we've signed up
|
||||
display_signed_up()
|
||||
else if(target)
|
||||
switch(action)
|
||||
if(NOTIFY_ATTACK)
|
||||
target.attack_ghost(G)
|
||||
if(NOTIFY_JUMP)
|
||||
var/turf/T = get_turf(target)
|
||||
if(T && isturf(T))
|
||||
G.loc = T
|
||||
if(NOTIFY_FOLLOW)
|
||||
G.ManualFollow(target)
|
||||
|
||||
/obj/screen/alert/notify_action/Topic(href, href_list)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
if(href_list["signup"] && isobserver(usr) && poll?.sign_up(usr))
|
||||
display_signed_up()
|
||||
|
||||
/obj/screen/alert/notify_action/proc/display_signed_up()
|
||||
var/image/I = image('icons/mob/screen_gen.dmi', icon_state = "selector")
|
||||
I.layer = FLOAT_LAYER
|
||||
I.plane = FLOAT_PLANE + 2
|
||||
overlays += I
|
||||
|
||||
/obj/screen/alert/notify_action/proc/display_stacks(stacks = 1)
|
||||
if(stacks <= 1)
|
||||
return
|
||||
|
||||
var/obj/O = new
|
||||
O.maptext = "<span style='font-family: \"Small Fonts\"; font-size: 32px; color: yellow;'>[stacks]x</span>"
|
||||
O.maptext_width = O.maptext_height = 128
|
||||
var/matrix/M = new
|
||||
M.Translate(4, 2)
|
||||
O.transform = M
|
||||
|
||||
var/image/I = image(O)
|
||||
I.layer = FLOAT_LAYER
|
||||
I.plane = FLOAT_PLANE + 1
|
||||
overlays += I
|
||||
|
||||
qdel(O)
|
||||
|
||||
/obj/screen/alert/notify_soulstone
|
||||
name = "Soul Stone"
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
user.do_attack_animation(M)
|
||||
. = M.attacked_by(src, user, def_zone)
|
||||
|
||||
add_attack_logs(user, M, "Attacked with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])", (M.ckey && force > 0 && damtype != STAMINA) ? null : ATKLOG_ALMOSTALL)
|
||||
add_attack_logs(user, M, "Attacked with [name] ([uppertext(user.a_intent)]) ([uppertext(damtype)])", (M.ckey && force > 0 && damtype != STAMINA) ? null : ATKLOG_ALMOSTALL)
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
|
||||
#define MIDDLE_CLICK 0
|
||||
#define ALT_CLICK 1
|
||||
#define CTRL_CLICK 2
|
||||
#define MAX_HARDSUIT_CLICK_MODE 2
|
||||
|
||||
/client
|
||||
var/hardsuit_click_mode = MIDDLE_CLICK
|
||||
|
||||
/client/verb/toggle_hardsuit_mode()
|
||||
set name = "Toggle Hardsuit Activation Mode"
|
||||
set desc = "Switch between hardsuit activation modes."
|
||||
set category = "OOC"
|
||||
|
||||
hardsuit_click_mode++
|
||||
if(hardsuit_click_mode > MAX_HARDSUIT_CLICK_MODE)
|
||||
hardsuit_click_mode = 0
|
||||
|
||||
switch(hardsuit_click_mode)
|
||||
if(MIDDLE_CLICK)
|
||||
to_chat(src, "Hardsuit activation mode set to middle-click.")
|
||||
if(ALT_CLICK)
|
||||
to_chat(src, "Hardsuit activation mode set to alt-click.")
|
||||
if(CTRL_CLICK)
|
||||
to_chat(src, "Hardsuit activation mode set to control-click.")
|
||||
else
|
||||
// should never get here, but just in case:
|
||||
log_runtime(EXCEPTION("Bad hardsuit click mode: [hardsuit_click_mode] - expected 0 to [MAX_HARDSUIT_CLICK_MODE]"), src)
|
||||
to_chat(src, "Somehow you bugged the system. Setting your hardsuit mode to middle-click.")
|
||||
hardsuit_click_mode = MIDDLE_CLICK
|
||||
|
||||
/mob/living/MiddleClickOn(atom/A)
|
||||
if(client && client.hardsuit_click_mode == MIDDLE_CLICK)
|
||||
if(HardsuitClickOn(A))
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/AltClickOn(atom/A)
|
||||
if(client && client.hardsuit_click_mode == ALT_CLICK)
|
||||
if(HardsuitClickOn(A))
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/CtrlClickOn(atom/A)
|
||||
if(client && client.hardsuit_click_mode == CTRL_CLICK)
|
||||
if(HardsuitClickOn(A))
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/proc/can_use_rig()
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/human/can_use_rig()
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/brain/can_use_rig()
|
||||
return istype(loc, /obj/item/mmi)
|
||||
|
||||
/mob/living/silicon/ai/can_use_rig()
|
||||
return istype(loc, /obj/item/aicard)
|
||||
|
||||
/mob/living/silicon/pai/can_use_rig()
|
||||
return loc == card
|
||||
|
||||
/mob/living/proc/HardsuitClickOn(var/atom/A, var/alert_ai = 0)
|
||||
if(!can_use_rig() || (next_move > world.time))
|
||||
return 0
|
||||
var/obj/item/rig/rig = get_rig()
|
||||
if(istype(rig) && !rig.offline && rig.selected_module)
|
||||
if(src != rig.wearer)
|
||||
if(rig.ai_can_move_suit(src, check_user_module = 1))
|
||||
message_admins("[key_name_admin(src)] is trying to force \the [key_name_admin(rig.wearer)] to use a hardsuit module.")
|
||||
else
|
||||
return 0
|
||||
rig.selected_module.engage(A, alert_ai)
|
||||
if(ismob(A)) // No instant mob attacking - though modules have their own cooldowns
|
||||
changeNext_move(CLICK_CD_MELEE)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
#undef MIDDLE_CLICK
|
||||
#undef ALT_CLICK
|
||||
#undef CTRL_CLICK
|
||||
#undef MAX_HARDSUIT_CLICK_MODE
|
||||
@@ -61,7 +61,6 @@
|
||||
var/usewhitelist = 0
|
||||
var/mods_are_mentors = 0
|
||||
var/load_jobs_from_txt = 0
|
||||
var/ToRban = 0
|
||||
var/automute_on = 0 //enables automuting/spam prevention
|
||||
var/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access.
|
||||
var/round_abandon_penalty_period = 30 MINUTES // Time from round start during which ghosting out is penalized
|
||||
@@ -578,9 +577,6 @@
|
||||
if("humans_need_surnames")
|
||||
humans_need_surnames = 1
|
||||
|
||||
if("tor_ban")
|
||||
ToRban = 1
|
||||
|
||||
if("automute_on")
|
||||
automute_on = 1
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* Startup hook.
|
||||
* Called in world.dm when the server starts.
|
||||
*/
|
||||
/hook/startup
|
||||
|
||||
/**
|
||||
* Roundstart hook.
|
||||
* Called in gameticker.dm when a round starts.
|
||||
*/
|
||||
/hook/roundstart
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* @file hooks.dm
|
||||
* Implements hooks, a simple way to run code on pre-defined events.
|
||||
*/
|
||||
|
||||
/** @page hooks Code hooks
|
||||
* @section hooks Hooks
|
||||
* A hook is defined under /hook in the type tree.
|
||||
*
|
||||
* To add some code to be called by the hook, define a proc under the type, as so:
|
||||
* @code
|
||||
/hook/foo/proc/bar()
|
||||
if(1)
|
||||
return 1 //Sucessful
|
||||
else
|
||||
return 0 //Error, or runtime.
|
||||
* @endcode
|
||||
* All hooks must return nonzero on success, as runtimes will force return null.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calls a hook, executing every piece of code that's attached to it.
|
||||
* @param hook Identifier of the hook to call.
|
||||
* @returns 1 if all hooked code runs successfully, 0 otherwise.
|
||||
*/
|
||||
/proc/callHook(hook, list/args=null)
|
||||
var/hook_path = text2path("/hook/[hook]")
|
||||
if(!hook_path)
|
||||
error("Invalid hook '/hook/[hook]' called.")
|
||||
return 0
|
||||
|
||||
var/caller = new hook_path
|
||||
var/status = 1
|
||||
for(var/P in typesof("[hook_path]/proc"))
|
||||
if(!call(caller, P)(arglist(args)))
|
||||
error("Hook '[P]' failed or runtimed.")
|
||||
status = 0
|
||||
|
||||
return status
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
var/static/list/failure_strikes //How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out!
|
||||
|
||||
var/offline_implications = "None" // What are the implications of this SS being offlined?
|
||||
var/offline_implications = "None. No immediate action is needed." // What are the implications of this SS being offlined?
|
||||
|
||||
//Do not override
|
||||
///datum/controller/subsystem/New()
|
||||
|
||||
@@ -21,7 +21,8 @@ SUBSYSTEM_DEF(afk)
|
||||
|
||||
/datum/controller/subsystem/afk/fire()
|
||||
var/list/toRemove = list()
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
if(!H?.ckey) // Useless non ckey creatures
|
||||
continue
|
||||
|
||||
|
||||
@@ -212,38 +212,38 @@ SUBSYSTEM_DEF(events)
|
||||
|
||||
if(href_list["toggle_report"])
|
||||
report_at_round_end = !report_at_round_end
|
||||
admin_log_and_message_admins("has [report_at_round_end ? "enabled" : "disabled"] the round end event report.")
|
||||
log_and_message_admins("has [report_at_round_end ? "enabled" : "disabled"] the round end event report.")
|
||||
else if(href_list["dec_timer"])
|
||||
var/datum/event_container/EC = locate(href_list["event"])
|
||||
var/decrease = (60 * RaiseToPower(10, text2num(href_list["dec_timer"])))
|
||||
EC.next_event_time -= decrease
|
||||
admin_log_and_message_admins("decreased timer for [GLOB.severity_to_string[EC.severity]] events by [decrease/600] minute(s).")
|
||||
log_and_message_admins("decreased timer for [GLOB.severity_to_string[EC.severity]] events by [decrease/600] minute(s).")
|
||||
else if(href_list["inc_timer"])
|
||||
var/datum/event_container/EC = locate(href_list["event"])
|
||||
var/increase = (60 * RaiseToPower(10, text2num(href_list["inc_timer"])))
|
||||
EC.next_event_time += increase
|
||||
admin_log_and_message_admins("increased timer for [GLOB.severity_to_string[EC.severity]] events by [increase/600] minute(s).")
|
||||
log_and_message_admins("increased timer for [GLOB.severity_to_string[EC.severity]] events by [increase/600] minute(s).")
|
||||
else if(href_list["select_event"])
|
||||
var/datum/event_container/EC = locate(href_list["select_event"])
|
||||
var/datum/event_meta/EM = EC.SelectEvent()
|
||||
if(EM)
|
||||
admin_log_and_message_admins("has queued the [GLOB.severity_to_string[EC.severity]] event '[EM.name]'.")
|
||||
log_and_message_admins("has queued the [GLOB.severity_to_string[EC.severity]] event '[EM.name]'.")
|
||||
else if(href_list["pause"])
|
||||
var/datum/event_container/EC = locate(href_list["pause"])
|
||||
EC.delayed = !EC.delayed
|
||||
admin_log_and_message_admins("has [EC.delayed ? "paused" : "resumed"] countdown for [GLOB.severity_to_string[EC.severity]] events.")
|
||||
log_and_message_admins("has [EC.delayed ? "paused" : "resumed"] countdown for [GLOB.severity_to_string[EC.severity]] events.")
|
||||
else if(href_list["interval"])
|
||||
var/delay = input("Enter delay modifier. A value less than one means events fire more often, higher than one less often.", "Set Interval Modifier") as num|null
|
||||
if(delay && delay > 0)
|
||||
var/datum/event_container/EC = locate(href_list["interval"])
|
||||
EC.delay_modifier = delay
|
||||
admin_log_and_message_admins("has set the interval modifier for [GLOB.severity_to_string[EC.severity]] events to [EC.delay_modifier].")
|
||||
log_and_message_admins("has set the interval modifier for [GLOB.severity_to_string[EC.severity]] events to [EC.delay_modifier].")
|
||||
else if(href_list["stop"])
|
||||
if(alert("Stopping an event may have unintended side-effects. Continue?","Stopping Event!","Yes","No") != "Yes")
|
||||
return
|
||||
var/datum/event/E = locate(href_list["stop"])
|
||||
var/datum/event_meta/EM = E.event_meta
|
||||
admin_log_and_message_admins("has stopped the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
|
||||
log_and_message_admins("has stopped the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
|
||||
E.kill()
|
||||
else if(href_list["view_events"])
|
||||
selected_event_container = locate(href_list["view_events"])
|
||||
@@ -265,23 +265,23 @@ SUBSYSTEM_DEF(events)
|
||||
var/datum/event_meta/EM = locate(href_list["set_weight"])
|
||||
EM.weight = weight
|
||||
if(EM != new_event)
|
||||
admin_log_and_message_admins("has changed the weight of the [GLOB.severity_to_string[EM.severity]] event '[EM.name]' to [EM.weight].")
|
||||
log_and_message_admins("has changed the weight of the [GLOB.severity_to_string[EM.severity]] event '[EM.name]' to [EM.weight].")
|
||||
else if(href_list["toggle_oneshot"])
|
||||
var/datum/event_meta/EM = locate(href_list["toggle_oneshot"])
|
||||
EM.one_shot = !EM.one_shot
|
||||
if(EM != new_event)
|
||||
admin_log_and_message_admins("has [EM.one_shot ? "set" : "unset"] the oneshot flag for the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
|
||||
log_and_message_admins("has [EM.one_shot ? "set" : "unset"] the oneshot flag for the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
|
||||
else if(href_list["toggle_enabled"])
|
||||
var/datum/event_meta/EM = locate(href_list["toggle_enabled"])
|
||||
EM.enabled = !EM.enabled
|
||||
admin_log_and_message_admins("has [EM.enabled ? "enabled" : "disabled"] the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
|
||||
log_and_message_admins("has [EM.enabled ? "enabled" : "disabled"] the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
|
||||
else if(href_list["remove"])
|
||||
if(alert("This will remove the event from rotation. Continue?","Removing Event!","Yes","No") != "Yes")
|
||||
return
|
||||
var/datum/event_meta/EM = locate(href_list["remove"])
|
||||
var/datum/event_container/EC = locate(href_list["EC"])
|
||||
EC.available_events -= EM
|
||||
admin_log_and_message_admins("has removed the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
|
||||
log_and_message_admins("has removed the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.")
|
||||
else if(href_list["add"])
|
||||
if(!new_event.name || !new_event.event_type)
|
||||
return
|
||||
@@ -289,12 +289,12 @@ SUBSYSTEM_DEF(events)
|
||||
return
|
||||
new_event.severity = selected_event_container.severity
|
||||
selected_event_container.available_events += new_event
|
||||
admin_log_and_message_admins("has added \a [GLOB.severity_to_string[new_event.severity]] event '[new_event.name]' of type [new_event.event_type] with weight [new_event.weight].")
|
||||
log_and_message_admins("has added \a [GLOB.severity_to_string[new_event.severity]] event '[new_event.name]' of type [new_event.event_type] with weight [new_event.weight].")
|
||||
new_event = new
|
||||
else if(href_list["clear"])
|
||||
var/datum/event_container/EC = locate(href_list["clear"])
|
||||
if(EC.next_event)
|
||||
admin_log_and_message_admins("has dequeued the [GLOB.severity_to_string[EC.severity]] event '[EC.next_event.name]'.")
|
||||
log_and_message_admins("has dequeued the [GLOB.severity_to_string[EC.severity]] event '[EC.next_event.name]'.")
|
||||
EC.next_event = null
|
||||
|
||||
Interact(usr)
|
||||
|
||||
@@ -4,7 +4,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
wait = 2 SECONDS
|
||||
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT
|
||||
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
|
||||
init_order = INIT_ORDER_GARBAGE
|
||||
init_order = INIT_ORDER_GARBAGE // Why does this have an init order if it has SS_NO_INIT?
|
||||
offline_implications = "Garbage collection is no longer functional, and objects will not be qdel'd. Immediate server restart recommended."
|
||||
|
||||
var/list/collection_timeout = list(2 MINUTES, 10 SECONDS) // deciseconds to wait before moving something up in the queue to the next level
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
SUBSYSTEM_DEF(ghost_spawns)
|
||||
name = "Ghost Spawns"
|
||||
init_order = INIT_ORDER_EVENTS
|
||||
flags = SS_BACKGROUND
|
||||
wait = 1 SECONDS
|
||||
runlevels = RUNLEVEL_GAME
|
||||
offline_implications = "Ghosts will no longer be able to respawn as event mobs (Blob, etc..). Shuttle call recommended."
|
||||
|
||||
/// List of polls currently ongoing, to be checked on next fire()
|
||||
var/list/datum/candidate_poll/currently_polling
|
||||
/// Whether there are active polls or not
|
||||
var/polls_active = FALSE
|
||||
/// Number of polls performed since the start
|
||||
var/total_polls = 0
|
||||
/// The poll that's closest to finishing
|
||||
var/datum/candidate_poll/next_poll_to_finish
|
||||
|
||||
/datum/controller/subsystem/ghost_spawns/fire()
|
||||
if(!polls_active)
|
||||
return
|
||||
if(!currently_polling) // if polls_active is TRUE then this shouldn't happen, but still..
|
||||
currently_polling = list()
|
||||
|
||||
for(var/poll in currently_polling)
|
||||
var/datum/candidate_poll/P = poll
|
||||
if(P.time_left() <= 0)
|
||||
polling_finished(P)
|
||||
|
||||
/**
|
||||
* Polls for candidates with a question and a preview of the role
|
||||
*
|
||||
* This proc replaces /proc/pollCandidates.
|
||||
* Should NEVER be used in a proc that has waitfor set to FALSE/0 (due to #define UNTIL)
|
||||
* Arguments:
|
||||
* * question - The question to ask to potential candidates
|
||||
* * role - The role to poll for. Should be a ROLE_x enum. If set, potential candidates who aren't eligible will be ignored
|
||||
* * antag_age_check - Whether to filter out potential candidates who don't have an old enough account
|
||||
* * poll_time - How long to poll for in deciseconds
|
||||
* * ignore_respawnability - Whether to ignore the player's respawnability
|
||||
* * min_hours - The amount of hours needed for a potential candidate to be eligible
|
||||
* * flash_window - Whether the poll should flash a potential candidate's game window
|
||||
* * check_antaghud - Whether to filter out potential candidates who enabled AntagHUD
|
||||
* * source - The atom, atom prototype, icon or mutable appearance to display as an icon in the alert
|
||||
*/
|
||||
/datum/controller/subsystem/ghost_spawns/proc/poll_candidates(question = "Would you like to play a special role?", role, antag_age_check = FALSE, poll_time = 30 SECONDS, ignore_respawnability = FALSE, min_hours = 0, flash_window = TRUE, check_antaghud = TRUE, source)
|
||||
log_debug("Polling candidates [role ? "for [get_roletext(role)]" : "\"[question]\""] for [poll_time / 10] seconds")
|
||||
|
||||
// Start firing
|
||||
polls_active = TRUE
|
||||
total_polls++
|
||||
|
||||
var/datum/candidate_poll/P = new(role, question, poll_time)
|
||||
LAZYADD(currently_polling, P)
|
||||
|
||||
// We're the poll closest to completion
|
||||
if(!next_poll_to_finish || poll_time < next_poll_to_finish.time_left())
|
||||
next_poll_to_finish = P
|
||||
|
||||
var/category = "[P.hash]_notify_action"
|
||||
|
||||
for(var/mob/dead/observer/M in (ignore_respawnability ? GLOB.player_list : GLOB.respawnable_list))
|
||||
if(!is_eligible(M, role, antag_age_check, role, min_hours, check_antaghud))
|
||||
continue
|
||||
|
||||
SEND_SOUND(M, 'sound/misc/notice2.ogg')
|
||||
if(flash_window)
|
||||
window_flash(M.client)
|
||||
|
||||
// If we somehow send two polls for the same mob type, but with a duration on the second one shorter than the time left on the first one,
|
||||
// we need to keep the first one's timeout rather than use the shorter one
|
||||
var/obj/screen/alert/notify_action/current_alert = LAZYACCESS(M.alerts, category)
|
||||
var/alert_time = poll_time
|
||||
var/alert_poll = P
|
||||
if(current_alert && current_alert.timeout > (world.time + poll_time - world.tick_lag))
|
||||
alert_time = current_alert.timeout - world.time + world.tick_lag
|
||||
alert_poll = current_alert.poll
|
||||
|
||||
// Send them an on-screen alert
|
||||
var/obj/screen/alert/notify_action/A = M.throw_alert(category, /obj/screen/alert/notify_action, timeout_override = alert_time, no_anim = TRUE)
|
||||
if(!A)
|
||||
continue
|
||||
|
||||
A.icon = ui_style2icon(M.client?.prefs.UI_style)
|
||||
A.name = "Looking for candidates"
|
||||
A.desc = "[question]\n\n(expires in [poll_time / 10] seconds)"
|
||||
A.show_time_left = TRUE
|
||||
A.poll = alert_poll
|
||||
|
||||
// Sign up inheritance and stacking
|
||||
var/inherited_sign_up = FALSE
|
||||
var/num_stack = 1
|
||||
for(var/existing_poll in currently_polling)
|
||||
var/datum/candidate_poll/P2 = existing_poll
|
||||
if(P != P2 && P.hash == P2.hash)
|
||||
// If there's already a poll for an identical mob type ongoing and the client is signed up for it, sign them up for this one
|
||||
if(!inherited_sign_up && (M in P2.signed_up) && P.sign_up(M, TRUE))
|
||||
A.display_signed_up()
|
||||
inherited_sign_up = TRUE
|
||||
// This number is used to display the number of polls the alert regroups
|
||||
num_stack++
|
||||
if(num_stack > 1)
|
||||
A.display_stacks(num_stack)
|
||||
|
||||
// Image to display
|
||||
var/image/I
|
||||
if(source)
|
||||
if(!ispath(source))
|
||||
var/atom/S = source
|
||||
var/old_layer = S.layer
|
||||
var/old_plane = S.plane
|
||||
|
||||
S.layer = FLOAT_LAYER
|
||||
S.plane = FLOAT_PLANE
|
||||
A.overlays += S
|
||||
S.layer = old_layer
|
||||
S.plane = old_plane
|
||||
else
|
||||
I = image(source, layer = FLOAT_LAYER, dir = SOUTH)
|
||||
else
|
||||
// Just use a generic image
|
||||
I = image('icons/effects/effects.dmi', icon_state = "static", layer = FLOAT_LAYER, dir = SOUTH)
|
||||
|
||||
if(I)
|
||||
I.layer = FLOAT_LAYER
|
||||
I.plane = FLOAT_PLANE
|
||||
A.overlays += I
|
||||
|
||||
// Chat message
|
||||
var/act_jump = ""
|
||||
if(isatom(source))
|
||||
act_jump = "<a href='?src=[M.UID()];jump=\ref[source]'>\[Teleport]</a>"
|
||||
var/act_signup = "<a href='?src=[A.UID()];signup=1'>\[Sign Up]</a>"
|
||||
to_chat(M, "<big><span class='boldnotice'>Now looking for candidates [role ? "to play as \an [get_roletext(role)]" : "\"[question]\""]. [act_jump] [act_signup]</span></big>")
|
||||
|
||||
// Start processing it so it updates visually the timer
|
||||
START_PROCESSING(SSprocessing, A)
|
||||
A.process()
|
||||
|
||||
// Sleep until the time is up
|
||||
UNTIL(P.finished)
|
||||
return P.signed_up
|
||||
|
||||
/**
|
||||
* Returns whether an observer is eligible to be an event mob
|
||||
*
|
||||
* Arguments:
|
||||
* * M - The mob to check eligibility
|
||||
* * role - The role to check eligibility for. Checks 1. the client has enabled the role 2. the account's age for this role if antag_age_check is TRUE
|
||||
* * antag_age_check - Whether to check the account's age or not for the given role.
|
||||
* * role_text - The role's clean text. Used for checking job bans to determine eligibility
|
||||
* * min_hours - The amount of minimum hours the client needs before being eligible
|
||||
* * check_antaghud - Whether to consider a client who enabled AntagHUD ineligible or not
|
||||
*/
|
||||
/datum/controller/subsystem/ghost_spawns/proc/is_eligible(mob/M, role, antag_age_check, role_text, min_hours, check_antaghud)
|
||||
. = FALSE
|
||||
if(!M.key || !M.client)
|
||||
return
|
||||
if(role)
|
||||
if(!(role in M.client.prefs.be_special))
|
||||
return
|
||||
if(antag_age_check)
|
||||
if(!player_old_enough_antag(M.client, role))
|
||||
return
|
||||
if(role_text)
|
||||
if(jobban_isbanned(M, role_text) || jobban_isbanned(M, "Syndicate"))
|
||||
return
|
||||
if(config.use_exp_restrictions && min_hours)
|
||||
if(M.client.get_exp_type_num(EXP_TYPE_LIVING) < min_hours * 60)
|
||||
return
|
||||
if(check_antaghud && cannotPossess(M))
|
||||
return
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Called by the subsystem when a poll's timer runs out
|
||||
*
|
||||
* Can be called manually to finish a poll prematurely
|
||||
* Arguments:
|
||||
* * P - The poll to finish
|
||||
*/
|
||||
/datum/controller/subsystem/ghost_spawns/proc/polling_finished(datum/candidate_poll/P)
|
||||
// Trim players who aren't eligible anymore
|
||||
var/len_pre_trim = length(P.signed_up)
|
||||
P.trim_candidates()
|
||||
log_debug("Candidate poll [P.role ? "for [get_roletext(P.role)]" : "\"[P.question]\""] finished. [len_pre_trim] players signed up, [length(P.signed_up)] after trimming")
|
||||
|
||||
P.finished = TRUE
|
||||
currently_polling -= P
|
||||
|
||||
// Determine which is the next poll closest the completion or "disable" firing if there's none
|
||||
if(!length(currently_polling))
|
||||
polls_active = FALSE
|
||||
next_poll_to_finish = null
|
||||
else if(P == next_poll_to_finish)
|
||||
next_poll_to_finish = null
|
||||
for(var/poll in currently_polling)
|
||||
var/datum/candidate_poll/P2 = poll
|
||||
if(!next_poll_to_finish || P2.time_left() < next_poll_to_finish.time_left())
|
||||
next_poll_to_finish = P2
|
||||
|
||||
/datum/controller/subsystem/ghost_spawns/stat_entry(msg)
|
||||
msg += "Active: [length(currently_polling)] | Total: [total_polls]"
|
||||
if(next_poll_to_finish)
|
||||
msg += " | Next: [DisplayTimeText(next_poll_to_finish.time_left())] ([length(next_poll_to_finish.signed_up)] candidates)"
|
||||
..(msg)
|
||||
|
||||
// The datum that describes one instance of candidate polling
|
||||
/datum/candidate_poll
|
||||
var/role // The role the poll is for
|
||||
var/question // The question asked to observers
|
||||
var/duration // The duration of the poll
|
||||
var/list/mob/dead/observer/signed_up // The players who signed up to this poll
|
||||
var/time_started // The world.time at which the poll was created
|
||||
var/finished = FALSE // Whether the polling is finished
|
||||
var/hash // Used to categorize in the alerts system
|
||||
|
||||
/datum/candidate_poll/New(polled_role, polled_question, poll_duration)
|
||||
role = polled_role
|
||||
question = polled_question
|
||||
duration = poll_duration
|
||||
signed_up = list()
|
||||
time_started = world.time
|
||||
hash = copytext(md5("[question]_[role ? role : "0"]"), 1, 7)
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Attempts to sign a (controlled) mob up
|
||||
*
|
||||
* Will fail if the mob is already signed up or the poll's timer ran out.
|
||||
* Does not check for eligibility
|
||||
* Arguments:
|
||||
* * M - The (controlled) mob to sign up
|
||||
* * silent - Whether no messages should appear or not. If not TRUE, signing up to this poll will also sign the mob up for identical polls
|
||||
*/
|
||||
/datum/candidate_poll/proc/sign_up(mob/dead/observer/M, silent = FALSE)
|
||||
. = FALSE
|
||||
if(!istype(M) || !M.key || !M.client)
|
||||
return
|
||||
if(M in signed_up)
|
||||
if(!silent)
|
||||
to_chat(M, "<span class='warning'>You have already signed up for this!</span>")
|
||||
return
|
||||
if(time_left() <= 0)
|
||||
if(!silent)
|
||||
to_chat(M, "<span class='danger'>Sorry, you were too late for the consideration!</span>")
|
||||
SEND_SOUND(M, 'sound/machines/buzz-sigh.ogg')
|
||||
return
|
||||
|
||||
signed_up += M
|
||||
if(!silent)
|
||||
to_chat(M, "<span class='notice'>You have signed up for this role! A candidate will be picked randomly soon..</span>")
|
||||
// Sign them up for any other polls with the same mob type
|
||||
for(var/existing_poll in SSghost_spawns.currently_polling)
|
||||
var/datum/candidate_poll/P = existing_poll
|
||||
if(src != P && hash == P.hash && !(M in P.signed_up))
|
||||
P.sign_up(M, TRUE)
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Deletes any candidates who may have disconnected from the list
|
||||
*/
|
||||
/datum/candidate_poll/proc/trim_candidates()
|
||||
listclearnulls(signed_up)
|
||||
for(var/mob in signed_up)
|
||||
var/mob/M = mob
|
||||
if(!M.key || !M.client)
|
||||
signed_up -= M
|
||||
|
||||
/**
|
||||
* Returns the time left for a poll
|
||||
*/
|
||||
/datum/candidate_poll/proc/time_left()
|
||||
return duration - (world.time - time_started)
|
||||
@@ -19,8 +19,18 @@ SUBSYSTEM_DEF(icon_smooth)
|
||||
can_fire = 0
|
||||
|
||||
/datum/controller/subsystem/icon_smooth/Initialize()
|
||||
smooth_zlevel(1,TRUE)
|
||||
smooth_zlevel(2,TRUE)
|
||||
log_startup_progress("Smoothing atoms...")
|
||||
// Smooth EVERYTHING in the world
|
||||
for(var/turf/T in world)
|
||||
if(T.smooth)
|
||||
smooth_icon(T)
|
||||
for(var/A in T)
|
||||
var/atom/AA = A
|
||||
if(AA.smooth)
|
||||
smooth_icon(AA)
|
||||
CHECK_TICK
|
||||
|
||||
// Incase any new atoms were added to the smoothing queue for whatever reason
|
||||
var/queue = smooth_queue
|
||||
smooth_queue = list()
|
||||
for(var/V in queue)
|
||||
|
||||
@@ -27,7 +27,7 @@ SUBSYSTEM_DEF(jobs)
|
||||
/datum/controller/subsystem/jobs/fire()
|
||||
if(!config.sql_enabled || !config.use_exp_tracking)
|
||||
return
|
||||
update_exp(5,0)
|
||||
INVOKE_ASYNC(GLOBAL_PROC, /.proc/update_exp, 5, 0)
|
||||
|
||||
/datum/controller/subsystem/jobs/proc/SetupOccupations(var/list/faction = list("Station"))
|
||||
occupations = list()
|
||||
@@ -644,6 +644,27 @@ SUBSYSTEM_DEF(jobs)
|
||||
oldjobdatum.current_positions--
|
||||
newjobdatum.current_positions++
|
||||
|
||||
/datum/controller/subsystem/jobs/proc/notify_dept_head(jobtitle, antext)
|
||||
// Used to notify the department head of jobtitle X that their employee was brigged, demoted or terminated
|
||||
if(!jobtitle || !antext)
|
||||
return
|
||||
var/datum/job/tgt_job = GetJob(jobtitle)
|
||||
if(!tgt_job)
|
||||
return
|
||||
if(!tgt_job.department_head[1])
|
||||
return
|
||||
var/boss_title = tgt_job.department_head[1]
|
||||
var/obj/item/pda/target_pda
|
||||
for(var/obj/item/pda/check_pda in GLOB.PDAs)
|
||||
if(check_pda.ownrank == boss_title)
|
||||
target_pda = check_pda
|
||||
break
|
||||
if(!target_pda)
|
||||
return
|
||||
var/datum/data/pda/app/messenger/PM = target_pda.find_program(/datum/data/pda/app/messenger)
|
||||
if(PM && PM.can_receive())
|
||||
PM.notify("<b>Automated Notification: </b>\"[antext]\" (Unable to Reply)")
|
||||
|
||||
|
||||
/datum/controller/subsystem/jobs/proc/fetch_transfer_record_html(var/centcom)
|
||||
var/record_html = "<TABLE border=\"1\">"
|
||||
|
||||
@@ -41,6 +41,28 @@ SUBSYSTEM_DEF(mapping)
|
||||
spawn_rivers(list(level_name_to_num(MINING)))
|
||||
log_startup_progress("Successfully populated lavaland in [stop_watch(lavaland_setup_timer)]s.")
|
||||
|
||||
// Now we make a list of areas for teleport locs
|
||||
// TOOD: Make these locs into lists on the SS itself, not globs
|
||||
for(var/area/AR in world)
|
||||
if(AR.no_teleportlocs)
|
||||
continue
|
||||
if(GLOB.teleportlocs[AR.name])
|
||||
continue
|
||||
var/turf/picked = safepick(get_area_turfs(AR.type))
|
||||
if(picked && is_station_level(picked.z))
|
||||
GLOB.teleportlocs[AR.name] = AR
|
||||
|
||||
GLOB.teleportlocs = sortAssoc(GLOB.teleportlocs)
|
||||
|
||||
for(var/area/AR in world)
|
||||
if(GLOB.ghostteleportlocs[AR.name])
|
||||
continue
|
||||
var/list/turfs = get_area_turfs(AR.type)
|
||||
if(turfs.len)
|
||||
GLOB.ghostteleportlocs[AR.name] = AR
|
||||
|
||||
GLOB.ghostteleportlocs = sortAssoc(GLOB.ghostteleportlocs)
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ SUBSYSTEM_DEF(mob_hunt)
|
||||
name = "Nano-Mob Hunter GO Server"
|
||||
init_order = INIT_ORDER_NANOMOB
|
||||
priority = FIRE_PRIORITY_NANOMOB // Low priority, no need for MC_TICK_CHECK due to extremely low performance impact.
|
||||
flags = SS_NO_INIT
|
||||
offline_implications = "Nano-Mob Hunter will no longer spawn mobs. No immediate action is needed."
|
||||
var/max_normal_spawns = 15 //change this to adjust the number of normal spawns that can exist at one time. trapped spawns (from traitors) don't count towards this
|
||||
var/list/normal_spawns = list()
|
||||
|
||||
@@ -3,6 +3,8 @@ PROCESSING_SUBSYSTEM_DEF(dcs)
|
||||
flags = SS_NO_INIT
|
||||
|
||||
var/list/elements_by_type = list()
|
||||
// Update this if you add in components which actually use this as a processor
|
||||
offline_implications = "This SS doesnt actually process anything yet. No immediate action is needed."
|
||||
|
||||
/datum/controller/subsystem/processing/dcs/Recover()
|
||||
comp_lookup = SSdcs.comp_lookup
|
||||
@@ -4,3 +4,4 @@ PROCESSING_SUBSYSTEM_DEF(fastprocess)
|
||||
name = "Fast Processing"
|
||||
wait = 2
|
||||
stat_tag = "FP"
|
||||
offline_implications = "Objects using the 'Fast Processing' processor will no longer process. Shuttle call recommended."
|
||||
|
||||
@@ -3,3 +3,4 @@ PROCESSING_SUBSYSTEM_DEF(obj)
|
||||
priority = FIRE_PRIORITY_OBJ
|
||||
flags = SS_NO_INIT
|
||||
wait = 20
|
||||
offline_implications = "Objects using the 'Objects' processor will no longer process. Shuttle call recommended."
|
||||
|
||||
@@ -9,6 +9,7 @@ SUBSYSTEM_DEF(processing)
|
||||
var/stat_tag = "P" //Used for logging
|
||||
var/list/processing = list()
|
||||
var/list/currentrun = list()
|
||||
offline_implications = "Objects using the default processor will no longer process. Shuttle call recommended."
|
||||
|
||||
/datum/controller/subsystem/processing/stat_entry()
|
||||
..("[stat_tag]:[processing.len]")
|
||||
|
||||
@@ -61,7 +61,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
if(GAME_STATE_STARTUP)
|
||||
// This is ran as soon as the MC starts firing, and should only run ONCE, unless startup fails
|
||||
round_start_time = world.time + (config.pregame_timestart * 10)
|
||||
to_chat(world, "<B><FONT color='blue'>Welcome to the pre-game lobby!</FONT></B>")
|
||||
to_chat(world, "<B><span class='darkmblue'>Welcome to the pre-game lobby!</span></B>")
|
||||
to_chat(world, "Please, setup your character and select ready. Game will start in [config.pregame_timestart] seconds")
|
||||
current_state = GAME_STATE_PREGAME
|
||||
fire() // TG says this is a good idea
|
||||
@@ -180,7 +180,14 @@ SUBSYSTEM_DEF(ticker)
|
||||
current_state = GAME_STATE_PLAYING
|
||||
Master.SetRunLevel(RUNLEVEL_GAME)
|
||||
|
||||
callHook("roundstart")
|
||||
// Generate the list of playable AI cores in the world
|
||||
for(var/obj/effect/landmark/start/S in GLOB.landmarks_list)
|
||||
if(S.name != "AI")
|
||||
continue
|
||||
if(locate(/mob/living) in S.loc)
|
||||
continue
|
||||
GLOB.empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(get_turf(S))
|
||||
|
||||
|
||||
//here to initialize the random events nicely at round start
|
||||
setup_economy()
|
||||
@@ -210,11 +217,11 @@ SUBSYSTEM_DEF(ticker)
|
||||
for(var/obj/effect/landmark/spacepod/random/R in L)
|
||||
qdel(R)
|
||||
|
||||
to_chat(world, "<FONT color='blue'><B>Enjoy the game!</B></FONT>")
|
||||
to_chat(world, "<span class='darkmblue'><B>Enjoy the game!</B></span>")
|
||||
world << sound('sound/AI/welcome.ogg')// Skie
|
||||
|
||||
if(SSholiday.holidays)
|
||||
to_chat(world, "<font color='blue'>and...</font>")
|
||||
to_chat(world, "<span class='darkmblue'>and...</span>")
|
||||
for(var/holidayname in SSholiday.holidays)
|
||||
var/datum/holiday/holiday = SSholiday.holidays[holidayname]
|
||||
to_chat(world, "<h4>[holiday.greet()]</h4>")
|
||||
@@ -279,10 +286,22 @@ SUBSYSTEM_DEF(ticker)
|
||||
for(var/mob/new_player/N in GLOB.mob_list)
|
||||
if(N.client)
|
||||
N.new_player_panel_proc()
|
||||
|
||||
// Now that every other piece of the round has initialized, lets setup player job scaling
|
||||
var/playercount = length(GLOB.clients)
|
||||
var/highpop_trigger = 80
|
||||
|
||||
if(playercount >= highpop_trigger)
|
||||
log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - loading highpop job config")
|
||||
SSjobs.LoadJobs("config/jobs_highpop.txt")
|
||||
else
|
||||
log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - keeping standard job config")
|
||||
|
||||
#ifdef UNIT_TESTS
|
||||
RunUnitTests()
|
||||
#endif
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/station_explosion_cinematic(station_missed = 0, override = null)
|
||||
if(cinematic)
|
||||
|
||||
@@ -6,16 +6,23 @@ GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets
|
||||
|
||||
/datum/controller/subsystem/tickets/mentor_tickets
|
||||
name = "Mentor Tickets"
|
||||
offline_implications = "Mentor tickets will no longer be marked as stale. No immediate action is needed."
|
||||
ticket_system_name = "Mentor Tickets"
|
||||
ticket_name = "Mentor Ticket"
|
||||
span_class = "mentorhelp"
|
||||
other_ticket_name = "Admin"
|
||||
other_ticket_permission = R_ADMIN
|
||||
close_rights = R_MENTOR | R_ADMIN
|
||||
|
||||
/datum/controller/subsystem/tickets/mentor_tickets/message_staff(var/msg)
|
||||
message_mentorTicket(msg)
|
||||
rights_needed = R_MENTOR | R_ADMIN | R_MOD
|
||||
|
||||
/datum/controller/subsystem/tickets/mentor_tickets/Initialize()
|
||||
close_messages = list("<font color='red' size='3'><b>- [ticket_name] Closed -</b></font>",
|
||||
"<span class='boldmessage'>Please try to be as descriptive as possible in mentor helps. Mentors do not know the full situation you're in and need more information to give you a helpful response.</span>",
|
||||
"<span class='[span_class]'>Your [ticket_name] has now been closed.</span>")
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/tickets/mentor_tickets/message_staff(msg)
|
||||
message_mentorTicket(msg)
|
||||
|
||||
/datum/controller/subsystem/tickets/mentor_tickets/create_other_system_ticket(datum/ticket/T)
|
||||
SStickets.newTicket(T.clientName, T.content, T.title)
|
||||
|
||||
@@ -12,17 +12,23 @@
|
||||
|
||||
SUBSYSTEM_DEF(tickets)
|
||||
name = "Admin Tickets"
|
||||
init_order = INIT_ORDER_TICKETS
|
||||
wait = 300
|
||||
priority = FIRE_PRIORITY_TICKETS
|
||||
offline_implications = "Admin tickets will no longer be marked as stale. No immediate action is needed."
|
||||
flags = SS_BACKGROUND
|
||||
|
||||
var/span_class = "adminticket"
|
||||
var/ticket_system_name = "Admin Tickets"
|
||||
var/ticket_name = "Admin Ticket"
|
||||
var/close_rights = R_ADMIN
|
||||
var/rights_needed = R_ADMIN | R_MOD
|
||||
|
||||
/// The name of the other ticket type to convert to
|
||||
var/other_ticket_name = "Mentor"
|
||||
/// Which permission to look for when seeing if there is staff available for the other ticket type
|
||||
var/other_ticket_permission = R_MENTOR
|
||||
var/list/close_messages
|
||||
init_order = INIT_ORDER_TICKETS
|
||||
wait = 300
|
||||
priority = FIRE_PRIORITY_TICKETS
|
||||
|
||||
flags = SS_BACKGROUND
|
||||
|
||||
var/list/allTickets = list() //make it here because someone might ahelp before the system has initialized
|
||||
|
||||
var/ticketCounter = 1
|
||||
@@ -113,9 +119,37 @@ SUBSYSTEM_DEF(tickets)
|
||||
to_chat_safe(returnClient(N), "<span class='[span_class]'>Your [ticket_name] has now been resolved.</span>")
|
||||
return TRUE
|
||||
|
||||
/datum/controller/subsystem/tickets/proc/convert_to_other_ticket(ticketId)
|
||||
if(!check_rights(rights_needed))
|
||||
return
|
||||
if(alert("Are you sure to convert this ticket to an '[other_ticket_name]' ticket?",,"Yes","No") != "Yes")
|
||||
return
|
||||
if(!other_ticket_system_staff_check())
|
||||
return
|
||||
var/datum/ticket/T = allTickets[ticketId]
|
||||
convert_ticket(T)
|
||||
|
||||
/datum/controller/subsystem/tickets/proc/other_ticket_system_staff_check()
|
||||
var/list/staff = staff_countup(other_ticket_permission)
|
||||
if(!staff[1])
|
||||
if(alert("No active staff online to answer the ticket. Are you sure you want to convert the ticket?",, "No", "Yes") != "Yes")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/controller/subsystem/tickets/proc/convert_ticket(datum/ticket/T)
|
||||
T.ticketState = TICKET_CLOSED
|
||||
var/client/C = usr.client
|
||||
to_chat_safe(T.clientName, list("<span class='[span_class]'>[key_name_hidden(C)] has converted your ticket to a [other_ticket_name] ticket.</span>",\
|
||||
"<span class='[span_class]'>Be sure to use the correct type of help next time!</span>"))
|
||||
message_staff("<span class='[span_class]'>[C] has converted ticket number [T.ticketNum] to a [other_ticket_name] ticket.</span>")
|
||||
log_game("[C] has converted ticket number [T.ticketNum] to a [other_ticket_name] ticket.")
|
||||
create_other_system_ticket(T)
|
||||
|
||||
/datum/controller/subsystem/tickets/proc/create_other_system_ticket(datum/ticket/T)
|
||||
SSmentor_tickets.newTicket(T.clientName, T.content, T.title)
|
||||
|
||||
/datum/controller/subsystem/tickets/proc/autoRespond(N)
|
||||
if(!check_rights(R_ADMIN|R_MOD))
|
||||
if(!check_rights(rights_needed))
|
||||
return
|
||||
|
||||
var/datum/ticket/T = allTickets[N]
|
||||
@@ -130,6 +164,7 @@ SUBSYSTEM_DEF(tickets)
|
||||
"Already Resolved" = "The problem has been resolved already.",
|
||||
"Mentorhelp" = "Please redirect your question to Mentorhelp, as they are better experienced with these types of questions.",
|
||||
"Happens Again" = "Thanks, let us know if it continues to happen.",
|
||||
"Github Issue Report" = "To report a bug, please go to our <a href='[config.githuburl]'>Github page</a>. Then go to 'Issues'. Then 'New Issue'. Then fill out the report form. If the report would reveal current-round information, file it after the round ends.",
|
||||
"Clear Cache" = "To fix a blank screen, go to the 'Special Verbs' tab and press 'Reload UI Resources'. If that fails, clear your BYOND cache (instructions provided with 'Reload UI Resources'). If that still fails, please adminhelp again, stating you have already done the following." ,
|
||||
"IC Issue" = "This is an In Character (IC) issue and will not be handled by admins. You could speak to Security, Internal Affairs, a Departmental Head, Nanotrasen Representetive, or any other relevant authority currently on station.",
|
||||
"Reject" = "Reject",
|
||||
@@ -156,14 +191,17 @@ SUBSYSTEM_DEF(tickets)
|
||||
resolveTicket(N)
|
||||
message_staff("[C] has auto responded to [T.clientName]\'s adminhelp with:<span class='adminticketalt'> [message_key] </span>")
|
||||
log_game("[C] has auto responded to [T.clientName]\'s adminhelp with: [response_phrases[message_key]]")
|
||||
if("Mentorhelp")
|
||||
convert_ticket(T)
|
||||
else
|
||||
var/msg_sound = sound('sound/effects/adminhelp.ogg')
|
||||
SEND_SOUND(returnClient(N), msg_sound)
|
||||
to_chat(returnClient(N), "<span class='[span_class]'>[key_name_hidden(C)] is autoresponding with: <span/> <span class='adminticketalt'>[response_phrases[message_key]]</span>")//for this we want the full value of whatever key this is to tell the player so we do response_phrases[message_key]
|
||||
to_chat_safe(returnClient(N), "<span class='[span_class]'>[key_name_hidden(C)] is autoresponding with: <span/> <span class='adminticketalt'>[response_phrases[message_key]]</span>")//for this we want the full value of whatever key this is to tell the player so we do response_phrases[message_key]
|
||||
message_staff("[C] has auto responded to [T.clientName]\'s adminhelp with:<span class='adminticketalt'> [message_key] </span>") //we want to use the short named keys for this instead of the full sentence which is why we just do message_key
|
||||
T.lastStaffResponse = "Autoresponse: [message_key]"
|
||||
resolveTicket(N)
|
||||
log_game("[C] has auto responded to [T.clientName]\'s adminhelp with: [response_phrases[message_key]]")
|
||||
|
||||
//Set ticket state with key N to closed
|
||||
/datum/controller/subsystem/tickets/proc/closeTicket(N)
|
||||
var/datum/ticket/T = allTickets[N]
|
||||
@@ -351,7 +389,7 @@ UI STUFF
|
||||
dat += "<tr><td>[T.content[i]]</td></tr>"
|
||||
|
||||
dat += "</table><br /><br />"
|
||||
dat += "<a href='?src=[UID()];detailreopen=[T.ticketNum]'>Re-Open</a>[check_rights(R_ADMIN|R_MOD, 0) ? "<a href='?src=[UID()];autorespond=[T.ticketNum]'>Auto</a>": ""]<a href='?src=[UID()];detailresolve=[T.ticketNum]'>Resolve</a><br /><br />"
|
||||
dat += "<a href='?src=[UID()];detailreopen=[T.ticketNum]'>Re-Open</a>[check_rights(rights_needed, 0) ? "<a href='?src=[UID()];autorespond=[T.ticketNum]'>Auto</a>": ""]<a href='?src=[UID()];detailresolve=[T.ticketNum]'>Resolve</a><br /><br />"
|
||||
|
||||
if(!T.staffAssigned)
|
||||
dat += "No staff member assigned to this [ticket_name] - <a href='?src=[UID()];assignstaff=[T.ticketNum]'>Take Ticket</a><br />"
|
||||
@@ -366,6 +404,7 @@ UI STUFF
|
||||
dat += "<br /><br />"
|
||||
|
||||
dat += "<a href='?src=[UID()];detailclose=[T.ticketNum]'>Close Ticket</a>"
|
||||
dat += "<a href='?src=[UID()];convert_ticket=[T.ticketNum]'>Convert Ticket</a>"
|
||||
|
||||
var/datum/browser/popup = new(user, "[ticket_system_name]detail", "[ticket_system_name] #[T.ticketNum]", 1000, 600)
|
||||
popup.set_content(dat)
|
||||
@@ -448,7 +487,6 @@ UI STUFF
|
||||
if(closeTicket(indexNum))
|
||||
showDetailUI(usr, indexNum)
|
||||
|
||||
|
||||
if(href_list["detailreopen"])
|
||||
var/indexNum = text2num(href_list["detailreopen"])
|
||||
if(openTicket(indexNum))
|
||||
@@ -468,6 +506,10 @@ UI STUFF
|
||||
var/indexNum = text2num(href_list["autorespond"])
|
||||
autoRespond(indexNum)
|
||||
|
||||
if(href_list["convert_ticket"])
|
||||
var/indexNum = text2num(href_list["convert_ticket"])
|
||||
convert_to_other_ticket(indexNum)
|
||||
|
||||
if(href_list["resolveall"])
|
||||
if(ticket_system_name == "Mentor Tickets")
|
||||
usr.client.resolveAllMentorTickets()
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/hook/startup/proc/setup_title_screen()
|
||||
SUBSYSTEM_DEF(title)
|
||||
name = "Title Screen"
|
||||
flags = SS_NO_FIRE
|
||||
init_order = INIT_ORDER_TITLE
|
||||
|
||||
/datum/controller/subsystem/title/Initialize()
|
||||
var/list/provisional_title_screens = flist("config/title_screens/images/")
|
||||
var/list/title_screens = list()
|
||||
var/use_rare_screens = prob(1)
|
||||
@@ -29,5 +34,5 @@
|
||||
|
||||
for(var/turf/unsimulated/wall/splashscreen/splash in world)
|
||||
splash.icon = icon
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
return ..()
|
||||
@@ -367,7 +367,7 @@ SUBSYSTEM_DEF(vote)
|
||||
var/votedesc = capitalize(mode)
|
||||
if(mode == "custom")
|
||||
votedesc += " ([question])"
|
||||
admin_log_and_message_admins("cancelled the running [votedesc] vote.")
|
||||
log_and_message_admins("cancelled the running [votedesc] vote.")
|
||||
reset()
|
||||
if("toggle_restart")
|
||||
if(admin)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
set name = "Restart Controller"
|
||||
set desc = "Restart one of the various periodic loop controllers for the game (be careful!)"
|
||||
|
||||
if(!holder)
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
switch(controller)
|
||||
if("Master")
|
||||
@@ -26,7 +26,8 @@
|
||||
set name = "Debug Controller"
|
||||
set desc = "Debug the various periodic loop controllers for the game (be careful!)"
|
||||
|
||||
if(!holder) return
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
switch(controller)
|
||||
if("failsafe")
|
||||
debug_variables(Failsafe)
|
||||
|
||||
+1
-2
@@ -131,6 +131,5 @@
|
||||
|
||||
/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time=3)
|
||||
var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time)
|
||||
spawn(0)
|
||||
newbeam.Start()
|
||||
INVOKE_ASYNC(newbeam, /datum/beam.proc/Start)
|
||||
return newbeam
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
if(!(flags & CALTROP_BYPASS_SHOES) && (H.shoes || feetCover))
|
||||
return
|
||||
|
||||
if((H.flying) || H.buckled)
|
||||
if(H.flying || H.floating || H.buckled)
|
||||
return
|
||||
|
||||
var/damage = rand(min_damage, max_damage)
|
||||
|
||||
@@ -51,6 +51,6 @@
|
||||
Additionally calls the parent's `after_slip()` proc on the `victim`.
|
||||
*/
|
||||
/datum/component/slippery/proc/Slip(datum/source, mob/living/carbon/human/victim)
|
||||
if(istype(victim) && prob(slip_chance) && victim.slip(description, stun, weaken, slip_tiles, walking_is_safe, slip_always, slip_verb))
|
||||
if(istype(victim) && !victim.flying && prob(slip_chance) && victim.slip(description, stun, weaken, slip_tiles, walking_is_safe, slip_always, slip_verb))
|
||||
var/atom/movable/owner = parent
|
||||
owner.after_slip(victim)
|
||||
|
||||
@@ -67,6 +67,14 @@
|
||||
var/obj/item/projectile/P = AM
|
||||
if(P.original != parent)
|
||||
return
|
||||
if(ismob(AM))
|
||||
var/mob/M = AM
|
||||
if(M.flying)
|
||||
return
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = M
|
||||
if(L.floating)
|
||||
return
|
||||
var/atom/current_parent = parent
|
||||
if(isturf(current_parent.loc))
|
||||
play_squeak()
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/hook/startup/proc/createDatacore()
|
||||
GLOB.data_core = new /datum/datacore()
|
||||
return 1
|
||||
|
||||
/datum/datacore
|
||||
var/list/medical = list()
|
||||
var/list/general = list()
|
||||
|
||||
@@ -395,8 +395,9 @@ GLOBAL_LIST_INIT(advance_cures, list(
|
||||
for(var/datum/disease/advance/AD in GLOB.active_diseases)
|
||||
AD.Refresh()
|
||||
|
||||
for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list))
|
||||
if(!is_station_level(H.z))
|
||||
for(var/thing in shuffle(GLOB.human_list))
|
||||
var/mob/living/carbon/human/H = thing
|
||||
if(H.stat == DEAD || !is_station_level(H.z))
|
||||
continue
|
||||
if(!H.HasDisease(D))
|
||||
H.ForceContractDisease(D)
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
W.plane = initial(W.plane)
|
||||
W.loc = affected_mob.loc
|
||||
W.dropped(affected_mob)
|
||||
if(isobj(affected_mob.loc))
|
||||
var/obj/O = affected_mob.loc
|
||||
O.force_eject_occupant()
|
||||
var/mob/living/new_mob = new new_form(affected_mob.loc)
|
||||
if(istype(new_mob))
|
||||
new_mob.a_intent = "harm"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
name = rename
|
||||
|
||||
/datum/map_template/proc/preload_size(path)
|
||||
var/bounds = GLOB.maploader.load_map(file(path), 1, 1, 1, cropMap = 0, measureOnly = 1)
|
||||
var/bounds = GLOB.maploader.load_map(file(path), 1, 1, 1, shouldCropMap = FALSE, measureOnly = TRUE)
|
||||
if(bounds)
|
||||
width = bounds[MAP_MAXX] // Assumes all templates are rectangular, have a single Z level, and begin at 1,1,1
|
||||
height = bounds[MAP_MAXY]
|
||||
@@ -49,7 +49,7 @@
|
||||
// if given a multi-z template
|
||||
// it might need to be adapted for that when that time comes
|
||||
GLOB.space_manager.add_dirt(placement.z)
|
||||
var/list/bounds = GLOB.maploader.load_map(get_file(), min_x, min_y, placement.z, cropMap = 1)
|
||||
var/list/bounds = GLOB.maploader.load_map(get_file(), min_x, min_y, placement.z, shouldCropMap = TRUE)
|
||||
if(!bounds)
|
||||
return 0
|
||||
if(bot_left == null || top_right == null)
|
||||
|
||||
+32
-13
@@ -3,32 +3,51 @@
|
||||
var/raw_time // When did this happen?
|
||||
var/what // What happened
|
||||
var/who // Who did it
|
||||
var/target // Who/what was targeted (can be a string)
|
||||
var/turf/where // Where did it happen
|
||||
var/target // Who/what was targeted
|
||||
var/where // Where did it happen
|
||||
|
||||
/datum/log_record/New(_log_type, _who, _what, _target, _where, _raw_time)
|
||||
log_type = _log_type
|
||||
|
||||
who = get_subject_text(_who)
|
||||
|
||||
who = get_subject_text(_who, _log_type)
|
||||
what = _what
|
||||
target = get_subject_text(_target)
|
||||
if(!_where)
|
||||
target = get_subject_text(_target, _log_type)
|
||||
if(!istext(_where) && !isturf(_where))
|
||||
_where = get_turf(_who)
|
||||
where = _where
|
||||
if(isturf(_where))
|
||||
var/turf/T = _where
|
||||
where = ADMIN_COORDJMP(T)
|
||||
else
|
||||
where = _where
|
||||
if(!_raw_time)
|
||||
_raw_time = world.time
|
||||
raw_time = _raw_time
|
||||
|
||||
/datum/log_record/proc/get_subject_text(subject)
|
||||
/datum/log_record/proc/get_subject_text(subject, log_type)
|
||||
if(ismob(subject) || isclient(subject) || istype(subject, /datum/mind))
|
||||
return key_name_admin(subject)
|
||||
if(isatom(subject))
|
||||
. = key_name_admin(subject)
|
||||
if(should_log_health(log_type) && isliving(subject))
|
||||
. += get_health_string(subject)
|
||||
else if(isatom(subject))
|
||||
var/atom/A = subject
|
||||
return A.name
|
||||
if(istype(subject, /datum))
|
||||
. = A.name
|
||||
else if(istype(subject, /datum))
|
||||
var/datum/D = subject
|
||||
return D.type
|
||||
return subject
|
||||
else
|
||||
. = subject
|
||||
|
||||
/datum/log_record/proc/get_health_string(var/mob/living/L)
|
||||
var/OX = L.getOxyLoss() > 50 ? "<b>[L.getOxyLoss()]</b>" : L.getOxyLoss()
|
||||
var/TX = L.getToxLoss() > 50 ? "<b>[L.getToxLoss()]</b>" : L.getToxLoss()
|
||||
var/BU = L.getFireLoss() > 50 ? "<b>[L.getFireLoss()]</b>" : L.getFireLoss()
|
||||
var/BR = L.getBruteLoss() > 50 ? "<b>[L.getBruteLoss()]</b>" : L.getBruteLoss()
|
||||
return " ([L.health]: <font color='deepskyblue'>[OX]</font> - <font color='green'>[TX]</font> - <font color='#FFA500'>[BU]</font> - <font color='red'>[BR]</font>)"
|
||||
|
||||
/datum/log_record/proc/should_log_health(log_type)
|
||||
if(log_type == ATTACK_LOG || log_type == DEFENSE_LOG)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/proc/compare_log_record(datum/log_record/A, datum/log_record/B)
|
||||
var/time_diff = A.raw_time - B.raw_time
|
||||
|
||||
+108
-24
@@ -1,31 +1,45 @@
|
||||
#define ALL_LOGS list(ATTACK_LOG, DEFENSE_LOG, CONVERSION_LOG, SAY_LOG, EMOTE_LOG, MISC_LOG)
|
||||
#define UPDATE_CKEY_MOB(__ckey) var/mob/result = selected_ckeys_mobs[__ckey];\
|
||||
if(!result || result.ckey != __ckey){\
|
||||
result = get_mob_by_ckey(__ckey);\
|
||||
selected_ckeys_mobs[__ckey] = result;\
|
||||
}
|
||||
|
||||
#define RECORD_WARN_LIMIT 1000
|
||||
#define RECORD_HARD_LIMIT 2500
|
||||
|
||||
/datum/log_viewer
|
||||
var/time_from = 0
|
||||
var/time_to = 4 HOURS // 4 Hours should be enough. INFINITY would screw the UI up
|
||||
var/list/selected_mobs = list() // The mobs in question
|
||||
var/list/selected_log_types = list() // The log types being searched for
|
||||
|
||||
var/list/selected_mobs = list() // The mobs in question.
|
||||
var/list/selected_ckeys = list() // The ckeys selected to search for. Will show all mobs the ckey is attached to
|
||||
var/list/mob/selected_ckeys_mobs = list()
|
||||
var/list/selected_log_types = ALL_LOGS // The log types being searched for
|
||||
var/list/log_records = list() // Found and sorted records
|
||||
|
||||
/datum/log_viewer/proc/clear_all()
|
||||
selected_mobs.Cut()
|
||||
selected_log_types.Cut()
|
||||
selected_log_types = ALL_LOGS
|
||||
selected_ckeys.Cut()
|
||||
selected_ckeys_mobs.Cut()
|
||||
time_from = initial(time_from)
|
||||
time_to = initial(time_to)
|
||||
log_records.Cut()
|
||||
return
|
||||
|
||||
/datum/log_viewer/proc/search()
|
||||
/datum/log_viewer/proc/search(user)
|
||||
log_records.Cut() // Empty the old results
|
||||
var/list/invalid_mobs = list()
|
||||
var/list/ckeys = selected_ckeys.Copy()
|
||||
for(var/i in selected_mobs)
|
||||
var/mob/M = i
|
||||
if(!M || QDELETED(M))
|
||||
if(!M || QDELETED(M) || !M.last_known_ckey)
|
||||
invalid_mobs |= M
|
||||
continue
|
||||
ckeys |= M.last_known_ckey
|
||||
|
||||
for(var/ckey in ckeys)
|
||||
for(var/log_type in selected_log_types)
|
||||
var/list/logs = M.logs[log_type]
|
||||
var/list/logs = GLOB.logging.get_logs_by_type(ckey, log_type)
|
||||
var/len_logs = length(logs)
|
||||
if(len_logs)
|
||||
var/start_index = get_earliest_log_index(logs)
|
||||
@@ -36,8 +50,8 @@
|
||||
continue
|
||||
log_records.Add(logs.Copy(start_index, end_index + 1))
|
||||
|
||||
if(invalid_mobs.len)
|
||||
to_chat(usr, "<span class='warning'>The search criteria contained invalid mobs. They have been removed from the criteria.</span>")
|
||||
if(length(invalid_mobs))
|
||||
to_chat(user, "<span class='warning'>The search criteria contained invalid mobs. They have been removed from the criteria.</span>")
|
||||
for(var/i in invalid_mobs)
|
||||
selected_mobs -= i // Cleanup
|
||||
|
||||
@@ -91,9 +105,23 @@
|
||||
return start
|
||||
return 0
|
||||
|
||||
/datum/log_viewer/proc/add_mob(mob/user, mob/M)
|
||||
/datum/log_viewer/proc/add_mobs(list/mob/mobs)
|
||||
if(!length(mobs))
|
||||
return
|
||||
for(var/i in mobs)
|
||||
add_mob(usr, i, FALSE)
|
||||
|
||||
/datum/log_viewer/proc/add_ckey(mob/user, ckey)
|
||||
if(!user || !ckey)
|
||||
return
|
||||
selected_ckeys |= ckey
|
||||
UPDATE_CKEY_MOB(ckey)
|
||||
show_ui(user)
|
||||
|
||||
/datum/log_viewer/proc/add_mob(mob/user, mob/M, show_the_ui = TRUE)
|
||||
if(!M || !user)
|
||||
return
|
||||
|
||||
selected_mobs |= M
|
||||
|
||||
show_ui(user)
|
||||
@@ -102,9 +130,9 @@
|
||||
var/all_log_types = ALL_LOGS
|
||||
var/trStyleTop = "border-top:2px solid; border-bottom:2px solid; padding-top: 5px; padding-bottom: 5px;"
|
||||
var/trStyle = "border-top:1px solid; border-bottom:1px solid; padding-top: 5px; padding-bottom: 5px;"
|
||||
var/dat
|
||||
dat += "<head><style>.adminticket{border:2px solid} td{border:1px solid grey;} th{border:1px solid grey;} span{float:left;width:150px;}</style></head>"
|
||||
dat += "<div style='height:15vh'>"
|
||||
var/list/dat = list()
|
||||
dat += "<head><meta http-equiv='X-UA-Compatible' content='IE=edge'><style>.adminticket{border:2px solid} td{border:1px solid grey;} th{border:1px solid grey;} span{float:left;width:150px;}</style></head>"
|
||||
dat += "<div style='min-height:100px'>"
|
||||
dat += "<span>Time Search Range:</span> <a href='?src=[UID()];start_time=1'>[gameTimestamp(wtime = time_from)]</a>"
|
||||
dat += " To: <a href='?src=[UID()];end_time=1'>[gameTimestamp(wtime = time_to)]</a>"
|
||||
dat += "<BR>"
|
||||
@@ -115,20 +143,26 @@
|
||||
if(QDELETED(M))
|
||||
selected_mobs -= i
|
||||
continue
|
||||
dat += "<a href='?src=[UID()];remove_mob=\ref[M]'>[M.name]</a>"
|
||||
dat += "<a href='?src=[UID()];remove_mob=\ref[M]'>[get_display_name(M)]</a>"
|
||||
dat += "<a href='?src=[UID()];add_mob=1'>Add Mob</a>"
|
||||
dat += "<a href='?src=[UID()];clear_mobs=1'>Clear All Mobs</a>"
|
||||
dat += "<BR>"
|
||||
|
||||
dat += "<span>Ckeys being used:</span>"
|
||||
for(var/ckey in selected_ckeys)
|
||||
dat += "<a href='?src=[UID()];remove_ckey=[ckey]'>[get_ckey_name(ckey)]</a>"
|
||||
dat += "<a href='?src=[UID()];add_ckey=1'>Add ckey</a>"
|
||||
dat += "<a href='?src=[UID()];clear_ckeys=1'>Clear All ckeys</a>"
|
||||
dat += "<BR>"
|
||||
|
||||
dat += "<span>Log Types:</span>"
|
||||
for(var/i in all_log_types)
|
||||
var/log_type = i
|
||||
for(var/log_type in all_log_types)
|
||||
var/enabled = (log_type in selected_log_types)
|
||||
var/text
|
||||
var/style
|
||||
if(enabled)
|
||||
text = "<b>[log_type]</b>"
|
||||
style = "background: [get_logtype_color(i)]"
|
||||
style = "background: [get_logtype_color(log_type)]"
|
||||
else
|
||||
text = log_type
|
||||
|
||||
@@ -142,9 +176,9 @@
|
||||
// Search results
|
||||
var/tdStyleTime = "width:80px; text-align:center;"
|
||||
var/tdStyleType = "width:80px; text-align:center;"
|
||||
var/tdStyleWho = "width:300px; text-align:center;"
|
||||
var/tdStyleWho = "width:400px; text-align:center;"
|
||||
var/tdStyleWhere = "width:150px; text-align:center;"
|
||||
dat += "<div style='overflow-y: auto; max-height:76vh;'>"
|
||||
dat += "<div style='overflow-y: auto; max-height:calc(100vh - 150px);'>"
|
||||
dat += "<table style='width:100%; border: 1px solid;'>"
|
||||
dat += "<tr style='[trStyleTop]'><th style='[tdStyleTime]'>When</th><th style='[tdStyleType]'>Type</th><th style='[tdStyleWho]'>Who</th><th>What</th><th>Target</th><th style='[tdStyleWhere]'>Where</th></tr>"
|
||||
for(var/i in log_records)
|
||||
@@ -153,13 +187,12 @@
|
||||
|
||||
dat +="<tr style='[trStyle]'><td style='[tdStyleTime]'>[time]</td><td style='[tdStyleType]background: [get_logtype_color(L.log_type)]'>[L.log_type]</td>\
|
||||
<td style='[tdStyleWho]'>[L.who]</td><td style='background: [get_logtype_color(L.log_type)];'>[L.what]</td>\
|
||||
<td style='[tdStyleWho]'>[L.target]</td><td style='[tdStyleWhere]'>[ADMIN_COORDJMP(L.where)]</td></tr>"
|
||||
|
||||
<td style='[tdStyleWho]'>[L.target]</td><td style='[tdStyleWhere]'>[L.where]</td></tr>"
|
||||
dat += "</table>"
|
||||
dat += "</div>"
|
||||
|
||||
var/datum/browser/popup = new(user, "Log viewer", "Log viewer", 1400, 600)
|
||||
popup.set_content(dat)
|
||||
var/datum/browser/popup = new(user, "Log Viewer", "Log Viewer", 1500, 600)
|
||||
popup.set_content(dat.Join())
|
||||
popup.open()
|
||||
|
||||
/datum/log_viewer/Topic(href, href_list)
|
||||
@@ -188,6 +221,19 @@
|
||||
return
|
||||
if(href_list["search"])
|
||||
search(usr)
|
||||
var/records_len = length(log_records)
|
||||
if(records_len > RECORD_WARN_LIMIT)
|
||||
var/datum/log_record/last_record = log_records[RECORD_WARN_LIMIT]
|
||||
var/last_time = gameTimestamp(wtime = last_record.raw_time - 9.99)
|
||||
var/answer = alert(usr, "More than [RECORD_WARN_LIMIT] records were found. continuing will take a long time. This won't cause much lag for the server. Time at the [RECORD_WARN_LIMIT]th record '[last_time]'", "Warning", "Continue", "Limit to [RECORD_WARN_LIMIT]", "Cancel")
|
||||
if(answer == "Limit to [RECORD_WARN_LIMIT]")
|
||||
log_records.Cut(RECORD_WARN_LIMIT)
|
||||
else if(answer == "Cancel")
|
||||
log_records.Cut()
|
||||
else
|
||||
if(records_len > RECORD_HARD_LIMIT)
|
||||
to_chat(usr, "<span class='warning'>Record limit reached. Limiting to [RECORD_HARD_LIMIT].</span>")
|
||||
log_records.Cut(RECORD_HARD_LIMIT)
|
||||
show_ui(usr)
|
||||
return
|
||||
if(href_list["clear_all"])
|
||||
@@ -198,17 +244,31 @@
|
||||
selected_mobs.Cut()
|
||||
show_ui(usr)
|
||||
return
|
||||
if(href_list["clear_ckeys"])
|
||||
selected_ckeys.Cut()
|
||||
selected_ckeys_mobs.Cut()
|
||||
show_ui(usr)
|
||||
return
|
||||
if(href_list["add_mob"])
|
||||
var/list/mobs = getpois(TRUE, TRUE)
|
||||
var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a mob: ", mobs)
|
||||
A.on_close(CALLBACK(src, .proc/add_mob, usr))
|
||||
return
|
||||
if(href_list["add_ckey"])
|
||||
var/list/ckeys = GLOB.logging.get_ckeys_logged()
|
||||
var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a ckey: ", ckeys)
|
||||
A.on_close(CALLBACK(src, .proc/add_ckey, usr))
|
||||
return
|
||||
if(href_list["remove_mob"])
|
||||
var/mob/M = locate(href_list["remove_mob"])
|
||||
if(M)
|
||||
selected_mobs -= M
|
||||
show_ui(usr)
|
||||
return
|
||||
if(href_list["remove_ckey"])
|
||||
selected_ckeys -= href_list["remove_ckey"]
|
||||
show_ui(usr)
|
||||
return
|
||||
if(href_list["toggle_log_type"])
|
||||
var/log_type = href_list["toggle_log_type"]
|
||||
if(log_type in selected_log_types)
|
||||
@@ -232,4 +292,28 @@
|
||||
return "deepskyblue"
|
||||
if(MISC_LOG)
|
||||
return "gray"
|
||||
if(DEADCHAT_LOG)
|
||||
return "#cc00c6"
|
||||
if(OOC_LOG)
|
||||
return "#002eb8"
|
||||
if(LOOC_LOG)
|
||||
return "#6699CC"
|
||||
return "slategray"
|
||||
|
||||
/datum/log_viewer/proc/get_display_name(mob/M)
|
||||
var/name = M.name
|
||||
if(M.name != M.real_name)
|
||||
name = "[name] ([M.real_name])"
|
||||
if(isobserver(M))
|
||||
name = "[name] (DEAD)"
|
||||
return "\[[M.last_known_ckey]\] [name]"
|
||||
|
||||
/datum/log_viewer/proc/get_ckey_name(ckey)
|
||||
UPDATE_CKEY_MOB(ckey)
|
||||
var/mob/M = selected_ckeys_mobs[ckey]
|
||||
|
||||
return get_display_name(M)
|
||||
|
||||
#undef UPDATE_CKEY_MOB
|
||||
#undef RECORD_WARN_LIMIT
|
||||
#undef RECORD_HARD_LIMIT
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/datum/logging
|
||||
var/list/datum/log_record/logs = list() // Assoc list of assoc lists (ckey, (log_type, list/logs))
|
||||
|
||||
/datum/logging/proc/add_log(ckey, datum/log_record/log)
|
||||
if(!ckey)
|
||||
log_debug("GLOB.logging.add_log called with an invalid ckey")
|
||||
return
|
||||
|
||||
if(!logs[ckey])
|
||||
logs[ckey] = list()
|
||||
|
||||
var/list/log_types_list = logs[ckey]
|
||||
|
||||
if(!log_types_list[log.log_type])
|
||||
log_types_list[log.log_type] = list()
|
||||
|
||||
var/list/datum/log_record/log_records = log_types_list[log.log_type]
|
||||
log_records.Add(log)
|
||||
|
||||
/datum/logging/proc/get_ckeys_logged()
|
||||
var/list/ckeys = list()
|
||||
for(var/ckey in logs)
|
||||
ckeys.Add(ckey)
|
||||
return ckeys
|
||||
|
||||
/* Returns the logs of a given ckey and log_type
|
||||
* If no logs exist it will return an empty list
|
||||
*/
|
||||
/datum/logging/proc/get_logs_by_type(ckey, log_type)
|
||||
if(!ckey)
|
||||
log_debug("GLOB.logging.get_logs_by_type called with an invalid ckey")
|
||||
return
|
||||
if(!log_type || !(log_type in ALL_LOGS))
|
||||
log_debug("GLOB.logging.get_logs_by_type called with an invalid log_type '[log_type]'")
|
||||
return
|
||||
|
||||
var/list/log_types_list = logs[ckey]
|
||||
// Check if logs exist for the ckey
|
||||
if(!length(log_types_list))
|
||||
return list()
|
||||
|
||||
var/list/datum/log_record/log_records = log_types_list[log_type]
|
||||
|
||||
// Check if logs exist for this type
|
||||
if(!log_records)
|
||||
return list()
|
||||
return log_records
|
||||
+4
-33
@@ -47,7 +47,6 @@
|
||||
|
||||
var/miming = 0 // Mime's vow of silence
|
||||
var/list/antag_datums
|
||||
var/speech_span // What span any body this mind has talks in.
|
||||
var/datum/changeling/changeling //changeling holder
|
||||
var/linglink
|
||||
var/datum/vampire/vampire //vampire holder
|
||||
@@ -65,8 +64,6 @@
|
||||
var/isblessed = FALSE // is this person blessed by a chaplain?
|
||||
var/num_blessed = 0 // for prayers
|
||||
|
||||
// the world.time since the mob has been brigged, or -1 if not at all
|
||||
var/brigged_since = -1
|
||||
var/suicided = FALSE
|
||||
|
||||
//put this here for easier tracking ingame
|
||||
@@ -103,14 +100,6 @@
|
||||
current.mind = null
|
||||
leave_all_huds() //leave all the huds in the old body, so it won't get huds if somebody else enters it
|
||||
|
||||
for(var/log_type in current.logs) // Copy the old logs
|
||||
var/list/logs = current.logs[log_type]
|
||||
if(new_character.logs[log_type])
|
||||
new_character.logs[log_type] += logs.Copy() // Append the old ones
|
||||
new_character.logs[log_type] = sortTim(new_character.logs[log_type], /proc/compare_log_record) // Sort them on time
|
||||
else
|
||||
new_character.logs[log_type] = logs.Copy() // Just copy them
|
||||
|
||||
SSnanoui.user_transferred(current, new_character)
|
||||
|
||||
if(new_character.mind) //remove any mind currently in our new body's mind variable
|
||||
@@ -1422,9 +1411,10 @@
|
||||
return A
|
||||
|
||||
/datum/mind/proc/announce_objectives()
|
||||
to_chat(current, "<span class='notice'>Your current objectives:</span>")
|
||||
for(var/line in splittext(gen_objective_text(), "<br>"))
|
||||
to_chat(current, line)
|
||||
if(current)
|
||||
to_chat(current, "<span class='notice'>Your current objectives:</span>")
|
||||
for(var/line in splittext(gen_objective_text(), "<br>"))
|
||||
to_chat(current, line)
|
||||
|
||||
/datum/mind/proc/find_syndicate_uplink()
|
||||
var/list/L = current.get_contents()
|
||||
@@ -1593,25 +1583,6 @@
|
||||
L = agent_landmarks[team]
|
||||
H.forceMove(L.loc)
|
||||
|
||||
|
||||
// check whether this mind's mob has been brigged for the given duration
|
||||
// have to call this periodically for the duration to work properly
|
||||
/datum/mind/proc/is_brigged(duration)
|
||||
var/turf/T = current.loc
|
||||
if(!istype(T))
|
||||
brigged_since = -1
|
||||
return 0
|
||||
|
||||
var/is_currently_brigged = current.is_in_brig()
|
||||
if(!is_currently_brigged)
|
||||
brigged_since = -1
|
||||
return 0
|
||||
|
||||
if(brigged_since == -1)
|
||||
brigged_since = world.time
|
||||
|
||||
return (duration <= world.time - brigged_since)
|
||||
|
||||
/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/S)
|
||||
spell_list += S
|
||||
S.action.Grant(current)
|
||||
|
||||
@@ -222,10 +222,10 @@
|
||||
name = "NT Undercover Operative"
|
||||
// Disguised NT special forces, sent to quietly eliminate or keep tabs on people in high positions (e.g: captain)
|
||||
|
||||
uniform = /obj/item/clothing/under/color/black
|
||||
uniform = /obj/item/clothing/under/color/random
|
||||
back = /obj/item/storage/backpack
|
||||
belt = /obj/item/storage/belt/utility/full/multitool
|
||||
gloves = /obj/item/clothing/gloves/combat
|
||||
gloves = /obj/item/clothing/gloves/color/yellow
|
||||
shoes = /obj/item/clothing/shoes/chameleon/noslip
|
||||
l_ear = /obj/item/radio/headset/centcom
|
||||
id = /obj/item/card/id
|
||||
|
||||
@@ -175,6 +175,7 @@
|
||||
description = "The crew of a space station awaken one hundred years after a crisis. Awaking to a derelict space station on the verge of collapse, and a hostile force of invading \
|
||||
hivebots. Can the surviving crew overcome the odds and survive and rebuild, or will the cold embrace of the stars become their new home?"
|
||||
cost = 2
|
||||
allow_duplicates = FALSE
|
||||
|
||||
/datum/map_template/ruin/space/wizardcrash
|
||||
id = "wizardcrash"
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
var/admin_notes
|
||||
|
||||
/datum/map_template/shuttle/New()
|
||||
shuttle_id = "[port_id]_[suffix]"
|
||||
mappath = "[prefix][shuttle_id].dmm"
|
||||
if(port_id && suffix)
|
||||
shuttle_id = "[port_id]_[suffix]"
|
||||
mappath = "[prefix][shuttle_id].dmm"
|
||||
. = ..()
|
||||
|
||||
/datum/map_template/shuttle/emergency
|
||||
|
||||
@@ -444,6 +444,11 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
|
||||
return
|
||||
|
||||
// Normally, AoE spells will generate an attack log for every turf they loop over, while searching for targets.
|
||||
// With this override, all /aoe_turf type spells will only generate 1 log, saying that the user has cast the spell.
|
||||
/obj/effect/proc_holder/spell/aoe_turf/perform(list/targets, recharge, mob/user, make_attack_logs)
|
||||
add_attack_logs(user, null, "Cast the AoE spell [name]", ATKLOG_ALL)
|
||||
return ..(targets, recharge, user, FALSE)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/proc/los_check(mob/A,mob/B)
|
||||
//Checks for obstacles from A to B
|
||||
|
||||
@@ -13,11 +13,6 @@
|
||||
action_icon_state = "knock"
|
||||
sound = 'sound/magic/knock.ogg'
|
||||
|
||||
// Knock doesn't need to generate an attack log for every turf, set `make_attack_logs` to FALSE and just create a custom one.
|
||||
/obj/effect/proc_holder/spell/aoe_turf/knock/perform(list/targets, recharge, mob/user)
|
||||
add_attack_logs(user, user, "cast the spell [name]", ATKLOG_ALL)
|
||||
return ..(targets, recharge, user, make_attack_logs = FALSE)
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets, mob/user = usr)
|
||||
for(var/turf/T in targets)
|
||||
for(var/obj/machinery/door/door in T.contents)
|
||||
|
||||
@@ -633,7 +633,6 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
|
||||
contains = list(/obj/machinery/power/emitter,
|
||||
/obj/machinery/power/emitter)
|
||||
cost = 10
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containername = "emitter crate"
|
||||
access = ACCESS_CE
|
||||
containertype = /obj/structure/closet/crate/secure/engineering
|
||||
@@ -717,7 +716,7 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
|
||||
name = "Supermatter Shard Crate"
|
||||
contains = list(/obj/machinery/power/supermatter_shard)
|
||||
cost = 50 //So cargo thinks twice before killing themselves with it
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containertype = /obj/structure/closet/crate/secure/engineering
|
||||
containername = "supermatter shard crate"
|
||||
access = ACCESS_CE
|
||||
|
||||
@@ -728,7 +727,7 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
|
||||
/obj/item/pipe/circulator,
|
||||
/obj/item/pipe/circulator)
|
||||
cost = 25
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containertype = /obj/structure/closet/crate/secure/engineering
|
||||
containername = "thermo-electric generator crate"
|
||||
access = ACCESS_CE
|
||||
announce_beacons = list("Engineering" = list("Chief Engineer's Desk", "Atmospherics"))
|
||||
@@ -1174,11 +1173,10 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
|
||||
containername = "fox crate"
|
||||
|
||||
/datum/supply_packs/organic/butterfly
|
||||
name = "Butterflies Crate"
|
||||
name = "Butterfly Crate"
|
||||
cost = 50
|
||||
containertype = /obj/structure/closet/critter/butterfly
|
||||
containername = "butterflies crate"
|
||||
contraband = 1
|
||||
containername = "butterfly crate"
|
||||
|
||||
/datum/supply_packs/organic/deer
|
||||
name = "Deer Crate"
|
||||
@@ -1767,6 +1765,16 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
|
||||
cost = 20
|
||||
containername = "polo supply crate"
|
||||
|
||||
/datum/supply_packs/misc/boxing //For non log spamming cargo brawls!
|
||||
name = "Boxing Supply Crate"
|
||||
// 4 boxing gloves
|
||||
contains = list(/obj/item/clothing/gloves/boxing/blue,
|
||||
/obj/item/clothing/gloves/boxing/green,
|
||||
/obj/item/clothing/gloves/boxing/yellow,
|
||||
/obj/item/clothing/gloves/boxing)
|
||||
cost = 15
|
||||
containername = "boxing supply crate"
|
||||
|
||||
///////////// Station Goals
|
||||
|
||||
/datum/supply_packs/misc/station_goal
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
return
|
||||
if(!L.client) //Only sentient people are going along with it!
|
||||
return
|
||||
if(L.flying)
|
||||
return
|
||||
L.adjustFireLoss(3)
|
||||
|
||||
/datum/weather/floor_is_lava/fake
|
||||
|
||||
@@ -15,16 +15,16 @@
|
||||
switch(index)
|
||||
if(BORG_WIRE_MAIN_POWER)
|
||||
return "Main Power"
|
||||
|
||||
|
||||
if(BORG_WIRE_LOCKED_DOWN)
|
||||
return "Lockdown"
|
||||
|
||||
|
||||
if(BORG_WIRE_CAMERA)
|
||||
return "Camera"
|
||||
|
||||
|
||||
if(BORG_WIRE_AI_CONTROL)
|
||||
return "AI Control"
|
||||
|
||||
|
||||
if(BORG_WIRE_LAWCHECK)
|
||||
return "Law Check"
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
if(BORG_WIRE_AI_CONTROL) //Cut the AI wire to reset AI control
|
||||
if(!mended)
|
||||
if(R.connected_ai)
|
||||
R.connected_ai = null
|
||||
R.disconnect_from_ai()
|
||||
|
||||
if(BORG_WIRE_CAMERA)
|
||||
if(!isnull(R.camera) && !R.scrambledcodes)
|
||||
@@ -74,8 +74,7 @@
|
||||
switch(index)
|
||||
if(BORG_WIRE_AI_CONTROL) //pulse the AI wire to make the borg reselect an AI
|
||||
if(!R.emagged)
|
||||
R.connected_ai = select_active_ai()
|
||||
R.notify_ai(1)
|
||||
R.connect_to_ai(select_active_ai())
|
||||
|
||||
if(BORG_WIRE_CAMERA)
|
||||
if(!isnull(R.camera) && R.camera.can_use() && !R.scrambledcodes)
|
||||
|
||||
@@ -194,7 +194,7 @@ GLOBAL_LIST_INIT(wireColours, list("red", "blue", "green", "black", "orange", "b
|
||||
return 1
|
||||
|
||||
/datum/wires/CanUseTopic(mob/user, datum/topic_state/state)
|
||||
if(!CanUse(user))
|
||||
if(!holder || !CanUse(user))
|
||||
return STATUS_CLOSE
|
||||
return ..()
|
||||
|
||||
|
||||
+11
-11
@@ -29,15 +29,15 @@ Actual Adjacent procs :
|
||||
//////////////////////
|
||||
|
||||
//A* nodes variables
|
||||
/PathNode
|
||||
/datum/pathnode
|
||||
var/turf/source //turf associated with the PathNode
|
||||
var/PathNode/prevNode //link to the parent PathNode
|
||||
var/datum/pathnode/prevNode //link to the parent PathNode
|
||||
var/f //A* Node weight (f = g + h)
|
||||
var/g //A* movement cost variable
|
||||
var/h //A* heuristic variable
|
||||
var/nt //count the number of Nodes traversed
|
||||
|
||||
/PathNode/New(s,p,pg,ph,pnt)
|
||||
/datum/pathnode/New(s,p,pg,ph,pnt)
|
||||
source = s
|
||||
prevNode = p
|
||||
g = pg
|
||||
@@ -46,7 +46,7 @@ Actual Adjacent procs :
|
||||
source.PNode = src
|
||||
nt = pnt
|
||||
|
||||
/PathNode/proc/calc_f()
|
||||
/datum/pathnode/proc/calc_f()
|
||||
f = g + h
|
||||
|
||||
//////////////////////
|
||||
@@ -54,11 +54,11 @@ Actual Adjacent procs :
|
||||
//////////////////////
|
||||
|
||||
//the weighting function, used in the A* algorithm
|
||||
/proc/PathWeightCompare(PathNode/a, PathNode/b)
|
||||
/proc/PathWeightCompare(datum/pathnode/a, datum/pathnode/b)
|
||||
return a.f - b.f
|
||||
|
||||
//reversed so that the Heap is a MinHeap rather than a MaxHeap
|
||||
/proc/HeapPathWeightCompare(PathNode/a, PathNode/b)
|
||||
/proc/HeapPathWeightCompare(datum/pathnode/a, datum/pathnode/b)
|
||||
return b.f - a.f
|
||||
|
||||
//wrapper that returns an empty list if A* failed to find a path
|
||||
@@ -82,13 +82,13 @@ Actual Adjacent procs :
|
||||
return 0
|
||||
maxnodedepth = maxnodes //no need to consider path longer than maxnodes
|
||||
|
||||
var/Heap/open = new /Heap(/proc/HeapPathWeightCompare) //the open list
|
||||
var/datum/heap/open = new /datum/heap(/proc/HeapPathWeightCompare) //the open list
|
||||
var/list/closed = new() //the closed list
|
||||
var/list/path = null //the returned path, if any
|
||||
var/PathNode/cur //current processed turf
|
||||
var/datum/pathnode/cur //current processed turf
|
||||
|
||||
//initialization
|
||||
open.Insert(new /PathNode(start,null,0,call(start,dist)(end),0))
|
||||
open.Insert(new /datum/pathnode(start,null,0,call(start,dist)(end),0))
|
||||
|
||||
//then run the main loop
|
||||
while(!open.IsEmpty() && !path)
|
||||
@@ -125,7 +125,7 @@ Actual Adjacent procs :
|
||||
|
||||
var/newg = cur.g + call(cur.source,dist)(T)
|
||||
if(!T.PNode) //is not already in open list, so add it
|
||||
open.Insert(new /PathNode(T,cur,newg,call(T,dist)(end),cur.nt+1))
|
||||
open.Insert(new /datum/pathnode(T,cur,newg,call(T,dist)(end),cur.nt+1))
|
||||
else //is already in open list, check if it's a better way from the current turf
|
||||
if(newg < T.PNode.g)
|
||||
T.PNode.prevNode = cur
|
||||
@@ -137,7 +137,7 @@ Actual Adjacent procs :
|
||||
}
|
||||
|
||||
//cleaning after us
|
||||
for(var/PathNode/PN in open.L)
|
||||
for(var/datum/pathnode/PN in open.L)
|
||||
PN.source.PNode = null
|
||||
for(var/turf/T in closed)
|
||||
T.PNode = null
|
||||
|
||||
@@ -83,10 +83,6 @@
|
||||
var/message = "[key_name(whom, 0)][isAntag(whom) ? "(ANTAG)" : ""][isLivingSSD(whom) ? "(SSD!)": ""]"
|
||||
return message
|
||||
|
||||
/proc/log_and_message_admins(var/message as text)
|
||||
/proc/log_and_message_admins(message)
|
||||
log_admin("[key_name(usr)] " + message)
|
||||
message_admins("[key_name_admin(usr)] " + message)
|
||||
|
||||
/proc/admin_log_and_message_admins(var/message as text)
|
||||
log_admin("[key_name(usr)] " + message)
|
||||
message_admins("[key_name_admin(usr)] " + message, 1)
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
// List is required to compile the resources into the game when it loads.
|
||||
// Dynamically loading it has bad results with sounds overtaking each other, even with the wait variable.
|
||||
|
||||
GLOBAL_LIST_INIT(vox_sounds, list("," = 'sound/vox_fem/,.ogg',
|
||||
GLOBAL_LIST_INIT(vox_alerts, list(
|
||||
"bizwarn" = 'sound/vox_fem/bizwarn.ogg',
|
||||
"bloop" = 'sound/vox_fem/bloop.ogg',
|
||||
"buzwarn" = 'sound/vox_fem/buzwarn.ogg',
|
||||
"dadeda" = 'sound/vox_fem/dadeda.ogg',
|
||||
"deeoo" = 'sound/vox_fem/deeoo.ogg'
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(vox_sounds, list(
|
||||
"," = 'sound/vox_fem/,.ogg',
|
||||
"." = 'sound/vox_fem/..ogg',
|
||||
"a" = 'sound/vox_fem/a.ogg',
|
||||
"abortions" = 'sound/vox_fem/abortions.ogg',
|
||||
|
||||
@@ -13,35 +13,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
|
||||
*/
|
||||
|
||||
/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
|
||||
/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/
|
||||
GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
/hook/startup/proc/process_teleport_locs()
|
||||
for(var/area/AR in world)
|
||||
if(AR.no_teleportlocs) continue
|
||||
if(GLOB.teleportlocs.Find(AR.name)) continue
|
||||
var/turf/picked = safepick(get_area_turfs(AR.type))
|
||||
if(picked && is_station_level(picked.z))
|
||||
GLOB.teleportlocs += AR.name
|
||||
GLOB.teleportlocs[AR.name] = AR
|
||||
|
||||
GLOB.teleportlocs = sortAssoc(GLOB.teleportlocs)
|
||||
|
||||
return 1
|
||||
|
||||
GLOBAL_LIST_EMPTY(ghostteleportlocs)
|
||||
/hook/startup/proc/process_ghost_teleport_locs()
|
||||
for(var/area/AR in world)
|
||||
if(GLOB.ghostteleportlocs.Find(AR.name)) continue
|
||||
var/list/turfs = get_area_turfs(AR.type)
|
||||
if(turfs.len)
|
||||
GLOB.ghostteleportlocs += AR.name
|
||||
GLOB.ghostteleportlocs[AR.name] = AR
|
||||
|
||||
GLOB.ghostteleportlocs = sortAssoc(GLOB.ghostteleportlocs)
|
||||
|
||||
return 1
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user