mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-22 19:47:22 +01:00
Merge remote-tracking branch 'upstream/master' into borger-tweaks
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
[](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)
|
||||
|
||||
+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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
|
||||
+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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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
|
||||
|
||||
+83
-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,48 @@ 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/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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,268 @@
|
||||
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))
|
||||
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
|
||||
|
||||
// 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)
|
||||
@@ -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\">"
|
||||
|
||||
@@ -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]")
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
/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)
|
||||
target = get_subject_text(_target, _log_type)
|
||||
if(!_where)
|
||||
_where = get_turf(_who)
|
||||
where = _where
|
||||
@@ -19,16 +19,31 @@
|
||||
_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
|
||||
|
||||
+84
-17
@@ -1,16 +1,23 @@
|
||||
#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;\
|
||||
}
|
||||
|
||||
/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()
|
||||
@@ -19,13 +26,17 @@
|
||||
/datum/log_viewer/proc/search()
|
||||
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)
|
||||
@@ -91,9 +102,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(!mobs?.len)
|
||||
return
|
||||
for(var/i in mobs)
|
||||
add_mob(usr, i, FALSE)
|
||||
|
||||
/datum/log_viewer/proc/add_ckey(mob/user, ckey)
|
||||
if(!user || !user)
|
||||
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)
|
||||
@@ -103,8 +128,8 @@
|
||||
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'>"
|
||||
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 +140,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 +173,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)
|
||||
@@ -158,7 +189,7 @@
|
||||
dat += "</table>"
|
||||
dat += "</div>"
|
||||
|
||||
var/datum/browser/popup = new(user, "Log viewer", "Log viewer", 1400, 600)
|
||||
var/datum/browser/popup = new(user, "Log Viewer", "Log Viewer", 1500, 600)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
@@ -198,17 +229,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 +277,26 @@
|
||||
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
|
||||
|
||||
@@ -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
-11
@@ -100,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
|
||||
@@ -1419,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()
|
||||
|
||||
@@ -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"))
|
||||
@@ -1767,6 +1766,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
/atom/movable/proc/get_cell()
|
||||
return
|
||||
|
||||
/atom/movable/proc/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
|
||||
/atom/movable/proc/start_pulling(atom/movable/AM, state, force = pull_force, show_message = FALSE)
|
||||
if(QDELETED(AM))
|
||||
return FALSE
|
||||
if(!(AM.can_be_pulled(src, state, force)))
|
||||
@@ -87,7 +87,7 @@
|
||||
if(ismob(AM))
|
||||
var/mob/M = AM
|
||||
add_attack_logs(src, M, "passively grabbed", ATKLOG_ALMOSTALL)
|
||||
if(!supress_message)
|
||||
if(show_message)
|
||||
visible_message("<span class='warning'>[src] has grabbed [M] passively!</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -120,12 +120,18 @@
|
||||
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1) //separated from our puller and not in the middle of a diagonal move.
|
||||
pulledby.stop_pulling()
|
||||
|
||||
/atom/movable/proc/can_be_pulled(user, grab_state, force)
|
||||
/atom/movable/proc/can_be_pulled(user, grab_state, force, show_message = FALSE)
|
||||
if(src == user || !isturf(loc))
|
||||
return FALSE
|
||||
if(anchored || throwing)
|
||||
if(anchored || move_resist == INFINITY)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='warning'>[src] appears to be anchored to the ground!</span>")
|
||||
return FALSE
|
||||
if(throwing)
|
||||
return FALSE
|
||||
if(force < (move_resist * MOVE_FORCE_PULL_RATIO))
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='warning'>[src] is too heavy to pull!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -567,3 +573,6 @@
|
||||
|
||||
/atom/movable/proc/portal_destroyed(obj/effect/portal/P)
|
||||
return
|
||||
|
||||
/atom/movable/proc/decompile_act(obj/item/matter_decompiler/C, mob/user) // For drones to decompile mobs and objs. See drone for an example.
|
||||
return FALSE
|
||||
|
||||
@@ -282,6 +282,9 @@
|
||||
occupant = null
|
||||
icon_state = "scanner_open"
|
||||
|
||||
/obj/machinery/dna_scannernew/force_eject_occupant()
|
||||
go_out(null, TRUE)
|
||||
|
||||
/obj/machinery/dna_scannernew/ex_act(severity)
|
||||
if(occupant)
|
||||
occupant.ex_act(severity)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
intercepttext += "<BR>Note in the event of a quarantine breach or uncontrolled spread of the biohazard, the directive 7-10 may be upgraded to a directive 7-12.<BR>"
|
||||
intercepttext += "Message ends."
|
||||
if(2)
|
||||
var/nukecode = rand(10000, 99999)
|
||||
var/nukecode = "[rand(10000, 99999)]"
|
||||
for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
|
||||
if(bomb && bomb.r_code)
|
||||
if(is_station_level(bomb.z))
|
||||
|
||||
@@ -104,10 +104,18 @@
|
||||
var/mob/C = null
|
||||
var/list/candidates = list()
|
||||
if(!new_overmind)
|
||||
// Create icon
|
||||
var/mutable_appearance/MA = new
|
||||
var/mutable_appearance/MA1 = new(icon, "blob")
|
||||
MA1.color = overmind ? overmind.blob_reagent_datum.color : color
|
||||
MA.overlays += MA1
|
||||
var/mutable_appearance/MA2 = new(icon, "blob_core_overlay")
|
||||
MA.overlays += MA2
|
||||
// sendit
|
||||
if(is_offspring)
|
||||
candidates = pollCandidates("Do you want to play as a blob offspring?", ROLE_BLOB, 1)
|
||||
candidates = SSghost_spawns.poll_candidates("Do you want to play as a blob offspring?", ROLE_BLOB, TRUE, source = MA)
|
||||
else
|
||||
candidates = pollCandidates("Do you want to play as a blob?", ROLE_BLOB, 1)
|
||||
candidates = SSghost_spawns.poll_candidates("Do you want to play as a blob?", ROLE_BLOB, TRUE, source = MA)
|
||||
|
||||
if(length(candidates))
|
||||
C = pick(candidates)
|
||||
|
||||
@@ -237,7 +237,7 @@
|
||||
blobber.AIStatus = AI_OFF
|
||||
blobber.LoseTarget()
|
||||
spawn()
|
||||
var/list/candidates = pollCandidates("Do you want to play as a blobbernaut?", ROLE_BLOB, 1, 100)
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a blobbernaut?", ROLE_BLOB, TRUE, 10 SECONDS, source = blobber)
|
||||
if(candidates.len)
|
||||
var/mob/C = pick(candidates)
|
||||
if(C)
|
||||
|
||||
@@ -20,8 +20,8 @@ GLOBAL_LIST_EMPTY(all_cults)
|
||||
var/mob/living/carbon/human/H = mind.current
|
||||
if(ismindshielded(H)) //mindshield protects against conversions unless removed
|
||||
return FALSE
|
||||
// if(mind.offstation_role) cant convert offstation roles such as ghost spawns
|
||||
// return FALSE Commented out until we can figure out why offstation_role is getting set to TRUE on normal crew
|
||||
if(mind.offstation_role)
|
||||
return FALSE
|
||||
if(issilicon(mind.current))
|
||||
return FALSE //can't convert machines, that's ratvar's thing
|
||||
if(isguardian(mind.current))
|
||||
@@ -231,6 +231,8 @@ GLOBAL_LIST_EMPTY(all_cults)
|
||||
/datum/game_mode/cult/proc/get_unconvertables()
|
||||
var/list/ucs = list()
|
||||
for(var/mob/living/carbon/human/player in GLOB.player_list)
|
||||
if(player.mind && player.mind.offstation_role)
|
||||
continue
|
||||
if(!is_convertable_to_cult(player.mind))
|
||||
ucs += player.mind
|
||||
return ucs
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var/cultist_name = "talisman"
|
||||
var/cultist_desc = "A basic talisman. It serves no purpose."
|
||||
var/invocation = "Naise meam!"
|
||||
info = "<center><img src='talisman.png'></center><br/><br/>"
|
||||
info = "<center>​<img src='talisman.png'></center><br/><br/>"
|
||||
var/uses = 1
|
||||
var/health_cost = 0 //The amount of health taken from the user when invoking the talisman
|
||||
|
||||
|
||||
@@ -291,7 +291,8 @@
|
||||
///////////////////////////////////
|
||||
/datum/game_mode/proc/get_living_heads()
|
||||
. = list()
|
||||
for(var/mob/living/carbon/human/player in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/player = thing
|
||||
var/list/real_command_positions = GLOB.command_positions.Copy() - "Nanotrasen Representative"
|
||||
if(player.stat != DEAD && player.mind && (player.mind.assigned_role in real_command_positions))
|
||||
. |= player.mind
|
||||
@@ -312,7 +313,8 @@
|
||||
//////////////////////////////////////////////
|
||||
/datum/game_mode/proc/get_living_sec()
|
||||
. = list()
|
||||
for(var/mob/living/carbon/human/player in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/player = thing
|
||||
if(player.stat != DEAD && player.mind && (player.mind.assigned_role in GLOB.security_positions))
|
||||
. |= player.mind
|
||||
|
||||
@@ -321,7 +323,8 @@
|
||||
////////////////////////////////////////
|
||||
/datum/game_mode/proc/get_all_sec()
|
||||
. = list()
|
||||
for(var/mob/living/carbon/human/player in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/player = thing
|
||||
if(player.mind && (player.mind.assigned_role in GLOB.security_positions))
|
||||
. |= player.mind
|
||||
|
||||
@@ -421,9 +424,9 @@ proc/display_roundstart_logout_report()
|
||||
return nukecode
|
||||
|
||||
/datum/game_mode/proc/replace_jobbanned_player(mob/living/M, role_type)
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as a [role_type]?", role_type, 0, 100)
|
||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as a [role_type]?", role_type, FALSE, 10 SECONDS)
|
||||
var/mob/dead/observer/theghost = null
|
||||
if(candidates.len)
|
||||
if(length(candidates))
|
||||
theghost = pick(candidates)
|
||||
to_chat(M, "<span class='userdanger'>Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!</span>")
|
||||
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)]) to replace a jobbanned player.")
|
||||
|
||||
@@ -83,6 +83,36 @@
|
||||
else
|
||||
add_ranged_ability(user, enable_text)
|
||||
|
||||
/datum/action/innate/ai/choose_modules
|
||||
name = "Choose Modules"
|
||||
desc = "Spend your processing time to gain a variety of different abilities."
|
||||
button_icon_state = "choose_module"
|
||||
auto_use_uses = FALSE // This is an infinite ability.
|
||||
|
||||
/datum/action/innate/ai/choose_modules/Grant(mob/living/L)
|
||||
. = ..()
|
||||
owner_AI.malf_picker = new /datum/module_picker
|
||||
|
||||
/datum/action/innate/ai/choose_modules/Trigger()
|
||||
. = ..()
|
||||
owner_AI.malf_picker.use(owner_AI)
|
||||
|
||||
/datum/action/innate/ai/return_to_core
|
||||
name = "Return to Main Core"
|
||||
desc = "Leave the APC you are shunted to, and return to your core."
|
||||
icon_icon = 'icons/obj/power.dmi'
|
||||
button_icon_state = "apcemag"
|
||||
auto_use_uses = FALSE // Here just to prevent the "You have X uses remaining" from popping up.
|
||||
|
||||
/datum/action/innate/ai/return_to_core/Trigger()
|
||||
. = ..()
|
||||
var/obj/machinery/power/apc/apc = owner_AI.loc
|
||||
if(!istype(apc)) // This shouldn't happen but here for safety.
|
||||
to_chat(src, "<span class='notice'>You are already in your Main Core.</span>")
|
||||
return
|
||||
apc.malfvacate()
|
||||
qdel(src)
|
||||
|
||||
//The datum and interface for the malf unlock menu, which lets them choose actions to unlock.
|
||||
/datum/module_picker
|
||||
var/temp
|
||||
@@ -96,13 +126,7 @@
|
||||
if((AM.power_type && AM.power_type != /datum/action/innate/ai) || AM.upgrade)
|
||||
possible_modules += AM
|
||||
|
||||
/datum/module_picker/proc/remove_malf_verbs(mob/living/silicon/ai/AI) //Removes all malfunction-related abilities from the target AI.
|
||||
for(var/datum/AI_Module/AM in possible_modules)
|
||||
for(var/datum/action/A in AI.actions)
|
||||
if(istype(A, initial(AM.power_type)))
|
||||
qdel(A)
|
||||
|
||||
/datum/module_picker/proc/use(user as mob)
|
||||
/datum/module_picker/proc/use(mob/user)
|
||||
var/dat
|
||||
dat += {"<B>Select use of processing time: (currently #[processing_time] left.)</B><BR>
|
||||
<HR>
|
||||
|
||||
@@ -394,7 +394,7 @@
|
||||
to_chat(src, "<font color='blue'> You are feeling far too docile to do that.</font>")
|
||||
return
|
||||
|
||||
var content = ""
|
||||
var/content = ""
|
||||
|
||||
content += "<table>"
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@
|
||||
src.verbs -= /mob/living/proc/guardian_reset
|
||||
for(var/mob/living/simple_animal/hostile/guardian/G in GLOB.mob_list)
|
||||
if(G.summoner == src)
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [G.real_name]?", ROLE_GUARDIAN, 0, 100)
|
||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as [G.real_name]?", ROLE_GUARDIAN, FALSE, 10 SECONDS, source = G)
|
||||
var/mob/dead/observer/new_stand = null
|
||||
if(candidates.len)
|
||||
new_stand = pick(candidates)
|
||||
@@ -312,7 +312,7 @@
|
||||
used = FALSE
|
||||
return
|
||||
to_chat(user, "[use_message]")
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_GUARDIAN, 0, 100)
|
||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_GUARDIAN, FALSE, 10 SECONDS, source = /mob/living/simple_animal/hostile/guardian)
|
||||
var/mob/dead/observer/theghost = null
|
||||
|
||||
if(candidates.len)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/item/projectile/guardian
|
||||
name = "crystal spray"
|
||||
icon_state = "guardian"
|
||||
damage = 5
|
||||
damage = 25
|
||||
damage_type = BRUTE
|
||||
armour_penetration = 100
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
melee_damage_upper = 10
|
||||
damage_transfer = 0.9
|
||||
projectiletype = /obj/item/projectile/guardian
|
||||
ranged_cooldown_time = 1 //fast!
|
||||
ranged_cooldown_time = 5 //fast!
|
||||
projectilesound = 'sound/effects/hit_on_shattered_glass.ogg'
|
||||
ranged = 1
|
||||
range = 13
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
/datum/event/spawn_morph/proc/get_morph()
|
||||
spawn()
|
||||
var/list/candidates = pollCandidates("Do you want to play as a morph?", ROLE_MORPH, 1)
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a morph?", ROLE_MORPH, TRUE, source = /mob/living/simple_animal/hostile/morph)
|
||||
if(!candidates.len)
|
||||
key_of_morph = null
|
||||
return kill()
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
var/icon_stun = "revenant_stun"
|
||||
var/icon_drain = "revenant_draining"
|
||||
incorporeal_move = 3
|
||||
see_invisible = INVISIBILITY_REVENANT
|
||||
invisibility = INVISIBILITY_REVENANT
|
||||
health = INFINITY //Revenants don't use health, they use essence instead
|
||||
maxHealth = INFINITY
|
||||
@@ -140,7 +141,7 @@
|
||||
giveObjectivesandGoals()
|
||||
giveSpells()
|
||||
else
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as a revenant?", poll_time = 15 SECONDS)
|
||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as a revenant?", poll_time = 15 SECONDS, source = /mob/living/simple_animal/revenant)
|
||||
var/mob/dead/observer/theghost = null
|
||||
if(candidates.len)
|
||||
theghost = pick(candidates)
|
||||
@@ -396,7 +397,7 @@
|
||||
spawn()
|
||||
if(!key_of_revenant)
|
||||
message_admins("The new revenant's old client either could not be found or is in a new, living mob - grabbing a random candidate instead...")
|
||||
var/list/candidates = pollCandidates("Do you want to play as a revenant?", ROLE_REVENANT, 1)
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a revenant?", ROLE_REVENANT, TRUE, source = /mob/living/simple_animal/revenant)
|
||||
if(!candidates.len)
|
||||
qdel(R)
|
||||
message_admins("No candidates were found for the new revenant. Oh well!")
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
return
|
||||
|
||||
spawn()
|
||||
var/list/candidates = pollCandidates("Do you want to play as a revenant?", ROLE_REVENANT, 1)
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a revenant?", ROLE_REVENANT, TRUE, source = /mob/living/simple_animal/revenant)
|
||||
if(!candidates.len)
|
||||
key_of_revenant = null
|
||||
return kill()
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
/mob/living/simple_animal/slaughter/cult/New()
|
||||
..()
|
||||
spawn(5)
|
||||
var/list/demon_candidates = pollCandidates("Do you want to play as a slaughter demon?", ROLE_DEMON, 1, 100)
|
||||
var/list/demon_candidates = SSghost_spawns.poll_candidates("Do you want to play as a slaughter demon?", ROLE_DEMON, TRUE, 10 SECONDS, source = /mob/living/simple_animal/slaughter/cult)
|
||||
if(!demon_candidates.len)
|
||||
visible_message("<span class='warning'>[src] disappears in a flash of red light!</span>")
|
||||
qdel(src)
|
||||
|
||||
@@ -53,7 +53,6 @@ proc/issyndicate(mob/living/M as mob)
|
||||
for(var/datum/mind/synd_mind in syndicates)
|
||||
synd_mind.assigned_role = SPECIAL_ROLE_NUKEOPS //So they aren't chosen for other jobs.
|
||||
synd_mind.special_role = SPECIAL_ROLE_NUKEOPS
|
||||
synd_mind.offstation_role = TRUE
|
||||
return 1
|
||||
|
||||
|
||||
@@ -113,7 +112,7 @@ proc/issyndicate(mob/living/M as mob)
|
||||
if(spawnpos > synd_spawn.len)
|
||||
spawnpos = 2
|
||||
synd_mind.current.loc = synd_spawn[spawnpos]
|
||||
|
||||
synd_mind.offstation_role = TRUE
|
||||
forge_syndicate_objectives(synd_mind)
|
||||
create_syndicate(synd_mind)
|
||||
greet_syndicate(synd_mind)
|
||||
|
||||
@@ -357,7 +357,8 @@
|
||||
var/list/name_counts = list()
|
||||
var/list/names = list()
|
||||
|
||||
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
|
||||
if(!trackable(H))
|
||||
continue
|
||||
|
||||
|
||||
@@ -385,7 +385,8 @@
|
||||
if(foecount == GLOB.score_arrested)
|
||||
GLOB.score_allarrested = 1
|
||||
|
||||
for(var/mob/living/carbon/human/player in GLOB.mob_living_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/player = thing
|
||||
if(player.mind)
|
||||
var/role = player.mind.assigned_role
|
||||
if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director"))
|
||||
@@ -415,7 +416,8 @@
|
||||
for(var/datum/mind/M in SSticker.mode:revolutionaries)
|
||||
if(M.current && M.current.stat != DEAD)
|
||||
revcount++
|
||||
for(var/mob/living/carbon/human/player in GLOB.mob_living_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/player = thing
|
||||
if(player.mind)
|
||||
var/role = player.mind.assigned_role
|
||||
if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director"))
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
GLOB.score_deadaipenalty++
|
||||
GLOB.score_deadcrew++
|
||||
|
||||
for(var/mob/living/carbon/human/I in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/I = thing
|
||||
if(I.stat == DEAD && is_station_level(I.z))
|
||||
GLOB.score_deadcrew++
|
||||
|
||||
@@ -60,7 +61,8 @@
|
||||
var/dmg_score = 0
|
||||
|
||||
if(SSshuttle.emergency.mode >= SHUTTLE_ENDGAME)
|
||||
for(var/mob/living/carbon/human/E in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/E = thing
|
||||
cash_score = 0
|
||||
dmg_score = 0
|
||||
var/turf/location = get_turf(E.loc)
|
||||
|
||||
@@ -74,7 +74,7 @@ Made by Xhuis
|
||||
required_enemies = 2
|
||||
recommended_enemies = 2
|
||||
restricted_jobs = list("AI", "Cyborg")
|
||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer")
|
||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Head of Personnel", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer")
|
||||
|
||||
/datum/game_mode/shadowling/announce()
|
||||
to_chat(world, "<b>The current game mode is - Shadowling!</b>")
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/self/rejuvenate
|
||||
name = "Rejuvenate"
|
||||
desc= "Flush your system with spare blood to remove any incapacitating effects."
|
||||
desc= "Use reserve blood to enliven your body, removing any incapacitating effects."
|
||||
action_icon_state = "vampire_rejuvinate"
|
||||
charge_max = 200
|
||||
stat_allowed = 1
|
||||
@@ -158,7 +158,7 @@
|
||||
user.SetParalysis(0)
|
||||
user.SetSleeping(0)
|
||||
U.adjustStaminaLoss(-75)
|
||||
to_chat(user, "<span class='notice'>You flush your system with clean blood and remove any incapacitating effects.</span>")
|
||||
to_chat(user, "<span class='notice'>You instill your body with clean blood and remove any incapacitating effects.</span>")
|
||||
spawn(1)
|
||||
if(usr.mind.vampire.get_ability(/datum/vampire_passive/regen))
|
||||
for(var/i = 1 to 5)
|
||||
@@ -354,10 +354,10 @@
|
||||
var/datum/objective/protect/serve_objective = new
|
||||
serve_objective.owner = user.mind
|
||||
serve_objective.target = H.mind
|
||||
serve_objective.explanation_text = "You have been Enthralled by [user]. Follow [user.p_their()] every command."
|
||||
serve_objective.explanation_text = "You have been Enthralled by [user.real_name]. Follow [user.p_their()] every command."
|
||||
H.mind.objectives += serve_objective
|
||||
|
||||
to_chat(H, "<span class='biggerdanger'>You have been Enthralled by [user]. Follow [user.p_their()] every command.</span>")
|
||||
to_chat(H, "<span class='biggerdanger'>You have been Enthralled by [user.real_name]. Follow [user.p_their()] every command.</span>")
|
||||
to_chat(user, "<span class='warning'>You have successfully Enthralled [H]. <i>If [H.p_they()] refuse[H.p_s()] to do as you say just adminhelp.</i></span>")
|
||||
H.Stun(2)
|
||||
add_attack_logs(user, H, "Vampire-thralled")
|
||||
|
||||
@@ -50,7 +50,8 @@
|
||||
to_chat(H, "You already used this contract!")
|
||||
return
|
||||
used = 1
|
||||
var/list/candidates = pollCandidates("Do you want to play as the wizard apprentice of [H.real_name]?", ROLE_WIZARD, 1)
|
||||
var/mutable_appearance/source = new('icons/obj/cardboard_cutout.dmi', "cutout_wizard")
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as the wizard apprentice of [H.real_name]?", ROLE_WIZARD, TRUE, source = source)
|
||||
if(candidates.len)
|
||||
var/mob/C = pick(candidates)
|
||||
new /obj/effect/particle_effect/smoke(H.loc)
|
||||
@@ -307,7 +308,8 @@ GLOBAL_LIST_EMPTY(multiverse)
|
||||
if(M.assigned == assigned)
|
||||
M.cooldown = cooldown
|
||||
|
||||
var/list/candidates = pollCandidates("Do you want to play as the wizard apprentice of [user.real_name]?", ROLE_WIZARD, 1, 100)
|
||||
var/mutable_appearance/source = new('icons/obj/cardboard_cutout.dmi', "cutout_wizard")
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as the wizard apprentice of [user.real_name]?", ROLE_WIZARD, TRUE, 10 SECONDS, source = source)
|
||||
if(candidates.len)
|
||||
var/mob/C = pick(candidates)
|
||||
spawn_copy(C.client, get_turf(user.loc), user)
|
||||
@@ -866,8 +868,9 @@ GLOBAL_LIST_EMPTY(multiverse)
|
||||
possible = list()
|
||||
if(!link)
|
||||
return
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
if(md5(H.dna.uni_identity) in link.fingerprints)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
if(H.stat != DEAD && (md5(H.dna.uni_identity) in link.fingerprints))
|
||||
possible |= H
|
||||
|
||||
/obj/item/voodoo/proc/GiveHint(mob/victim,force=0)
|
||||
|
||||
@@ -118,7 +118,8 @@
|
||||
return FALSE
|
||||
making_mage = TRUE
|
||||
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as a raging Space Wizard?", ROLE_WIZARD, TRUE, poll_time = 20 SECONDS)
|
||||
var/mutable_appearance/source = new('icons/obj/cardboard_cutout.dmi', "cutout_wizard")
|
||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as a raging Space Wizard?", ROLE_WIZARD, TRUE, poll_time = 20 SECONDS, source = source)
|
||||
var/mob/dead/observer/harry = null
|
||||
message_admins("SWF is still pissed, sending another wizard - [max_mages - mages_made] left.")
|
||||
|
||||
|
||||
@@ -363,7 +363,7 @@
|
||||
break
|
||||
|
||||
if(!chosen_ghost) //Failing that, we grab a ghost
|
||||
var/list/consenting_candidates = pollCandidates("Would you like to play as a Shade?", ROLE_CULTIST, FALSE, poll_time = 100)
|
||||
var/list/consenting_candidates = SSghost_spawns.poll_candidates("Would you like to play as a Shade?", ROLE_CULTIST, FALSE, poll_time = 10 SECONDS, source = /mob/living/simple_animal/shade)
|
||||
if(consenting_candidates.len)
|
||||
chosen_ghost = pick(consenting_candidates)
|
||||
if(!T)
|
||||
|
||||
@@ -610,7 +610,7 @@
|
||||
var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon - /datum/spellbook_entry/loadout
|
||||
for(var/T in entry_types)
|
||||
var/datum/spellbook_entry/E = new T
|
||||
if(GAMEMODE_IS_WIZARD && E.is_ragin_restricted)
|
||||
if(GAMEMODE_IS_RAGIN_MAGES && E.is_ragin_restricted)
|
||||
qdel(E)
|
||||
continue
|
||||
entries |= E
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 300
|
||||
exp_type = EXP_TYPE_CREW
|
||||
alt_titles = list("Android", "Robot")
|
||||
alt_titles = list("Robot")
|
||||
|
||||
/datum/job/cyborg/equip(mob/living/carbon/human/H)
|
||||
if(!H)
|
||||
|
||||
+10
-12
@@ -224,19 +224,17 @@ GLOBAL_LIST_INIT(role_playtime_requirements, list(
|
||||
else
|
||||
return "none"
|
||||
|
||||
/proc/update_exp(var/mins, var/ann = 0)
|
||||
if(!establish_db_connection())
|
||||
return -1
|
||||
spawn(0)
|
||||
for(var/client/L in GLOB.clients)
|
||||
if(L.inactivity >= (10 MINUTES))
|
||||
continue
|
||||
spawn(0)
|
||||
L.update_exp_client(mins, ann)
|
||||
sleep(10)
|
||||
/proc/update_exp(mins = 0, ann = 0)
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
return
|
||||
for(var/client/L in GLOB.clients)
|
||||
if(L.inactivity >= (10 MINUTES))
|
||||
continue
|
||||
L.update_exp_client(mins, ann)
|
||||
CHECK_TICK
|
||||
|
||||
/client/proc/update_exp_client(var/minutes, var/announce_changes = 0)
|
||||
if(!src ||!ckey)
|
||||
/client/proc/update_exp_client(minutes = 0, announce_changes = 0)
|
||||
if(!src || !ckey || !GLOB.dbcon.IsConnected())
|
||||
return
|
||||
var/DBQuery/exp_read = GLOB.dbcon.NewQuery("SELECT exp FROM [format_table_name("player")] WHERE ckey='[ckey]'")
|
||||
if(!exp_read.Execute())
|
||||
|
||||
@@ -411,6 +411,9 @@
|
||||
for(var/atom/movable/A in contents - component_parts - list(beaker))
|
||||
A.forceMove(loc)
|
||||
|
||||
/obj/machinery/sleeper/force_eject_occupant()
|
||||
go_out()
|
||||
|
||||
/obj/machinery/sleeper/proc/inject_chemical(mob/living/user as mob, chemical, amount)
|
||||
if(!(chemical in possible_chems))
|
||||
to_chat(user, "<span class='notice'>The sleeper does not offer that chemical!</span>")
|
||||
|
||||
@@ -172,6 +172,9 @@
|
||||
for(var/atom/movable/A in contents - component_parts)
|
||||
A.forceMove(loc)
|
||||
|
||||
/obj/machinery/bodyscanner/force_eject_occupant()
|
||||
go_out()
|
||||
|
||||
/obj/machinery/bodyscanner/ex_act(severity)
|
||||
if(occupant)
|
||||
occupant.ex_act(severity)
|
||||
|
||||
@@ -390,7 +390,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
if(!job_in_department(SSjobs.GetJob(t1)))
|
||||
return 0
|
||||
if(t1 == "Custom")
|
||||
var/temp_t = sanitize(copytext(input("Enter a custom job assignment.","Assignment"),1,MAX_MESSAGE_LEN))
|
||||
var/temp_t = sanitize(reject_bad_name(copytext(input("Enter a custom job assignment.", "Assignment"), 1, MAX_MESSAGE_LEN), TRUE))
|
||||
//let custom jobs function as an impromptu alt title, mainly for sechuds
|
||||
if(temp_t && modify)
|
||||
SSjobs.log_job_transfer(modify.registered_name, modify.getRankAndAssignment(), temp_t, scan.registered_name)
|
||||
@@ -419,7 +419,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
message_admins("[key_name_admin(usr)] has reassigned \"[modify.registered_name]\" from \"[jobnamedata]\" to \"[t1]\".")
|
||||
|
||||
SSjobs.log_job_transfer(modify.registered_name, jobnamedata, t1, scan.registered_name)
|
||||
SSjobs.slot_job_transfer(modify.rank, t1)
|
||||
if(modify.owner_uid)
|
||||
SSjobs.slot_job_transfer(modify.rank, t1)
|
||||
|
||||
var/mob/living/carbon/human/H = modify.getPlayer()
|
||||
if(istype(H))
|
||||
@@ -436,7 +437,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
if(is_authenticated(usr) && !target_dept)
|
||||
var/t2 = modify
|
||||
if((modify == t2 && (in_range(src, usr) || (istype(usr, /mob/living/silicon))) && istype(loc, /turf)))
|
||||
var/temp_name = reject_bad_name(href_list["reg"])
|
||||
var/temp_name = reject_bad_name(href_list["reg"], TRUE)
|
||||
if(temp_name)
|
||||
modify.registered_name = temp_name
|
||||
else
|
||||
@@ -465,6 +466,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
if(is_authenticated(usr) && !target_dept)
|
||||
var/delcount = SSjobs.delete_log_records(scan.registered_name, TRUE)
|
||||
if(delcount)
|
||||
message_admins("[key_name_admin(usr)] has wiped all ID computer logs.")
|
||||
usr.create_log(MISC_LOG, "wiped all ID computer logs.")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
SSnanoui.update_uis(src)
|
||||
|
||||
@@ -504,9 +507,16 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
if("terminate")
|
||||
if(is_authenticated(usr) && !target_dept)
|
||||
var/jobnamedata = modify.getRankAndAssignment()
|
||||
log_game("[key_name(usr)] has terminated the employment of \"[modify.registered_name]\" the \"[jobnamedata]\".")
|
||||
message_admins("[key_name_admin(usr)] has terminated the employment of \"[modify.registered_name]\" the \"[jobnamedata]\".")
|
||||
var/reason = sanitize(copytext(input("Enter legal reason for termination. Enter nothing to cancel.", "Employment Termination"), 1, MAX_MESSAGE_LEN))
|
||||
if(!reason || !is_authenticated(usr) || !modify)
|
||||
return FALSE
|
||||
var/m_ckey = modify.getPlayerCkey()
|
||||
var/m_ckey_text = m_ckey ? "([m_ckey])" : "(no ckey)"
|
||||
log_game("[key_name(usr)] has terminated the employment of \"[modify.registered_name]\" [m_ckey_text] the \"[jobnamedata]\" for: \"[reason]\".")
|
||||
message_admins("[key_name_admin(usr)] has terminated the employment of \"[modify.registered_name]\" [m_ckey_text] the \"[jobnamedata]\" for: \"[reason]\".")
|
||||
usr.create_log(MISC_LOG, "terminated the employment of \"[modify.registered_name]\" [m_ckey_text] the \"[jobnamedata]\"")
|
||||
SSjobs.log_job_transfer(modify.registered_name, jobnamedata, "Terminated", scan.registered_name)
|
||||
SSjobs.notify_dept_head(modify.rank, "[scan.registered_name] has terminated the employment of \"[modify.registered_name]\" the \"[jobnamedata]\" for \"[reason]\".")
|
||||
modify.assignment = "Terminated"
|
||||
modify.access = list()
|
||||
|
||||
@@ -518,16 +528,20 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
if(!job_in_department(SSjobs.GetJob(modify.rank), FALSE))
|
||||
visible_message("<span class='notice'>[src]: Heads may only demote members of their own department.</span>")
|
||||
return 0
|
||||
|
||||
var/reason = sanitize(copytext(input("Enter legal reason for demotion. Enter nothing to cancel.","Legal Demotion"),1,MAX_MESSAGE_LEN))
|
||||
if(!reason || !is_authenticated(usr) || !modify)
|
||||
return 0
|
||||
var/list/access = list()
|
||||
var/datum/job/jobdatum = new /datum/job/civilian
|
||||
access = jobdatum.get_access()
|
||||
|
||||
var/jobnamedata = modify.getRankAndAssignment()
|
||||
log_game("[key_name(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" to \"Civilian (Demoted)\".")
|
||||
message_admins("[key_name_admin(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" to \"Civilian (Demoted)\".")
|
||||
var/m_ckey = modify.getPlayerCkey()
|
||||
var/m_ckey_text = m_ckey ? "([m_ckey])" : "(no ckey)"
|
||||
log_game("[key_name(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" [m_ckey_text] to \"Civilian (Demoted)\" for: \"[reason]\".")
|
||||
message_admins("[key_name_admin(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" [m_ckey_text] to \"Civilian (Demoted)\" for: \"[reason]\".")
|
||||
usr.create_log(MISC_LOG, "demoted \"[modify.registered_name]\" [m_ckey_text] the \"[jobnamedata]\"")
|
||||
SSjobs.log_job_transfer(modify.registered_name, jobnamedata, "Demoted", scan.registered_name)
|
||||
|
||||
SSjobs.notify_dept_head(modify.rank, "[scan.registered_name] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" for \"[reason]\".")
|
||||
modify.access = access
|
||||
modify.rank = "Civilian"
|
||||
modify.assignment = "Demoted"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user