This commit is contained in:
Ghommie
2019-11-21 09:18:14 +01:00
692 changed files with 35914 additions and 137039 deletions
@@ -49,7 +49,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"as" = (
@@ -70,7 +70,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"at" = (
@@ -89,7 +89,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"au" = (
@@ -129,7 +129,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"ay" = (
@@ -149,7 +149,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"az" = (
@@ -170,7 +170,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aA" = (
@@ -190,7 +190,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aB" = (
@@ -209,7 +209,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aC" = (
@@ -225,7 +225,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aD" = (
@@ -242,7 +242,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aE" = (
@@ -261,7 +261,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aF" = (
@@ -282,7 +282,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aG" = (
@@ -301,7 +301,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aH" = (
@@ -321,7 +321,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aI" = (
@@ -341,7 +341,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aJ" = (
@@ -368,7 +368,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aL" = (
@@ -394,7 +394,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aO" = (
@@ -415,7 +415,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aP" = (
@@ -448,7 +448,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aU" = (
@@ -472,7 +472,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aW" = (
@@ -493,7 +493,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aX" = (
@@ -522,7 +522,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"aZ" = (
@@ -542,7 +542,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"ba" = (
@@ -559,7 +559,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bb" = (
@@ -588,7 +588,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bd" = (
@@ -631,7 +631,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bg" = (
@@ -732,7 +732,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bt" = (
@@ -758,7 +758,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bx" = (
@@ -775,7 +775,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"by" = (
@@ -792,7 +792,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bz" = (
@@ -817,7 +817,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bB" = (
@@ -825,7 +825,7 @@
icon_state = "bananium";
name = "bananium floor";
sound = 'sound/effects/clownstep1.ogg';
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bC" = (
@@ -846,7 +846,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bD" = (
@@ -872,7 +872,7 @@
icon_state = "bananium";
name = "bananium floor";
sound = 'sound/effects/clownstep1.ogg';
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bH" = (
@@ -881,7 +881,7 @@
icon_state = "bananium";
name = "bananium floor";
sound = 'sound/effects/clownstep1.ogg';
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bI" = (
@@ -899,7 +899,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bK" = (
@@ -918,7 +918,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bL" = (
@@ -942,7 +942,7 @@
icon_state = "bananium";
name = "bananium floor";
sound = 'sound/effects/clownstep1.ogg';
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bP" = (
@@ -970,8 +970,8 @@
/turf/open/floor/carpet,
/area/ruin/powered/clownplanet)
"bT" = (
/obj/item/slime_extract/rainbow,
/obj/structure/table/glass,
/obj/item/reagent_containers/spray/waterflower/superlube,
/turf/open/floor/carpet,
/area/ruin/powered/clownplanet)
"bU" = (
@@ -989,7 +989,7 @@
icon_state = "bananium";
name = "bananium floor";
sound = 'sound/effects/clownstep1.ogg';
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bY" = (
@@ -999,7 +999,7 @@
icon_state = "bananium";
name = "bananium floor";
sound = 'sound/effects/clownstep1.ogg';
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"bZ" = (
@@ -1008,7 +1008,7 @@
icon_state = "bananium";
name = "bananium floor";
sound = 'sound/effects/clownstep1.ogg';
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"ca" = (
@@ -1018,7 +1018,7 @@
icon_state = "bananium";
name = "bananium floor";
sound = 'sound/effects/clownstep1.ogg';
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"cc" = (
@@ -1052,7 +1052,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"dC" = (
@@ -1075,7 +1075,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"dD" = (
@@ -1097,7 +1097,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"dE" = (
@@ -1120,7 +1120,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"dF" = (
@@ -1175,7 +1175,7 @@
},
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"dK" = (
@@ -1202,7 +1202,7 @@
icon_state = "bananium";
name = "bananium floor";
sound = 'sound/effects/clownstep1.ogg';
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"dO" = (
@@ -1211,7 +1211,7 @@
icon_state = "bananium";
name = "bananium floor";
sound = 'sound/effects/clownstep1.ogg';
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"eX" = (
@@ -1260,7 +1260,7 @@
/obj/effect/turf_decal/tile/yellow,
/turf/open/indestructible{
icon_state = "darkfull";
wet = 8
wet = 16
},
/area/ruin/powered/clownplanet)
"KX" = (
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+12 -4
View File
@@ -616,6 +616,9 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 4
},
/obj/item/twohanded/required/kirbyplants{
icon_state = "plant-24"
},
/turf/open/floor/plasteel,
/area/security/prison)
"abB" = (
@@ -57136,9 +57139,7 @@
/turf/open/floor/plating,
/area/maintenance/port)
"hwu" = (
/obj/item/twohanded/required/kirbyplants{
icon_state = "plant-24"
},
/obj/machinery/vr_sleeper,
/turf/open/floor/plasteel,
/area/security/prison)
"hEm" = (
@@ -57158,6 +57159,13 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel/white,
/area/science/circuit)
"ihn" = (
/obj/structure/cable{
icon_state = "1-2"
},
/obj/machinery/vr_sleeper,
/turf/open/floor/plasteel,
/area/security/prison)
"iiW" = (
/turf/open/floor/wood,
/area/maintenance/bar)
@@ -85235,7 +85243,7 @@ aav
aaL
aaQ
aaY
aav
ihn
abE
acg
acJ
+72 -44
View File
@@ -16541,16 +16541,10 @@
/area/security/prison)
"aId" = (
/obj/machinery/seed_extractor,
/obj/structure/cable/white{
icon_state = "4-8"
},
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel,
/area/security/prison)
"aIe" = (
/obj/structure/cable/white{
icon_state = "4-8"
},
/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -16568,9 +16562,6 @@
/obj/structure/cable/white{
icon_state = "2-4"
},
/obj/structure/cable/white{
icon_state = "2-8"
},
/obj/structure/cable/white{
icon_state = "1-2"
},
@@ -18952,25 +18943,11 @@
/obj/machinery/atmospherics/components/unary/vent_pump/on,
/turf/open/floor/plasteel,
/area/security/prison)
"aMd" = (
/obj/structure/table,
/obj/item/storage/crayons,
/obj/item/storage/crayons,
/obj/structure/sign/warning/electricshock{
pixel_y = 32
},
/obj/effect/decal/cleanable/cobweb,
/turf/open/floor/plating{
icon_state = "platingdmg2"
},
/area/security/prison)
"aMe" = (
/obj/structure/table,
/obj/machinery/computer/libraryconsole/bookmanagement,
/obj/structure/cable/white{
icon_state = "1-4"
},
/turf/open/floor/plating,
/turf/open/floor/plasteel,
/area/security/prison)
"aMf" = (
/obj/structure/easel,
@@ -126743,6 +126720,10 @@
dir = 1
},
/area/science/circuit)
"gUV" = (
/obj/item/twohanded/required/kirbyplants/random,
/turf/open/floor/plasteel,
/area/security/prison)
"gVS" = (
/obj/item/clothing/head/kitty,
/obj/item/clothing/under/maid,
@@ -126780,6 +126761,9 @@
dir = 10
},
/area/science/circuit)
"hlc" = (
/turf/open/floor/plasteel,
/area/security/prison)
"hrP" = (
/obj/structure/cable/white{
icon_state = "1-2"
@@ -127397,6 +127381,17 @@
},
/turf/open/floor/plasteel/dark,
/area/science/mixing)
"mvf" = (
/obj/structure/table,
/obj/machinery/computer/libraryconsole/bookmanagement,
/obj/structure/cable/white{
icon_state = "1-2"
},
/obj/structure/cable/white{
icon_state = "2-8"
},
/turf/open/floor/plating,
/area/security/prison)
"mvm" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/cable/white{
@@ -127418,6 +127413,16 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/circuit/green,
/area/science/research/abandoned)
"mEy" = (
/obj/structure/table,
/obj/effect/decal/cleanable/cobweb,
/obj/item/storage/crayons,
/obj/item/storage/crayons,
/obj/structure/cable/white{
icon_state = "4-8"
},
/turf/open/floor/plasteel,
/area/security/prison)
"mIi" = (
/obj/item/electropack/shockcollar,
/obj/item/assembly/signaler,
@@ -127607,6 +127612,13 @@
},
/turf/open/floor/plasteel/dark,
/area/science/mixing)
"oNW" = (
/obj/machinery/vr_sleeper,
/obj/structure/cable/white{
icon_state = "4-8"
},
/turf/open/floor/plasteel,
/area/security/prison)
"oOb" = (
/obj/structure/window/reinforced{
dir = 8
@@ -127710,6 +127722,18 @@
},
/turf/open/floor/plating,
/area/science/research/abandoned)
"pEq" = (
/obj/structure/sign/warning/electricshock{
pixel_y = 32
},
/obj/machinery/vr_sleeper,
/obj/structure/cable/white{
icon_state = "4-8"
},
/turf/open/floor/plating{
icon_state = "platingdmg2"
},
/area/security/prison)
"pHf" = (
/obj/effect/turf_decal/tile/neutral{
dir = 4
@@ -127852,6 +127876,10 @@
},
/turf/open/floor/plasteel,
/area/science/circuit)
"tmZ" = (
/obj/machinery/light/small,
/turf/open/floor/plasteel,
/area/security/prison)
"twt" = (
/obj/machinery/vr_sleeper,
/obj/effect/turf_decal/tile/neutral{
@@ -179430,10 +179458,10 @@ aaa
aaa
aaa
aaa
aaa
ajr
aad
aad
aeH
aFm
aIc
aFm
aFm
aFm
aFm
@@ -179687,10 +179715,10 @@ aaa
aaa
aaa
aaa
aaa
ajr
aaa
aad
aeH
aFm
mEy
bbt
aFm
aMc
aNx
@@ -179944,10 +179972,10 @@ aaa
aaa
aaa
aaa
aaa
aad
aaa
aad
aeH
aFm
oNW
tmZ
aFm
aKV
aNy
@@ -180202,11 +180230,11 @@ aaa
ajr
ajr
aad
aad
aaa
aad
aFm
aMd
pEq
hlc
gUV
hlc
aNz
aPh
aQZ
@@ -180459,10 +180487,10 @@ aaa
ajr
aad
aad
aad
aad
aad
aFn
mvf
aJA
aJA
aMe
aNA
aPi
@@ -180717,7 +180745,7 @@ ajr
aad
aFm
aFm
aIc
aFm
aFm
aFm
aMf
+64 -36
View File
@@ -213,18 +213,12 @@
"aaG" = (
/obj/machinery/hydroponics/constructable,
/obj/item/seeds/ambrosia,
/obj/structure/cable/yellow{
icon_state = "4-8"
},
/turf/open/floor/plasteel,
/area/security/prison)
"aaH" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
},
/obj/structure/cable/yellow{
icon_state = "2-8"
},
/obj/structure/cable/yellow{
icon_state = "2-4"
},
@@ -394,30 +388,16 @@
/obj/item/canvas/twentythreeXtwentythree,
/turf/open/floor/plasteel,
/area/security/prison)
"abk" = (
/obj/structure/table,
/obj/item/folder,
/obj/item/paper/guides/jobs/hydroponics,
/obj/structure/cable/yellow{
icon_state = "1-2"
},
/obj/item/pen,
/obj/item/storage/crayons,
/obj/structure/cable/yellow{
icon_state = "2-8"
},
/turf/open/floor/plasteel,
/area/security/prison)
"abl" = (
/obj/structure/table,
/obj/machinery/computer/libraryconsole/bookmanagement,
/turf/open/floor/plasteel,
/area/security/prison)
"abm" = (
/obj/machinery/computer/arcade,
/obj/machinery/computer/security/telescreen/entertainment{
pixel_y = 32
},
/obj/machinery/vr_sleeper,
/turf/open/floor/plasteel,
/area/security/prison)
"abn" = (
@@ -83303,6 +83283,13 @@
},
/turf/open/floor/plasteel/dark,
/area/crew_quarters/cryopod)
"ghT" = (
/obj/machinery/computer/arcade{
icon_state = "arcade";
dir = 1
},
/turf/open/floor/plasteel,
/area/security/prison)
"gnZ" = (
/obj/item/radio/intercom{
pixel_y = -30
@@ -83417,6 +83404,15 @@
},
/turf/open/floor/plating,
/area/maintenance/port/aft)
"hYs" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
},
/obj/structure/cable/yellow{
icon_state = "2-8"
},
/turf/open/floor/plasteel,
/area/security/prison)
"ioI" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -83528,6 +83524,10 @@
},
/turf/open/floor/plasteel/white,
/area/science/circuit)
"jVj" = (
/obj/machinery/vr_sleeper,
/turf/open/floor/plasteel,
/area/security/prison)
"kfu" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel/white,
@@ -83819,6 +83819,17 @@
},
/turf/open/floor/plasteel/white,
/area/science/circuit)
"odR" = (
/obj/structure/table,
/obj/item/folder,
/obj/item/paper/guides/jobs/hydroponics,
/obj/structure/cable/yellow{
icon_state = "1-2"
},
/obj/item/pen,
/obj/item/storage/crayons,
/turf/open/floor/plasteel,
/area/security/prison)
"ohj" = (
/obj/item/integrated_electronics/analyzer,
/obj/item/integrated_electronics/debugger,
@@ -83924,6 +83935,13 @@
},
/turf/open/floor/plating,
/area/maintenance/port/fore)
"pzu" = (
/obj/structure/chair/stool,
/obj/machinery/light/small{
dir = 4
},
/turf/open/floor/plasteel,
/area/security/prison)
"pCV" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
@@ -84241,6 +84259,16 @@
/obj/machinery/vending/assist,
/turf/open/floor/plasteel,
/area/science/mixing)
"uEa" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
},
/obj/machinery/door/airlock/public/glass{
id_tag = "permahydro";
name = "Recreation Module"
},
/turf/open/floor/plasteel,
/area/security/prison)
"uGW" = (
/obj/effect/turf_decal/stripes/line{
dir = 4
@@ -106416,10 +106444,10 @@ aaa
aaa
aaf
aaa
aaa
aaa
aaf
aaa
aax
aax
aaF
aax
aax
abj
aaR
@@ -106673,12 +106701,12 @@ aaa
aaa
aaf
aaf
aaf
aaf
aaf
aaf
aay
abk
odR
hYs
abC
uEa
hYs
abC
abC
acr
@@ -106930,13 +106958,13 @@ aaa
aaa
aaf
aaa
aaa
aaf
aaa
aaa
aax
abl
abD
pzu
ghT
aax
jVj
aaR
aaR
aaI
acF
@@ -107189,7 +107217,7 @@ aaa
aaa
aax
aax
aaF
aax
aax
aax
abm
+113 -66
View File
@@ -1181,19 +1181,6 @@
},
/turf/open/floor/plasteel/dark,
/area/security/prison)
"aeI" = (
/obj/machinery/seed_extractor,
/obj/machinery/light{
dir = 4
},
/obj/effect/turf_decal/tile/green{
dir = 1
},
/obj/effect/turf_decal/tile/green{
dir = 8
},
/turf/open/floor/plasteel/dark,
/area/security/prison)
"aeJ" = (
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
dir = 8
@@ -1508,24 +1495,13 @@
/turf/open/floor/plasteel/dark,
/area/security/prison)
"afr" = (
/obj/effect/turf_decal/tile/blue{
dir = 8
},
/obj/effect/turf_decal/tile/blue{
dir = 4
},
/obj/machinery/light/small,
/obj/effect/turf_decal/tile/blue{
dir = 4
},
/obj/effect/turf_decal/tile/blue{
dir = 8
},
/turf/open/floor/plasteel/cafeteria,
/area/security/prison)
"afs" = (
/obj/structure/table,
/obj/structure/bedsheetbin,
/obj/effect/turf_decal/tile/blue{
dir = 4
},
/obj/effect/turf_decal/tile/blue{
dir = 8
},
/turf/open/floor/plasteel/cafeteria,
/area/security/prison)
"aft" = (
@@ -52882,6 +52858,19 @@
icon_state = "platingdmg3"
},
/area/maintenance/department/security/brig)
"cJd" = (
/obj/machinery/seed_extractor,
/obj/effect/turf_decal/tile/green{
dir = 1
},
/obj/effect/turf_decal/tile/green{
dir = 8
},
/obj/machinery/light{
dir = 4
},
/turf/open/floor/plasteel/dark,
/area/security/prison)
"cJo" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 5
@@ -53223,6 +53212,21 @@
},
/turf/open/floor/plasteel/dark,
/area/chapel/office)
"dqi" = (
/obj/structure/table,
/obj/structure/bedsheetbin,
/obj/effect/turf_decal/tile/blue{
dir = 4
},
/obj/effect/turf_decal/tile/blue{
dir = 8
},
/obj/structure/window/reinforced,
/obj/machinery/light/small{
dir = 4
},
/turf/open/floor/plasteel/cafeteria,
/area/security/prison)
"dqw" = (
/obj/machinery/door/airlock/maintenance{
req_access_txt = "0";
@@ -55028,6 +55032,15 @@
/obj/item/clothing/glasses/regular,
/turf/open/floor/plating,
/area/maintenance/department/science)
"hyl" = (
/obj/effect/turf_decal/tile/blue{
dir = 8
},
/obj/effect/turf_decal/tile/blue{
dir = 4
},
/turf/open/floor/plasteel/cafeteria,
/area/security/prison)
"hzc" = (
/obj/effect/turf_decal/stripes/line{
dir = 1
@@ -58617,6 +58630,12 @@
},
/turf/open/floor/plasteel/dark,
/area/science/explab)
"pED" = (
/obj/structure/cable{
icon_state = "2-8"
},
/turf/open/floor/plasteel/dark,
/area/security/prison)
"pEL" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 1
@@ -60956,6 +60975,12 @@
},
/turf/open/floor/plating,
/area/maintenance/department/science)
"vtz" = (
/obj/structure/cable{
icon_state = "1-4"
},
/turf/open/floor/plasteel/dark,
/area/security/prison)
"vtT" = (
/turf/open/floor/plating,
/area/maintenance/solars/port)
@@ -62168,6 +62193,19 @@
},
/turf/open/floor/plating,
/area/maintenance/department/engine)
"yff" = (
/obj/machinery/vr_sleeper{
icon_state = "sleeper";
dir = 8
},
/obj/effect/turf_decal/tile/blue{
dir = 8
},
/obj/effect/turf_decal/tile/blue{
dir = 4
},
/turf/open/floor/plasteel/cafeteria,
/area/security/prison)
"yfO" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/effect/turf_decal/tile/yellow,
@@ -62184,6 +62222,15 @@
},
/turf/open/floor/plating,
/area/maintenance/department/cargo)
"yhs" = (
/obj/effect/turf_decal/tile/blue{
dir = 4
},
/obj/effect/turf_decal/tile/blue{
dir = 8
},
/turf/open/floor/plasteel/cafeteria,
/area/security/prison)
"yjy" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/machinery/light{
@@ -81546,8 +81593,8 @@ aaa
aaa
adR
aaa
abI
aaa
aem
aem
aem
aem
aem
@@ -81804,8 +81851,8 @@ aaa
adR
aaa
aem
aem
aem
aeo
aeC
aeT
afn
agy
@@ -82060,9 +82107,9 @@ aaa
aaa
adR
abI
aem
aeo
aeC
aen
aep
aeD
aeU
aeU
afC
@@ -82317,9 +82364,9 @@ aaa
aaa
adR
aaa
aen
aep
aeD
aem
aeq
aeE
aeU
afo
afD
@@ -82574,9 +82621,9 @@ aaa
aaa
adR
abI
aem
aeq
aeE
aen
aer
aeF
aeU
afp
afE
@@ -82831,9 +82878,9 @@ aaa
aaa
adR
aaa
aen
aer
aeF
aem
aes
aeG
aeV
afq
afF
@@ -83088,10 +83135,10 @@ aaa
aaa
adR
abI
aem
aes
aeG
aeU
aen
aet
aeH
vtz
afo
afG
aeU
@@ -83345,10 +83392,10 @@ aaa
aaa
adR
aaa
aen
aet
aeH
aeH
aem
aeu
cJd
pED
aeH
afH
aeH
@@ -83603,8 +83650,8 @@ aaa
adR
abI
aem
aeu
aeI
agy
agy
lGp
aeU
aae
@@ -83860,9 +83907,9 @@ aaa
adR
aaa
aem
aem
aem
aeW
yhs
hyl
afr
agy
agc
@@ -84116,11 +84163,11 @@ aaa
aaa
adR
aaa
abI
aaa
aem
aeX
afs
dqi
yff
yff
agy
agd
agp
@@ -84372,8 +84419,6 @@ aaa
aaa
aaa
aaa
aed
adR
abI
aem
aem
@@ -84385,6 +84430,8 @@ aem
aem
aem
aem
aem
aem
ahL
ahL
ahL
@@ -84630,9 +84677,9 @@ aaa
aaa
aaa
aaa
aaa
aaa
aaa
aed
adR
abI
aaa
aaa
aaa
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
#define FORCE_MAP "_maps/multiz_debug.json"
+6
View File
@@ -0,0 +1,6 @@
{
"map_name": "MultiZ Debug",
"map_path": "map_files/debug",
"map_file": "multiz.dmm",
"traits": [{"Up": 1}, {"Up": 1, "Down": -1}, {"Down": -1}]
}
+177 -176
View File
@@ -2,15 +2,21 @@
"aa" = (
/turf/template_noop,
/area/template_noop)
"ac" = (
/obj/machinery/porta_turret/syndicate{
"ab" = (
/obj/machinery/porta_turret/syndicate/shuttle{
dir = 9
},
/turf/closed/wall/mineral/plastitanium,
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/bridge)
"ac" = (
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/bridge)
"ad" = (
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/bridge)
/obj/machinery/porta_turret/syndicate/shuttle{
dir = 10
},
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/hallway)
"ae" = (
/obj/structure/window/plastitanium,
/obj/machinery/door/poddoor/shutters{
@@ -21,11 +27,8 @@
/turf/open/floor/plating,
/area/shuttle/syndicate/bridge)
"af" = (
/obj/machinery/porta_turret/syndicate{
dir = 5
},
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/bridge)
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/hallway)
"ag" = (
/obj/machinery/computer/med_data/syndie,
/obj/effect/turf_decal/bot_white,
@@ -144,7 +147,7 @@
/area/shuttle/syndicate/bridge)
"au" = (
/obj/machinery/status_display/evac,
/turf/closed/wall/mineral/plastitanium,
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/bridge)
"av" = (
/obj/machinery/door/airlock/hatch{
@@ -164,14 +167,14 @@
/turf/open/floor/plasteel/dark,
/area/shuttle/syndicate/bridge)
"aw" = (
/obj/machinery/porta_turret/syndicate{
dir = 10
/obj/machinery/porta_turret/syndicate/shuttle{
dir = 9
},
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/hallway)
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/eva)
"ax" = (
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/hallway)
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/eva)
"ay" = (
/obj/structure/table/reinforced,
/obj/item/stack/cable_coil/white,
@@ -222,11 +225,8 @@
/turf/open/floor/plasteel/dark,
/area/shuttle/syndicate/hallway)
"aB" = (
/obj/machinery/porta_turret/syndicate{
dir = 6
},
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/hallway)
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/airlock)
"aC" = (
/obj/structure/chair/comfy/shuttle{
dir = 4;
@@ -265,14 +265,17 @@
/turf/open/floor/plasteel/dark,
/area/shuttle/syndicate/hallway)
"aF" = (
/obj/machinery/porta_turret/syndicate{
/obj/machinery/porta_turret/syndicate/shuttle{
dir = 5
},
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/armory)
"aG" = (
/obj/machinery/porta_turret/syndicate/shuttle{
dir = 9
},
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/eva)
"aG" = (
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/eva)
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/medical)
"aH" = (
/obj/structure/chair/comfy/shuttle{
dir = 4;
@@ -314,14 +317,11 @@
/turf/open/floor/plasteel/dark,
/area/shuttle/syndicate/hallway)
"aJ" = (
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/airlock)
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/medical)
"aK" = (
/obj/machinery/porta_turret/syndicate{
dir = 5
},
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/armory)
/turf/closed/wall/r_wall/syndicate/nodiagonal,
/area/shuttle/syndicate/medical)
"aL" = (
/obj/machinery/suit_storage_unit/syndicate,
/obj/effect/turf_decal/stripes/line{
@@ -508,7 +508,7 @@
/obj/structure/sign/warning/vacuum/external{
layer = 4
},
/turf/closed/wall/mineral/plastitanium,
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/airlock)
"be" = (
/obj/machinery/suit_storage_unit/syndicate,
@@ -517,11 +517,6 @@
},
/turf/open/floor/mineral/plastitanium,
/area/shuttle/syndicate/eva)
"bf" = (
/obj/structure/reagent_dispensers/fueltank,
/obj/effect/turf_decal/bot_white,
/turf/open/floor/plasteel/dark,
/area/shuttle/syndicate/eva)
"bg" = (
/obj/structure/grille,
/obj/structure/window/plastitanium,
@@ -543,31 +538,28 @@
/turf/open/floor/mineral/plastitanium/red,
/area/shuttle/syndicate/airlock)
"bj" = (
/obj/machinery/porta_turret/syndicate{
dir = 9
},
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/medical)
/turf/closed/wall/r_wall/syndicate/nodiagonal,
/area/shuttle/syndicate/armory)
"bk" = (
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/medical)
"bl" = (
/obj/machinery/status_display/ai,
/turf/closed/wall/mineral/plastitanium,
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/medical)
"bm" = (
/turf/closed/wall/mineral/plastitanium/nodiagonal,
/area/shuttle/syndicate/medical)
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/armory)
"bn" = (
/turf/closed/wall/mineral/plastitanium/nodiagonal,
/obj/machinery/status_display/evac,
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/armory)
"bo" = (
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/armory)
"bp" = (
/obj/machinery/status_display/evac,
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/armory)
/obj/machinery/nuclearbomb/syndicate{
anchored = 1
},
/obj/machinery/door/window{
dir = 1
},
/turf/open/floor/circuit/red,
/area/shuttle/syndicate/hallway)
"bq" = (
/obj/machinery/sleeper/syndie{
dir = 4
@@ -1043,14 +1035,6 @@
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/shuttle/syndicate/hallway)
"cm" = (
/obj/machinery/nuclearbomb/syndicate,
/obj/machinery/door/window{
dir = 1;
name = "Theatre Stage"
},
/turf/open/floor/circuit/red,
/area/shuttle/syndicate/hallway)
"cn" = (
/obj/machinery/light{
dir = 4
@@ -1169,18 +1153,6 @@
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/plating/airless,
/area/shuttle/syndicate/medical)
"cC" = (
/obj/machinery/porta_turret/syndicate{
dir = 6
},
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/medical)
"cD" = (
/obj/machinery/porta_turret/syndicate{
dir = 10
},
/turf/closed/wall/mineral/plastitanium,
/area/shuttle/syndicate/armory)
"cE" = (
/obj/structure/shuttle/engine/propulsion/left,
/obj/effect/turf_decal/stripes/line,
@@ -1196,6 +1168,35 @@
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/plating/airless,
/area/shuttle/syndicate/armory)
"dp" = (
/obj/machinery/porta_turret/syndicate/shuttle{
dir = 10
},
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/armory)
"pd" = (
/obj/machinery/porta_turret/syndicate/shuttle{
dir = 5
},
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/bridge)
"vv" = (
/obj/structure/reagent_dispensers/fueltank,
/obj/effect/turf_decal/bot_white,
/turf/open/floor/plasteel/dark,
/area/shuttle/syndicate/eva)
"In" = (
/obj/machinery/porta_turret/syndicate/shuttle{
dir = 6
},
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/hallway)
"MJ" = (
/obj/machinery/porta_turret/syndicate/shuttle{
dir = 6
},
/turf/closed/wall/r_wall/syndicate,
/area/shuttle/syndicate/medical)
(1,1,1) = {"
aa
@@ -1211,16 +1212,16 @@ aa
aa
aa
aa
bj
bk
bk
bk
bk
bk
bk
bk
bk
bk
aG
aJ
aJ
aJ
aJ
aJ
aJ
aJ
aJ
aJ
"}
(2,1,1) = {"
aa
@@ -1230,13 +1231,13 @@ aa
aa
aa
aa
aF
aG
aG
aG
aG
aG
bk
aw
ax
ax
ax
ax
ax
aJ
bq
bC
bq
@@ -1255,13 +1256,13 @@ aa
aa
aa
aa
aG
ax
aL
aR
aR
aR
be
bk
aJ
br
bD
bH
@@ -1280,13 +1281,13 @@ aa
aa
aa
aa
aG
ax
aM
aM
aM
aM
aM
bl
bk
bs
bD
bI
@@ -1298,51 +1299,51 @@ cu
cB
"}
(5,1,1) = {"
ab
ac
ac
ac
ac
ad
ad
ad
ad
aa
aa
aG
ax
aM
aM
aM
aM
aM
bk
aJ
bt
bD
bJ
bT
cb
bm
bk
bk
cC
aK
aJ
aJ
MJ
"}
(6,1,1) = {"
ad
ac
ag
an
at
ac
ad
aw
aa
aG
ax
aN
aS
aU
aZ
bf
bk
vv
aJ
bu
bD
bJ
bT
cc
bk
aJ
aa
aa
aa
@@ -1352,24 +1353,24 @@ ae
ah
ao
at
ad
ac
af
af
ax
ax
ax
ax
aG
aG
aG
aG
ba
bg
bm
aK
bv
bv
bK
bv
bk
bk
ax
ax
aJ
aJ
af
af
aa
"}
(8,1,1) = {"
@@ -1417,7 +1418,7 @@ aD
bL
bU
az
cm
bo
cr
cw
aa
@@ -1427,7 +1428,7 @@ ae
ak
ap
at
ad
ac
aA
aE
aI
@@ -1452,75 +1453,75 @@ ae
al
ar
at
ad
ax
ax
ax
ax
aJ
aJ
ac
af
af
af
af
aB
aB
bb
bh
bn
bj
bw
bw
bM
bw
bo
bo
ax
ax
bm
bm
af
af
aa
"}
(12,1,1) = {"
ad
ac
am
as
at
ad
aB
ac
In
aa
aJ
aB
aO
aO
aX
bc
aO
bo
bm
bx
bG
bN
bV
ce
bo
bm
aa
aa
aa
"}
(13,1,1) = {"
af
ad
ad
ad
ad
pd
ac
ac
ac
ac
aa
aa
aJ
aB
aP
aP
aP
aP
aP
bo
bm
by
bG
bN
bV
cf
bn
bo
bo
cD
bj
bm
bm
dp
"}
(14,1,1) = {"
aa
@@ -1530,13 +1531,13 @@ aa
aa
aa
aa
aJ
aB
aP
aP
aP
aP
aP
bp
bn
bz
bG
bO
@@ -1555,13 +1556,13 @@ aa
aa
aa
aa
aJ
aB
aQ
aT
aT
aT
bi
bo
bm
bA
bG
bP
@@ -1580,13 +1581,13 @@ aa
aa
aa
aa
aK
aJ
aJ
aF
aB
aB
aY
bd
aJ
bo
aB
bm
bB
bG
bQ
@@ -1611,14 +1612,14 @@ aa
aa
aa
aa
aK
bo
bo
bo
bo
bo
bo
bo
bo
bo
aF
bm
bm
bm
bm
bm
bm
bm
bm
bm
"}
+10 -10
View File
@@ -2,12 +2,12 @@
#define MC_SPLIT_TICK_INIT(phase_count) var/original_tick_limit = Master.current_ticklimit; var/split_tick_phases = ##phase_count
#define MC_SPLIT_TICK \
if(split_tick_phases > 1){\
Master.current_ticklimit = ((original_tick_limit - TICK_USAGE) / split_tick_phases) + TICK_USAGE;\
--split_tick_phases;\
} else {\
Master.current_ticklimit = original_tick_limit;\
}
if(split_tick_phases > 1){\
Master.current_ticklimit = ((original_tick_limit - TICK_USAGE) / split_tick_phases) + TICK_USAGE;\
--split_tick_phases;\
} else {\
Master.current_ticklimit = original_tick_limit;\
}
// Used to smooth out costs to try and avoid oscillation.
#define MC_AVERAGE_FAST(average, current) (0.7 * (average) + 0.3 * (current))
@@ -65,14 +65,14 @@
#define SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/##X);\
/datum/controller/subsystem/##X/New(){\
NEW_SS_GLOBAL(SS##X);\
PreInit();\
NEW_SS_GLOBAL(SS##X);\
PreInit();\
}\
/datum/controller/subsystem/##X
#define PROCESSING_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/processing/##X);\
/datum/controller/subsystem/processing/##X/New(){\
NEW_SS_GLOBAL(SS##X);\
PreInit();\
NEW_SS_GLOBAL(SS##X);\
PreInit();\
}\
/datum/controller/subsystem/processing/##X
+10 -4
View File
@@ -3,8 +3,8 @@
//Creates a global initializer with a given InitValue expression, do not use
#define GLOBAL_MANAGED(X, InitValue)\
/datum/controller/global_vars/proc/InitGlobal##X(){\
##X = ##InitValue;\
gvars_datum_init_order += #X;\
##X = ##InitValue;\
gvars_datum_init_order += #X;\
}
//Creates an empty global initializer, do not use
#define GLOBAL_UNMANAGED(X) /datum/controller/global_vars/proc/InitGlobal##X() { return; }
@@ -13,8 +13,8 @@
#ifndef TESTING
#define GLOBAL_PROTECT(X)\
/datum/controller/global_vars/InitGlobal##X(){\
..();\
gvars_datum_protected_varlist[#X] = TRUE;\
..();\
gvars_datum_protected_varlist[#X] = TRUE;\
}
#else
#define GLOBAL_PROTECT(X)
@@ -41,6 +41,12 @@
//Create a list global that is initialized as an empty list
#define GLOBAL_LIST_EMPTY(X) GLOBAL_LIST_INIT(X, list())
// Create a typed list global with an initializer expression
#define GLOBAL_LIST_INIT_TYPED(X, Typepath, InitValue) GLOBAL_RAW(/list##Typepath/X); GLOBAL_MANAGED(X, InitValue)
// Create a typed list global that is initialized as an empty list
#define GLOBAL_LIST_EMPTY_TYPED(X, Typepath) GLOBAL_LIST_INIT_TYPED(X, Typepath, list())
//Create a typed global with an initializer expression
#define GLOBAL_DATUM_INIT(X, Typepath, InitValue) GLOBAL_RAW(Typepath/##X); GLOBAL_MANAGED(X, InitValue)
+3 -3
View File
@@ -1,10 +1,10 @@
#define GENERAL_PROTECT_DATUM(Path)\
##Path/can_vv_get(var_name){\
return FALSE;\
return FALSE;\
}\
##Path/vv_edit_var(var_name, var_value){\
return FALSE;\
return FALSE;\
}\
##Path/CanProcCall(procname){\
return FALSE;\
return FALSE;\
}
+24 -1
View File
@@ -143,8 +143,24 @@
#define ATMOS_PASS_NO 0
#define ATMOS_PASS_PROC -1 //ask CanAtmosPass()
#define ATMOS_PASS_DENSITY -2 //just check density
#define CANATMOSPASS(A, O) ( A.CanAtmosPass == ATMOS_PASS_PROC ? A.CanAtmosPass(O) : ( A.CanAtmosPass == ATMOS_PASS_DENSITY ? !A.density : A.CanAtmosPass ) )
#define CANATMOSPASS(A, O) ( A.CanAtmosPass == ATMOS_PASS_PROC ? A.CanAtmosPass(O) : ( A.CanAtmosPass == ATMOS_PASS_DENSITY ? !A.density : A.CanAtmosPass ) )
#define CANVERTICALATMOSPASS(A, O) ( A.CanAtmosPassVertical == ATMOS_PASS_PROC ? A.CanAtmosPass(O, TRUE) : ( A.CanAtmosPassVertical == ATMOS_PASS_DENSITY ? !A.density : A.CanAtmosPassVertical ) )
//OPEN TURF ATMOS
#define OPENTURF_DEFAULT_ATMOS "o2=22;n2=82;TEMP=293.15" //the default air mix that open turfs spawn
#define TCOMMS_ATMOS "n2=100;TEMP=80" //-193,15°C telecommunications. also used for xenobiology slime killrooms
#define AIRLESS_ATMOS "TEMP=2.7" //space
#define FROZEN_ATMOS "o2=22;n2=82;TEMP=180" //-93.15°C snow and ice turfs
#define BURNMIX_ATMOS "o2=2500;plasma=5000;TEMP=370" //used in the holodeck burn test program
//ATMOSPHERICS DEPARTMENT GAS TANK TURFS
#define ATMOS_TANK_N2O "n2o=6000;TEMP=293.15"
#define ATMOS_TANK_CO2 "co2=50000;TEMP=293.15"
#define ATMOS_TANK_PLASMA "plasma=70000;TEMP=293.15"
#define ATMOS_TANK_O2 "o2=100000;TEMP=293.15"
#define ATMOS_TANK_N2 "n2=100000;TEMP=293.15"
#define ATMOS_TANK_AIRMIX "o2=2644;n2=10580;TEMP=293.15"
//LAVALAND
#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland
#define LAVALAND_DEFAULT_ATMOS "o2=14;n2=23;TEMP=300"
@@ -249,6 +265,13 @@
out_var += cached_gases[total_moles_id];\
}
#ifdef TESTING
GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0))
#define CALCULATE_ADJACENT_TURFS(T) if (SSadjacent_air.queue[T]) { GLOB.atmos_adjacent_savings[1] += 1 } else { GLOB.atmos_adjacent_savings[2] += 1; SSadjacent_air.queue[T] = 1 }
#else
#define CALCULATE_ADJACENT_TURFS(T) SSadjacent_air.queue[T] = 1
#endif
//Unomos - So for whatever reason, garbage collection actually drastically decreases the cost of atmos later in the round. Turning this into a define yields massively improved performance.
#define GAS_GARBAGE_COLLECT(GASGASGAS)\
var/list/CACHE_GAS = GASGASGAS;\
+13 -13
View File
@@ -17,17 +17,17 @@
#define POD_DESC 3
#define POD_STYLES list(\
list("supplypod", "supply pod", "A Nanotrasen supply drop pod."),\
list("bluespacepod", "bluespace supply pod" , "A Nanotrasen Bluespace supply pod. Teleports back to CentCom after delivery."),\
list("centcompod", "\improper Centcom supply pod", "A Nanotrasen supply pod, this one has been marked with Central Command's designations. Teleports back to Centcom after delivery."),\
list("syndiepod", "blood-red supply pod", "A dark, intimidating supply pod, covered in the blood-red markings of the Syndicate. It's probably best to stand back from this."),\
list("squadpod", "\improper MK. II supply pod", "A Nanotrasen supply pod. This one has been marked the markings of some sort of elite strike team."),\
list("cultpod", "bloody supply pod", "A Nanotrasen supply pod covered in scratch-marks, blood, and strange runes."),\
list("missilepod", "cruise missile", "A big ass missile that didn't seem to fully detonate. It was likely launched from some far-off deep space missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
list("smissilepod", "\improper Syndicate cruise missile", "A big ass, blood-red missile that didn't seem to fully detonate. It was likely launched from some deep space Syndicate missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
list("boxpod", "\improper Aussec supply crate", "An incredibly sturdy supply crate, designed to withstand orbital re-entry. Has 'Aussec Armory - 2532' engraved on the side."),\
list("honkpod", "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\
list("fruitpod", "\improper Orange", "An angry orange."),\
list("", "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\
list("gondolapod", "gondola", "The silent walker. This one seems to be part of a delivery agency.")\
list("supplypod", "supply pod", "A Nanotrasen supply drop pod."),\
list("bluespacepod", "bluespace supply pod" , "A Nanotrasen Bluespace supply pod. Teleports back to CentCom after delivery."),\
list("centcompod", "\improper Centcom supply pod", "A Nanotrasen supply pod, this one has been marked with Central Command's designations. Teleports back to Centcom after delivery."),\
list("syndiepod", "blood-red supply pod", "A dark, intimidating supply pod, covered in the blood-red markings of the Syndicate. It's probably best to stand back from this."),\
list("squadpod", "\improper MK. II supply pod", "A Nanotrasen supply pod. This one has been marked the markings of some sort of elite strike team."),\
list("cultpod", "bloody supply pod", "A Nanotrasen supply pod covered in scratch-marks, blood, and strange runes."),\
list("missilepod", "cruise missile", "A big ass missile that didn't seem to fully detonate. It was likely launched from some far-off deep space missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
list("smissilepod", "\improper Syndicate cruise missile", "A big ass, blood-red missile that didn't seem to fully detonate. It was likely launched from some deep space Syndicate missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
list("boxpod", "\improper Aussec supply crate", "An incredibly sturdy supply crate, designed to withstand orbital re-entry. Has 'Aussec Armory - 2532' engraved on the side."),\
list("honkpod", "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\
list("fruitpod", "\improper Orange", "An angry orange."),\
list("", "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\
list("gondolapod", "gondola", "The silent walker. This one seems to be part of a delivery agency.")\
)
+11 -1
View File
@@ -72,11 +72,16 @@
#define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" //from base of atom/screwdriver_act(): (mob/living/user, obj/item/I)
#define COMSIG_ATOM_INTERCEPT_TELEPORT "intercept_teleport" //called when teleporting into a protected turf: (channel, turf/origin, turf/destination)
#define COMPONENT_BLOCK_TELEPORT 1
#define COMSIG_ATOM_HEARER_IN_VIEW "atom_hearer_in_view" //called when an atom with HEAR_1 is added to the hearers on /proc/get_hearers_in_view(): (list/processing_list, list/hearers)
/////////////////
#define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost" //from base of atom/attack_ghost(): (mob/dead/observer/ghost)
#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand" //from base of atom/attack_hand(): (mob/user)
#define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw" //from base of atom/attack_paw(): (mob/user)
#define COMPONENT_NO_ATTACK_HAND 1 //works on all 3.
//This signal return value bitflags can be found in __DEFINES/misc.dm
#define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact" //called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels)
/////////////////
#define COMSIG_ENTER_AREA "enter_area" //from base of area/Entered(): (/area)
@@ -98,6 +103,7 @@
// /turf signals
#define COMSIG_TURF_CHANGE "turf_change" //from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/transferring_comps)
#define COMSIG_TURF_HAS_GRAVITY "turf_has_gravity" //from base of atom/has_gravity(): (atom/asker, list/forced_gravities)
#define COMSIG_TURF_MULTIZ_NEW "turf_multiz_new" //from base of turf/New(): (turf/source, direction)
// /atom/movable signals
#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir)
@@ -123,8 +129,10 @@
#define COMSIG_MIND_TRANSFER "mind_transfer" //from base of mind/transfer_to(): (new_character, old_character)
// /mob signals
#define COMSIG_MOB_EXAMINATE "mob_examinate" //from base of /mob/verb/examinate(): (atom/A)
#define COMPONENT_ALLOW_EXAMINE 1
#define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed)
#define COMSIG_MOB_GHOSTIZE "mob_ghostize" //from base of mob/Ghostize() (can_reenter_corpse)
#define COMSIG_MOB_GHOSTIZE "mob_ghostize" //from base of mob/Ghostize(): (can_reenter_corpse)
#define COMPONENT_BLOCK_GHOSTING 1
#define COMSIG_MOB_ALLOWED "mob_allowed" //from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
@@ -149,6 +157,8 @@
#define SPEECH_FORCED 7 */
// /mob/living signals
#define COMSIG_LIVING_FULLY_HEAL "living_fully_healed" //from base of /mob/living/fully_heal(): (admin_revive)
#define COMSIG_LIVING_REGENERATE_LIMBS "living_regenerate_limbs" //from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs)
#define COMSIG_LIVING_RESIST "living_resist" //from base of mob/living/resist() (/mob/living)
#define COMSIG_LIVING_IGNITED "living_ignite" //from base of mob/living/IgniteMob() (/mob/living)
#define COMSIG_LIVING_EXTINGUISHED "living_extinguished" //from base of mob/living/ExtinguishMob() (/mob/living)
+6 -6
View File
@@ -1,10 +1,10 @@
#define DONATOR_GROUP_TIER_1_CONFIG_PATH /datum/config_entry/keyed_list/donator_group/tier_1_donators
#define DONATOR_GROUP_TIER_2_CONFIG_PATH /datum/config_entry/keyed_list/donator_group/tier_2_donators
#define DONATOR_GROUP_TIER_3_CONFIG_PATH /datum/config_entry/keyed_list/donator_group/tier_3_donators
#define DONATOR_GROUP_TIER_1_CONFIG_PATH /datum/config_entry/multi_keyed_flag/donator_group/tier_1_donators
#define DONATOR_GROUP_TIER_2_CONFIG_PATH /datum/config_entry/multi_keyed_flag/donator_group/tier_2_donators
#define DONATOR_GROUP_TIER_3_CONFIG_PATH /datum/config_entry/multi_keyed_flag/donator_group/tier_3_donators
#define DONATOR_GROUP_TIER_1_CONFIG_SUBPATH keyed_list/donator_group/tier_1_donators
#define DONATOR_GROUP_TIER_2_CONFIG_SUBPATH keyed_list/donator_group/tier_2_donators
#define DONATOR_GROUP_TIER_3_CONFIG_SUBPATH keyed_list/donator_group/tier_3_donators
#define DONATOR_GROUP_TIER_1_CONFIG_SUBPATH multi_keyed_flag/donator_group/tier_1_donators
#define DONATOR_GROUP_TIER_2_CONFIG_SUBPATH multi_keyed_flag/donator_group/tier_2_donators
#define DONATOR_GROUP_TIER_3_CONFIG_SUBPATH multi_keyed_flag/donator_group/tier_3_donators
#define TIER_1_DONATORS CONFIG_GET(DONATOR_GROUP_TIER_1_CONFIG_SUBPATH)
#define TIER_2_DONATORS CONFIG_GET(DONATOR_GROUP_TIER_2_CONFIG_SUBPATH)
+13
View File
@@ -9,6 +9,16 @@
//Turfs
//#define isturf(A) (istype(A, /turf)) This is actually a byond built-in. Added here for completeness sake.
GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
/turf/open/space,
/turf/open/chasm,
/turf/open/lava,
/turf/open/water,
/turf/open/openspace
)))
#define isgroundlessturf(A) (is_type_in_typecache(A, GLOB.turfs_without_ground))
#define isopenturf(A) (istype(A, /turf/open))
#define isindestructiblefloor(A) (istype(A, /turf/open/indestructible))
@@ -56,6 +66,7 @@
#define ishumanbasic(A) (is_species(A, /datum/species/human))
#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) )
#define isdwarf(A) (is_species(A, /datum/species/dwarf))
#define isdullahan(A) (is_species(A, /datum/species/dullahan))
// Citadel specific species
#define isipcperson(A) (is_species(A, /datum/species/ipc))
@@ -199,6 +210,8 @@ GLOBAL_LIST_INIT(heavyfootmob, typecacheof(list(
#define isitem(A) (istype(A, /obj/item))
#define isidcard(I) (istype(I, /obj/item/card/id))
#define isstructure(A) (istype(A, /obj/structure))
#define ismachinery(A) (istype(A, /obj/machinery))
+21 -17
View File
@@ -9,6 +9,7 @@
#define FLOOR_PLANE -2
#define GAME_PLANE -1
#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals
#define SPACE_LAYER 1.8
//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
#define MID_TURF_LAYER 2.02
@@ -83,25 +84,28 @@
#define ABOVE_LIGHTING_PLANE 16
#define ABOVE_LIGHTING_LAYER 16
#define BYOND_LIGHTING_PLANE 17
#define BYOND_LIGHTING_LAYER 17
#define FLOOR_OPENSPACE_PLANE 17
#define OPENSPACE_LAYER 17
#define CAMERA_STATIC_PLANE 18
#define CAMERA_STATIC_LAYER 18
#define BYOND_LIGHTING_PLANE 18
#define BYOND_LIGHTING_LAYER 18
#define CAMERA_STATIC_PLANE 19
#define CAMERA_STATIC_LAYER 19
//HUD layer defines
#define FULLSCREEN_PLANE 19
#define FLASH_LAYER 19
#define FULLSCREEN_LAYER 19.1
#define UI_DAMAGE_LAYER 19.2
#define BLIND_LAYER 19.3
#define CRIT_LAYER 19.4
#define CURSE_LAYER 19.5
#define FULLSCREEN_PLANE 20
#define FLASH_LAYER 20
#define FULLSCREEN_LAYER 20.1
#define UI_DAMAGE_LAYER 20.2
#define BLIND_LAYER 20.3
#define CRIT_LAYER 20.4
#define CURSE_LAYER 20.5
#define HUD_PLANE 20
#define HUD_LAYER 20
#define ABOVE_HUD_PLANE 21
#define ABOVE_HUD_LAYER 21
#define HUD_PLANE 21
#define HUD_LAYER 21
#define ABOVE_HUD_PLANE 22
#define ABOVE_HUD_LAYER 22
#define SPLASHSCREEN_LAYER 22
#define SPLASHSCREEN_PLANE 22
#define SPLASHSCREEN_LAYER 23
#define SPLASHSCREEN_PLANE 23
+2 -1
View File
@@ -30,7 +30,8 @@
#define LIMBGROWER (1<<6) //Uses synthetic flesh
#define SMELTER (1<<7) //uses various minerals
#define AUTOYLATHE (1<<8) // CITADEL ADD
#define NANITE_COMPILER (1<<9) //Prints nanite disks
#define NANITE_COMPILER (1<<9) //Prints nanite disks
#define AUTOBOTTLER (1<<10) //Uses booze, for printing
//Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable.
//Modular computer/NTNet defines
+14 -13
View File
@@ -37,6 +37,7 @@ require only minor tweaks.
#define ZTRAIT_AWAY "Away Mission"
#define ZTRAIT_SPACE_RUINS "Space Ruins"
#define ZTRAIT_LAVA_RUINS "Lava Ruins"
#define ZTRAIT_ISOLATED_RUINS "Isolated Ruins" //Placing ruins on z levels with this trait will use turf reservation instead of usual placement.
// prevents certain turfs from being stripped by a singularity
#define ZTRAIT_PLANET "Planet"
@@ -52,12 +53,12 @@ require only minor tweaks.
// enum - how space transitions should affect this level
#define ZTRAIT_LINKAGE "Linkage"
// UNAFFECTED if absent - no space transitions
#define UNAFFECTED null
// SELFLOOPING - space transitions always self-loop
#define SELFLOOPING "Self"
// CROSSLINKED - mixed in with the cross-linked space pool
#define CROSSLINKED "Cross"
// UNAFFECTED if absent - no space transitions
#define UNAFFECTED null
// SELFLOOPING - space transitions always self-loop
#define SELFLOOPING "Self"
// CROSSLINKED - mixed in with the cross-linked space pool
#define CROSSLINKED "Cross"
// default trait definitions, used by SSmapping
#define ZTRAITS_CENTCOM list(ZTRAIT_CENTCOM = TRUE)
@@ -72,7 +73,7 @@ require only minor tweaks.
// must correspond to _basemap.dm for things to work correctly
#define DEFAULT_MAP_TRAITS list(\
DECLARE_LEVEL("CentCom", ZTRAITS_CENTCOM),\
DECLARE_LEVEL("CentCom", ZTRAITS_CENTCOM),\
)
// Camera lock flags
@@ -89,10 +90,10 @@ require only minor tweaks.
#define PLACEMENT_TRIES 100 //How many times we try to fit the ruin somewhere until giving up (really should just swap to some packing algo)
#define PLACE_DEFAULT "random"
#define PLACE_SAME_Z "same"
#define PLACE_SPACE_RUIN "space"
#define PLACE_LAVA_RUIN "lavaland"
#define PLACE_SAME_Z "same" //On same z level as original ruin
#define PLACE_SPACE_RUIN "space" //On space ruin z level(s)
#define PLACE_LAVA_RUIN "lavaland" //On lavaland ruin z levels(s)
#define PLACE_BELOW "below" //On z levl below - centered on same tile
#define PLACE_ISOLATED "isolated" //On isolated ruin z level
//Map type stuff.
#define MAP_TYPE_STATION "station"
#define MAP_TYPE_STATION "station"
+21 -6
View File
@@ -203,11 +203,12 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)
#define LOCKED_SENSORS 2
//Wet floor type flags. Stronger ones should be higher in number.
#define TURF_DRY 0
#define TURF_WET_WATER 1
#define TURF_WET_PERMAFROST 2
#define TURF_WET_ICE 4
#define TURF_WET_LUBE 8
#define TURF_DRY (0)
#define TURF_WET_WATER (1<<0)
#define TURF_WET_PERMAFROST (1<<1)
#define TURF_WET_ICE (1<<2)
#define TURF_WET_LUBE (1<<3)
#define TURF_WET_SUPERLUBE (1<<4)
#define IS_WET_OPEN_TURF(O) O.GetComponent(/datum/component/wet_floor)
@@ -281,9 +282,11 @@ GLOBAL_LIST_INIT(pda_styles, list(MONO, VT, ORBITRON, SHARE))
#define PDA_SKIN_ALT "Holographic"
#define PDA_SKIN_RUGGED "Rugged"
#define PDA_SKIN_MODERN "Modern"
#define PDA_SKIN_MINIMAL "Minimal"
GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_SKIN_ALT = 'icons/obj/pda_alt.dmi',
PDA_SKIN_RUGGED = 'icons/obj/pda_rugged.dmi', PDA_SKIN_MODERN = 'icons/obj/pda_modern.dmi'))
PDA_SKIN_RUGGED = 'icons/obj/pda_rugged.dmi', PDA_SKIN_MODERN = 'icons/obj/pda_modern.dmi',
PDA_SKIN_MINIMAL = 'icons/obj/pda_minimal.dmi'))
/////////////////////////////////////
// atom.appearence_flags shortcuts //
@@ -506,10 +509,22 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define AREASELECT_CORNERA "corner A"
#define AREASELECT_CORNERB "corner B"
#define VARSET_FROM_LIST(L, V) if(L && L[#V]) V = L[#V]
#define VARSET_FROM_LIST_IF(L, V, C...) if(L && L[#V] && (C)) V = L[#V]
#define VARSET_TO_LIST(L, V) if(L) L[#V] = V
#define VARSET_TO_LIST_IF(L, V, C...) if(L && (C)) L[#V] = V
#define PREF_SAVELOAD_COOLDOWN 5
#define VOMIT_TOXIC 1
#define VOMIT_PURPLE 2
// possible bitflag return values of intercept_zImpact(atom/movable/AM, levels = 1) calls
#define FALL_INTERCEPTED (1<<0) //Stops the movable from falling further and crashing on the ground
#define FALL_NO_MESSAGE (1<<1) //Used to suppress the "[A] falls through [old_turf]" messages where it'd make little sense at all, like going downstairs.
#define FALL_STOP_INTERCEPTING (1<<2) //Used in situations where halting the whole "intercept" loop would be better, like supermatter dusting (and thus deleting) the atom.
//Misc text define. Does 4 spaces. Used as a makeshift tabulator.
#define FOURSPACES "&nbsp;&nbsp;&nbsp;&nbsp;"
#define CRYOMOBS 'icons/obj/cryo_mobs.dmi'
+2
View File
@@ -201,6 +201,8 @@
#define SLIDE (1<<1)
#define GALOSHES_DONT_HELP (1<<2)
#define SLIDE_ICE (1<<3)
#define SLIP_WHEN_CRAWLING (1<<4) //clown planet ruin
#define SLIP_WHEN_JOGGING (1<<5) //slips prevented by walking are also dodged if the mob is not sprinting or fatigued... unless this flag is on.
#define MAX_CHICKENS 50
+1
View File
@@ -11,6 +11,7 @@
#define USES_TGUI (1<<7) //put on things that use tgui on ui_interact instead of custom/old UI.
#define FROZEN (1<<8)
#define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
#define BLOCK_Z_FALL (1<<10)
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
+7
View File
@@ -75,3 +75,10 @@
#define JP_LOW 1
#define JP_MEDIUM 2
#define JP_HIGH 3
//Chaos levels for dynamic voting
#define CHAOS_NONE "None (Extended)"
#define CHAOS_LOW "Low"
#define CHAOS_MED "Medium"
#define CHAOS_HIGH "High"
#define CHAOS_MAX "Maximum"
+24
View File
@@ -0,0 +1,24 @@
/// Represents a proc or verb path.
///
/// Despite having no DM-defined static type, proc paths have some variables,
/// listed below. These are not modifiable, but for a given procpath P,
/// `new P(null, "Name", "Desc")` can be used to create a new procpath with the
/// same code but new `name` and `desc` values. The other variables cannot be
/// changed in this way.
///
/// This type exists only to act as an annotation, providing reasonable static
/// typing for procpaths. Previously, types like `/atom/verb` were used, with
/// the `name` and `desc` vars of `/atom` thus being accessible. Proc and verb
/// paths will fail `istype` and `ispath` checks against `/procpath`.
/procpath
// Although these variables are effectively const, if they are marked const
// below, their accesses are optimized away.
/// A text string of the verb's name.
var/name as text
/// The verb's help text or description.
var/desc as text
/// The category or tab the verb will appear in.
var/category as text
/// Only clients/mobs with `see_invisibility` higher can use the verb.
var/invisibility as num
+13
View File
@@ -0,0 +1,13 @@
// Interfaces for the SpacemanDMM linter, define'd to nothing when the linter
// is not in use.
// The SPACEMAN_DMM define is set by the linter and other tooling when it runs.
#ifdef SPACEMAN_DMM
#define RETURN_TYPE(X) set SpacemanDMM_return_type = X
#define SHOULD_CALL_PARENT(X) set SpacemanDMM_should_call_parent = X
#define UNLINT(X) SpacemanDMM_unlint(X)
#else
#define RETURN_TYPE(X)
#define SHOULD_CALL_PARENT(X)
#define UNLINT(X) X
#endif
+6 -10
View File
@@ -26,10 +26,6 @@
#define TIMER_ID_NULL -1
//For servers that can't do with any additional lag, set this to none in flightpacks.dm in subsystem/processing.
#define FLIGHTSUIT_PROCESSING_NONE 0
#define FLIGHTSUIT_PROCESSING_FULL 1
#define INITIALIZATION_INSSATOMS 0 //New should not call Initialize
#define INITIALIZATION_INNEW_MAPLOAD 2 //New should call Initialize(TRUE)
#define INITIALIZATION_INNEW_REGULAR 1 //New should call Initialize(FALSE)
@@ -40,11 +36,11 @@
//type and all subtypes should always call Initialize in New()
#define INITIALIZE_IMMEDIATE(X) ##X/New(loc, ...){\
..();\
if(!(flags_1 & INITIALIZED_1)) {\
args[1] = TRUE;\
SSatoms.InitAtom(src, args);\
}\
..();\
if(!(flags_1 & INITIALIZED_1)) {\
args[1] = TRUE;\
SSatoms.InitAtom(src, args);\
}\
}
// Subsystem init_order, from highest priority to lowest priority
@@ -112,10 +108,10 @@
#define FIRE_PRIORITY_DEFAULT 50
#define FIRE_PRIORITY_PARALLAX 65
#define FIRE_PRIORITY_NPC 80
#define FIRE_PRIORITY_FLIGHTPACKS 80
#define FIRE_PRIORITY_MOBS 100
#define FIRE_PRIORITY_TGUI 110
#define FIRE_PRIORITY_TICKER 200
#define FIRE_PRIORITY_ATMOS_ADJACENCY 300
#define FIRE_PRIORITY_CHAT 400
#define FIRE_PRIORITY_OVERLAYS 500
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
+2 -2
View File
@@ -192,7 +192,6 @@
#define STASIS_MUTE "stasis"
#define GENETICS_SPELL "genetics_spell"
#define EYES_COVERED "eyes_covered"
#define CULT_TRAIT "cult"
#define CLOWN_NUKE_TRAIT "clown-nuke"
#define STICKY_MOUSTACHE_TRAIT "sticky-moustache"
#define CHAINSAW_FRENZY_TRAIT "chainsaw-frenzy"
@@ -213,4 +212,5 @@
#define LOCKED_HELMET_TRAIT "locked-helmet"
#define NINJA_SUIT_TRAIT "ninja-suit"
#define ANTI_DROP_IMPLANT_TRAIT "anti-drop-implant"
#define ABDUCTOR_ANTAGONIST "abductor-antagonist"
#define ABDUCTOR_ANTAGONIST "abductor-antagonist"
#define MADE_UNCLONEABLE "made-uncloneable"
+1
View File
@@ -3,3 +3,4 @@
#define CHANGETURF_FORCEOP 4
#define CHANGETURF_SKIP 8 // A flag for PlaceOnTop to just instance the new turf instead of calling ChangeTurf. Used for uninitialized turfs NOTHING ELSE
#define CHANGETURF_INHERIT_AIR 16 // Inherit air from previous turf. Implies CHANGETURF_IGNORE_AIR
#define CHANGETURF_RECALC_ADJACENT 32 //Immediately recalc adjacent atmos turfs instead of queuing.
+1 -1
View File
@@ -2,7 +2,7 @@
#define TYPEID_NULL "0"
#define TYPEID_NORMAL_LIST "f"
//helper macros
#define GET_TYPEID(ref) ( ( (lentext(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, lentext(ref)-6) ) )
#define GET_TYPEID(ref) ( ( (length(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, length(ref)-6) ) )
#define IS_NORMAL_LIST(L) (GET_TYPEID("\ref[L]") == TYPEID_NORMAL_LIST)
+10 -1
View File
@@ -124,6 +124,7 @@
//returns a new list with only atoms that are in typecache L
/proc/typecache_filter_list(list/atoms, list/typecache)
RETURN_TYPE(/list)
. = list()
for(var/thing in atoms)
var/atom/A = thing
@@ -131,6 +132,7 @@
. += A
/proc/typecache_filter_list_reverse(list/atoms, list/typecache)
RETURN_TYPE(/list)
. = list()
for(var/thing in atoms)
var/atom/A = thing
@@ -257,6 +259,7 @@
//Pick a random element from the list and remove it from the list.
/proc/pick_n_take(list/L)
RETURN_TYPE(L[_].type)
if(L.len)
var/picked = rand(1,L.len)
. = L[picked]
@@ -570,4 +573,10 @@
if(key in L1)
L1[key] += other_value
else
L1[key] = other_value
L1[key] = other_value
/proc/assoc_list_strip_value(list/input)
var/list/ret = list()
for(var/key in input)
ret += key
return ret
+1 -1
View File
@@ -7,7 +7,7 @@
#define WRITE_LOG(log, text) rustg_log_write(log, text)
//print a warning message to world.log
#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].")
#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [UNLINT(src)] usr: [usr].")
/proc/warning(msg)
msg = "## WARNING: [msg]"
log_world(msg)
+6
View File
@@ -87,3 +87,9 @@ GLOBAL_VAR_INIT(cmp_field, "name")
/proc/cmp_uplink_items_asc(datum/uplink_item/A, datum/uplink_item/B)
return sorttext(initial(A.name), initial(B.name))
/proc/cmp_numbered_displays_name_asc(datum/numbered_display/A, datum/numbered_display/B)
return sorttext(A.sample_object.name, B.sample_object.name)
/proc/cmp_numbered_displays_name_dsc(datum/numbered_display/A, datum/numbered_display/B)
return sorttext(B.sample_object.name, A.sample_object.name)
+6 -5
View File
@@ -1,9 +1,9 @@
//supposedly the fastest way to do this according to https://gist.github.com/Giacom/be635398926bb463b42a
#define RANGE_TURFS(RADIUS, CENTER) \
block( \
locate(max(CENTER.x-(RADIUS),1), max(CENTER.y-(RADIUS),1), CENTER.z), \
locate(min(CENTER.x+(RADIUS),world.maxx), min(CENTER.y+(RADIUS),world.maxy), CENTER.z) \
)
block( \
locate(max(CENTER.x-(RADIUS),1), max(CENTER.y-(RADIUS),1), CENTER.z), \
locate(min(CENTER.x+(RADIUS),world.maxx), min(CENTER.y+(RADIUS),world.maxy), CENTER.z) \
)
#define Z_TURFS(ZLEVEL) block(locate(1,1,ZLEVEL), locate(world.maxx, world.maxy, ZLEVEL))
#define CULT_POLL_WAIT 2400
@@ -264,6 +264,7 @@
var/atom/A = processing_list[1]
if(A.flags_1 & HEAR_1)
. += A
SEND_SIGNAL(A, COMSIG_ATOM_HEARER_IN_VIEW, processing_list, .)
processing_list.Cut(1, 2)
processing_list += A.contents
@@ -446,7 +447,7 @@
var/list/candidates = list()
for(var/mob/dead/observer/G in GLOB.player_list)
if(G.can_reenter_round)
if(G.reenter_round_timeout < world.realtime)
candidates += G
return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates)
+1 -1
View File
@@ -105,7 +105,7 @@
continue
GLOB.uplink_items += path
//(sub)typesof entries are listed by the order they are loaded in the code, so we'll have to rearrange them here.
sortList(GLOB.uplink_items, /proc/cmp_uplink_items_asc)
GLOB.uplink_items = sortList(GLOB.uplink_items, /proc/cmp_uplink_items_asc)
init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
+7 -1
View File
@@ -313,8 +313,14 @@
parts += "[FOURSPACES]Threat level: [mode.threat_level]"
parts += "[FOURSPACES]Threat left: [mode.threat]"
parts += "[FOURSPACES]Executed rules:"
for(var/str in mode.threat_log)
parts += "[FOURSPACES][FOURSPACES][str]"
for(var/entry in mode.threat_tallies)
parts += "[FOURSPACES][FOURSPACES][entry] added [mode.threat_tallies[entry]]"
/*
for(var/datum/dynamic_ruleset/rule in mode.executed_rules)
parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - <b>[rule.name]</b>: -[rule.cost] threat"
parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - <b>[rule.name]</b>: -[rule.cost + rule.scaled_times * rule.scaling_cost] threat"
*/
return parts.Join("<br>")
/client/proc/roundend_report_file()
+11 -11
View File
@@ -304,9 +304,9 @@
//is in the other string at the same spot (assuming it is not a replace char).
//This is used for fingerprints
var/newtext = text
if(lentext(text) != lentext(compare))
if(length(text) != length(compare))
return 0
for(var/i = 1, i < lentext(text), i++)
for(var/i = 1, i < length(text), i++)
var/a = copytext(text,i,i+1)
var/b = copytext(compare,i,i+1)
//if it isn't both the same letter, or if they are both the replacement character
@@ -326,7 +326,7 @@
if(!text || !character)
return 0
var/count = 0
for(var/i = 1, i <= lentext(text), i++)
for(var/i = 1, i <= length(text), i++)
var/a = copytext(text,i,i+1)
if(a == character)
count++
@@ -607,8 +607,8 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
continue
var/buffer = ""
var/early_culling = TRUE
for(var/pos = 1, pos <= lentext(string), pos++)
var/let = copytext(string, pos, (pos + 1) % lentext(string))
for(var/pos = 1, pos <= length(string), pos++)
var/let = copytext(string, pos, (pos + 1) % length(string))
if(early_culling && !findtext(let,GLOB.is_alphanumeric))
continue
early_culling = FALSE
@@ -616,9 +616,9 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
if(!findtext(buffer,GLOB.is_alphanumeric))
continue
var/punctbuffer = ""
var/cutoff = lentext(buffer)
for(var/pos = lentext(buffer), pos >= 0, pos--)
var/let = copytext(buffer, pos, (pos + 1) % lentext(buffer))
var/cutoff = length(buffer)
for(var/pos = length(buffer), pos >= 0, pos--)
var/let = copytext(buffer, pos, (pos + 1) % length(buffer))
if(findtext(let,GLOB.is_alphanumeric))
break
if(findtext(let,GLOB.is_punctuation))
@@ -628,8 +628,8 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
var/exclaim = FALSE
var/question = FALSE
var/periods = 0
for(var/pos = lentext(punctbuffer), pos >= 0, pos--)
var/punct = copytext(punctbuffer, pos, (pos + 1) % lentext(punctbuffer))
for(var/pos = length(punctbuffer), pos >= 0, pos--)
var/punct = copytext(punctbuffer, pos, (pos + 1) % length(punctbuffer))
if(!exclaim && findtext(punct,"!"))
exclaim = TRUE
if(!question && findtext(punct,"?"))
@@ -651,7 +651,7 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
buffer = copytext(buffer, 1, cutoff) + punctbuffer
if(!findtext(buffer,GLOB.is_alphanumeric))
continue
if(!buffer || lentext(buffer) > 280 || lentext(buffer) <= cullshort || buffer in accepted)
if(!buffer || length(buffer) > 280 || length(buffer) <= cullshort || buffer in accepted)
continue
accepted += buffer
+2 -2
View File
@@ -9,8 +9,8 @@
return t
proc/TextPreview(var/string,var/len=40)
if(lentext(string) <= len)
if(!lentext(string))
if(length(string) <= len)
if(!length(string))
return "\[...\]"
else
return string
+1 -1
View File
@@ -11,7 +11,7 @@
var/dest_y
/datum/projectile_data/New(var/src_x, var/src_y, var/time, var/distance, \
var/power_x, var/power_y, var/dest_x, var/dest_y)
var/power_x, var/power_y, var/dest_x, var/dest_y)
src.src_x = src_x
src.src_y = src_y
src.time = time
+1 -1
View File
@@ -193,7 +193,7 @@ GLOBAL_LIST_INIT(bitfields, list(
"clear_conversion" = list(
"REACTION_CLEAR_IMPURE" = REACTION_CLEAR_IMPURE,
"REACTION_CLEAR_INVERSE" = REACTION_CLEAR_INVERSE
),
),
"organ_flags" = list(
"ORGAN_SYNTHETIC" = ORGAN_SYNTHETIC,
"ORGAN_FROZEN" = ORGAN_FROZEN,
+3 -3
View File
@@ -7,15 +7,15 @@ GLOBAL_LIST_EMPTY(facial_hair_styles_list) //stores /datum/sprite_accessory/faci
GLOBAL_LIST_EMPTY(facial_hair_styles_male_list) //stores only hair names
GLOBAL_LIST_EMPTY(facial_hair_styles_female_list) //stores only hair names
//Underwear
GLOBAL_LIST_EMPTY(underwear_list) //stores /datum/sprite_accessory/underwear/bottom indexed by name
GLOBAL_LIST_EMPTY_TYPED(underwear_list, /datum/sprite_accessory/underwear/bottom) //stores bottoms indexed by name
GLOBAL_LIST_EMPTY(underwear_m) //stores only underwear name
GLOBAL_LIST_EMPTY(underwear_f) //stores only underwear name
//Undershirts
GLOBAL_LIST_EMPTY(undershirt_list) //stores /datum/sprite_accessory/underwear/top indexed by name
GLOBAL_LIST_EMPTY_TYPED(undershirt_list, /datum/sprite_accessory/underwear/top) //stores tops indexed by name
GLOBAL_LIST_EMPTY(undershirt_m) //stores only undershirt name
GLOBAL_LIST_EMPTY(undershirt_f) //stores only undershirt name
//Socks
GLOBAL_LIST_EMPTY(socks_list) //stores /datum/sprite_accessory/underwear/socks indexed by name
GLOBAL_LIST_EMPTY_TYPED(socks_list, /datum/sprite_accessory/underwear/socks) //stores socks indexed by name
//Lizard Bits (all datum lists indexed by name)
GLOBAL_LIST_EMPTY(body_markings_list)
GLOBAL_LIST_EMPTY(tails_list_lizard)
+12 -2
View File
@@ -1,6 +1,16 @@
GLOBAL_LIST_INIT(cardinals, list(NORTH, SOUTH, EAST, WEST))
GLOBAL_LIST_INIT(alldirs, list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
GLOBAL_LIST_INIT(cardinals_multiz, list(NORTH, SOUTH, EAST, WEST, UP, DOWN))
GLOBAL_LIST_INIT(diagonals, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
GLOBAL_LIST_INIT(corners_multiz, list(UP|NORTHEAST, UP|NORTHWEST, UP|SOUTHEAST, UP|SOUTHWEST, DOWN|NORTHEAST, DOWN|NORTHWEST, DOWN|SOUTHEAST, DOWN|SOUTHWEST))
GLOBAL_LIST_INIT(diagonals_multiz, list(
NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST,
UP|NORTH, UP|SOUTH, UP|EAST, UP|WEST, UP|NORTHEAST, UP|NORTHWEST, UP|SOUTHEAST, UP|SOUTHWEST,
DOWN|NORTH, DOWN|SOUTH, DOWN|EAST, DOWN|WEST, DOWN|NORTHEAST, DOWN|NORTHWEST, DOWN|SOUTHEAST, DOWN|SOUTHWEST))
GLOBAL_LIST_INIT(alldirs_multiz, list(
NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST,
UP, UP|NORTH, UP|SOUTH, UP|EAST, UP|WEST, UP|NORTHEAST, UP|NORTHWEST, UP|SOUTHEAST, UP|SOUTHWEST,
DOWN, DOWN|NORTH, DOWN|SOUTH, DOWN|EAST, DOWN|WEST, DOWN|NORTHEAST, DOWN|NORTHWEST, DOWN|SOUTHEAST, DOWN|SOUTHWEST))
GLOBAL_LIST_INIT(alldirs, list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
GLOBAL_LIST_EMPTY(landmarks_list) //list of all landmarks created
GLOBAL_LIST_EMPTY(start_landmarks_list) //list of all spawn points created
@@ -35,6 +45,6 @@ GLOBAL_LIST_EMPTY(vr_spawnpoints)
//used by jump-to-area etc. Updated by area/updateName()
GLOBAL_LIST_EMPTY(sortedAreas)
/// An association from typepath to area instance. Only includes areas with `unique` set.
GLOBAL_LIST_EMPTY(areas_by_type)
GLOBAL_LIST_EMPTY_TYPED(areas_by_type, /area)
GLOBAL_LIST_EMPTY(all_abstract_markers)
+2
View File
@@ -1,6 +1,8 @@
GLOBAL_LIST_EMPTY(clients) //all clients
GLOBAL_LIST_EMPTY(admins) //all clients whom are admins
GLOBAL_PROTECT(admins)
GLOBAL_LIST_EMPTY(mentors) //all clients whom are mentors
GLOBAL_PROTECT(mentors)
GLOBAL_LIST_EMPTY(deadmins) //all ckeys who have used the de-admin verb.
GLOBAL_LIST_EMPTY(directory) //all ckeys with associated client
+4
View File
@@ -13,6 +13,8 @@
#define POLL_IGNORE_GOLEM "golem"
#define POLL_IGNORE_SWARMER "swarmer"
#define POLL_IGNORE_DRONE "drone"
#define POLL_IGNORE_DEMON "demon"
#define POLL_IGNORE_WIZARD "wizard"
#define POLL_IGNORE_CLONE "clone"
GLOBAL_LIST_INIT(poll_ignore_desc, list(
@@ -29,6 +31,8 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list(
POLL_IGNORE_GOLEM = "Golems",
POLL_IGNORE_SWARMER = "Swarmer shells",
POLL_IGNORE_DRONE = "Drone shells",
POLL_IGNORE_DEMON = "Demons",
POLL_IGNORE_WIZARD = "Wizards",
POLL_IGNORE_CLONE = "Defective/SDGF clones"
))
GLOBAL_LIST_INIT(poll_ignore, init_poll_ignore())
+33 -33
View File
@@ -1,37 +1,37 @@
#define js_dropdowns {"
function dropdowns() {
var divs = document.getElementsByTagName('div');
var headers = new Array();
var links = new Array();
for(var i=0;i<divs.length;i++){
if(divs\[i\].className=='header') {
divs\[i\].className='header closed';
divs\[i\].innerHTML = divs\[i\].innerHTML+' +';
headers.push(divs\[i\]);
}
if(divs\[i\].className=='links') {
divs\[i\].className='links hidden';
links.push(divs\[i\]);
}
}
for(var i=0;i<headers.length;i++){
if(typeof(links\[i\])!== 'undefined' && links\[i\]!=null) {
headers\[i\].onclick = (function(elem) {
return function() {
if(elem.className.search('visible')>=0) {
elem.className = elem.className.replace('visible','hidden');
this.className = this.className.replace('open','closed');
this.innerHTML = this.innerHTML.replace('-','+');
}
else {
elem.className = elem.className.replace('hidden','visible');
this.className = this.className.replace('closed','open');
this.innerHTML = this.innerHTML.replace('+','-');
}
return false;
}
})(links\[i\]);
}
}
var divs = document.getElementsByTagName('div');
var headers = new Array();
var links = new Array();
for(var i=0;i<divs.length;i++){
if(divs\[i\].className=='header') {
divs\[i\].className='header closed';
divs\[i\].innerHTML = divs\[i\].innerHTML+' +';
headers.push(divs\[i\]);
}
if(divs\[i\].className=='links') {
divs\[i\].className='links hidden';
links.push(divs\[i\]);
}
}
for(var i=0;i<headers.length;i++){
if(typeof(links\[i\])!== 'undefined' && links\[i\]!=null) {
headers\[i\].onclick = (function(elem) {
return function() {
if(elem.className.search('visible')>=0) {
elem.className = elem.className.replace('visible','hidden');
this.className = this.className.replace('open','closed');
this.innerHTML = this.innerHTML.replace('-','+');
}
else {
elem.className = elem.className.replace('hidden','visible');
this.className = this.className.replace('closed','open');
this.innerHTML = this.innerHTML.replace('+','-');
}
return false;
}
})(links\[i\]);
}
}
}
"}
+3 -2
View File
@@ -68,9 +68,10 @@
/atom/movable/Adjacent(var/atom/neighbor)
if(neighbor == loc)
return TRUE
if(!isturf(loc))
var/turf/T = loc
if(!istype(T))
return FALSE
if(loc.Adjacent(neighbor,target = neighbor, mover = src))
if(T.Adjacent(neighbor, neighbor, src))
return TRUE
return FALSE
+1 -2
View File
@@ -321,8 +321,7 @@
return
/atom/proc/ShiftClick(mob/user)
SEND_SIGNAL(src, COMSIG_CLICK_SHIFT, user)
if(user.client && user.client.eye == user || user.client.eye == user.loc)
user.examinate(src)
user.examinate(src)
return
/*
+22
View File
@@ -16,6 +16,28 @@
//Trust me, you need one. Period. If you don't think you do, you're doing something extremely wrong.
/obj/screen/plane_master/proc/backdrop(mob/mymob)
/obj/screen/plane_master/openspace
name = "open space plane master"
plane = FLOOR_OPENSPACE_PLANE
appearance_flags = PLANE_MASTER
blend_mode = BLEND_MULTIPLY
alpha = 255
/obj/screen/plane_master/openspace/backdrop(mob/mymob)
filters = list()
filters += filter(type = "drop_shadow", color = "#04080FAA", size = -10)
filters += filter(type = "drop_shadow", color = "#04080FAA", size = -15)
filters += filter(type = "drop_shadow", color = "#04080FAA", size = -20)
/obj/screen/plane_master/proc/outline(_size, _color)
filters += filter(type = "outline", size = _size, color = _color)
/obj/screen/plane_master/proc/shadow(_size, _offset = 0, _x = 0, _y = 0, _color = "#04080FAA")
filters += filter(type = "drop_shadow", x = _x, y = _y, color = _color, size = _size, offset = _offset)
/obj/screen/plane_master/proc/clear_filters()
filters = list()
/obj/screen/plane_master/floor
name = "floor plane master"
plane = FLOOR_PLANE
@@ -211,3 +211,27 @@
/datum/config_entry/keyed_list/vv_edit_var(var_name, var_value)
return var_name != "splitter" && ..()
//snowflake for donator things being on one line smh
/datum/config_entry/multi_keyed_flag
vv_VAS = FALSE
abstract_type = /datum/config_entry/multi_keyed_flag
config_entry_value = list()
var/delimiter = "|"
/datum/config_entry/multi_keyed_flag/vv_edit_var(var_name, var_value)
if(var_name == NAMEOF(src, delimiter))
return FALSE
return ..()
/datum/config_entry/multi_keyed_flag/ValidateAndSet(str_val)
if(!VASProcCallGuard(str_val))
return FALSE
str_val = trim(str_val)
var/list/keys = splittext(str_val, delimiter)
for(var/i in keys)
config_entry_value[process_key(i)] = TRUE
return length(keys)? TRUE : FALSE
/datum/config_entry/multi_keyed_flag/proc/process_key(key)
return trim(key)
@@ -34,7 +34,7 @@
if(_directory)
directory = _directory
if(entries)
CRASH("[THIS_PROC_TYPE_WEIRD] called more than once!")
CRASH("/datum/controller/configuration/Load() called more than once!")
InitEntries()
LoadModes()
if(fexists("[directory]/config.txt") && LoadEntries("config.txt") <= 1)
@@ -1,22 +1,23 @@
/datum/config_entry/keyed_list/donator_group
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_FLAG
abstract_type = /datum/config_entry/keyed_list/donator_group
/datum/config_entry/multi_keyed_flag/donator_group
abstract_type = /datum/config_entry/multi_keyed_flag/donator_group
//If we're in the middle of a config load, only do the regeneration afterwards to prevent this from wasting a massive amount of CPU for list regenerations.
/datum/config_entry/keyed_list/donator_group/ValidateAndSet(str_val, during_load)
/datum/config_entry/multi_keyed_flag/donator_group/ValidateAndSet(str_val, during_load)
. = ..()
if(. && during_load)
if(. && !during_load)
regenerate_donator_grouping_list()
/datum/config_entry/keyed_list/donator_group/OnPostload()
/datum/config_entry/multi_keyed_flag/donator_group/process_key(key)
return ckey(key)
/datum/config_entry/multi_keyed_flag/donator_group/OnPostload()
. = ..()
regenerate_donator_grouping_list()
//This is kinda weird in that the config entries are defined here but all the handling/calculations are in __HELPERS/donator_groupings.dm
/datum/config_entry/keyed_list/donator_group/tier_1_donators
/datum/config_entry/multi_keyed_flag/donator_group/tier_1_donators
/datum/config_entry/keyed_list/donator_group/tier_2_donators
/datum/config_entry/multi_keyed_flag/donator_group/tier_2_donators
/datum/config_entry/keyed_list/donator_group/tier_3_donators
/datum/config_entry/multi_keyed_flag/donator_group/tier_3_donators
@@ -0,0 +1,90 @@
/datum/config_entry/flag/dynamic_voting
/datum/config_entry/number/dynamic_high_pop_limit
config_entry_value = 55
min_val = 1
/datum/config_entry/number/dynamic_pop_per_requirement
config_entry_value = 6
min_val = 1
/datum/config_entry/number/dynamic_midround_delay_min
config_entry_value = 15
min_val = 1
/datum/config_entry/number/dynamic_midround_delay_max
config_entry_value = 35
min_val = 1
/datum/config_entry/number/dynamic_latejoin_delay_min
config_entry_value = 5
min_val = 1
/datum/config_entry/number/dynamic_latejoin_delay_max
config_entry_value = 25
min_val = 1
/datum/config_entry/number/dynamic_first_midround_delay_min
config_entry_value = 20
min_val = 1
/datum/config_entry/number/dynamic_first_midround_delay_max
config_entry_value = 40
min_val = 1
/datum/config_entry/number/dynamic_first_latejoin_delay_min
config_entry_value = 10
min_val = 1
/datum/config_entry/number/dynamic_first_latejoin_delay_max
config_entry_value = 30
min_val = 1
/datum/config_entry/keyed_list/dynamic_cost
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
/datum/config_entry/keyed_list/dynamic_weight
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
/datum/config_entry/keyed_list/dynamic_requirements
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM_LIST
/datum/config_entry/keyed_list/dynamic_high_population_requirement
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
/datum/config_entry/number_list/dynamic_second_rule_requirements
/datum/config_entry/number_list/dynamic_third_rule_requirements
/datum/config_entry/number/dynamic_second_rule_high_pop_requirement
config_entry_value = 50
/datum/config_entry/number/dynamic_third_rule_high_pop_requirement
config_entry_value = 70
/datum/config_entry/number_list/dynamic_hijack_requirements
/datum/config_entry/number/dynamic_hijack_high_population_requirement
config_entry_value = 25
/datum/config_entry/number/dynamic_hijack_cost
config_entry_value = 5
/datum/config_entry/number/dynamic_glorious_death_cost
config_entry_value = 5
/datum/config_entry/number/dynamic_assassinate_cost
config_entry_value = 2
/datum/config_entry/number/dynamic_warops_requirement
config_entry_value = 60
min_val = 0
/datum/config_entry/number/dynamic_warops_cost
config_entry_value = 10
min_val = 0
@@ -139,6 +139,14 @@
min_val = 0
max_val = 1
/datum/config_entry/number/suicide_reenter_round_timer
config_entry_value = 30
min_val = 0
/datum/config_entry/number/roundstart_suicide_time_limit
config_entry_value = 30
min_val = 0
/datum/config_entry/number/shuttle_refuel_delay
config_entry_value = 12000
min_val = 0
@@ -371,43 +379,3 @@
/datum/config_entry/number/auto_transfer_delay
config_entry_value = 72000
min_val = 0
/datum/config_entry/number/dynamic_high_pop_limit
config_entry_value = 55
min_val = 1
/datum/config_entry/number/dynamic_pop_per_requirement
config_entry_value = 6
min_val = 1
/datum/config_entry/number/dynamic_midround_delay_min
config_entry_value = 15
min_val = 1
/datum/config_entry/number/dynamic_midround_delay_max
config_entry_value = 35
min_val = 1
/datum/config_entry/number/dynamic_latejoin_delay_min
config_entry_value = 5
min_val = 1
/datum/config_entry/number/dynamic_latejoin_delay_max
config_entry_value = 25
min_val = 1
/datum/config_entry/keyed_list/dynamic_cost
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
/datum/config_entry/keyed_list/dynamic_weight
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
/datum/config_entry/keyed_list/dynamic_requirements
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM_LIST
/datum/config_entry/keyed_list/dynamic_high_population_requirement
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
@@ -141,6 +141,11 @@
/datum/config_entry/flag/load_legacy_ranks_only //Loads admin ranks only from legacy admin_ranks.txt, while enabled ranks are mirrored to the database
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/mentors_mobname_only
/datum/config_entry/flag/mentor_legacy_system //Defines whether the server uses the legacy mentor system with mentors.txt or the SQL system
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/string/hostedby
/datum/config_entry/flag/norespawn
@@ -0,0 +1,35 @@
SUBSYSTEM_DEF(adjacent_air)
name = "Atmos Adjacency"
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
wait = 10
priority = FIRE_PRIORITY_ATMOS_ADJACENCY
var/list/queue = list()
/datum/controller/subsystem/adjacent_air/stat_entry()
#ifdef TESTING
..("P:[length(queue)], S:[GLOB.atmos_adjacent_savings[1]], T:[GLOB.atmos_adjacent_savings[2]]")
#else
..("P:[length(queue)]")
#endif
/datum/controller/subsystem/adjacent_air/Initialize()
while(length(queue))
fire(mc_check = FALSE)
return ..()
/datum/controller/subsystem/adjacent_air/fire(resumed = FALSE, mc_check = TRUE)
var/list/queue = src.queue
while (length(queue))
var/turf/currT = queue[1]
queue.Cut(1,2)
currT.ImmediateCalculateAdjacentTurfs()
if(mc_check)
if(MC_TICK_CHECK)
break
else
CHECK_TICK
+13
View File
@@ -29,6 +29,7 @@ SUBSYSTEM_DEF(chat)
target = GLOB.clients
//Some macros remain in the string even after parsing and fuck up the eventual output
var/original_message = message
message = replacetext(message, "\improper", "")
message = replacetext(message, "\proper", "")
if(handle_whitespace)
@@ -45,6 +46,12 @@ SUBSYSTEM_DEF(chat)
for(var/I in target)
var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible
if(!C)
return
//Send it to the old style output window.
SEND_TEXT(C, original_message)
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
continue
@@ -57,6 +64,12 @@ SUBSYSTEM_DEF(chat)
else
var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible
if(!C)
return
//Send it to the old style output window.
SEND_TEXT(C, original_message)
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
return
+40
View File
@@ -658,6 +658,46 @@ SUBSYSTEM_DEF(job)
message_admins(msg)
CRASH(msg)
/datum/controller/subsystem/job/proc/equip_loadout(mob/dead/new_player/N, mob/living/M, equipbackpackstuff)
var/mob/the_mob = N
if(!the_mob)
the_mob = M // cause this doesn't get assigned if player is a latejoiner
if(the_mob.client && the_mob.client.prefs && (the_mob.client.prefs.chosen_gear && the_mob.client.prefs.chosen_gear.len))
if(!ishuman(M))//no silicons allowed
return
for(var/i in the_mob.client.prefs.chosen_gear)
var/datum/gear/G = i
G = GLOB.loadout_items[slot_to_string(initial(G.category))][initial(G.name)]
if(!G)
continue
var/permitted = TRUE
if(G.restricted_roles && G.restricted_roles.len && !(M.mind.assigned_role in G.restricted_roles))
permitted = FALSE
if(G.donoritem && !G.donator_ckey_check(the_mob.client.ckey))
permitted = FALSE
if(!equipbackpackstuff && G.category == SLOT_IN_BACKPACK)//snowflake check since plopping stuff in the backpack doesnt work for pre-job equip loadout stuffs
permitted = FALSE
if(equipbackpackstuff && G.category != SLOT_IN_BACKPACK)//ditto
permitted = FALSE
if(!permitted)
continue
var/obj/item/I = new G.path
if(!M.equip_to_slot_if_possible(I, G.category, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // If the job's dresscode compliant, try to put it in its slot, first
if(iscarbon(M))
var/mob/living/carbon/C = M
var/obj/item/storage/backpack/B = C.back
if(!B || !SEND_SIGNAL(B, COMSIG_TRY_STORAGE_INSERT, I, null, TRUE, TRUE)) // Otherwise, try to put it in the backpack, for carbons.
I.forceMove(get_turf(C))
else if(!M.equip_to_slot_if_possible(I, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // Otherwise, try to put it in the backpack
I.forceMove(get_turf(M)) // If everything fails, just put it on the floor under the mob.
/datum/controller/subsystem/job/proc/FreeRole(rank)
if(!rank)
return
var/datum/job/job = GetJob(rank)
if(!job)
return FALSE
job.current_positions = max(0, job.current_positions - 1)
///////////////////////////////////
//Keeps track of all living heads//
+27 -15
View File
@@ -14,6 +14,7 @@ SUBSYSTEM_DEF(mapping)
var/list/ruins_templates = list()
var/list/space_ruins_templates = list()
var/list/lava_ruins_templates = list()
var/datum/space_level/isolated_ruins_z //Created on demand during ruin loading.
var/list/shuttle_templates = list()
var/list/shelter_templates = list()
@@ -25,6 +26,7 @@ SUBSYSTEM_DEF(mapping)
var/list/datum/turf_reservations //list of turf reservations
var/list/used_turfs = list() //list of turf = datum/turf_reservation
var/list/reservation_ready = list()
var/clearing_reserved_turfs = FALSE
// Z-manager stuff
@@ -95,7 +97,7 @@ SUBSYSTEM_DEF(mapping)
// Set up Z-level transitions.
setup_map_transitions()
generate_station_area_list()
initialize_reserved_level()
initialize_reserved_level(transit.z_value)
return ..()
/* Nuke threats, for making the blue tiles on the station go RED
@@ -442,7 +444,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
GLOB.the_gateway.wait = world.time
/datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override, border_type_override)
UNTIL(initialized && !clearing_reserved_turfs)
UNTIL((!z || reservation_ready["[z]"]) && !clearing_reserved_turfs)
var/datum/turf_reservation/reserve = new type
if(turf_type_override)
reserve.turf_type = turf_type_override
@@ -454,8 +456,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
return reserve
//If we didn't return at this point, theres a good chance we ran out of room on the exisiting reserved z levels, so lets try a new one
num_of_res_levels += 1
var/newReserved = add_new_zlevel("Transit/Reserved [num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE))
if(reserve.Reserve(width, height, newReserved))
var/datum/space_level/newReserved = add_new_zlevel("Transit/Reserved [num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE))
initialize_reserved_level(newReserved.z_value)
if(reserve.Reserve(width, height, newReserved.z_value))
return reserve
else
if(!level_trait(z, ZTRAIT_RESERVED))
@@ -467,19 +470,22 @@ GLOBAL_LIST_EMPTY(the_station_areas)
QDEL_NULL(reserve)
//This is not for wiping reserved levels, use wipe_reservations() for that.
/datum/controller/subsystem/mapping/proc/initialize_reserved_level()
/datum/controller/subsystem/mapping/proc/initialize_reserved_level(z)
UNTIL(!clearing_reserved_turfs) //regardless, lets add a check just in case.
clearing_reserved_turfs = TRUE //This operation will likely clear any existing reservations, so lets make sure nothing tries to make one while we're doing it.
for(var/i in levels_by_trait(ZTRAIT_RESERVED))
var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,i))
var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,i))
var/block = block(A, B)
for(var/t in block)
// No need to empty() these, because it's world init and they're
// already /turf/open/space/basic.
var/turf/T = t
T.flags_1 |= UNUSED_RESERVATION_TURF_1
unused_turfs["[i]"] = block
if(!level_trait(z,ZTRAIT_RESERVED))
clearing_reserved_turfs = FALSE
CRASH("Invalid z level prepared for reservations.")
var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,z))
var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,z))
var/block = block(A, B)
for(var/t in block)
// No need to empty() these, because it's world init and they're
// already /turf/open/space/basic.
var/turf/T = t
T.flags_1 |= UNUSED_RESERVATION_TURF_1
unused_turfs["[z]"] = block
reservation_ready["[z]"] = TRUE
clearing_reserved_turfs = FALSE
/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs)
@@ -513,3 +519,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
for(var/B in areas)
var/area/A = B
A.reg_in_areas_in_z()
/datum/controller/subsystem/mapping/proc/get_isolated_ruin_z()
if(!isolated_ruins_z)
isolated_ruins_z = add_new_zlevel("Isolated Ruins/Reserved", list(ZTRAIT_RESERVED = TRUE, ZTRAIT_ISOLATED_RUINS = TRUE))
initialize_reserved_level(isolated_ruins_z.z_value)
return isolated_ruins_z.z_value
+6
View File
@@ -69,6 +69,10 @@ SUBSYSTEM_DEF(pai)
candidate.comments = copytext(sanitize(candidate.comments),1,MAX_MESSAGE_LEN)
if("submit")
if(isobserver(usr))
var/mob/dead/observer/O = usr
if(!O.can_reenter_round())
return FALSE
if(candidate)
candidate.ready = 1
for(var/obj/item/paicard/p in pai_card_list)
@@ -148,6 +152,8 @@ SUBSYSTEM_DEF(pai)
continue
if(!(ROLE_PAI in G.client.prefs.be_special))
continue
if(!G.can_reenter_round()) // this should use notify_ghosts() instead one day.
return FALSE
to_chat(G, "<span class='ghostalert'>[user] is requesting a pAI personality! Use the pAI button to submit yourself as one.</span>")
addtimer(CALLBACK(src, .proc/spam_again), spam_delay)
var/list/available = list()
+205 -10
View File
@@ -4,24 +4,32 @@ SUBSYSTEM_DEF(research)
priority = FIRE_PRIORITY_RESEARCH
wait = 10
init_order = INIT_ORDER_RESEARCH
//TECHWEB STATIC
var/list/techweb_nodes = list() //associative id = node datum
var/list/techweb_designs = list() //associative id = node datum
var/list/datum/techweb/techwebs = list()
var/datum/techweb/science/science_tech
var/datum/techweb/admin/admin_tech
var/datum/techweb_node/error_node/error_node //These two are what you get if a node/design is deleted and somehow still stored in a console.
var/datum/design/error_design/error_design
//ERROR LOGGING
var/list/invalid_design_ids = list() //associative id = number of times
var/list/invalid_node_ids = list() //associative id = number of times
var/list/invalid_node_boost = list() //associative id = error message
var/list/obj/machinery/rnd/server/servers = list()
var/datum/techweb/science/science_tech
var/datum/techweb/admin/admin_tech
var/list/techweb_nodes = list() //associative id = node datum
var/list/techweb_categories = list() //category name = list(node.id = node)
var/list/techweb_designs = list() //associative id = node datum
var/list/techweb_nodes_starting = list() //associative id = node datum
var/list/techweb_nodes_starting = list() //associative id = TRUE
var/list/techweb_categories = list() //category name = list(node.id = TRUE)
var/list/techweb_boost_items = list() //associative double-layer path = list(id = list(point_type = point_discount))
var/list/techweb_nodes_hidden = list() //Nodes that should be hidden by default.
var/list/techweb_nodes_hidden = list() //Node ids that should be hidden by default.
var/list/techweb_point_items = list( //path = list(point type = value)
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 2500),
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 5000), // Cit three more anomalys anomalys
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 7500),
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 10000),
// - Slime Extracts! -
// - Slime Extracts! -
/obj/item/slime_extract/grey = list(TECHWEB_POINT_TYPE_GENERIC = 500), // Adds in slime core deconing
/obj/item/slime_extract/metal = list(TECHWEB_POINT_TYPE_GENERIC = 750),
/obj/item/slime_extract/purple = list(TECHWEB_POINT_TYPE_GENERIC = 750),
@@ -294,6 +302,8 @@ SUBSYSTEM_DEF(research)
science_tech = new /datum/techweb/science
admin_tech = new /datum/techweb/admin
autosort_categories()
error_design = new
error_node = new
return ..()
/datum/controller/subsystem/research/fire()
@@ -330,6 +340,191 @@ SUBSYSTEM_DEF(research)
for(var/i in techweb_nodes)
var/datum/techweb_node/I = techweb_nodes[i]
if(techweb_categories[I.category])
techweb_categories[I.category][I.id] = I
techweb_categories[I.category][I.id] = TRUE
else
techweb_categories[I.category] = list(I.id = I)
techweb_categories[I.category] = list(I.id = TRUE)
/datum/controller/subsystem/research/proc/techweb_node_by_id(id)
return techweb_nodes[id] || error_node
/datum/controller/subsystem/research/proc/techweb_design_by_id(id)
return techweb_designs[id] || error_design
/datum/controller/subsystem/research/proc/on_design_deletion(datum/design/D)
for(var/i in techweb_nodes)
var/datum/techweb_node/TN = techwebs[i]
TN.on_design_deletion(TN)
for(var/i in techwebs)
var/datum/techweb/T = i
T.recalculate_nodes(TRUE)
/datum/controller/subsystem/research/proc/on_node_deletion(datum/techweb_node/TN)
for(var/i in techweb_nodes)
var/datum/techweb_node/TN2 = techwebs[i]
TN2.on_node_deletion(TN)
for(var/i in techwebs)
var/datum/techweb/T = i
T.recalculate_nodes(TRUE)
/datum/controller/subsystem/research/proc/initialize_all_techweb_nodes(clearall = FALSE)
if(islist(techweb_nodes) && clearall)
QDEL_LIST(techweb_nodes)
if(islist(techweb_nodes_starting && clearall))
techweb_nodes_starting.Cut()
var/list/returned = list()
for(var/path in subtypesof(/datum/techweb_node))
var/datum/techweb_node/TN = path
if(isnull(initial(TN.id)))
continue
TN = new path
if(returned[initial(TN.id)])
stack_trace("WARNING: Techweb node ID clash with ID [initial(TN.id)] detected! Path: [path]")
errored_datums[TN] = initial(TN.id)
continue
returned[initial(TN.id)] = TN
if(TN.starting_node)
techweb_nodes_starting[TN.id] = TRUE
for(var/id in techweb_nodes)
var/datum/techweb_node/TN = techweb_nodes[id]
TN.Initialize()
techweb_nodes = returned
if (!verify_techweb_nodes()) //Verify all nodes have ids and such.
stack_trace("Invalid techweb nodes detected")
calculate_techweb_nodes()
calculate_techweb_boost_list()
if (!verify_techweb_nodes()) //Verify nodes and designs have been crosslinked properly.
CRASH("Invalid techweb nodes detected")
/datum/controller/subsystem/research/proc/initialize_all_techweb_designs(clearall = FALSE)
if(islist(techweb_designs) && clearall)
QDEL_LIST(techweb_designs)
var/list/returned = list()
for(var/path in subtypesof(/datum/design))
var/datum/design/DN = path
if(isnull(initial(DN.id)))
stack_trace("WARNING: Design with null ID detected. Build path: [initial(DN.build_path)]")
continue
else if(initial(DN.id) == DESIGN_ID_IGNORE)
continue
DN = new path
if(returned[initial(DN.id)])
stack_trace("WARNING: Design ID clash with ID [initial(DN.id)] detected! Path: [path]")
errored_datums[DN] = initial(DN.id)
continue
returned[initial(DN.id)] = DN
techweb_designs = returned
verify_techweb_designs()
/datum/controller/subsystem/research/proc/verify_techweb_nodes()
. = TRUE
for(var/n in techweb_nodes)
var/datum/techweb_node/N = techweb_nodes[n]
if(!istype(N))
WARNING("Invalid research node with ID [n] detected and removed.")
techweb_nodes -= n
research_node_id_error(n)
. = FALSE
for(var/p in N.prereq_ids)
var/datum/techweb_node/P = techweb_nodes[p]
if(!istype(P))
WARNING("Invalid research prerequisite node with ID [p] detected in node [N.display_name]\[[N.id]\] removed.")
N.prereq_ids -= p
research_node_id_error(p)
. = FALSE
for(var/d in N.design_ids)
var/datum/design/D = techweb_designs[d]
if(!istype(D))
WARNING("Invalid research design with ID [d] detected in node [N.display_name]\[[N.id]\] removed.")
N.design_ids -= d
design_id_error(d)
. = FALSE
for(var/u in N.unlock_ids)
var/datum/techweb_node/U = techweb_nodes[u]
if(!istype(U))
WARNING("Invalid research unlock node with ID [u] detected in node [N.display_name]\[[N.id]\] removed.")
N.unlock_ids -= u
research_node_id_error(u)
. = FALSE
for(var/p in N.boost_item_paths)
if(!ispath(p))
N.boost_item_paths -= p
WARNING("[p] is not a valid path.")
node_boost_error(N.id, "[p] is not a valid path.")
. = FALSE
var/list/points = N.boost_item_paths[p]
if(islist(points))
for(var/i in points)
if(!isnum(points[i]))
WARNING("[points[i]] is not a valid number.")
node_boost_error(N.id, "[points[i]] is not a valid number.")
. = FALSE
else if(!point_types[i])
WARNING("[i] is not a valid point type.")
node_boost_error(N.id, "[i] is not a valid point type.")
. = FALSE
else if(!isnull(points))
N.boost_item_paths -= p
node_boost_error(N.id, "No valid list.")
WARNING("No valid list.")
. = FALSE
CHECK_TICK
/datum/controller/subsystem/research/proc/verify_techweb_designs()
for(var/d in techweb_designs)
var/datum/design/D = techweb_designs[d]
if(!istype(D))
stack_trace("WARNING: Invalid research design with ID [d] detected and removed.")
techweb_designs -= d
CHECK_TICK
/datum/controller/subsystem/research/proc/research_node_id_error(id)
if(invalid_node_ids[id])
invalid_node_ids[id]++
else
invalid_node_ids[id] = 1
/datum/controller/subsystem/research/proc/design_id_error(id)
if(invalid_design_ids[id])
invalid_design_ids[id]++
else
invalid_design_ids[id] = 1
/datum/controller/subsystem/research/proc/calculate_techweb_nodes()
for(var/design_id in techweb_designs)
var/datum/design/D = techweb_designs[design_id]
D.unlocked_by.Cut()
for(var/node_id in techweb_nodes)
var/datum/techweb_node/node = techweb_nodes[node_id]
node.unlock_ids = list()
for(var/i in node.design_ids)
var/datum/design/D = techweb_designs[i]
node.design_ids[i] = TRUE
D.unlocked_by += node.id
if(node.hidden)
techweb_nodes_hidden[node.id] = TRUE
CHECK_TICK
generate_techweb_unlock_linking()
/datum/controller/subsystem/research/proc/generate_techweb_unlock_linking()
for(var/node_id in techweb_nodes) //Clear all unlock links to avoid duplication.
var/datum/techweb_node/node = techweb_nodes[node_id]
node.unlock_ids = list()
for(var/node_id in techweb_nodes)
var/datum/techweb_node/node = techweb_nodes[node_id]
for(var/prereq_id in node.prereq_ids)
var/datum/techweb_node/prereq_node = techweb_node_by_id(prereq_id)
prereq_node.unlock_ids[node.id] = node
/datum/controller/subsystem/research/proc/calculate_techweb_boost_list(clearall = FALSE)
if(clearall)
techweb_boost_items = list()
for(var/node_id in techweb_nodes)
var/datum/techweb_node/node = techweb_nodes[node_id]
for(var/path in node.boost_item_paths)
if(!ispath(path))
continue
if(length(techweb_boost_items[path]))
techweb_boost_items[path][node.id] = node.boost_item_paths[path]
else
techweb_boost_items[path] = list(node.id = node.boost_item_paths[path])
CHECK_TICK
+8
View File
@@ -638,3 +638,11 @@ SUBSYSTEM_DEF(shuttle)
C.update_hidden_docking_ports(remove_images, add_images)
QDEL_LIST(remove_images)
/datum/controller/subsystem/shuttle/proc/autoEnd() //CIT CHANGE - allows shift to end after 2 hours have passed.
if((world.realtime - SSshuttle.realtimeofstart) > auto_call && EMERGENCY_IDLE_OR_RECALLED) //2 hours
SSshuttle.emergency.request(silent = TRUE)
priority_announce("The shift has come to an end and the shuttle called. [seclevel2num(get_security_level()) == SEC_LEVEL_RED ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [emergency.timeLeft(600)] minutes.", null, "shuttlecalled", "Priority")
log_game("Round time limit reached. Shuttle has been auto-called.")
message_admins("Round time limit reached. Shuttle called.")
emergencyNoRecall = TRUE
+5
View File
@@ -147,6 +147,11 @@ SUBSYSTEM_DEF(throwing)
if (callback)
callback.Invoke()
if(!thrownthing.zfalling) // I don't think you can zfall while thrown but hey, just in case.
var/turf/T = get_turf(thrownthing)
if(T && thrownthing.has_gravity(T))
T.zFall(thrownthing)
qdel(src)
/datum/thrownthing/proc/hit_atom(atom/A)
+2 -1
View File
@@ -479,7 +479,8 @@ SUBSYSTEM_DEF(ticker)
if(SSticker.timeLeft < 900)
SSticker.timeLeft = 900
SSticker.modevoted = TRUE
SSvote.initiate_vote("roundtype","server",TRUE)
var/dynamic = CONFIG_GET(flag/dynamic_voting)
SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE)
/datum/controller/subsystem/ticker/Recover()
current_state = SSticker.current_state
+2 -2
View File
@@ -40,7 +40,7 @@ SUBSYSTEM_DEF(traumas)
"cats" = strings(PHOBIA_FILE, "cats"),
"syndicate"= strings(PHOBIA_FILE, "syndicate"),
"eye" = strings(PHOBIA_FILE, "eye")
)
)
phobia_mobs = list("spiders" = typecacheof(list(/mob/living/simple_animal/hostile/poison/giant_spider)),
"security" = typecacheof(list(/mob/living/simple_animal/bot/secbot, /mob/living/simple_animal/bot/ed209)),
@@ -166,7 +166,7 @@ SUBSYSTEM_DEF(traumas)
"syndicate" = typecacheof(list(/obj/item/stack/tile/mineral/plastitanium, /obj/machinery/computer/shuttle/syndicate, /obj/machinery/computer/shuttle/syndicate/recall, /obj/machinery/computer/shuttle/syndicate/drop_pod, /obj/machinery/computer/camera_advanced/shuttle_docker/syndicate, /obj/machinery/recharge_station,
/obj/machinery/porta_turret/syndicate, /obj/structure/closet/syndicate, /obj/machinery/suit_storage_unit/syndicate, /obj/item/clothing/under/syndicate, /obj/item/folder/syndicate, /obj/item/documents/syndicate, /obj/item/clothing/glasses/phantomthief/syndicate, /obj/item/antag_spawner/nuke_ops, /obj/item/storage/box/syndicate,
/obj/structure/fluff/empty_sleeper/syndicate, /obj/item/implant/radio/syndicate, /obj/item/clothing/head/helmet/space/syndicate, /obj/machinery/nuclearbomb/syndicate, /obj/item/grenade/syndieminibomb, /obj/item/storage/backpack/duffelbag/syndie, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver/syndie,
/obj/structure/fluff/empty_sleeper/syndicate, /obj/item/implant/radio/syndicate, /obj/item/clothing/head/helmet/space/syndicate, /obj/machinery/nuclearbomb/syndicate, /obj/item/grenade/syndieminibomb, /obj/item/storage/backpack/duffelbag/syndie, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver,
/obj/item/gun/ballistic/automatic/shotgun/bulldog, /obj/item/gun/ballistic/automatic/c20r, /obj/item/gun/ballistic/automatic/m90, /obj/item/gun/ballistic/automatic/l6_saw, /obj/item/storage/belt/grenade/full, /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate, /obj/item/gun/energy/kinetic_accelerator/crossbow,
/obj/item/melee/transforming/energy/sword/saber, /obj/item/twohanded/dualsaber, /obj/item/melee/powerfist, /obj/item/storage/box/syndie_kit, /obj/item/grenade/spawnergrenade/manhacks, /obj/item/grenade/chem_grenade/bioterrorfoam, /obj/item/reagent_containers/spray/chemsprayer/bioterror, /obj/item/ammo_box/magazine/m10mm,
/obj/item/ammo_box/magazine/pistolm9mm, /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/m12g, /obj/item/ammo_box/magazine/mm195x129, /obj/item/antag_spawner/nuke_ops, /obj/mecha/combat/gygax/dark, /obj/mecha/combat/marauder/mauler, /obj/item/soap/syndie, /obj/item/gun/syringe/syndicate, /obj/item/cartridge/virus/syndicate,
+36 -2
View File
@@ -87,7 +87,7 @@ SUBSYSTEM_DEF(vote)
/datum/controller/subsystem/vote/proc/announce_result()
var/list/winners = get_result()
var/text
var/was_roundtype_vote = mode == "roundtype"
var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic"
if(winners.len > 0)
if(question)
text += "<b>[question]</b>"
@@ -124,6 +124,9 @@ SUBSYSTEM_DEF(vote)
message_admins(admintext)
return .
#define PEACE "calm"
#define CHAOS "chaotic"
/datum/controller/subsystem/vote/proc/result()
. = announce_result()
var/restart = 0
@@ -146,6 +149,32 @@ SUBSYSTEM_DEF(vote)
restart = 1
else
GLOB.master_mode = .
if("dynamic")
if(SSticker.current_state > GAME_STATE_PREGAME)//Don't change the mode if the round already started.
return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.")
GLOB.master_mode = "dynamic"
var/mean = 0
var/voters = 0
for(var/client/c in GLOB.clients)
var/vote = c.prefs.preferred_chaos
if(vote)
voters += 1
switch(vote)
if(CHAOS_NONE)
mean -= 0.1
if(CHAOS_LOW)
mean -= 0.05
if(CHAOS_HIGH)
mean += 0.05
if(CHAOS_MAX)
mean += 0.1
mean/=voters
if(voted.len != 0)
mean += (choices[PEACE]*-1+choices[CHAOS])/voted.len
GLOB.dynamic_curve_centre = mean*20
GLOB.dynamic_curve_width = CLAMP(2-abs(mean*5),0.5,4)
to_chat(world,"<span class='boldannounce'>Dynamic curve centre set to [GLOB.dynamic_curve_centre] and width set to [GLOB.dynamic_curve_width].</span>")
log_admin("Dynamic curve centre set to [GLOB.dynamic_curve_centre] and width set to [GLOB.dynamic_curve_width]")
if("map")
var/datum/map_config/VM = config.maplist[.]
message_admins("The map has been voted for and will change to: [VM.map_name]")
@@ -223,6 +252,8 @@ SUBSYSTEM_DEF(vote)
choices |= M
if("roundtype") //CIT CHANGE - adds the roundstart secret/extended vote
choices.Add("secret", "extended")
if("dynamic")
choices.Add(PEACE,CHAOS)
if("custom")
question = stripped_input(usr,"What is the vote for?")
if(!question)
@@ -379,4 +410,7 @@ SUBSYSTEM_DEF(vote)
else if(owner.ckey)
var/datum/player_details/P = GLOB.player_details[owner.ckey]
if(P)
P.player_actions -= src
P.player_actions -= src
#undef PEACE
#undef CHAOS
+7 -7
View File
@@ -74,10 +74,10 @@ SUBSYSTEM_DEF(weather)
next_hit_by_zlevel["[z]"] = null
/datum/controller/subsystem/weather/proc/get_weather(z, area/active_area)
var/datum/weather/A
for(var/V in processing)
var/datum/weather/W = V
if((z in W.impacted_z_levels) && W.area_type == active_area.type)
A = W
break
return A
var/datum/weather/A
for(var/V in processing)
var/datum/weather/W = V
if((z in W.impacted_z_levels) && W.area_type == active_area.type)
A = W
break
return A
+45 -45
View File
@@ -1,70 +1,70 @@
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]"
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
. = locate(ARMORID)
if (!.)
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
. = locate(ARMORID)
if (!.)
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
/datum/armor
datum_flags = DF_USE_TAG
var/melee
var/bullet
var/laser
var/energy
var/bomb
var/bio
var/rad
var/fire
var/acid
var/magic
datum_flags = DF_USE_TAG
var/melee
var/bullet
var/laser
var/energy
var/bomb
var/bio
var/rad
var/fire
var/acid
var/magic
/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
src.melee = melee
src.bullet = bullet
src.laser = laser
src.energy = energy
src.bomb = bomb
src.bio = bio
src.rad = rad
src.fire = fire
src.acid = acid
src.magic = magic
tag = ARMORID
src.melee = melee
src.bullet = bullet
src.laser = laser
src.energy = energy
src.bomb = bomb
src.bio = bio
src.rad = rad
src.fire = fire
src.acid = acid
src.magic = magic
tag = ARMORID
/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic)
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic)
/datum/armor/proc/modifyAllRatings(modifier = 0)
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier)
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier)
/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
return getArmor((isnull(melee) ? src.melee : melee),\
(isnull(bullet) ? src.bullet : bullet),\
(isnull(laser) ? src.laser : laser),\
(isnull(energy) ? src.energy : energy),\
(isnull(bomb) ? src.bomb : bomb),\
(isnull(bio) ? src.bio : bio),\
(isnull(rad) ? src.rad : rad),\
(isnull(fire) ? src.fire : fire),\
(isnull(acid) ? src.acid : acid),\
(isnull(magic) ? src.magic : magic))
return getArmor((isnull(melee) ? src.melee : melee),\
(isnull(bullet) ? src.bullet : bullet),\
(isnull(laser) ? src.laser : laser),\
(isnull(energy) ? src.energy : energy),\
(isnull(bomb) ? src.bomb : bomb),\
(isnull(bio) ? src.bio : bio),\
(isnull(rad) ? src.rad : rad),\
(isnull(fire) ? src.fire : fire),\
(isnull(acid) ? src.acid : acid),\
(isnull(magic) ? src.magic : magic))
/datum/armor/proc/getRating(rating)
return vars[rating]
return vars[rating]
/datum/armor/proc/getList()
return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic)
return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic)
/datum/armor/proc/attachArmor(datum/armor/AA)
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic)
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic)
/datum/armor/proc/detachArmor(datum/armor/AA)
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic)
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic)
/datum/armor/vv_edit_var(var_name, var_value)
if (var_name == NAMEOF(src, tag))
return FALSE
. = ..()
tag = ARMORID // update tag in case armor values were edited
if (var_name == NAMEOF(src, tag))
return FALSE
. = ..()
tag = ARMORID // update tag in case armor values were edited
#undef ARMORID
+1 -1
View File
@@ -194,7 +194,7 @@
.=..()
opentime = 0
/datum/browser/modal/open()
/datum/browser/modal/open(use_onclose = 1)
set waitfor = 0
opentime = world.time
+1 -1
View File
@@ -4,7 +4,7 @@
/datum/component/lockon_aiming
dupe_mode = COMPONENT_DUPE_ALLOWED
var/lock_icon = 'icons/mob/blob.dmi'
var/lock_icon = 'icons/mob/cameramob.dmi'
var/lock_icon_state = "marker"
var/mutable_appearance/lock_appearance
var/list/image/lock_images
+5 -2
View File
@@ -8,7 +8,7 @@
var/mood_level = 5 //To track what stage of moodies they're on
var/sanity_level = 5 //To track what stage of sanity they're on
var/mood_modifier = 1 //Modifier to allow certain mobs to be less affected by moodlets
var/datum/mood_event/list/mood_events = list()
var/list/datum/mood_event/mood_events = list()
var/insanity_effect = 0 //is the owner being punished for low mood? If so, how much?
var/obj/screen/mood/screen_obj
@@ -125,6 +125,9 @@
screen_obj.icon_state = "mood[mood_level]"
/datum/component/mood/process() //Called on SSmood process
if(QDELETED(parent)) // workaround to an obnoxious sneaky periodical runtime.
qdel(src)
return
var/mob/living/owner = parent
switch(mood_level)
@@ -249,7 +252,7 @@
RegisterSignal(screen_obj, COMSIG_CLICK, .proc/hud_click)
/datum/component/mood/proc/unmodify_hud(datum/source)
if(!screen_obj)
if(!screen_obj || !parent)
return
var/mob/living/owner = parent
var/datum/hud/hud = owner.hud_used
+2 -2
View File
@@ -310,10 +310,10 @@
if(!user.put_in_hands(inhand, TRUE))
qdel(inhand) // it isn't going to be added to offhands anyway
break
LAZYADD(equipped, src)
LAZYADD(equipped, inhand)
var/amount_equipped = LAZYLEN(equipped)
if(amount_equipped)
LAZYADD(offhands[L], amount_equipped)
LAZYADD(offhands[L], equipped)
if(amount_equipped >= amount_required)
return TRUE
unequip_buckle_inhands(L)
@@ -1,5 +1,5 @@
/datum/component/storage/concrete/secret_satchel/can_be_inserted(I,msg,user)
/datum/component/storage/concrete/secret_satchel/can_be_inserted(obj/item/I, stop_messages = FALSE, mob/M)
if(SSpersistence.spawned_objects[I])
to_chat(user, "<span class='warning'>[I] is unstable after its journey through space and time, it wouldn't survive another trip.</span>")
to_chat(M, "<span class='warning'>[I] is unstable after its journey through space and time, it wouldn't survive another trip.</span>")
return FALSE
return ..()
@@ -309,6 +309,7 @@
else
var/datum/numbered_display/ND = .[I.type]
ND.number++
. = sortTim(., /proc/cmp_numbered_displays_name_asc, associative = TRUE)
//This proc determines the size of the inventory to be displayed. Please touch it only if you know what you're doing.
/datum/component/storage/proc/orient2hud(mob/user, maxcolumns)
+10 -10
View File
@@ -1,15 +1,15 @@
/datum/component/waddling
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
/datum/component/waddling/Initialize()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Waddle)
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Waddle)
/datum/component/waddling/proc/Waddle()
var/mob/living/L = parent
if(L.incapacitated() || L.lying)
return
animate(L, pixel_z = 4, time = 0)
animate(pixel_z = 0, transform = turn(matrix(), pick(-12, 0, 12)), time=2)
animate(pixel_z = 0, transform = matrix(), time = 0)
var/mob/living/L = parent
if(L.incapacitated() || L.lying)
return
animate(L, pixel_z = 4, time = 0)
animate(pixel_z = 0, transform = turn(matrix(), pick(-12, 0, 12)), time=2)
animate(pixel_z = 0, transform = matrix(), time = 0)
+4 -1
View File
@@ -88,6 +88,9 @@
if(TURF_WET_PERMAFROST)
intensity = 120
lube_flags = SLIDE_ICE | GALOSHES_DONT_HELP
if(TURF_WET_SUPERLUBE)
intensity = 120
lube_flags = SLIDE | GALOSHES_DONT_HELP | SLIP_WHEN_CRAWLING
else
qdel(parent.GetComponent(/datum/component/slippery))
return
@@ -159,7 +162,7 @@
//NB it's possible we get deleted after this, due to inherit
/datum/component/wet_floor/proc/add_wet(type, duration_minimum = 0, duration_add = 0, duration_maximum = MAXIMUM_WET_TIME, _permanent = FALSE)
var/static/list/allowed_types = list(TURF_WET_WATER, TURF_WET_LUBE, TURF_WET_ICE, TURF_WET_PERMAFROST)
var/static/list/allowed_types = list(TURF_WET_WATER, TURF_WET_LUBE, TURF_WET_ICE, TURF_WET_PERMAFROST, TURF_WET_SUPERLUBE)
if(duration_minimum <= 0 || !type)
return FALSE
if(type in allowed_types)
+1 -1
View File
@@ -4,7 +4,7 @@
var/list/datum_components //for /datum/components
var/list/status_traits
var/list/comp_lookup //it used to be for looking up components which had registered a signal but now anything can register
var/list/signal_procs
var/list/list/datum/callback/signal_procs
var/signal_enabled = FALSE
var/datum_flags = NONE
var/datum/weakref/weak_reference
+8 -8
View File
@@ -875,14 +875,14 @@
return
// text2num conveniently returns a null on invalid values
O.armor = O.armor.setRating(melee = text2num(result["values"]["melee"]),\
bullet = text2num(result["values"]["bullet"]),\
laser = text2num(result["values"]["laser"]),\
energy = text2num(result["values"]["energy"]),\
bomb = text2num(result["values"]["bomb"]),\
bio = text2num(result["values"]["bio"]),\
rad = text2num(result["values"]["rad"]),\
fire = text2num(result["values"]["fire"]),\
acid = text2num(result["values"]["acid"]))
bullet = text2num(result["values"]["bullet"]),\
laser = text2num(result["values"]["laser"]),\
energy = text2num(result["values"]["energy"]),\
bomb = text2num(result["values"]["bomb"]),\
bio = text2num(result["values"]["bio"]),\
rad = text2num(result["values"]["rad"]),\
fire = text2num(result["values"]["fire"]),\
acid = text2num(result["values"]["acid"]))
log_admin("[key_name(usr)] modified the armor on [O] ([O.type]) to melee: [O.armor.melee], bullet: [O.armor.bullet], laser: [O.armor.laser], energy: [O.armor.energy], bomb: [O.armor.bomb], bio: [O.armor.bio], rad: [O.armor.rad], fire: [O.armor.fire], acid: [O.armor.acid]")
message_admins("<span class='notice'>[key_name_admin(usr)] modified the armor on [O] ([O.type]) to melee: [O.armor.melee], bullet: [O.armor.bullet], laser: [O.armor.laser], energy: [O.armor.energy], bomb: [O.armor.bomb], bio: [O.armor.bio], rad: [O.armor.rad], fire: [O.armor.fire], acid: [O.armor.acid]</span>")
else
+42 -42
View File
@@ -1,53 +1,53 @@
#define EMBEDID "embed-[embed_chance]-[embedded_fall_chance]-[embedded_pain_chance]-[embedded_pain_multiplier]-[embedded_fall_pain_multiplier]-[embedded_impact_pain_multiplier]-[embedded_unsafe_removal_pain_multiplier]-[embedded_unsafe_removal_time]"
/proc/getEmbeddingBehavior(embed_chance = EMBED_CHANCE,
embedded_fall_chance = EMBEDDED_ITEM_FALLOUT,
embedded_pain_chance = EMBEDDED_PAIN_CHANCE,
embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER,
embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER,
embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME)
. = locate(EMBEDID)
if (!.)
. = new /datum/embedding_behavior(embed_chance, embedded_fall_chance, embedded_pain_chance, embedded_pain_multiplier, embedded_fall_pain_multiplier, embedded_impact_pain_multiplier, embedded_unsafe_removal_pain_multiplier, embedded_unsafe_removal_time)
embedded_fall_chance = EMBEDDED_ITEM_FALLOUT,
embedded_pain_chance = EMBEDDED_PAIN_CHANCE,
embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER,
embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER,
embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME)
. = locate(EMBEDID)
if (!.)
. = new /datum/embedding_behavior(embed_chance, embedded_fall_chance, embedded_pain_chance, embedded_pain_multiplier, embedded_fall_pain_multiplier, embedded_impact_pain_multiplier, embedded_unsafe_removal_pain_multiplier, embedded_unsafe_removal_time)
/datum/embedding_behavior
var/embed_chance
var/embedded_fall_chance
var/embedded_pain_chance
var/embedded_pain_multiplier //The coefficient of multiplication for the damage this item does while embedded (this*w_class)
var/embedded_fall_pain_multiplier //The coefficient of multiplication for the damage this item does when falling out of a limb (this*w_class)
var/embedded_impact_pain_multiplier //The coefficient of multiplication for the damage this item does when first embedded (this*w_class)
var/embedded_unsafe_removal_pain_multiplier //The coefficient of multiplication for the damage removing this without surgery causes (this*w_class)
var/embedded_unsafe_removal_time //A time in ticks, multiplied by the w_class.
var/embed_chance
var/embedded_fall_chance
var/embedded_pain_chance
var/embedded_pain_multiplier //The coefficient of multiplication for the damage this item does while embedded (this*w_class)
var/embedded_fall_pain_multiplier //The coefficient of multiplication for the damage this item does when falling out of a limb (this*w_class)
var/embedded_impact_pain_multiplier //The coefficient of multiplication for the damage this item does when first embedded (this*w_class)
var/embedded_unsafe_removal_pain_multiplier //The coefficient of multiplication for the damage removing this without surgery causes (this*w_class)
var/embedded_unsafe_removal_time //A time in ticks, multiplied by the w_class.
/datum/embedding_behavior/New(embed_chance = EMBED_CHANCE,
embedded_fall_chance = EMBEDDED_ITEM_FALLOUT,
embedded_pain_chance = EMBEDDED_PAIN_CHANCE,
embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER,
embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER,
embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME)
src.embed_chance = embed_chance
src.embedded_fall_chance = embedded_fall_chance
src.embedded_pain_chance = embedded_pain_chance
src.embedded_pain_multiplier = embedded_pain_multiplier
src.embedded_fall_pain_multiplier = embedded_fall_pain_multiplier
src.embedded_impact_pain_multiplier = embedded_impact_pain_multiplier
src.embedded_unsafe_removal_pain_multiplier = embedded_unsafe_removal_pain_multiplier
src.embedded_unsafe_removal_time = embedded_unsafe_removal_time
tag = EMBEDID
embedded_fall_chance = EMBEDDED_ITEM_FALLOUT,
embedded_pain_chance = EMBEDDED_PAIN_CHANCE,
embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER,
embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER,
embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME)
src.embed_chance = embed_chance
src.embedded_fall_chance = embedded_fall_chance
src.embedded_pain_chance = embedded_pain_chance
src.embedded_pain_multiplier = embedded_pain_multiplier
src.embedded_fall_pain_multiplier = embedded_fall_pain_multiplier
src.embedded_impact_pain_multiplier = embedded_impact_pain_multiplier
src.embedded_unsafe_removal_pain_multiplier = embedded_unsafe_removal_pain_multiplier
src.embedded_unsafe_removal_time = embedded_unsafe_removal_time
tag = EMBEDID
/datum/embedding_behavior/proc/setRating(embed_chance, embedded_fall_chance, embedded_pain_chance, embedded_pain_multiplier, embedded_fall_pain_multiplier, embedded_impact_pain_multiplier, embedded_unsafe_removal_pain_multiplier, embedded_unsafe_removal_time)
return getEmbeddingBehavior((isnull(embed_chance) ? src.embed_chance : embed_chance),\
(isnull(embedded_fall_chance) ? src.embedded_fall_chance : embedded_fall_chance),\
(isnull(embedded_pain_chance) ? src.embedded_pain_chance : embedded_pain_chance),\
(isnull(embedded_pain_multiplier) ? src.embedded_pain_multiplier : embedded_pain_multiplier),\
(isnull(embedded_fall_pain_multiplier) ? src.embedded_fall_pain_multiplier : embedded_fall_pain_multiplier),\
(isnull(embedded_impact_pain_multiplier) ? src.embedded_impact_pain_multiplier : embedded_impact_pain_multiplier),\
(isnull(embedded_unsafe_removal_pain_multiplier) ? src.embedded_unsafe_removal_pain_multiplier : embedded_unsafe_removal_pain_multiplier),\
(isnull(embedded_unsafe_removal_time) ? src.embedded_unsafe_removal_time : embedded_unsafe_removal_time))
return getEmbeddingBehavior((isnull(embed_chance) ? src.embed_chance : embed_chance),\
(isnull(embedded_fall_chance) ? src.embedded_fall_chance : embedded_fall_chance),\
(isnull(embedded_pain_chance) ? src.embedded_pain_chance : embedded_pain_chance),\
(isnull(embedded_pain_multiplier) ? src.embedded_pain_multiplier : embedded_pain_multiplier),\
(isnull(embedded_fall_pain_multiplier) ? src.embedded_fall_pain_multiplier : embedded_fall_pain_multiplier),\
(isnull(embedded_impact_pain_multiplier) ? src.embedded_impact_pain_multiplier : embedded_impact_pain_multiplier),\
(isnull(embedded_unsafe_removal_pain_multiplier) ? src.embedded_unsafe_removal_pain_multiplier : embedded_unsafe_removal_pain_multiplier),\
(isnull(embedded_unsafe_removal_time) ? src.embedded_unsafe_removal_time : embedded_unsafe_removal_time))
#undef EMBEDID
+1 -1
View File
@@ -192,7 +192,7 @@
if (T && isturf(T))
if (!D.stat)
D.emote("scream")
D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, /mob/living/carbon/human/.Knockdown, 20))
D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, /mob/living/carbon/human.proc/Knockdown, 20))
log_combat(A, D, "has thrown with wrestling")
return 0
@@ -5,8 +5,8 @@
mood_change = -1
/datum/mood_event/broken_vow //Used for when mimes break their vow of silence
description = "<span class='boldwarning'>I have brought shame upon my name, and betrayed my fellow mimes by breaking our sacred vow...</span>\n"
mood_change = -8
description = "<span class='boldwarning'>I have brought shame upon my name, and betrayed my fellow mimes by breaking our sacred vow...</span>\n"
mood_change = -8
/datum/mood_event/on_fire
description = "<span class='boldwarning'>I'M ON FIRE!!!</span>\n"
@@ -55,14 +55,14 @@
timeout = 2 MINUTES
/datum/mood_event/shameful_suicide //suicide_acts that return SHAME, like sord
description = "<span class='boldwarning'>I can't even end it all!</span>\n"
mood_change = -10
timeout = 1 MINUTES
description = "<span class='boldwarning'>I can't even end it all!</span>\n"
mood_change = -10
timeout = 1 MINUTES
/datum/mood_event/dismembered
description = "<span class='boldwarning'>AHH! I WAS USING THAT LIMB!</span>\n"
mood_change = -8
timeout = 2400
description = "<span class='boldwarning'>AHH! I WAS USING THAT LIMB!</span>\n"
mood_change = -8
timeout = 2400
/datum/mood_event/noshoes
description = "<span class='warning'>I am a disgrace to comedy everywhere!</span>\n"
@@ -92,20 +92,20 @@
mood_change = 2
/datum/mood_event/brain_damage
mood_change = -3
mood_change = -3
/datum/mood_event/brain_damage/add_effects()
var/damage_message = pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage")
description = "<span class='warning'>Hurr durr... [damage_message]</span>\n"
var/damage_message = pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage")
description = "<span class='warning'>Hurr durr... [damage_message]</span>\n"
/datum/mood_event/hulk //Entire duration of having the hulk mutation
description = "<span class='warning'>HULK SMASH!</span>\n"
mood_change = -4
description = "<span class='warning'>HULK SMASH!</span>\n"
mood_change = -4
/datum/mood_event/epilepsy //Only when the mutation causes a seizure
description = "<span class='warning'>I should have paid attention to the epilepsy warning.</span>\n"
mood_change = -3
timeout = 3000
description = "<span class='warning'>I should have paid attention to the epilepsy warning.</span>\n"
mood_change = -3
timeout = 3000
/datum/mood_event/nyctophobia
description = "<span class='warning'>It sure is dark around here...</span>\n"
@@ -80,12 +80,12 @@
description = "<span class='nicegreen'>Heh...hehehe...hehe...</span>\n"
mood_change = 4
/datum/mood_event/chemical_laughter
/datum/mood_event/chemical_laughter
description = "<span class='nicegreen'>Laughter really is the best medicine! Or is it?</span>\n"
mood_change = 4
timeout = 3 MINUTES
/datum/mood_event/chemical_superlaughter
/datum/mood_event/chemical_superlaughter
description = "<span class='nicegreen'>*WHEEZE*</span>\n"
mood_change = 12
timeout = 3 MINUTES
+2 -2
View File
@@ -30,7 +30,7 @@ GLOBAL_LIST_EMPTY(mutations_list)
. = on_losing(owner)
/datum/mutation/human/proc/set_se(se_string, on = 1)
if(!se_string || lentext(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
if(!se_string || length(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
return
var/before = copytext(se_string, 1, ((dna_block - 1) * DNA_BLOCK_SIZE) + 1)
var/injection = num2hex(on ? rand(lowest_value, (256 * 16) - 1) : rand(0, lowest_value - 1), DNA_BLOCK_SIZE)
@@ -42,7 +42,7 @@ GLOBAL_LIST_EMPTY(mutations_list)
owner.dna.struc_enzymes = set_se(owner.dna.struc_enzymes, on)
/datum/mutation/human/proc/check_block_string(se_string)
if(!se_string || lentext(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
if(!se_string || length(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
return 0
if(hex2num(getblock(se_string, dna_block)) >= lowest_value)
return 1
+7
View File
@@ -163,6 +163,13 @@
suffix = "lavaland_surface_xeno_nest.dmm"
cost = 20 */
/datum/map_template/ruin/lavaland/alien_nest
name = "Alien Nest"
id = "alien-nest"
description = "Not even Necropolis is safe from alien infestation. The competition for hosts has locked the legion and aliens in an endless conflict that can only be resolved by a PKA."
suffix = "lavaland_surface_alien_nest.dmm"
cost = 20
/datum/map_template/ruin/lavaland/fountain
name = "Fountain Hall"
id = "fountain"
+2 -2
View File
@@ -170,7 +170,7 @@
tick_interval = 4
alert_type = /obj/screen/alert/status_effect/his_grace
var/bloodlust = 0
/obj/screen/alert/status_effect/his_grace
name = "His Grace"
desc = "His Grace hungers, and you must feed Him."
@@ -356,7 +356,7 @@
var/new_staminaloss = owner.getStaminaLoss()
if(new_staminaloss < last_staminaloss)
var/heal_amount = -5 // CIT CHANGE - makes blood drunk status effect not exhaust you
owner.adjustStaminaLoss(heal_amount, updating_health = FALSE)
owner.adjustStaminaLoss(heal_amount, FALSE)
new_staminaloss = owner.getStaminaLoss()
needs_health_update = TRUE
last_staminaloss = new_staminaloss
+2 -2
View File
@@ -11,7 +11,7 @@
//do things for each entry in Generate_list
//return value sets Generate_list[verbpath]
/datum/verbs/proc/HandleVerb(list/entry, atom/verb/verbpath, ...)
/datum/verbs/proc/HandleVerb(list/entry, procpath/verbpath, ...)
return entry
/datum/verbs/New()
@@ -82,7 +82,7 @@
. += childlist
for (var/thing in verblist)
var/atom/verb/verbpath = thing
var/procpath/verbpath = thing
if (!verbpath)
stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]")
var/list/entry = list()
@@ -80,7 +80,7 @@
return TRUE
if(ishuman(L)) //Are you immune?
var/mob/living/carbon/human/H = L
var/thermal_protection = H.get_thermal_protection()
var/thermal_protection = H.easy_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
return TRUE
if(isliving(L))// if we're a non immune mob inside an immune mob we have to reconsider if that mob is immune to protect ourselves
+36 -2
View File
@@ -1,10 +1,35 @@
/datum/wires/airlock
holder_type = /obj/machinery/door/airlock
proper_name = "Airlock"
proper_name = "Generic Airlock"
var/wiretype
/datum/wires/airlock/secure
randomize = TRUE
/datum/wires/airlock/command
proper_name = "Command Airlock"
wiretype = "commandairlock"
/datum/wires/airlock/security
proper_name = "Security Airlock"
wiretype = "securityairlock"
/datum/wires/airlock/engineering
proper_name = "Engineering Airlock"
wiretype = "engineeringairlock"
/datum/wires/airlock/science
proper_name = "Science Airlock"
wiretype = "scienceairlock"
/datum/wires/airlock/medical
proper_name = "Medical Airlock"
wiretype = "medicalairlock"
/datum/wires/airlock/cargo
proper_name = "Cargo Airlock"
wiretype = "cargoairlock"
/datum/wires/airlock/New(atom/holder)
wires = list(
WIRE_POWER1, WIRE_POWER2,
@@ -14,7 +39,16 @@
WIRE_ZAP1, WIRE_ZAP2
)
add_duds(2)
..()
. = ..()
if(randomize || !wiretype)
return
if(!GLOB.wire_color_directory[wiretype])
colors = list()
randomize()
GLOB.wire_color_directory[wiretype] = colors
GLOB.wire_name_directory[wiretype] = proper_name
else
colors = GLOB.wire_color_directory[wiretype]
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
+15
View File
@@ -250,7 +250,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/disposal/incinerator
name = "Incinerator"
icon_state = "disposal"
/area/maintenance/bar
name = "Maintenance Bar"
icon_state = "maintbar"
/area/maintenance/bar/cafe
name = "Abandoned Cafe"
//Hallway
@@ -499,6 +504,16 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Abandoned Theatre"
icon_state = "Theatre"
/area/crew_quarters/theatre/clown
name = "Clown's Office"
/area/crew_quarters/theatre/mime
name = "Mime's Office"
/area/crew_quarters/cryopod
name = "Cryogenics"
icon_state = "cryosleep"
/area/library
name = "Library"
icon_state = "library"
-3
View File
@@ -53,8 +53,6 @@
var/parallax_movedir = 0
var/global/global_uid = 0
var/uid
var/list/ambientsounds = GENERIC
flags_1 = CAN_BE_DIRTY_1
@@ -96,7 +94,6 @@ GLOBAL_LIST_EMPTY(teleportlocs)
/area/Initialize()
icon_state = ""
layer = AREA_LAYER
uid = ++global_uid
map_name = name // Save the initial (the name set in the map) name of the area.
canSmoothWithAreas = typecacheof(canSmoothWithAreas)
+10 -3
View File
@@ -186,6 +186,10 @@
else
M.forceMove(src)
//common name
/atom/proc/update_multiz(prune_on_fail = FALSE)
return FALSE
/atom/proc/assume_air(datum/gas_mixture/giver)
qdel(giver)
return null
@@ -266,7 +270,7 @@
if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED)
should_override = TRUE
if(blood_DNA && !istype(src, /obj/effect/decal))
override[EXAMINE_POSITION_BEFORE] = " blood-stained "
should_override = TRUE
@@ -563,7 +567,7 @@
//Hook for running code when a dir change occurs
/atom/proc/setDir(newdir)
/atom/proc/setDir(newdir, ismousemovement=FALSE)
SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir)
dir = newdir
@@ -832,4 +836,7 @@ Proc for attack log creation, because really why not
if(filter_data && filter_data[name])
filter_data -= name
update_filters()
return TRUE
return TRUE
/atom/proc/intercept_zImpact(atom/movable/AM, levels = 1)
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels)
+45
View File
@@ -34,6 +34,51 @@
var/datum/component/orbiter/orbiting
var/can_be_z_moved = TRUE
var/zfalling = FALSE
/atom/movable/proc/can_zFall(turf/source, levels = 1, turf/target, direction)
if(!direction)
direction = DOWN
if(!source)
source = get_turf(src)
if(!source)
return FALSE
if(!target)
target = get_step_multiz(source, direction)
if(!target)
return FALSE
return !(movement_type & FLYING) && has_gravity(source) && !throwing
/atom/movable/proc/onZImpact(turf/T, levels)
var/atom/highest = T
for(var/i in T.contents)
var/atom/A = i
if(!A.density)
continue
if(isobj(A) || ismob(A))
if(A.layer > highest.layer)
highest = A
INVOKE_ASYNC(src, .proc/SpinAnimation, 5, 2)
throw_impact(highest)
return TRUE
//For physical constraints to travelling up/down.
/atom/movable/proc/can_zTravel(turf/destination, direction)
var/turf/T = get_turf(src)
if(!T)
return FALSE
if(!direction)
if(!destination)
return FALSE
direction = get_dir(T, destination)
if(direction != UP && direction != DOWN)
return FALSE
if(!destination)
destination = get_step_multiz(src, direction)
if(!destination)
return FALSE
return T.zPassOut(src, direction, destination) && destination.zPassIn(src, direction, T)
/atom/movable/vv_edit_var(var_name, var_value)
var/static/list/banned_edits = list("step_x", "step_y", "step_size")
var/static/list/careful_edits = list("bound_x", "bound_y", "bound_width", "bound_height")
+1 -4
View File
@@ -167,6 +167,7 @@ Credit where due:
number_players -= 30
starter_servants += round(number_players / 10)
starter_servants = min(starter_servants, 8) //max 8 servants (that sould only happen with a ton of players)
GLOB.clockwork_vitality += 50 * starter_servants //some starter Vitality to help recover from initial fuck ups
while(starter_servants)
var/datum/mind/servant = antag_pick(antag_candidates)
servants_to_serve += servant
@@ -338,10 +339,6 @@ Credit where due:
CLOCKCULTCHANGELOG\
</ul>\
<hr>\
<li><b>Zelus oil:</b> A new reagent. It can be used to heal the faithful to Ratvar, or kill heretics and moreso stun blood cultists,\
or splashed onto metal sheets to make brass. This chemical can be found in minimal quantities by grinding brass sheets.\
<li><b>Brass Flasks:</b>Intended to store Zelus Oil in, but can also be used as fragile single use throwing weapons in a pinch! \
These are crafted with a single sheet of brass and fit in the Clockwork Cuirass' suit storage.\
<b>Good luck!</b>"
/obj/item/paper/servant_primer/Initialize()
@@ -138,7 +138,7 @@
var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.signal_enabled = active
/obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1)
/obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
if(active)
if(iscarbon(thrower))
var/mob/living/carbon/C = thrower
+258 -164
View File
@@ -11,15 +11,26 @@
#define RULESET_STOP_PROCESSING 1
// -- Injection delays
GLOBAL_VAR_INIT(dynamic_latejoin_delay_min, (5 MINUTES))
GLOBAL_VAR_INIT(dynamic_latejoin_delay_max, (25 MINUTES))
GLOBAL_VAR_INIT(dynamic_latejoin_delay_min, (10 MINUTES))
GLOBAL_VAR_INIT(dynamic_latejoin_delay_max, (30 MINUTES))
GLOBAL_VAR_INIT(dynamic_midround_delay_min, (15 MINUTES))
GLOBAL_VAR_INIT(dynamic_midround_delay_max, (35 MINUTES))
GLOBAL_VAR_INIT(dynamic_midround_delay_min, (10 MINUTES))
GLOBAL_VAR_INIT(dynamic_midround_delay_max, (30 MINUTES))
GLOBAL_VAR_INIT(dynamic_event_delay_min, (10 MINUTES))
GLOBAL_VAR_INIT(dynamic_event_delay_max, (30 MINUTES)) // this is on top of regular events, so can't be quite as often
// -- Roundstart injection delays
GLOBAL_VAR_INIT(dynamic_first_latejoin_delay_min, (2 MINUTES))
GLOBAL_VAR_INIT(dynamic_first_latejoin_delay_max, (30 MINUTES))
GLOBAL_VAR_INIT(dynamic_first_midround_delay_min, (20 MINUTES))
GLOBAL_VAR_INIT(dynamic_first_midround_delay_max, (30 MINUTES))
// Are HIGHLANDER_RULESETs allowed to stack?
GLOBAL_VAR_INIT(dynamic_no_stacking, TRUE)
// A number between -5 and +5.
// A number between -5 and +5.
// A negative value will give a more peaceful round and
// a positive value will give a round with higher threat.
GLOBAL_VAR_INIT(dynamic_curve_centre, 0)
@@ -27,7 +38,7 @@ GLOBAL_VAR_INIT(dynamic_curve_centre, 0)
// Higher value will favour extreme rounds and
// lower value rounds closer to the average.
GLOBAL_VAR_INIT(dynamic_curve_width, 1.8)
// If enabled only picks a single starting rule and executes only autotraitor midround ruleset.
// If enabled only picks a single starting rule and executes only autotraitor midround ruleset.
GLOBAL_VAR_INIT(dynamic_classic_secret, FALSE)
// How many roundstart players required for high population override to take effect.
GLOBAL_VAR_INIT(dynamic_high_pop_limit, 55)
@@ -38,7 +49,7 @@ GLOBAL_VAR_INIT(dynamic_forced_extended, FALSE)
GLOBAL_VAR_INIT(dynamic_stacking_limit, 90)
// List of forced roundstart rulesets.
GLOBAL_LIST_EMPTY(dynamic_forced_roundstart_ruleset)
// Forced threat level, setting this to zero or higher forces the roundstart threat to the value.
// Forced threat level, setting this to zero or higher forces the roundstart threat to the value.
GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
/datum/game_mode/dynamic
@@ -49,20 +60,28 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
announce_text = "Dynamic mode!" // This needs to be changed maybe
reroll_friendly = FALSE;
// Threat logging vars
/// The "threat cap", threat shouldn't normally go above this and is used in ruleset calculations
var/threat_level = 0
var/threat_level = 0
/// Set at the beginning of the round. Spent by the mode to "purchase" rules.
var/threat = 0
/// Starting threat level, for things that increase it but can bring it back down.
var/initial_threat_level = 0
/// Things that cause a rolling threat adjustment to be displayed at roundend.
var/list/threat_tallies = list()
/// Running information about the threat. Can store text or datum entries.
var/list/threat_log = list()
/// As above, but with info such as refunds.
var/list/threat_log_verbose = list()
/// List of roundstart rules used for selecting the rules.
var/list/roundstart_rules = list()
/// List of latejoin rules used for selecting the rules.
var/list/latejoin_rules = list()
/// List of midround rules used for selecting the rules.
var/list/midround_rules = list()
/// List of events used for reducing threat without causing antag injection (necessarily).
var/list/events = list()
/** # Pop range per requirement.
* If the value is five the range is:
* 0-4, 5-9, 10-14, 15-19, 20-24, 25-29, 30-34, 35-39, 40-54, 45+
@@ -71,15 +90,21 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
* If it is seven the range is:
* 0-6, 7-13, 14-20, 21-27, 28-34, 35-41, 42-48, 49-55, 56-62, 63+
*/
var/pop_per_requirement = 6
/// The requirement used for checking if a second rule should be selected.
var/pop_per_requirement = 9
/// The requirement used for checking if a second rule should be selected. Index based on pop_per_requirement.
var/list/second_rule_req = list(100, 100, 80, 70, 60, 50, 30, 20, 10, 0)
/// The requirement used for checking if a third rule should be selected.
/// The probability for a second ruleset with index being every ten threat.
var/list/second_rule_prob = list(0,0,60,80,80,80,100,100,100,100)
/// The requirement used for checking if a third rule should be selected. Index based on pop_per_requirement.
var/list/third_rule_req = list(100, 100, 100, 90, 80, 70, 60, 50, 40, 30)
/// Threat requirement for a second ruleset when high pop override is in effect.
/// The probability for a third ruleset with index being every ten threat.
var/list/third_rule_prob = list(0,0,0,0,60,60,80,90,100,100)
/// Threat requirement for a second ruleset when high pop override is in effect.
var/high_pop_second_rule_req = 40
/// Threat requirement for a third ruleset when high pop override is in effect.
/// Threat requirement for a third ruleset when high pop override is in effect.
var/high_pop_third_rule_req = 60
/// The amount of additional rulesets waiting to be picked.
var/extra_rulesets_amount = 0
/// Number of players who were ready on roundstart.
var/roundstart_pop_ready = 0
/// List of candidates used on roundstart rulesets.
@@ -94,6 +119,8 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
var/latejoin_injection_cooldown = 0
/// When world.time is over this number the mode tries to inject a midround ruleset.
var/midround_injection_cooldown = 0
/// When wor.dtime is over this number the mode tries to do an event.
var/event_injection_cooldown = 0
/// When TRUE GetInjectionChance returns 100.
var/forced_injection = FALSE
/// Forced ruleset to be executed for the next latejoin.
@@ -106,19 +133,33 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
var/highlander_executed = FALSE
/// If a only ruleset has been executed.
var/only_ruleset_executed = FALSE
/// Antags rolled by rules so far, to keep track of and discourage scaling past a certain ratio of crew/antags especially on lowpop.
var/antags_rolled = 0
/datum/game_mode/dynamic/New() // i have NO IDEA if this is the proper way to do this.
..()
pop_per_requirement = CONFIG_GET(number/dynamic_pop_per_requirement)
second_rule_req = CONFIG_GET(number_list/dynamic_second_rule_requirements)
third_rule_req = CONFIG_GET(number_list/dynamic_third_rule_requirements)
if(second_rule_req.len<10)
second_rule_req = list(101, 101, 101, 101, 100, 90, 80, 70, 60, 50)
if(third_rule_req.len<10)
third_rule_req = list(101, 101, 101, 101, 101, 100, 90, 80, 70, 60)
high_pop_second_rule_req = CONFIG_GET(number/dynamic_second_rule_high_pop_requirement)
high_pop_third_rule_req = CONFIG_GET(number/dynamic_third_rule_high_pop_requirement)
GLOB.dynamic_high_pop_limit = CONFIG_GET(number/dynamic_high_pop_limit)
GLOB.dynamic_latejoin_delay_min = CONFIG_GET(number/dynamic_latejoin_delay_min)*600
GLOB.dynamic_latejoin_delay_max = CONFIG_GET(number/dynamic_latejoin_delay_max)*600
GLOB.dynamic_midround_delay_min = CONFIG_GET(number/dynamic_midround_delay_min)*600
GLOB.dynamic_midround_delay_max = CONFIG_GET(number/dynamic_midround_delay_max)*600
GLOB.dynamic_first_latejoin_delay_min = CONFIG_GET(number/dynamic_first_latejoin_delay_min)*600
GLOB.dynamic_first_latejoin_delay_max = CONFIG_GET(number/dynamic_first_latejoin_delay_max)*600
GLOB.dynamic_first_midround_delay_min = CONFIG_GET(number/dynamic_first_midround_delay_min)*600
GLOB.dynamic_first_midround_delay_max = CONFIG_GET(number/dynamic_first_midround_delay_max)*600
/datum/game_mode/dynamic/admin_panel()
var/list/dat = list("<html><head><title>Game Mode Panel</title></head><body><h1><B>Game Mode Panel</B></h1>")
dat += "Dynamic Mode <a href='?_src_=vars;[HrefToken()];Vars=[REF(src)]'>\[VV\]</A><BR>"
dat += "Dynamic Mode <a href='?_src_=vars;[HrefToken()];Vars=[REF(src)]'>\[VV\]</A><a href='?src=\ref[src];[HrefToken()]'>\[Refresh\]</A><BR>"
dat += "Threat Level: <b>[threat_level]</b><br/>"
dat += "Threat to Spend: <b>[threat]</b> <a href='?src=\ref[src];[HrefToken()];adjustthreat=1'>\[Adjust\]</A> <a href='?src=\ref[src];[HrefToken()];threatlog=1'>\[View Log\]</a><br/>"
@@ -140,6 +181,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
dat += "<br>Injection Timers: (<b>[get_injection_chance(TRUE)]%</b> chance)<BR>"
dat += "Latejoin: [(latejoin_injection_cooldown-world.time)>60*10 ? "[round((latejoin_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(latejoin_injection_cooldown-world.time)] seconds"] <a href='?src=\ref[src];[HrefToken()];injectlate=1'>\[Now!\]</a><BR>"
dat += "Midround: [(midround_injection_cooldown-world.time)>60*10 ? "[round((midround_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(midround_injection_cooldown-world.time)] seconds"] <a href='?src=\ref[src];[HrefToken()];injectmid=1'>\[Now!\]</a><BR>"
dat += "Event: [(event_injection_cooldown-world.time)>60*10 ? "[round((event_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(event_injection_cooldown-world.time)] seconds"] <a href='?src=\ref[src];[HrefToken()];forceevent=1'>\[Now!\]</a><BR>"
usr << browse(dat.Join(), "window=gamemode_panel;size=500x500")
/datum/game_mode/dynamic/Topic(href, href_list)
@@ -171,11 +213,15 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
midround_injection_cooldown = 0
forced_injection = TRUE
message_admins("[key_name(usr)] forced a midround injection.", 1)
else if (href_list["forceevent"])
event_injection_cooldown = 0
// events always happen anyway
message_admins("[key_name(usr)] forced an event.", 1)
else if (href_list["threatlog"])
show_threatlog(usr)
else if (href_list["stacking_limit"])
GLOB.dynamic_stacking_limit = input(usr,"Change the threat limit at which round-endings rulesets will start to stack.", "Change stacking limit", null) as num
admin_panel() // Refreshes the window
// Checks if there are HIGHLANDER_RULESETs and calls the rule's round_result() proc
@@ -193,30 +239,33 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
/datum/game_mode/dynamic/send_intercept()
. = "<b><i>Central Command Status Summary</i></b><hr>"
switch(round(threat_level))
if(0 to 19)
update_playercounts()
if(!current_players[CURRENT_LIVING_ANTAGS].len)
. += "<b>Peaceful Waypoint</b></center><BR>"
. += "Your station orbits deep within controlled, core-sector systems and serves as a waypoint for routine traffic through Nanotrasen's trade empire. Due to the combination of high security, interstellar traffic, and low strategic value, it makes any direct threat of violence unlikely. Your primary enemies will be incompetence and bored crewmen: try to organize team-building events to keep staffers interested and productive."
else
if(0 to 20)
. += "<b>Peaceful Waypoint</b></center><BR>"
. += "Your station orbits deep within controlled, core-sector systems and serves as a waypoint for routine traffic through Nanotrasen's trade empire. Due to the combination of high security, interstellar traffic, and low strategic value, it makes any direct threat of violence unlikely. Your primary enemies will be incompetence and bored crewmen: try to organize team-building events to keep staffers interested and productive. However, even deep in our territory there may be subversive elements, especially for such a high-value target as your station. Keep an eye out, but don't expect much trouble."
set_security_level(SEC_LEVEL_GREEN)
if(21 to 79)
var/perc_green = 100-round(100*((threat_level-21)/(79-21)))
if(prob(perc_green))
. += "<b>Core Territory</b></center><BR>"
. += "Your station orbits within reliably mundane, secure space. Although Nanotrasen has a firm grip on security in your region, the valuable resources and strategic position aboard your station make it a potential target for infiltrations. Monitor crew for non-loyal behavior, but expect a relatively tame shift free of large-scale destruction. We expect great things from your station."
if(20 to 39)
. += "<b>Anomalous Exogeology</b></center><BR>"
. += "Although your station lies within what is generally considered Nanotrasen-controlled space, the course of its orbit has caused it to cross unusually close to exogeological features with anomalous readings. Although these features offer opportunities for our research department, it is known that these little understood readings are often correlated with increased activity from competing interstellar organizations and individuals, among them the Wizard Federation and Cult of the Geometer of Blood - all known competitors for Anomaly Type B sites. Exercise elevated caution."
if(40 to 65)
. += "<b>Contested System</b></center><BR>"
. += "Your station's orbit passes along the edge of Nanotrasen's sphere of influence. While subversive elements remain the most likely threat against your station, hostile organizations are bolder here, where our grip is weaker. Exercise increased caution against elite Syndicate strike forces, or Executives forbid, some kind of ill-conceived unionizing attempt."
if(66 to 79)
. += "<b>Uncharted Space</b></center><BR>"
. += "Congratulations and thank you for participating in the NT 'Frontier' space program! Your station is actively orbiting a high value system far from the nearest support stations. Little is known about your region of space, and the opportunity to encounter the unknown invites greater glory. You are encouraged to elevate security as necessary to protect Nanotrasen assets."
set_security_level(SEC_LEVEL_GREEN)
else if(prob(perc_green))
. += "<b>Contested System</b></center><BR>"
. += "Your station's orbit passes along the edge of Nanotrasen's sphere of influence. While subversive elements remain the most likely threat against your station, hostile organizations are bolder here, where our grip is weaker. Exercise increased caution against elite Syndicate strike forces, or Executives forbid, some kind of ill-conceived unionizing attempt."
set_security_level(SEC_LEVEL_BLUE)
else
. += "<b>Uncharted Space</b></center><BR>"
. += "Congratulations and thank you for participating in the NT 'Frontier' space program! Your station is actively orbiting a high value system far from the nearest support stations. Little is known about your region of space, and the opportunity to encounter the unknown invites greater glory. You are encouraged to elevate security as necessary to protect Nanotrasen assets."
set_security_level(SEC_LEVEL_BLUE)
if(80 to 99)
. += "<b>Black Orbit</b></center><BR>"
. += "As part of a mandatory security protocol, we are required to inform you that as a result of your orbital pattern directly behind an astrological body (oriented from our nearest observatory), your station will be under decreased monitoring and support. It is anticipated that your extreme location and decreased surveillance could pose security risks. Avoid unnecessary risks and attempt to keep your station in one piece."
set_security_level(SEC_LEVEL_AMBER)
if(100)
. += "<b>Impending Doom</b></center><BR>"
. += "Your station is somehow in the middle of hostile territory, in clear view of any enemy of the corporation. Your likelihood to survive is low, and station destruction is expected and almost inevitable. Secure any sensitive material and neutralize any enemy you will come across. It is important that you at least try to maintain the station.<BR>"
. += "Good luck."
set_security_level(SEC_LEVEL_RED)
if(station_goals.len)
. += "<hr><b>Special Orders for [station_name()]:</b>"
@@ -225,9 +274,10 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
. += G.get_report()
print_command_report(., "Central Command Status Summary", announce=FALSE)
priority_announce("A summary has been copied and printed to all communications consoles.", "Security level elevated.", "intercept")
if(GLOB.security_level < SEC_LEVEL_BLUE)
set_security_level(SEC_LEVEL_BLUE)
if(GLOB.security_level >= SEC_LEVEL_BLUE)
priority_announce("A summary has been copied and printed to all communications consoles.", "Security level elevated.", "intercept")
else
priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no likely threats to [station_name()]. Have a secure shift!", "Security Report", "commandreport")
// Yes, this is copy pasted from game_mode
/datum/game_mode/dynamic/check_finished(force_ending)
@@ -245,6 +295,11 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if(rule.flags & HIGHLANDER_RULESET)
return rule.check_finished()
/datum/game_mode/dynamic/proc/log_threat(var/log_str,var/verbose = FALSE)
threat_log_verbose += ("[worldtime2text()]: "+log_str)
if(!verbose)
threat_log += log_str
/datum/game_mode/dynamic/proc/show_threatlog(mob/admin)
if(!SSticker.HasRoundStarted())
alert("The round hasn't started yet!")
@@ -253,9 +308,9 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if(!check_rights(R_ADMIN))
return
var/list/out = list("<TITLE>Threat Log</TITLE><B><font size='3'>Threat Log</font></B><br><B>Starting Threat:</B> [threat_level]<BR>")
var/list/out = list("<TITLE>Threat Log</TITLE><B><font size='3'>Threat Log</font></B><br><B>Starting Threat:</B> [initial_threat_level]<BR>")
for(var/entry in threat_log)
for(var/entry in threat_log_verbose)
if(istext(entry))
out += "[entry]<BR>"
@@ -273,15 +328,6 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
threat = threat_level
/datum/game_mode/dynamic/can_start()
/* Disabled for now, had some changes that need to be tested and this might interfere with that.
if(GLOB.dynamic_curve_centre == 0)
// 10 is when the centre starts to decrease
// 6 is just 1 + 5 (from the maximum value and the one decreased)
// 1 just makes the curve look better, I don't know.
// Limited between 1 and 5 then inverted and rounded
// With this you get a centre curve that stays at -5 until 10 then first rapidly decreases but slows down at the end
GLOB.dynamic_curve_centre = round(-CLAMP((10*6/GLOB.player_list.len)-1, 0, 5), 0.5)
*/
message_admins("Dynamic mode parameters for the round:")
message_admins("Centre is [GLOB.dynamic_curve_centre], Width is [GLOB.dynamic_curve_width], Forced extended is [GLOB.dynamic_forced_extended ? "Enabled" : "Disabled"], No stacking is [GLOB.dynamic_no_stacking ? "Enabled" : "Disabled"].")
message_admins("Stacking limit is [GLOB.dynamic_stacking_limit], Classic secret is [GLOB.dynamic_classic_secret ? "Enabled" : "Disabled"], High population limit is [GLOB.dynamic_high_pop_limit].")
@@ -294,12 +340,17 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
else
generate_threat()
var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_latejoin_delay_max + GLOB.dynamic_latejoin_delay_min)
latejoin_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_latejoin_delay_min, GLOB.dynamic_latejoin_delay_max)) + world.time
var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_latejoin_delay_max + GLOB.dynamic_first_latejoin_delay_min)
latejoin_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_first_latejoin_delay_min, GLOB.dynamic_first_latejoin_delay_max)) + world.time
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_midround_delay_max + GLOB.dynamic_midround_delay_min)
midround_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_midround_delay_min, GLOB.dynamic_midround_delay_max)) + world.time
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_midround_delay_min + GLOB.dynamic_first_midround_delay_max)
midround_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_first_midround_delay_min, GLOB.dynamic_first_midround_delay_max)) + world.time
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
event_injection_cooldown = (round(CLAMP(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) + world.time)
log_game("DYNAMIC: Dynamic Mode initialized with a Threat Level of... [threat_level]!")
initial_threat_level = threat_level
return TRUE
/datum/game_mode/dynamic/pre_setup()
@@ -316,24 +367,30 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if ("Midround")
if (ruleset.weight)
midround_rules += ruleset
if("Event")
if(ruleset.weight)
events += ruleset
for(var/mob/dead/new_player/player in GLOB.player_list)
if(player.ready == PLAYER_READY_TO_PLAY && player.mind)
roundstart_pop_ready++
candidates.Add(player)
log_game("DYNAMIC: Listing [roundstart_rules.len] round start rulesets, and [candidates.len] players ready.")
if (candidates.len <= 0)
log_game("DYNAMIC: [candidates.len] candidates.")
return TRUE
if (roundstart_rules.len <= 0)
log_game("DYNAMIC: [roundstart_rules.len] rules.")
return TRUE
if(GLOB.dynamic_forced_roundstart_ruleset.len > 0)
rigged_roundstart()
else
else
roundstart()
var/starting_rulesets = ""
for (var/datum/dynamic_ruleset/roundstart/DR in executed_rules)
starting_rulesets += "[DR.name], "
log_game("DYNAMIC: Picked the following roundstart rules: [starting_rulesets]")
candidates.Cut()
return TRUE
@@ -341,9 +398,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
update_playercounts()
for(var/datum/dynamic_ruleset/roundstart/rule in executed_rules)
rule.candidates.Cut() // The rule should not use candidates at this point as they all are null.
if(!rule.execute())
stack_trace("The starting rule \"[rule.name]\" failed to execute.")
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_roundstart_rule, rule), rule.delay)
..()
/// A simple roundstart proc used when dynamic_forced_roundstart_ruleset has rules in it.
@@ -354,6 +409,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
message_admins("Drafting players for forced ruleset [rule.name].")
log_game("DYNAMIC: Drafting players for forced ruleset [rule.name].")
rule.mode = src
rule.acceptable(GLOB.player_list.len, threat_level) // Assigns some vars in the modes, running it here for consistency
rule.candidates = candidates.Copy()
rule.trim_candidates()
if (rule.ready(TRUE))
@@ -365,18 +421,20 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
return TRUE
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/roundstart/rule in roundstart_rules)
if (rule.acceptable(roundstart_pop_ready, threat_level) && threat >= rule.cost) // If we got the population and threat required
if (rule.acceptable(GLOB.player_list.len, threat_level) && threat >= rule.cost) // If we got the population and threat required
rule.candidates = candidates.Copy()
rule.trim_candidates()
if (rule.ready() && rule.candidates.len > 0)
drafted_rules[rule] = rule.weight
var/indice_pop = min(10,round(roundstart_pop_ready/pop_per_requirement)+1)
var/extra_rulesets_amount = 0
if(!drafted_rules.len)
message_admins("Not enough threat level for roundstart antags!")
log_game("DYNAMIC: Not enough threat level for roundstart antags!")
var/indice_pop = min(10,round(GLOB.player_list.len/pop_per_requirement)+1)
extra_rulesets_amount = 0
if (GLOB.dynamic_classic_secret)
extra_rulesets_amount = 0
else
if (roundstart_pop_ready > GLOB.dynamic_high_pop_limit)
if (GLOB.player_list.len > GLOB.dynamic_high_pop_limit)
message_admins("High Population Override is in effect! Threat Level will have more impact on which roles will appear, and player population less.")
log_game("DYNAMIC: High Population Override is in effect! Threat Level will have more impact on which roles will appear, and player population less.")
if (threat_level > high_pop_second_rule_req)
@@ -384,23 +442,28 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if (threat_level > high_pop_third_rule_req)
extra_rulesets_amount++
else
if (threat_level >= second_rule_req[indice_pop])
var/threat_indice = min(10, max(round(threat_level ? threat_level/10 : 1), 1)) // 0-9 threat = 1, 10-19 threat = 2 ...
if (threat_level >= second_rule_req[indice_pop] && prob(second_rule_prob[threat_indice]))
extra_rulesets_amount++
if (threat_level >= third_rule_req[indice_pop])
if (threat_level >= third_rule_req[indice_pop] && prob(third_rule_prob[threat_indice]))
extra_rulesets_amount++
log_game("DYNAMIC: Trying to roll [extra_rulesets_amount + 1] roundstart rulesets. Picking from [drafted_rules.len] eligible rulesets.")
if (drafted_rules.len > 0 && picking_roundstart_rule(drafted_rules))
if (extra_rulesets_amount > 0) // We've got enough population and threat for a second rulestart rule
log_game("DYNAMIC: First ruleset picked successfully. [extra_rulesets_amount] remaining.")
while(extra_rulesets_amount > 0 && drafted_rules.len > 0) // We had enough threat for one or two more rulesets
for (var/datum/dynamic_ruleset/roundstart/rule in drafted_rules)
if (rule.cost > threat)
drafted_rules -= rule
if (drafted_rules.len > 0 && picking_roundstart_rule(drafted_rules))
if (extra_rulesets_amount > 1) // We've got enough population and threat for a third rulestart rule
for (var/datum/dynamic_ruleset/roundstart/rule in drafted_rules)
if (rule.cost > threat)
drafted_rules -= rule
picking_roundstart_rule(drafted_rules)
if(drafted_rules.len)
picking_roundstart_rule(drafted_rules)
extra_rulesets_amount--
log_game("DYNAMIC: Additional ruleset picked successfully, now [executed_rules.len] picked. [extra_rulesets_amount] remaining.")
else
if(threat >= 50)
message_admins("DYNAMIC: Picking first roundstart ruleset failed. You should report this.")
log_game("DYNAMIC: Picking first roundstart ruleset failed. drafted_rules.len = [drafted_rules.len] and threat = [threat]/[threat_level]")
return FALSE
return TRUE
@@ -408,68 +471,74 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
/datum/game_mode/dynamic/proc/picking_roundstart_rule(list/drafted_rules = list(), forced = FALSE)
var/datum/dynamic_ruleset/roundstart/starting_rule = pickweight(drafted_rules)
if(!starting_rule)
log_game("DYNAMIC: Couldn't pick a starting ruleset. No rulesets available")
return FALSE
if(!forced)
if(only_ruleset_executed)
return FALSE
// Check if a blocking ruleset has been executed.
else if(check_blocking(starting_rule.blocking_rules, executed_rules))
else if(check_blocking(starting_rule.blocking_rules, executed_rules)) // Should already be filtered out, but making sure. Check filtering at end of proc if reported.
drafted_rules -= starting_rule
if(drafted_rules.len <= 0)
log_game("DYNAMIC: Picking [starting_rule.name] failed due to blocking_rules and no more rulesets available. Report this.")
return FALSE
starting_rule = pickweight(drafted_rules)
// Check if the ruleset is highlander and if a highlander ruleset has been executed
else if(starting_rule.flags & HIGHLANDER_RULESET)
if(threat < GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
else if(starting_rule.flags & HIGHLANDER_RULESET) // Should already be filtered out, but making sure. Check filtering at end of proc if reported.
if(threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
if(highlander_executed)
drafted_rules -= starting_rule
if(drafted_rules.len <= 0)
log_game("DYNAMIC: Picking [starting_rule.name] failed due to no highlander stacking and no more rulesets available. Report this.")
return FALSE
starting_rule = pickweight(drafted_rules)
// With low pop and high threat there might be rulesets that get executed with no valid candidates.
else if(!starting_rule.ready()) // Should already be filtered out, but making sure. Check filtering at end of proc if reported.
drafted_rules -= starting_rule
if(drafted_rules.len <= 0)
log_game("DYNAMIC: Picking [starting_rule.name] failed because there were not enough candidates and no more rulesets available. Report this.")
return FALSE
starting_rule = pickweight(drafted_rules)
log_game("DYNAMIC: Picking a [istype(starting_rule, /datum/dynamic_ruleset/roundstart/delayed/) ? " delayed " : ""] ruleset [starting_rule.name]")
log_game("DYNAMIC: Picked a ruleset: [starting_rule.name]")
roundstart_rules -= starting_rule
drafted_rules -= starting_rule
if (istype(starting_rule, /datum/dynamic_ruleset/roundstart/delayed/))
var/datum/dynamic_ruleset/roundstart/delayed/rule = starting_rule
addtimer(CALLBACK(src, .proc/execute_delayed, rule), rule.delay)
starting_rule.trim_candidates()
var/added_threat = starting_rule.scale_up(extra_rulesets_amount, threat)
if (starting_rule.pre_execute())
spend_threat(starting_rule.cost)
threat_log += "[worldtime2text()]: Roundstart [starting_rule.name] spent [starting_rule.cost]"
spend_threat(starting_rule.cost + added_threat)
log_threat("[starting_rule.ruletype] - <b>[starting_rule.name]</b> -[starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat")
if(starting_rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
else if(starting_rule.flags & ONLY_RULESET)
only_ruleset_executed = TRUE
executed_rules += starting_rule
if (starting_rule.persistent)
current_rules += starting_rule
for(var/mob/M in starting_rule.assigned)
for (var/datum/dynamic_ruleset/roundstart/rule in roundstart_rules)
if (!rule.ready())
drafted_rules -= rule // And removing rules that are no longer elligible
for(var/datum/dynamic_ruleset/roundstart/rule in drafted_rules)
if(check_blocking(rule.blocking_rules, executed_rules))
drafted_rules -= rule
if(highlander_executed && rule.flags & HIGHLANDER_RULESET)
drafted_rules -= rule
if(!rule.ready())
drafted_rules -= rule // And removing rules that are no longer eligible
return TRUE
else
stack_trace("The starting rule \"[starting_rule.name]\" failed to pre_execute.")
return FALSE
/// Executes delayed roundstart rules and has a hack in it.
/datum/game_mode/dynamic/proc/execute_delayed(datum/dynamic_ruleset/roundstart/delayed/rule)
update_playercounts()
rule.candidates = current_players[CURRENT_LIVING_PLAYERS].Copy()
rule.trim_candidates()
/// Mainly here to facilitate delayed rulesets. All roundstart rulesets are executed with a timered callback to this proc.
/datum/game_mode/dynamic/proc/execute_roundstart_rule(sent_rule)
var/datum/dynamic_ruleset/rule = sent_rule
if(rule.execute())
executed_rules += rule
if (rule.persistent)
if(rule.persistent)
current_rules += rule
return TRUE
else
stack_trace("The delayed roundstart rule \"[rule.name]\" failed to execute.")
return FALSE
rule.clean_up() // Refund threat, delete teams and so on.
executed_rules -= rule
stack_trace("The starting rule \"[rule.name]\" failed to execute.")
return FALSE
/// Picks a random midround OR latejoin rule from the list given as an argument and executes it.
/// Also this could be named better.
@@ -477,7 +546,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
var/datum/dynamic_ruleset/rule = pickweight(drafted_rules)
if(!rule)
return FALSE
if(!forced)
if(only_ruleset_executed)
return FALSE
@@ -489,23 +558,75 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
rule = pickweight(drafted_rules)
// Check if the ruleset is highlander and if a highlander ruleset has been executed
else if(rule.flags & HIGHLANDER_RULESET)
if(threat < GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
if(threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
if(highlander_executed)
drafted_rules -= rule
if(drafted_rules.len <= 0)
return FALSE
rule = pickweight(drafted_rules)
if(!rule.repeatable)
if(rule.ruletype == "Latejoin")
latejoin_rules = remove_from_list(latejoin_rules, rule.type)
else if(rule.type == "Midround")
else if(rule.ruletype == "Midround")
midround_rules = remove_from_list(midround_rules, rule.type)
else if(rule.ruletype == "Event")
events = remove_from_list(events,rule.type)
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_midround_latejoin_rule, rule), rule.delay)
return TRUE
/// An experimental proc to allow admins to call rules on the fly or have rules call other rules.
/datum/game_mode/dynamic/proc/picking_specific_rule(ruletype, forced = FALSE)
var/datum/dynamic_ruleset/midround/new_rule
if(ispath(ruletype))
new_rule = new ruletype() // You should only use it to call midround rules though.
else if(istype(ruletype, /datum/dynamic_ruleset))
new_rule = ruletype
else
return FALSE
if(!new_rule)
return FALSE
if(!forced)
if(only_ruleset_executed)
return FALSE
// Check if a blocking ruleset has been executed.
else if(check_blocking(new_rule.blocking_rules, executed_rules))
return FALSE
// Check if the ruleset is highlander and if a highlander ruleset has been executed
else if(new_rule.flags & HIGHLANDER_RULESET)
if(threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
if(highlander_executed)
return FALSE
update_playercounts()
if ((forced || (new_rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && new_rule.cost <= threat)))
new_rule.trim_candidates()
if (new_rule.ready(forced))
spend_threat(new_rule.cost)
log_threat("[new_rule.ruletype] - <b>[new_rule.name]</b> -[new_rule.cost] threat")
if (new_rule.execute()) // This should never fail since ready() returned 1
if(new_rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
else if(new_rule.flags & ONLY_RULESET)
only_ruleset_executed = TRUE
log_game("DYNAMIC: Making a call to a specific ruleset...[new_rule.name]!")
executed_rules += new_rule
if (new_rule.persistent)
current_rules += new_rule
return TRUE
else if (forced)
log_game("DYNAMIC: The ruleset [new_rule.name] couldn't be executed due to lack of eligible players.")
return FALSE
/// Mainly here to facilitate delayed rulesets. All midround/latejoin rulesets are executed with a timered callback to this proc.
/datum/game_mode/dynamic/proc/execute_midround_latejoin_rule(sent_rule)
var/datum/dynamic_ruleset/rule = sent_rule
if (rule.execute())
log_game("DYNAMIC: Injected a [rule.ruletype == "latejoin" ? "latejoin" : "midround"] ruleset [rule.name].")
spend_threat(rule.cost)
threat_log += "[worldtime2text()]: [rule.ruletype] [rule.name] spent [rule.cost]"
log_threat("[rule.ruletype] [rule.name] spent [rule.cost]")
if(rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
else if(rule.flags & ONLY_RULESET)
@@ -519,54 +640,8 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if (rule.persistent)
current_rules += rule
return TRUE
else
stack_trace("The [rule.ruletype] rule \"[rule.name]\" failed to execute.")
return FALSE
/// An experimental proc to allow admins to call rules on the fly or have rules call other rules.
/datum/game_mode/dynamic/proc/picking_specific_rule(ruletype, forced = FALSE)
var/datum/dynamic_ruleset/midround/new_rule
if(ispath(ruletype))
new_rule = new ruletype() // You should only use it to call midround rules though.
else if(istype(ruletype, /datum/dynamic_ruleset))
new_rule = ruletype
else
return FALSE
if(!new_rule)
return FALSE
if(!forced)
if(only_ruleset_executed)
return FALSE
// Check if a blocking ruleset has been executed.
else if(check_blocking(new_rule.blocking_rules, executed_rules))
return FALSE
// Check if the ruleset is highlander and if a highlander ruleset has been executed
else if(new_rule.flags & HIGHLANDER_RULESET)
if(threat < GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
if(highlander_executed)
return FALSE
update_playercounts()
if ((forced || (new_rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && new_rule.cost <= threat)))
new_rule.candidates = current_players.Copy()
new_rule.trim_candidates()
if (new_rule.ready(forced))
spend_threat(new_rule.cost)
threat_log += "[worldtime2text()]: Forced rule [new_rule.name] spent [new_rule.cost]"
if (new_rule.execute()) // This should never fail since ready() returned 1
if(new_rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
else if(new_rule.flags & ONLY_RULESET)
only_ruleset_executed = TRUE
log_game("DYNAMIC: Making a call to a specific ruleset...[new_rule.name]!")
executed_rules += new_rule
if (new_rule.persistent)
current_rules += new_rule
return TRUE
else if (forced)
log_game("DYNAMIC: The ruleset [new_rule.name] couldn't be executed due to lack of elligible players.")
rule.clean_up()
stack_trace("The [rule.ruletype] rule \"[rule.name]\" failed to execute.")
return FALSE
/datum/game_mode/dynamic/process()
@@ -581,35 +656,54 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if (midround_injection_cooldown < world.time)
if (GLOB.dynamic_forced_extended)
return
// Somehow it manages to trigger midround multiple times so this was moved here.
// Somehow it managed to trigger midround multiple times so this was moved here.
// There is no way this should be able to trigger an injection twice now.
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_midround_delay_max + GLOB.dynamic_midround_delay_min)
midround_injection_cooldown = (round(CLAMP(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_midround_delay_min, GLOB.dynamic_midround_delay_max)) + world.time)
// Time to inject some threat into the round
if(EMERGENCY_ESCAPED_OR_ENDGAMED) // Unless the shuttle is gone
return
message_admins("DYNAMIC: Checking for midround injection.")
log_game("DYNAMIC: Checking for midround injection.")
log_game("DYNAMIC: Checking state of the round.")
update_playercounts()
if (prob(get_injection_chance()))
if (get_injection_chance())
var/cur_threat_frac = threat/threat_level
var/list/drafted_rules = list()
var/antag_num = current_players[CURRENT_LIVING_ANTAGS].len
for (var/datum/dynamic_ruleset/midround/rule in midround_rules)
// if there are antags OR the rule is an antag rule, antag_acceptable will be true.
if (rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && threat >= rule.cost)
// Classic secret : only autotraitor/minor roles
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
rule.candidates = list()
rule.candidates = current_players.Copy()
rule.trim_candidates()
if (rule.ready() && rule.candidates.len > 0)
drafted_rules[rule] = rule.get_weight()
if (rule.ready())
if(!antag_num)
drafted_rules[rule] = round(rule.get_weight() + (rule.cost * cur_threat_frac))
else
drafted_rules[rule] = rule.get_weight()
if (drafted_rules.len > 0)
picking_midround_latejoin_rule(drafted_rules)
else
midround_injection_cooldown = (midround_injection_cooldown + world.time)/2
if(event_injection_cooldown < world.time)
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
event_injection_cooldown = (round(CLAMP(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) + world.time)
message_admins("DYNAMIC: Doing event injection.")
log_game("DYNAMIC: Doing event injection.")
update_playercounts()
var/list/drafted_rules = list()
for(var/datum/dynamic_ruleset/event/rule in events)
if(rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && threat >= rule.cost)
if(rule.ready())
drafted_rules[rule] = rule.get_weight()
if(drafted_rules.len > 0)
picking_midround_latejoin_rule(drafted_rules)
/// Updates current_players.
/datum/game_mode/dynamic/proc/update_playercounts()
current_players[CURRENT_LIVING_PLAYERS] = list()
@@ -641,7 +735,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
var/high_pop_factor = (current_players[CURRENT_LIVING_PLAYERS].len >= GLOB.dynamic_high_pop_limit)
var/max_pop_per_antag = max(5,15 - round(threat_level/10) - round(current_players[CURRENT_LIVING_PLAYERS].len/(high_pop_factor ? 10 : 5)))
if (!current_players[CURRENT_LIVING_ANTAGS].len)
chance += 50 // No antags at all? let's boost those odds!
chance += 80 // No antags at all? let's boost those odds!
else
var/current_pop_per_antag = current_players[CURRENT_LIVING_PLAYERS].len / current_players[CURRENT_LIVING_ANTAGS].len
if (current_pop_per_antag > max_pop_per_antag)
@@ -704,11 +798,11 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
// Classic secret : only autotraitor/minor roles
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
// No stacking : only one round-enter, unless > stacking_limit threat.
if (threat < GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
// No stacking : only one round-ender, unless threat level > stacking_limit.
if (threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
if(rule.flags & HIGHLANDER_RULESET && highlander_executed)
continue
rule.candidates = list(newPlayer)
rule.trim_candidates()
if (rule.ready())
+90 -69
View File
@@ -1,22 +1,28 @@
#define EXTRA_RULESET_PENALTY 20 // Changes how likely a gamemode is to scale based on how many other roundstart rulesets are waiting to be rolled.
#define POP_SCALING_PENALTY 50 // Discourages scaling up rulesets if ratio of antags to crew is high.
#define REVOLUTION_VICTORY 1
#define STATION_VICTORY 2
/datum/dynamic_ruleset
/// For admin logging and round end screen.
var/name = ""
/// For admin logging and round end screen, do not change this unless making a new rule type.
var/ruletype = ""
var/ruletype = ""
/// For config purposes, similar to config_tag for secret game modes.
var/config_tag = null
/// If set to TRUE, the rule won't be discarded after being executed, and dynamic will call rule_process() every time it ticks.
var/persistent = FALSE
var/persistent = FALSE
/// If set to TRUE, dynamic mode will be able to draft this ruleset again later on. (doesn't apply for roundstart rules)
var/repeatable = FALSE
var/repeatable = FALSE
/// If set higher than 0 decreases weight by itself causing the ruleset to appear less often the more it is repeated.
var/repeatable_weight_decrease = 2
var/repeatable_weight_decrease = 2
/// List of players that are being drafted for this rule
var/list/mob/candidates = list()
var/list/mob/candidates = list()
/// List of players that were selected for this rule
var/list/datum/mind/assigned = list()
var/list/datum/mind/assigned = list()
/// Preferences flag such as ROLE_WIZARD that need to be turned on for players to be antag
var/antag_flag = null
var/antag_flag = null
/// The antagonist datum that is assigned to the mobs mind on ruleset execution.
var/datum/antagonist/antag_datum = null
/// The required minimum account age for this ruleset.
@@ -24,19 +30,25 @@
/// If set, and config flag protect_roles_from_antagonist is false, then the rule will not pick players from these roles.
var/list/protected_roles = list()
/// If set, rule will deny candidates from those roles always.
var/list/restricted_roles = list()
var/list/restricted_roles = list()
/// If set, rule will only accept candidates from those roles, IMPORTANT: DOES NOT WORK ON ROUNDSTART RULESETS.
var/list/exclusive_roles = list()
var/list/exclusive_roles = list()
/// If set, there needs to be a certain amount of players doing those roles (among the players who won't be drafted) for the rule to be drafted IMPORTANT: DOES NOT WORK ON ROUNDSTART RULESETS.
var/list/enemy_roles = list()
var/list/enemy_roles = list()
/// If enemy_roles was set, this is the amount of enemy job workers needed per threat_level range (0-10,10-20,etc) IMPORTANT: DOES NOT WORK ON ROUNDSTART RULESETS.
var/required_enemies = list(1,1,0,0,0,0,0,0,0,0)
var/required_enemies = list(1,1,0,0,0,0,0,0,0,0)
/// The rule needs this many candidates (post-trimming) to be executed (example: Cult needs 4 players at round start)
var/required_candidates = 0
var/required_candidates = 0
/// 1 -> 9, probability for this rule to be picked against other rules
var/weight = 5
var/weight = 5
/// Threat cost for this rule, this is decreased from the mode's threat when the rule is executed.
var/cost = 0
var/cost = 0
/// Cost per level the rule scales up.
var/scaling_cost = 0
/// How many times a rule has scaled up upon getting picked.
var/scaled_times = 0
/// Used for the roundend report
var/total_cost = 0
/// A flag that determines how the ruleset is handled
/// HIGHLANDER_RULESET are rulesets can end the round.
/// TRAITOR_RULESET and MINOR_RULESET can't end the round and have no difference right now.
@@ -46,20 +58,28 @@
/// Requirements are the threat level requirements per pop range.
/// With the default values, The rule will never get drafted below 10 threat level (aka: "peaceful extended"), and it requires a higher threat level at lower pops.
var/list/requirements = list(40,30,20,10,10,10,10,10,10,10)
/// An alternative, static requirement used instead when pop is over mode's high_pop_limit.
/// An alternative, static requirement used instead when pop is over mode's high_pop_limit.
var/high_population_requirement = 10
/// Reference to the mode, use this instead of SSticker.mode.
var/datum/game_mode/dynamic/mode = null
/// If a role is to be considered another for the purpose of banning.
var/antag_flag_override = null
var/antag_flag_override = null
/// If a ruleset type which is in this list has been executed, then the ruleset will not be executed.
var/list/blocking_rules = list()
/// The minimum amount of players required for the rule to be considered.
/// The minimum amount of players required for the rule to be considered.
var/minimum_players = 0
/// The maximum amount of players required for the rule to be considered.
/// Anything below zero or exactly zero is ignored.
/// Anything below zero or exactly zero is ignored.
var/maximum_players = 0
/// Calculated during acceptable(), used in scaling and team sizes.
var/indice_pop = 0
/// Population scaling. Used by team antags and scaling for solo antags.
var/list/antag_cap = list()
/// Base probability used in scaling. The higher it is, the more likely to scale. Kept as a var to allow for config editing._SendSignal(sigtype, list/arguments)
var/base_prob = 60
/// Delay for when execute will get called from the time of post_setup (roundstart) or process (midround/latejoin).
/// Make sure your ruleset works with execute being called during the game when using this, and that the clean_up proc reverts it properly in case of faliure.
var/delay = 0
/datum/dynamic_ruleset/New()
..()
@@ -87,10 +107,6 @@
/datum/dynamic_ruleset/roundstart // One or more of those drafted at roundstart
ruletype = "Roundstart"
/datum/dynamic_ruleset/roundstart/delayed/ // Executed with a 30 seconds delay
var/delay = 30 SECONDS
var/required_type = /mob/living/carbon/human // No ghosts, new players or silicons allowed.
// Can be drafted when a player joins the server
/datum/dynamic_ruleset/latejoin
ruletype = "Latejoin"
@@ -103,17 +119,48 @@
if(maximum_players > 0 && population > maximum_players)
return FALSE
if (population >= GLOB.dynamic_high_pop_limit)
return (threat_level >= high_population_requirement)
indice_pop = 10
if(threat_level < high_population_requirement)
log_game("DYNAMIC: [name] did not reach threat level threshold: [threat_level]/[high_population_requirement]")
return FALSE
else
return TRUE
else
pop_per_requirement = pop_per_requirement > 0 ? pop_per_requirement : mode.pop_per_requirement
var/indice_pop = min(10,round(population/pop_per_requirement)+1)
return (threat_level >= requirements[indice_pop])
if(antag_cap.len && requirements.len != antag_cap.len)
message_admins("DYNAMIC: requirements and antag_cap lists have different lengths in ruleset [name]. Likely config issue, report this.")
log_game("DYNAMIC: requirements and antag_cap lists have different lengths in ruleset [name]. Likely config issue, report this.")
indice_pop = min(requirements.len,round(population/pop_per_requirement)+1)
if(threat_level < requirements[indice_pop])
log_game("DYNAMIC: [name] did not reach threat level threshold: [threat_level]/[requirements[indice_pop]]")
return FALSE
else
return TRUE
/// Called when a suitable rule is picked during roundstart(). Will some times attempt to scale a rule up when there is threat remaining. Returns the amount of scaled steps.
/datum/dynamic_ruleset/proc/scale_up(extra_rulesets = 0, remaining_threat_level = 0)
remaining_threat_level -= cost
if(scaling_cost && scaling_cost <= remaining_threat_level) // Only attempts to scale the modes with a scaling cost explicitly set.
var/new_prob
var/pop_to_antags = (mode.antags_rolled + (antag_cap[indice_pop] * (scaled_times + 1))) / mode.roundstart_pop_ready
log_game("DYNAMIC: [name] roundstart ruleset attempting to scale up with [extra_rulesets] rulesets waiting and [remaining_threat_level] threat remaining.")
for(var/i in 1 to 3) //Can scale a max of 3 times
if(remaining_threat_level >= scaling_cost && pop_to_antags < 0.25)
new_prob = base_prob + (remaining_threat_level) - (scaled_times * scaling_cost) - (extra_rulesets * EXTRA_RULESET_PENALTY) - (pop_to_antags * POP_SCALING_PENALTY)
if (!prob(new_prob))
break
remaining_threat_level -= scaling_cost
scaled_times++
pop_to_antags = (mode.antags_rolled + (antag_cap[indice_pop] * (scaled_times + 1))) / mode.roundstart_pop_ready
log_game("DYNAMIC: [name] roundstart ruleset failed scaling up at [new_prob ? new_prob : 0]% chance after [scaled_times]/3 successful scaleups. [remaining_threat_level] threat remaining, antag to crew ratio: [pop_to_antags*100]%.")
mode.antags_rolled += (1 + scaled_times) * antag_cap[indice_pop]
return scaled_times * scaling_cost
/// This is called if persistent variable is true everytime SSTicker ticks.
/datum/dynamic_ruleset/proc/rule_process()
return
/// Called on game mode pre_setup, used for non-delayed roundstart rulesets only.
/// Called on game mode pre_setup for roundstart rulesets.
/// Do everything you need to do before job is assigned here.
/// IMPORTANT: ASSIGN special_role HERE
/datum/dynamic_ruleset/proc/pre_execute()
@@ -126,20 +173,20 @@
M.add_antag_datum(antag_datum)
return TRUE
/// Called after delay set in ruleset.
/// Give your candidates or assignees equipment and antag datum here.
/datum/dynamic_ruleset/roundstart/delayed/execute()
if (SSticker && SSticker.current_state < GAME_STATE_PLAYING)
CRASH("The delayed ruleset [name] executed before the round started.")
/// Here you can perform any additional checks you want. (such as checking the map etc)
/// Remember that on roundstart no one knows what their job is at this point.
/// IMPORTANT: If ready() returns TRUE, that means pre_execute() or execute() should never fail!
/datum/dynamic_ruleset/proc/ready(forced = 0)
if (required_candidates > candidates.len)
/datum/dynamic_ruleset/proc/ready(forced = 0)
if (required_candidates > candidates.len)
return FALSE
return TRUE
/// Runs from gamemode process() if ruleset fails to start, like delayed rulesets not getting valid candidates.
/// This one only handles refunding the threat, override in ruleset to clean up the rest.
/datum/dynamic_ruleset/proc/clean_up()
mode.refund_threat(cost + (scaled_times * scaling_cost))
mode.log_threat("[ruletype] [name] refunded [cost + (scaled_times * scaling_cost)]",verbose=TRUE)
/// Gets weight of the ruleset
/// Note that this decreases weight if repeatable is TRUE and repeatable_weight_decrease is higher than 0
/// Note: If you don't want repeatable rulesets to decrease their weight use the weight variable directly
@@ -156,14 +203,6 @@
/datum/dynamic_ruleset/proc/trim_candidates()
return
/// Counts how many players are ready at roundstart.
/// Used only by non-delayed roundstart rulesets.
/datum/dynamic_ruleset/proc/num_players()
. = 0
for(var/mob/dead/new_player/P in GLOB.player_list)
if(P.client && P.ready == PLAYER_READY_TO_PLAY)
. ++
/// Set mode result and news report here.
/// Only called if ruleset is flagged as HIGHLANDER_RULESET
/datum/dynamic_ruleset/proc/round_result()
@@ -191,32 +230,14 @@
if(P.mind.special_role) // We really don't want to give antag to an antag.
candidates.Remove(P)
continue
if (!(antag_flag in P.client.prefs.be_special) || jobban_isbanned(P.ckey, list(antag_flag, ROLE_SYNDICATE)) || (antag_flag_override && jobban_isbanned(P.ckey, list(antag_flag_override, ROLE_SYNDICATE))))//are they willing and not antag-banned?
candidates.Remove(P)
continue
/// Checks if candidates are required mob type, connected, banned and if the job is exclusive to the role.
/datum/dynamic_ruleset/roundstart/delayed/trim_candidates()
. = ..()
for (var/mob/P in candidates)
if (!istype(P, required_type))
candidates.Remove(P) // Can be a new_player, etc.
continue
if(!mode.check_age(P.client, minimum_required_age))
candidates.Remove(P)
continue
if (!P.client || !P.mind || !P.mind.assigned_role) // Are they connected?
candidates.Remove(P)
continue
if(P.mind.special_role || P.mind.antag_datums?.len > 0) // Are they an antag already?
candidates.Remove(P)
continue
if (!(antag_flag in P.client.prefs.be_special) || jobban_isbanned(P.ckey, list(antag_flag, ROLE_SYNDICATE)) || (antag_flag_override && jobban_isbanned(P.ckey, list(antag_flag_override, ROLE_SYNDICATE))))//are they willing and not antag-banned?
candidates.Remove(P)
continue
if ((exclusive_roles.len > 0) && !(P.mind.assigned_role in exclusive_roles)) // Is the rule exclusive to their job?
candidates.Remove(P)
continue
if(antag_flag_override)
if(!(antag_flag_override in P.client.prefs.be_special) || jobban_isbanned(P.ckey, antag_flag_override))
candidates.Remove(P)
continue
else
if(!(antag_flag in P.client.prefs.be_special) || jobban_isbanned(P.ckey, antag_flag))
candidates.Remove(P)
continue
/// Do your checks if the ruleset is ready to be executed here.
/// Should ignore certain checks if forced is TRUE
@@ -0,0 +1,345 @@
/datum/dynamic_ruleset/event
ruletype = "Event"
var/typepath // typepath of the event
var/triggering
/datum/dynamic_ruleset/event/execute()
var/datum/round_event/E = new typepath()
E.current_players = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1)
// E.control = src // can't be done! we just don't use events that require these, those can be from_ghost almost always
testing("[time2text(world.time, "hh:mm:ss")] [E.type]")
deadchat_broadcast("<span class='deadsay'><b>[name]</b> has just been triggered by dynamic!</span>")
log_game("Random Event triggering: [name] ([typepath])")
return E
/datum/dynamic_ruleset/event/ready(forced = FALSE) // same as midround cause we're still using enemy system
if (!forced)
var/job_check = 0
if (enemy_roles.len > 0)
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
if (M.stat == DEAD)
continue // Dead players cannot count as opponents
if (M.mind && M.mind.assigned_role && (M.mind.assigned_role in enemy_roles))
job_check++ // Checking for "enemies" (such as sec officers). To be counters, they must either not be candidates to that rule, or have a job that restricts them from it
var/threat = round(mode.threat_level/10)
if (job_check < required_enemies[threat])
return FALSE
return TRUE
//////////////////////////////////////////////
// //
// PIRATES //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/event/pirates
name = "Space Pirates"
config_tag = "pirates"
typepath = /datum/round_event/pirates
antag_flag = ROLE_TRAITOR
enemy_roles = list("AI","Security Officer","Head of Security","Captain")
required_enemies = list(2,2,1,1,0,0,0,0,0,0)
weight = 5
cost = 10
blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear)
requirements = list(70,60,50,50,40,40,40,30,20,15)
high_population_requirement = 15
/datum/dynamic_ruleset/event/pirates/ready(forced = FALSE)
if (!SSmapping.empty_space)
return FALSE
return ..()
//////////////////////////////////////////////
// //
// SPIDERS //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/event/spiders
name = "Spider Infestation"
config_tag = "spiders"
typepath = /datum/round_event/spider_infestation
enemy_roles = list("AI","Security Officer","Head of Security","Captain")
required_enemies = list(2,2,1,1,0,0,0,0,0,0)
weight = 5
cost = 10
requirements = list(70,60,50,50,40,40,40,30,20,15)
high_population_requirement = 15
//////////////////////////////////////////////
// //
// CLOGGED VENTS //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/event/ventclog
name = "Clogged Vents"
config_tag = "ventclog"
typepath = /datum/round_event/vent_clog
enemy_roles = list("Chemist","Medical Doctor","Chief Medical Officer")
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
cost = 2
weight = 4
repeatable_weight_decrease = 3
requirements = list(5,5,5,5,5,5,5,5,5,5) // yes, can happen on fake-extended
high_population_requirement = 5
repeatable = TRUE
/datum/dynamic_ruleset/event/ventclog/ready()
if(mode.threat_level > 30 && mode.threat >= 5 && prob(20))
name = "Clogged Vents: Threatening"
cost = 5
required_enemies = list(3,3,3,2,2,2,1,1,1,1)
typepath = /datum/round_event/vent_clog/threatening
else if(mode.threat_level > 15 && mode.threat > 15 && prob(30))
name = "Clogged Vents: Catastrophic"
cost = 15
required_enemies = list(2,2,1,1,1,1,0,0,0,0)
typepath = /datum/round_event/vent_clog/catastrophic
else
cost = 2
name = "Clogged Vents: Normal"
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
typepath = /datum/round_event/vent_clog
return ..()
//////////////////////////////////////////////
// //
// ION STORM //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/event/ion_storm
name = "Ion Storm"
config_tag = "ion_storm"
typepath = /datum/round_event/ion_storm
enemy_roles = list("Research Director","Captain","Chief Engineer")
required_enemies = list(1,1,0,0,0,0,0,0,0,0)
weight = 4
// no repeatable weight decrease. too variable to be unfun multiple times in one round
cost = 3
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
//////////////////////////////////////////////
// //
// METEORS //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/event/meteor_wave
name = "Meteor Wave"
config_tag = "meteor_wave"
typepath = /datum/round_event/meteor_wave
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Captain","Cyborg")
required_enemies = list(3,3,3,3,3,3,3,3,3,3)
cost = 15
weight = 3
repeatable_weight_decrease = 2
requirements = list(60,50,40,30,30,30,30,30,30,30)
high_population_requirement = 30
/datum/dynamic_ruleset/event/meteor_wave/ready()
if(mode.threat_level > 40 && mode.threat >= 25 && prob(20))
cost = 25
typepath = /datum/round_event/meteor_wave/threatening
else if(mode.threat_level > 50 && mode.threat >= 40 && prob(30))
cost = 40
typepath = /datum/round_event/meteor_wave/catastrophic
else
cost = 15
typepath = /datum/round_event/meteor_wave
return ..()
//////////////////////////////////////////////
// //
// ANOMALIES //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/event/anomaly_bluespace
name = "Anomaly: Bluespace"
config_tag = "anomaly_bluespace"
typepath = /datum/round_event/anomaly/anomaly_bluespace
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain")
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
weight = 2
repeatable_weight_decrease = 1
cost = 3
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
/datum/dynamic_ruleset/event/anomaly_flux
name = "Anomaly: Hyper-Energetic Flux"
config_tag = "anomaly_flux"
typepath = /datum/round_event/anomaly/anomaly_flux
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain")
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
weight = 2
repeatable_weight_decrease = 1
cost = 5
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 10
repeatable = TRUE
/datum/dynamic_ruleset/event/anomaly_gravitational
name = "Anomaly: Gravitational"
config_tag = "anomaly_gravitational"
typepath = /datum/round_event/anomaly/anomaly_grav
weight = 2
repeatable_weight_decrease = 1
cost = 3
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
/datum/dynamic_ruleset/event/anomaly_pyroclastic
name = "Anomaly: Pyroclastic"
config_tag = "anomaly_pyroclastic"
typepath = /datum/round_event/anomaly/anomaly_pyro
weight = 2
repeatable_weight_decrease = 1
cost = 5
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain","Cyborg")
required_enemies = list(1,1,1,1,1,1,1,1,1,1)
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
/datum/dynamic_ruleset/event/anomaly_vortex
name = "Anomaly: Vortex"
config_tag = "anomaly_vortex"
typepath = /datum/round_event/anomaly/anomaly_vortex
weight = 2
repeatable_weight_decrease = 1
cost = 5
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain","Cyborg")
required_enemies = list(1,1,1,1,1,1,1,1,1,1)
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
//////////////////////////////////////////////
// //
// WOW THAT'S A LOT OF EVENTS //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/event/brand_intelligence
name = "Brand Intelligence"
config_tag = "brand_intelligence"
typepath = /datum/round_event/brand_intelligence
weight = 1
repeatable_weight_decrease = 1
cost = 2
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain","Cyborg")
required_enemies = list(1,1,1,1,0,0,0,0,0,0)
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
/datum/dynamic_ruleset/event/carp_migration
name = "Carp Migration"
config_tag = "carp_migration"
typepath = /datum/round_event/carp_migration
weight = 7
repeatable_weight_decrease = 3
cost = 4
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
/datum/dynamic_ruleset/event/communications_blackout
name = "Communications Blackout"
config_tag = "communications_blackout"
typepath = /datum/round_event/communications_blackout
cost = 4
weight = 2
repeatable_weight_decrease = 3
enemy_roles = list("Chief Engineer","Station Engineer")
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
/datum/dynamic_ruleset/event/processor_overload
name = "Processor Overload"
config_tag = "processor_overload"
typepath = /datum/round_event/processor_overload
cost = 4
weight = 2
repeatable_weight_decrease = 3
enemy_roles = list("Chief Engineer","Station Engineer")
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
/datum/dynamic_ruleset/event/space_dust
name = "Minor Space Dust"
config_tag = "space_dust"
typepath = /datum/round_event/space_dust
cost = 2
weight = 2
repeatable_weight_decrease = 1
enemy_roles = list("Chief Engineer","Station Engineer")
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
/datum/dynamic_ruleset/event/major_dust
name = "Major Space Dust"
config_tag = "major_dust"
typepath = /datum/round_event/meteor_wave/major_dust
cost = 4
weight = 2
repeatable_weight_decrease = 1
enemy_roles = list("Chief Engineer","Station Engineer")
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
/datum/dynamic_ruleset/event/electrical_storm
name = "Electrical Storm"
config_tag = "electrical_storm"
typepath = /datum/round_event/electrical_storm
cost = 1
weight = 2
repeatable_weight_decrease = 1
enemy_roles = list("Chief Engineer","Station Engineer")
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
/datum/dynamic_ruleset/event/heart_attack
name = "Random Heart Attack"
config_tag = "heart_attack"
typepath = /datum/round_event/heart_attack
cost = 3
weight = 2
repeatable_weight_decrease = 1
enemy_roles = list("Medical Doctor","Chief Medical Officer")
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
requirements = list(101,101,101,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
/datum/dynamic_ruleset/event/radiation_storm
name = "Radiation Storm"
config_tag = "radiation_storm"
typepath = /datum/round_event/radiation_storm
cost = 3
weight = 1
enemy_roles = list("Chemist","Chief Medical Officer","Geneticist","Medical Doctor","AI","Captain")
required_enemies = list(1,1,1,1,1,1,1,1,1,1)
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
@@ -12,9 +12,14 @@
if(!mode.check_age(P.client, minimum_required_age))
candidates.Remove(P)
continue
if (!(antag_flag in P.client.prefs.be_special) || jobban_isbanned(P.ckey, list(antag_flag, ROLE_SYNDICATE)) || (antag_flag_override && jobban_isbanned(P.ckey, list(antag_flag_override))))//are they willing and not antag-banned?
candidates.Remove(P)
continue
if(antag_flag_override)
if(!(antag_flag_override in P.client.prefs.be_special) || jobban_isbanned(P.ckey, list(antag_flag_override)))
candidates.Remove(P)
continue
else
if(!(antag_flag in P.client.prefs.be_special) || jobban_isbanned(P.ckey, list(antag_flag, ROLE_SYNDICATE)))
candidates.Remove(P)
continue
if (P.mind.assigned_role in restricted_roles) // Does their job allow for it?
candidates.Remove(P)
continue
@@ -60,8 +65,8 @@
required_candidates = 1
weight = 7
cost = 5
requirements = list(40,30,20,10,10,10,10,10,10,10)
high_population_requirement = 10
requirements = list(40,30,20,15,15,15,15,15,15,15)
high_population_requirement = 15
repeatable = TRUE
flags = TRAITOR_RULESET
@@ -73,40 +78,138 @@
/datum/dynamic_ruleset/latejoin/provocateur
name = "Provocateur"
persistent = TRUE
config_tag = "latejoin_revolution"
antag_datum = /datum/antagonist/rev/head
antag_flag = ROLE_REV_HEAD
antag_flag_override = ROLE_REV
restricted_roles = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
enemy_roles = list("AI", "Cyborg", "Security Officer","Detective","Head of Security", "Captain", "Warden")
required_enemies = list(2,2,1,1,1,1,1,0,0,0)
required_enemies = list(4,4,3,3,3,3,3,2,2,1)
required_candidates = 1
weight = 2
delay = 1 MINUTES // Prevents rule start while head is offstation.
cost = 20
requirements = list(101,101,70,40,30,20,20,20,20,20)
high_population_requirement = 50
requirements = list(101,101,70,40,40,40,40,40,40,40)
high_population_requirement = 40
flags = HIGHLANDER_RULESET
var/required_heads = 3
var/required_heads_of_staff = 3
var/finished = FALSE
var/datum/team/revolution/revolution
/datum/dynamic_ruleset/latejoin/provocateur/ready(forced=FALSE)
if (forced)
required_heads = 1
required_heads_of_staff = 1
if(!..())
return FALSE
var/head_check = 0
for(var/mob/player in mode.current_players[CURRENT_LIVING_PLAYERS])
if (player.mind.assigned_role in GLOB.command_positions)
head_check++
return (head_check >= required_heads)
return (head_check >= required_heads_of_staff)
/datum/dynamic_ruleset/latejoin/provocateur/execute()
var/mob/M = pick(candidates)
assigned += M.mind
M.mind.special_role = antag_flag
var/datum/antagonist/rev/head/new_head = new()
new_head.give_flash = TRUE
new_head.give_hud = TRUE
new_head.remove_clumsy = TRUE
new_head = M.mind.add_antag_datum(new_head)
new_head.rev_team.max_headrevs = 1 // Only one revhead if it is latejoin.
var/mob/M = pick(candidates) // This should contain a single player, but in case.
if(check_eligible(M.mind)) // Didnt die/run off z-level/get implanted since leaving shuttle.
assigned += M.mind
M.mind.special_role = antag_flag
revolution = new()
var/datum/antagonist/rev/head/new_head = new()
new_head.give_flash = TRUE
new_head.give_hud = TRUE
new_head.remove_clumsy = TRUE
new_head = M.mind.add_antag_datum(new_head, revolution)
revolution.update_objectives()
revolution.update_heads()
SSshuttle.registerHostileEnvironment(src)
return TRUE
else
log_game("DYNAMIC: [ruletype] [name] discarded [M.name] from head revolutionary due to ineligibility.")
log_game("DYNAMIC: [ruletype] [name] failed to get any eligible headrevs. Refunding [cost] threat.")
return FALSE
/datum/dynamic_ruleset/latejoin/provocateur/rule_process()
if(check_rev_victory())
finished = REVOLUTION_VICTORY
return RULESET_STOP_PROCESSING
else if (check_heads_victory())
finished = STATION_VICTORY
SSshuttle.clearHostileEnvironment(src)
priority_announce("It appears the mutiny has been quelled. Please return yourself and your colleagues to work. \
We have remotely blacklisted the head revolutionaries from your cloning software to prevent accidental cloning.", null, "attention", null, "Central Command Loyalty Monitoring Division")
for(var/datum/mind/M in revolution.members) // Remove antag datums and prevent headrev cloning then restarting rebellions.
if(M.has_antag_datum(/datum/antagonist/rev/head))
var/datum/antagonist/rev/head/R = M.has_antag_datum(/datum/antagonist/rev/head)
R.remove_revolutionary(FALSE, "gamemode")
var/mob/living/carbon/C = M.current
if(C.stat == DEAD)
C.makeUncloneable()
if(M.has_antag_datum(/datum/antagonist/rev))
var/datum/antagonist/rev/R = M.has_antag_datum(/datum/antagonist/rev)
R.remove_revolutionary(FALSE, "gamemode")
return RULESET_STOP_PROCESSING
/// Checks for revhead loss conditions and other antag datums.
/datum/dynamic_ruleset/latejoin/provocateur/proc/check_eligible(var/datum/mind/M)
var/turf/T = get_turf(M.current)
if(!considered_afk(M) && considered_alive(M) && is_station_level(T.z) && !M.antag_datums?.len && !HAS_TRAIT(M, TRAIT_MINDSHIELD))
return TRUE
return FALSE
/datum/dynamic_ruleset/latejoin/provocateur/check_finished()
if(finished == REVOLUTION_VICTORY)
return TRUE
else
return ..()
/datum/dynamic_ruleset/latejoin/provocateur/proc/check_rev_victory()
for(var/datum/objective/mutiny/objective in revolution.objectives)
if(!(objective.check_completion()))
return FALSE
return TRUE
/datum/dynamic_ruleset/latejoin/provocateur/proc/check_heads_victory()
for(var/datum/mind/rev_mind in revolution.head_revolutionaries())
var/turf/T = get_turf(rev_mind.current)
if(!considered_afk(rev_mind) && considered_alive(rev_mind) && is_station_level(T.z))
if(ishuman(rev_mind.current) || ismonkey(rev_mind.current))
return FALSE
return TRUE
/datum/dynamic_ruleset/latejoin/provocateur/round_result()
if(finished == REVOLUTION_VICTORY)
SSticker.mode_result = "win - heads killed"
SSticker.news_report = REVS_WIN
else if(finished == STATION_VICTORY)
SSticker.mode_result = "loss - rev heads killed"
SSticker.news_report = REVS_LOSE
//////////////////////////////////////////////
// //
// VAMPIRE //
// //
//////////////////////////////////////////////
/*
/datum/dynamic_ruleset/latejoin/vampire
name = "vampire"
config_tag = "vampire_latejoin"
antag_flag = ROLE_VAMPIRE
antag_datum = ANTAG_DATUM_VAMPIRE
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain")
restricted_roles = list("AI", "Cyborg")
required_candidates = 1
weight = 5
cost = 15
requirements = list(80,70,60,50,40,20,20,15,15,15)
repeatable = TRUE
high_population_requirement = 15
/datum/dynamic_ruleset/latejoin/vampire/pre_execute()
var/mob/M = pick(candidates)
candidates -= M
assigned += M.mind
M.mind.restricted_roles = restricted_roles
M.mind.special_role = ROLE_VAMPIRE
return TRUE
*/

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