Added New Mods

Added
- MRAA + Blindside Military Animation Pack
- Dynamic Zone Transitions
- Corpse Twitching
- Artifact Inspection
- Animated Lead Box
This commit is contained in:
2025-01-17 23:53:41 -05:00
parent 2009ca2711
commit fd1ec3a2ba
797 changed files with 20762 additions and 145 deletions
@@ -0,0 +1,9 @@
; This file is used to spawn additional anomalies alongside
; the dynamic ones for spots that do not have any level IDs
; LTXs only with the map name excluding any suffixes
; contain section declarations for vanilla transitions.
;
; Also have a look in transition_settings.ltx. There, we
; define the amount actually spawned for those transitions.
#include "static_spawns_*.ltx"
@@ -0,0 +1,77 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; AGROPROM
;[agr_space_restrictor_to_garbage_1]
;[agr_space_restrictor_to_garbage_2]
[agr_space_restrictor_to_marsh_1]
38 = 7.1278715133667, -1.1934068202972, -329.45394897461, 204779, 874
39 = 4.8432908058167, -2.1126570701599, -328.99157714844, 202917, 874
40 = 5.1247625350952, -0.84827768802643, -325.54443359375, 202922, 874
41 = 8.2897596359253, 0.96960097551346, -324.41470336914, 205418, 874
42 = 6.828905582428, 0.92622298002243, -321.46881103516, 204791, 874
43 = 1.7108774185181, -0.23149189352989, -318.39694213867, 199849, 874
44 = 0.34228760004044, -0.39086857438087, -316.57531738281, 199187, 874
45 = 2.2392160892487, 0.12310338020325, -313.48403930664, 202329, 874
46 = 5.3186836242676, 1.0852041244507, -313.17834472656, 203548, 874
47 = 8.5272331237793, 2.0534398555756, -316.30099487305, 206050, 874
48 = 11.474328994751, 2.9087827205658, -316.94378662109, 206690, 874
49 = 9.1935129165649, 2.4477939605713, -312.71032714844, 205435, 874
50 = 3.7447240352631, 0.62608486413956, -311.57556152344, 202330, 874
51 = -12.604326248169, -4.0735487937927, -321.56134033203, 187406, 874
52 = -15.236064910889, -2.7933685779572, -322.3337097168, 185063, 874
53 = -18.818815231323, -1.5740978717804, -325.36010742188, 181383, 874
54 = -20.372766494751, -0.73312258720398, -327.40264892578, 180745, 874
55 = -21.849370956421, 0.36907207965851, -330.72998046875, 179455, 874
56 = -21.442398071289, 0.77996963262558, -332.85009765625, 179451, 874
57 = -24.501438140869, 1.5999574661255, -331.29150390625, 177045, 874
58 = -23.180507659912, 0.36972212791443, -328.09155273438, 178216, 874
59 = -16.364517211914, 0.028274089097977, -331.66854858398, 184451, 874
60 = -13.307909011841, -0.65463227033615, -329.76510620117, 186825, 874
61 = -8.8884792327881, -1.8423039913177, -328.80386352539, 190157, 874
62 = -8.2067403793335, -0.92648035287857, -331.23333740234, 190753, 874
63 = -10.008470535278, 0.17145177721977, -333.39004516602, 189603, 874
64 = -10.739408493042, 0.87095266580582, -335.55523681641, 188501, 874
65 = -8.3304328918457, 0.46548253297806, -335.75073242188, 189601, 874
66 = -6.162814617157, -0.38622558116913, -333.88061523438, 192608, 874
67 = -2.8659353256226, -1.168829202652, -333.94152832031, 195798, 874
68 = -13.629974365234, 0.56860786676407, -333.41137695312, 186820, 874
69 = -11.512769699097, -1.1493105888367, -328.119140625, 188511, 874
70 = -13.862146377563, -1.9250459671021, -326.015625, 186243, 874
[agr_space_restrictor_to_yantar_1]
2 = -228.71862792969, 17.283645629883, 219.88198852539, 10141, 875
3 = -227.18379211426, 20.052219390869, 221.7829284668, 11358, 875
4 = -225.3427734375, 19.830532073975, 219.40946960449, 11358, 875
5 = -224.56454467773, 16.730308532715, 215.50811767578, 11358, 875
6 = -221.85592651367, 17.125350952148, 214.43397521973, 13197, 875
7 = -220.40197753906, 20.030179977417, 216.35032653809, 13197, 875
8 = -221.66473388672, 22.210523605347, 219.9490814209, 13197, 875
9 = -218.17512512207, 22.903377532959, 218.92083740234, 13197, 875
10 = -216.8176574707, 21.744396209717, 215.5354309082, 13197, 875
11 = -217.9914855957, 18.492328643799, 213.15667724609, 13197, 875
12 = -220.68180847168, 17.03003692627, 212.7431640625, 15031, 875
13 = -220.41815185547, 15.218297958374, 210.10562133789, 15649, 875
14 = -217.93209838867, 15.829367637634, 208.58068847656, 16921, 875
15 = -215.70448303223, 18.300731658936, 209.74096679688, 16922, 875
16 = -213.96231079102, 21.021488189697, 211.60934448242, 16922, 875
17 = -211.09765625, 23.071792602539, 213.79759216309, 23638, 875
18 = -211.00421142578, 21.200790405273, 209.48559570312, 24988, 875
19 = -213.41175842285, 18.462162017822, 208.00715637207, 24988, 875
20 = -216.7603302002, 14.689471244812, 205.80545043945, 18158, 875
21 = -231.83657836914, 17.119812011719, 205.20013427734, 8924, 875
22 = -232.09478759766, 19.049312591553, 201.79345703125, 8924, 875
23 = -228.12683105469, 16.591115951538, 201.20237731934, 10730, 875
24 = -227.77778625488, 17.418581008911, 199.41741943359, 11946, 875
25 = -226.54742431641, 17.551170349121, 197.40985107422, 11946, 875
26 = -224.73565673828, 16.278217315674, 197.30642700195, 13792, 875
27 = -226.15870666504, 18.232265472412, 194.63040161133, 15012, 875
28 = -228.84385681152, 19.237617492676, 193.45780944824, 15012, 875
29 = -230.43876647949, 20.102291107178, 194.25550842285, 15012, 875
30 = -231.97967529297, 21.884582519531, 193.19897460938, 15012, 875
31 = -233.43771362305, 22.76305770874, 191.03286743164, 15012, 875
32 = -230.9568939209, 21.630224227905, 189.36093139648, 15012, 875
33 = -227.4875793457, 19.455501556396, 190.15299987793, 15012, 875
34 = -228.86647033691, 20.896678924561, 187.37213134766, 15012, 875
35 = -221.13958740234, 17.625482559204, 188.90077209473, 15012, 875
36 = -225.02124023438, 19.367382049561, 188.6520690918, 15012, 875
@@ -0,0 +1,8 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; ARMY WAREHOUSES
;[mil_space_restrictor_to_bar_1]
;[mil_space_restrictor_to_dead_city_1]
;[mil_space_restrictor_to_radar_1]
;[mil_space_restrictor_to_red_1]
;[mil_space_restrictor_to_tc]
@@ -0,0 +1,554 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; CORDON
; Army outpost @ South
[esc_space_restrictor_to_marsh_1]
1 = -275.09515380859, -21.694849014282, -275.31805419922, 1795, 363
2 = -272.27801513672, -21.661056518555, -276.31658935547, 2813, 363
3 = -269.85870361328, -21.680835723877, -274.63067626953, 3673, 363
4 = -270.78024291992, -21.529163360596, -278.60540771484, 3360, 363
5 = -269.4055480957, -21.512428283691, -281.20132446289, 4251, 363
6 = -267.19317626953, -21.048156738281, -280.3737487793, 4826, 363
7 = -265.17959594727, -21.073490142822, -282.4423828125, 5698, 363
8 = -261.69540405273, -21.315422058105, -282.52828979492, 7359, 363
9 = -259.59722900391, -21.228063583374, -283.37078857422, 7926, 363
10 = -259.63339233398, -20.949098587036, -285.80517578125, 7923, 363
11 = -261.7653503418, -20.553447723389, -286.70190429688, 7639, 363
12 = -265.44067382812, -20.211387634277, -287.33108520508, 6547, 363
13 = -263.45574951172, -19.596050262451, -288.67517089844, 6547, 363
14 = -262.19177246094, -19.358034133911, -290.39013671875, 6815, 363
15 = -263.95574951172, -18.95263671875, -292.3967590332, 6268, 363
16 = -262.0556640625, -20.193536758423, -293.86361694336, 7083, 363
17 = -261.69027709961, -21.195943832397, -296.18350219727, 7080, 363
18 = -258.86486816406, -22.475267410278, -296.19235229492, 8201, 363
19 = -258.07904052734, -22.588600158691, -293.97302246094, 8488, 363
20 = -255.96624755859, -22.931037902832, -292.46139526367, 9322, 363
21 = -255.12783813477, -22.627017974854, -289.51702880859, 9950, 363
22 = -256.55627441406, -21.953088760376, -287.43157958984, 9040, 363
23 = -255.39125061035, -21.701698303223, -285.40069580078, 9957, 363
24 = -252.52345275879, -21.478687286377, -283.56384277344, 10903, 363
25 = -251.9168548584, -20.253902435303, -280.63256835938, 11232, 363
26 = -254.81878662109, -18.809743881226, -279.07196044922, 9959, 363
27 = -247.5386505127, -22.308818817139, -283.21136474609, 12708, 363
28 = -244.18821716309, -23.649343490601, -285.3219909668, 16710, 363
29 = -243.94721984863, -24.337715148926, -287.61318969727, 16710, 363
30 = -244.27072143555, -24.970941543579, -290.19360351562, 15024, 363
31 = -246.54852294922, -24.756052017212, -291.28228759766, 13819, 363
32 = -247.48635864258, -25.035816192627, -293.6369934082, 13444, 363
33 = -248.6978302002, -24.778518676758, -294.0859375, 13076, 363
34 = -251.04817199707, -23.726114273071, -291.25582885742, 11569, 363
35 = -252.18490600586, -23.107866287231, -289.09851074219, 11224, 363
36 = -253.52294921875, -23.088481903076, -290.18499755859, 10575, 363
37 = -253.97248840332, -23.342929840088, -292.50369262695, 10258, 363
38 = -251.92901611328, -23.922763824463, -293.97930908203, 11217, 363
39 = -251.8215637207, -24.18906211853, -295.65246582031, 10886, 363
40 = -255.57992553711, -23.427133560181, -296.59698486328, 9626, 363
41 = -253.71788024902, -23.959516525269, -298.48538208008, 10564, 363
42 = -253.05255126953, -24.08392906189, -300.93060302734, 10560, 363
43 = -251.22828674316, -24.814249038696, -299.98568725586, 11563, 363
44 = -249.4623260498, -24.260999679565, -292.31454467773, 12697, 363
45 = -247.83016967773, -25.538841247559, -297.10531616211, 13813, 363
46 = -261.06948852539, -20.202243804932, -292.35140991211, 7355, 363
47 = -258.98593139648, -20.716327667236, -290.57821655273, 8205, 363
48 = -259.56741333008, -21.296581268311, -293.22036743164, 7634, 363
49 = -255.12283325195, -23.342758178711, -294.36318969727, 9629, 363
50 = -250.10668945312, -22.556798934937, -285.52709960938, 12312, 363
51 = -249.8923034668, -21.105163574219, -281.65844726562, 11578, 363
[esc_space_restrictor_to_marsh_2]
1 = -198.61148071289, 25.12819480896, 223.34855651855, 52735, 364
2 = -166.91549682617, 15.05362033844, 228.02954101562, 83823, 364
3 = -164.40682983398, 13.795787811279, 227.91389465332, 85408, 364
4 = -162.10963439941, 13.873215675354, 225.73629760742, 88483, 627
5 = -161.04653930664, 14.853354454041, 223.35098266602, 91602, 627
6 = -161.44631958008, 16.278057098389, 221.40380859375, 91602, 627
7 = -161.85643005371, 17.239618301392, 220.18124389648, 91602, 627
8 = -162.20120239258, 18.373527526855, 218.5654296875, 91602, 627
9 = -164.53062438965, 18.437976837158, 220.9107208252, 91602, 627
10 = -164.73991394043, 17.041980743408, 223.40420532227, 85405, 627
11 = -164.65980529785, 15.308051109314, 225.96842956543, 86173, 627
12 = -167.26150512695, 15.903677940369, 227.09019470215, 83011, 364
13 = -169.01135253906, 15.387639045715, 228.44442749023, 82175, 364
14 = -171.01025390625, 16.229839324951, 228.42118835449, 82175, 364
15 = -169.98136901855, 17.699974060059, 225.98524475098, 83011, 364
16 = -171.05297851562, 19.376361846924, 224.49452209473, 83011, 364
17 = -168.76013183594, 19.675659179688, 222.83947753906, 83011, 364
18 = -171.35649108887, 20.647006988525, 223.03416442871, 83011, 364
19 = -173.09838867188, 19.535558700562, 224.97653198242, 83011, 364
20 = -175.24479675293, 17.999513626099, 227.27502441406, 73400, 364
21 = -177.59622192383, 18.852998733521, 226.84443664551, 71527, 364
22 = -177.40930175781, 20.542240142822, 225.09645080566, 71527, 364
23 = -174.47741699219, 21.96336555481, 223.00653076172, 71527, 364
24 = -180.06817626953, 23.964792251587, 221.48724365234, 68975, 364
25 = -180.83624267578, 21.724639892578, 224.16938781738, 68975, 364
26 = -182.94438171387, 20.225238800049, 226.4259185791, 67077, 364
27 = -184.89443969727, 21.671575546265, 224.98454284668, 65787, 364
28 = -184.43089294434, 23.942810058594, 222.40441894531, 65787, 364
29 = -186.65194702148, 25.656326293945, 220.40408325195, 63217, 364
30 = -188.88290405273, 25.884174346924, 220.38485717773, 61344, 364
31 = -189.19155883789, 24.560920715332, 223.25941467285, 61344, 364
32 = -190.11630249023, 22.554885864258, 225.28997802734, 60097, 364
33 = -193.44085693359, 23.37520980835, 225.66923522949, 56958, 364
34 = -195.00433349609, 24.59342956543, 223.8874206543, 56958, 364
35 = -193.53164672852, 26.215412139893, 219.05972290039, 56958, 364
36 = -196.97369384766, 26.109039306641, 219.6428527832, 53341, 364
37 = -199.43533325195, 25.82893371582, 222.04627990723, 52116, 364
38 = -194.63293457031, 25.351577758789, 221.6162109375, 56958, 364
39 = -197.62773132324, 26.68563079834, 250.30546569824, 55134, 364
40 = -194.20504760742, 26.15566444397, 250.35163879395, 55737, 364
41 = -192.83027648926, 25.852613449097, 247.95021057129, 57603, 364
42 = -194.54499816895, 24.968654632568, 245.78218078613, 56348, 364
43 = -195.36431884766, 24.253879547119, 243.12565612793, 56348, 364
44 = -195.77445983887, 23.792060852051, 241.48480224609, 56348, 364
45 = -197.83544921875, 24.744010925293, 241.46987915039, 56348, 364
46 = -198.79888916016, 24.317651748657, 239.14556884766, 56348, 364
47 = -197.04179382324, 22.863069534302, 238.11343383789, 56348, 364
48 = -197.19259643555, 22.468481063843, 236.3044128418, 55134, 364
49 = -195.90278625488, 21.735591888428, 234.75219726562, 55737, 364
50 = -193.45483398438, 21.112329483032, 235.40338134766, 58233, 364
51 = -192.79582214355, 21.503814697266, 238.08932495117, 58233, 364
52 = -193.86026000977, 22.267578125, 239.33139038086, 56969, 364
53 = -193.45645141602, 22.897197723389, 241.25880432129, 57603, 364
54 = -190.8757019043, 23.283170700073, 242.1731262207, 59500, 364
55 = -187.72512817383, 23.269872665405, 241.61352539062, 61986, 364
56 = -186.75241088867, 21.902328491211, 239.04968261719, 63228, 364
57 = -187.72384643555, 20.939695358276, 237.52365112305, 63228, 364
58 = -186.86973571777, 20.179565429688, 236.18127441406, 63874, 364
59 = -184.34721374512, 20.223726272583, 236.1157989502, 66435, 364
60 = -181.46527099609, 20.047494888306, 237.49095153809, 68370, 364
61 = -177.74169921875, 18.964065551758, 238.73942565918, 73412, 364
62 = -175.16836547852, 18.992191314697, 241.25308227539, 74060, 364
63 = -172.35403442383, 17.550098419189, 241.12879943848, 76685, 364
64 = -169.60372924805, 16.565021514893, 241.04454040527, 76685, 364
65 = -168.74732971191, 15.619213104248, 239.4986114502, 78868, 364
66 = -166.62503051758, 15.232550621033, 241.18896484375, 79679, 364
67 = -164.93524169922, 14.825362205505, 242.28067016602, 79679, 364
68 = -163.30404663086, 13.554557800293, 240.88768005371, 90815, 364
69 = -167.34889221191, 16.018974304199, 242.39218139648, 90815, 364
70 = -169.40953063965, 17.45259475708, 243.66259765625, 90815, 364
71 = -171.3440246582, 17.963817596436, 243.0212097168, 90815, 364
72 = -173.63391113281, 19.462600708008, 243.53308105469, 90815, 364
73 = -175.46008300781, 20.22020149231, 243.16149902344, 90815, 364
74 = -176.94351196289, 19.857719421387, 241.10836791992, 74060, 364
75 = -178.63739013672, 20.937582015991, 241.45904541016, 74060, 364
76 = -180.12294006348, 21.254409790039, 240.607421875, 74060, 364
77 = -181.09791564941, 20.672134399414, 238.7583770752, 74060, 364
78 = -183.66862487793, 21.898721694946, 238.84161376953, 74060, 364
79 = -184.82194519043, 22.875385284424, 240.50836181641, 74060, 364
80 = -186.6692199707, 23.688142776489, 242.32148742676, 74060, 364
81 = -188.02261352539, 24.098634719849, 243.40437316895, 74060, 364
82 = -189.83688354492, 24.411502838135, 244.37405395508, 74060, 364
83 = -192.32893371582, 24.027992248535, 243.9919128418, 74060, 364
84 = -192.67523193359, 25.001327514648, 246.09585571289, 74060, 364
85 = -195.32647705078, 25.767292022705, 247.1506652832, 74060, 364
86 = -197.5376739502, 26.508390426636, 245.63558959961, 74060, 364
87 = -200.07434082031, 27.382318496704, 245.15789794922, 74060, 364
88 = -191.44563293457, 25.557529449463, 250.99182128906, 74060, 364
89 = -192.853515625, 25.784116744995, 253.00451660156, 74060, 364
90 = -193.88531494141, 25.8743019104, 256.64300537109, 74060, 364
91 = -196.5237121582, 26.454412460327, 252.50370788574, 74060, 364
92 = -190.47891235352, 25.308706283569, 248.37628173828, 74060, 364
93 = -190.70486450195, 25.005348205566, 245.78143310547, 74060, 364
94 = -188.08262634277, 24.75378036499, 248.53594970703, 74060, 364
95 = -188.82678222656, 24.959741592407, 252.1900177002, 74060, 364
96 = -185.58401489258, 24.15411567688, 247.51564025879, 74060, 364
97 = -186.04360961914, 24.242784500122, 243.97079467773, 74060, 364
98 = -186.5400390625, 24.386238098145, 250.99615478516, 74060, 364
99 = -184.31625366211, 23.784412384033, 249.97775268555, 74060, 364
100 = -183.90106201172, 23.690082550049, 247.7357635498, 74060, 364
101 = -183.66754150391, 23.654373168945, 244.49786376953, 74060, 364
102 = -183.01651000977, 23.461786270142, 242.4641418457, 74060, 364
103 = -180.41381835938, 22.425579071045, 243.71401977539, 74060, 364
104 = -178.01678466797, 21.364185333252, 243.20826721191, 74060, 364
105 = -171.05030822754, 18.518815994263, 245.82418823242, 76685, 364
106 = -173.84439086914, 19.739784240723, 246.14875793457, 74714, 364
107 = -176.28503417969, 20.839080810547, 246.84039306641, 74060, 364
108 = -178.52125549316, 21.790328979492, 246.53588867188, 74060, 364
109 = -180.6483001709, 22.752586364746, 247.20114135742, 74060, 364
110 = -182.70321655273, 23.351722717285, 248.43936157227, 74060, 364
111 = -175.88143920898, 20.5397605896, 244.77014160156, 74060, 364
112 = -172.09571838379, 19.220417022705, 249.12588500977, 76685, 364
113 = -175.27949523926, 20.630760192871, 250.62991333008, 74060, 364
114 = -179.07308959961, 22.210838317871, 249.55587768555, 74060, 364
115 = -190.88417053223, 25.33837890625, 254.26184082031, 74060, 364
116 = -181.4051361084, 22.954677581787, 251.32655334473, 74060, 364
117 = -174.07363891602, 19.929716110229, 247.69918823242, 74060, 364
118 = -178.23950195312, 21.766004562378, 248.17124938965, 74060, 364
119 = -173.92962646484, 18.445760726929, 226.43267822266, 73400, 364
120 = -175.84844970703, 20.486125946045, 224.84710693359, 71527, 364
121 = -180.56246948242, 22.952142715454, 223.26051330566, 68975, 364
122 = -184.1452331543, 23.000993728638, 223.66883850098, 65787, 364
123 = -187.2684173584, 22.28600692749, 225.15469360352, 63217, 364
124 = -187.60269165039, 25.316265106201, 221.34635925293, 61975, 364
125 = -190.97763061523, 26.170307159424, 219.3536529541, 58222, 364
126 = -193.37643432617, 25.664262771606, 220.74703979492, 56958, 364
127 = -197.3310546875, 25.457187652588, 221.58212280273, 53341, 364
128 = -183.73959350586, 24.68119430542, 220.94744873047, 65787, 364
129 = -178.16310119629, 22.690055847168, 223.16976928711, 68975, 364
130 = -172.6842956543, 21.09366607666, 223.22503662109, 71527, 364
131 = -168.62301635742, 17.83006477356, 225.37945556641, 83011, 364
132 = -166.45199584961, 16.926780700684, 225.17953491211, 85405, 627
133 = -165.60746765137, 18.274221420288, 222.24975585938, 85405, 627
134 = -162.44622802734, 13.142259597778, 227.98475646973, 88486, 627
135 = -162.86459350586, 15.123009681702, 224.60600280762, 87703, 627
136 = -163.1875, 17.113761901855, 221.75628662109, 87703, 627
137 = -160.9895324707, 13.143977165222, 226.98628234863, 90034, 627
138 = -159.1678314209, 13.328948020935, 224.67486572266, 92433, 627
139 = -157.29956054688, 12.782279968262, 223.33157348633, 94131, 627
140 = -159.48480224609, 14.436009407043, 222.44323730469, 91602, 627
141 = -157.50184631348, 14.459730148315, 220.32647705078, 93279, 627
142 = -159.51884460449, 15.960982322693, 219.81832885742, 93279, 627
143 = -158.48361206055, 16.422731399536, 217.87327575684, 93279, 627
144 = -160.0865020752, 17.803646087646, 217.24160766602, 93279, 627
145 = -173.40026855469, 18.672370910645, 242.3501739502, 76025, 364
146 = -180.12934875488, 22.26256942749, 243.06503295898, 74060, 364
147 = -181.86083984375, 22.386814117432, 241.02563476562, 74060, 364
148 = -175.34631347656, 17.936330795288, 239.1940612793, 74060, 364
149 = -170.33087158203, 16.413932800293, 239.85514831543, 77366, 364
;[esc_space_restrictor_to_darkscape_1]
[esc_space_restrictor_to_pole_1]
1 = 321.33123779297, 16.825109481812, 337.62133789062, 603795, 427
2 = 323.83737182617, 16.974868774414, 323.31469726562, 605830, 427
3 = 326.02230834961, 17.658029556274, 321.70697021484, 607031, 427
4 = 330.13916015625, 19.238260269165, 321.95840454102, 608510, 427
5 = 330.18310546875, 18.781482696533, 317.03527832031, 609260, 427
6 = 326.0451965332, 17.390544891357, 314.59802246094, 607020, 427
7 = 331.01348876953, 20.154054641724, 326.15966796875, 607409, 427
8 = 328.7477722168, 19.53945350647, 328.99835205078, 607409, 427
9 = 325.34255981445, 18.084705352783, 331.77569580078, 605025, 427
10 = 323.04989624023, 17.440631866455, 335.22705078125, 604622, 427
11 = 325.66885375977, 18.221746444702, 333.61334228516, 605026, 427
12 = 320.4723815918, 16.379745483398, 340.71340942383, 603799, 427
13 = 329.30947875977, 19.60152053833, 332.29000854492, 605025, 427
14 = 330.70831298828, 20.486637115479, 334.99438476562, 605026, 427
15 = 328.03393554688, 18.932607650757, 337.39459228516, 605026, 427
16 = 329.47210693359, 19.423557281494, 342.64428710938, 605026, 427
17 = 333.91589355469, 21.70442199707, 342.55908203125, 605026, 427
18 = 325.37707519531, 18.133380889893, 336.47387695312, 605026, 427
19 = 320.98449707031, 16.797010421753, 334.37246704102, 604210, 427
20 = 322.10589599609, 17.06685256958, 332.01675415039, 604619, 427
21 = 324.28952026367, 17.708168029785, 328.72448730469, 604619, 427
22 = 327.09008789062, 18.80249786377, 330.19091796875, 605025, 427
23 = 319.35836791992, 16.060352325439, 336.72381591797, 602942, 427
24 = 323.30255126953, 16.534858703613, 318.01223754883, 605418, 427
25 = 326.24307250977, 17.556049346924, 317.15936279297, 607024, 427
26 = 303.87783813477, 12.887364387512, 346.10638427734, 593694, 427
27 = 312.24981689453, 15.247632026672, 346.14813232422, 598712, 427
28 = 307.11322021484, 12.222060203552, 340.93807983398, 595804, 427
29 = 304.00942993164, 11.208079338074, 339.67352294922, 593685, 427
30 = 304.5908203125, 10.89642906189, 336.91491699219, 594112, 427
31 = 302.96231079102, 10.017067909241, 334.76107788086, 593243, 427
32 = 304.8415222168, 10.089618682861, 331.29925537109, 594104, 427
33 = 301.38806152344, 9.8905897140503, 336.84548950195, 592355, 427
34 = 317.26773071289, 15.137119293213, 335.20294189453, 601688, 427
35 = 299.50238037109, 11.808996200562, 345.68420410156, 590972, 427
36 = 317.79821777344, 15.251942634583, 332.93560791016, 602102, 427
37 = 320.50659179688, 16.311363220215, 330.98791503906, 603787, 427
38 = 320.90097045898, 16.275564193726, 328.3586730957, 603354, 427
39 = 319.89028930664, 15.57973575592, 325.79025268555, 603350, 427
40 = 321.83810424805, 16.28479385376, 324.39416503906, 604616, 427
41 = 310.00894165039, 17.308681488037, 351.85568237305, 597893, 427
42 = 323.22515869141, 17.31559753418, 329.55908203125, 604619, 427
43 = 324.59637451172, 17.547569274902, 325.59213256836, 605831, 427
44 = 326.97592163086, 18.43483543396, 324.88293457031, 606632, 427
45 = 327.67523193359, 18.455451965332, 322.84930419922, 607409, 427
46 = 329.75445556641, 18.902811050415, 320.59216308594, 608510, 427
47 = 330.09765625, 19.961847305298, 326.99307250977, 608510, 427
48 = 333.02154541016, 21.603618621826, 330.95816040039, 608510, 427
49 = 333.17700195312, 21.829565048218, 332.98275756836, 608510, 427
50 = 329.13195800781, 19.38987159729, 335.08770751953, 608510, 427
51 = 327.78424072266, 18.828725814819, 337.89318847656, 608146, 427
52 = 306.87023925781, 15.42750453949, 350.51501464844, 595817, 427
53 = 325.50396728516, 18.003164291382, 341.20812988281, 607031, 427
54 = 323.21426391602, 17.27193069458, 341.87390136719, 603801, 427
55 = 323.65231323242, 17.327966690063, 344.86434936523, 603802, 427
56 = 324.03503417969, 18.044982910156, 349.13464355469, 603802, 427
57 = 327.09045410156, 18.412162780762, 348.48187255859, 603802, 427
58 = 329.87255859375, 19.5378074646, 347.64947509766, 603802, 427
59 = 331.09564208984, 20.060192108154, 343.47817993164, 603802, 427
60 = 332.95178222656, 21.210306167603, 341.53924560547, 603800, 427
61 = 331.89569091797, 20.849985122681, 338.65533447266, 603800, 427
62 = 334.89447021484, 22.75790977478, 335.27310180664, 603800, 427
63 = 308.44519042969, 15.181963920593, 348.70526123047, 596664, 427
64 = 336.63632202148, 23.379034042358, 339.61883544922, 603800, 427
65 = 338.47817993164, 24.756771087646, 342.86602783203, 603802, 427
66 = 340.94708251953, 26.523204803467, 346.57586669922, 603802, 427
67 = 331.14135742188, 20.047468185425, 347.27355957031, 603802, 427
68 = 325.93103027344, 18.313663482666, 334.14791870117, 603800, 427
69 = 308.02105712891, 13.78523349762, 345.40618896484, 596237, 427
70 = 305.1242980957, 13.271563529968, 346.26348876953, 594549, 427
71 = 300.39544677734, 12.198830604553, 345.85736083984, 591435, 427
72 = 302.74914550781, 11.226148605347, 341.65063476562, 593252, 427
73 = 305.3317565918, 11.476439476013, 339.37850952148, 594539, 427
74 = 307.00555419922, 11.19765663147, 335.166015625, 595796, 427
75 = 303.33880615234, 10.576528549194, 336.91882324219, 593246, 427
76 = 303.1637878418, 11.455243110657, 342.10357666016, 593253, 427
77 = 300.94869995117, 10.691424369812, 341.58758544922, 592358, 427
78 = 298.44732666016, 10.018589019775, 342.42184448242, 590035, 427
79 = 295.06597900391, 9.8908758163452, 344.69689941406, 588171, 427
80 = 301.19702148438, 10.011868476868, 337.77545166016, 591897, 427
81 = 302.74713134766, 9.7934579849243, 333.15948486328, 592803, 427
82 = 300.88562011719, 8.982515335083, 330.63562011719, 591886, 427
83 = 300.82440185547, 9.2859907150269, 333.60098266602, 591891, 427
84 = 301.01788330078, 9.5755310058594, 335.87741088867, 591894, 427
85 = 298.38995361328, 9.4666166305542, 339.55450439453, 590031, 427
86 = 296.37356567383, 8.9817972183228, 340.59350585938, 588641, 427
87 = 298.39398193359, 8.8641395568848, 336.70666503906, 590027, 427
88 = 300.95532226562, 9.684910774231, 336.52770996094, 591895, 427
89 = 301.3203125, 10.773880958557, 341.40356445312, 592358, 427
90 = 297.21719360352, 9.9755458831787, 343.39038085938, 589574, 427
91 = 295.34002685547, 8.8972616195679, 341.55923461914, 588167, 427
92 = 293.0791015625, 8.2224578857422, 340.25244140625, 586757, 427
93 = 294.17584228516, 7.9749326705933, 337.49438476562, 587221, 427
94 = 296.17587280273, 8.3099718093872, 336.55447387695, 588635, 427
95 = 298.16644287109, 8.5734300613403, 333.91384887695, 590023, 427
96 = 299.37051391602, 8.7019138336182, 331.43817138672, 590951, 427
97 = 300.56079101562, 8.7904758453369, 329.89611816406, 591417, 427
98 = 302.44372558594, 9.2764329910278, 329.02355957031, 592797, 427
99 = 304.57333374023, 9.5938682556152, 328.39993286133, 594100, 427
100 = 306.20855712891, 9.7345514297485, 325.87976074219, 594941, 427
101 = 308.46990966797, 10.511311531067, 325.24844360352, 596631, 427
102 = 309.38311767578, 10.662689208984, 322.84350585938, 596629, 427
103 = 307.61090087891, 9.984974861145, 320.2822265625, 595775, 427
104 = 309.25653076172, 10.720614433289, 318.43756103516, 597036, 427
105 = 312.06378173828, 11.713084220886, 319.90948486328, 599112, 427
106 = 313.66409301758, 12.535683631897, 322.65432739258, 600803, 427
107 = 312.56579589844, 12.941073417664, 330.76187133789, 599120, 427
108 = 307.9241027832, 11.466057777405, 334.31713867188, 596222, 427
109 = 304.36553955078, 11.33361530304, 339.92538452148, 594117, 427
110 = 303.20559692383, 11.600989341736, 342.54580688477, 593253, 427
111 = 300.82653808594, 11.813572883606, 344.57870483398, 591901, 427
112 = 300.83877563477, 11.79779624939, 344.52386474609, 591901, 427
113 = 302.35522460938, 12.639138221741, 346.36566162109, 592817, 427
114 = 298.21109008789, 11.667765617371, 346.47732543945, 590506, 427
115 = 298.63107299805, 9.962477684021, 342.0224609375, 590501, 427
116 = 297.60653686523, 9.3421812057495, 340.16052246094, 589569, 427
117 = 298.72094726562, 9.3622426986694, 338.58264160156, 590496, 427
118 = 298.61120605469, 8.8941450119019, 336.52621459961, 590493, 427
119 = 300.71603393555, 9.291675567627, 334.14013671875, 591891, 427
120 = 303.4753112793, 10.388276100159, 335.7265625, 593680, 427
121 = 306.51391601562, 10.96373462677, 333.62109375, 595374, 427
122 = 310.42074584961, 11.693634986877, 327.9274597168, 597453, 427
123 = 303.62854003906, 9.0474853515625, 326.12585449219, 593666, 427
124 = 297.44155883789, 7.8424987792969, 328.802734375, 589556, 427
125 = 295.30096435547, 7.6795468330383, 332.07666015625, 588153, 427
126 = 293.66589355469, 7.595808506012, 335.04339599609, 587218, 427
127 = 291.66107177734, 7.5512914657593, 337.94152832031, 585817, 427
128 = 295.46905517578, 8.4190645217896, 338.90274047852, 588163, 427
129 = 302.02905273438, 10.404735565186, 338.32711791992, 592357, 427
130 = 307.47485351562, 11.747811317444, 337.85308837891, 595800, 427
; Army outpost @ North
[esc_space_restrictor_to_garbage_1]
1 = 24.708316802979, 16.518863677979, 679.75170898438, 334664, 369
2 = 22.447031021118, 16.518089294434, 675.58831787109, 332028, 369
[esc_space_restrictor_to_garbage_2]
1 = -170.61889648438, 1.3416738510132, 328.96716308594, 81345, 367
2 = -171.36253356934, 2.1363625526428, 330.51303100586, 79680, 367
3 = -172.70593261719, 2.9752719402313, 328.650390625, 79680, 367
4 = -174.13133239746, 4.3163833618164, 329.64169311523, 79680, 367
5 = -173.36894226074, 3.9902536869049, 332.34255981445, 79680, 367
6 = -171.84924316406, 2.8466436862946, 335.38003540039, 78869, 604
7 = -171.68969726562, 2.4180417060852, 338.75387573242, 78871, 604
8 = -173.98370361328, 4.3958697319031, 339.36538696289, 78091, 604
9 = -175.16668701172, 5.7275595664978, 337.03472900391, 78091, 604
10 = -176.34623718262, 6.9067158699036, 332.37423706055, 78091, 604
11 = -177.66215515137, 8.3214426040649, 329.93280029297, 78091, 604
12 = -178.54539489746, 9.4112310409546, 330.27508544922, 78091, 604
13 = -179.2649230957, 10.334289550781, 332.5869140625, 78091, 604
14 = -180.4750213623, 11.355184555054, 333.72241210938, 78091, 604
15 = -181.16128540039, 12.25426197052, 331.49282836914, 78091, 604
16 = -182.59107971191, 13.511216163635, 329.51635742188, 78091, 604
17 = -183.68608093262, 14.260587692261, 330.18511962891, 78091, 604
18 = -183.20529174805, 14.014281272888, 332.24743652344, 78091, 604
19 = -183.9826965332, 14.468770027161, 336.0407409668, 78091, 604
20 = -185.91261291504, 15.548970222473, 337.30044555664, 78091, 604
21 = -187.60890197754, 16.209489822388, 334.32852172852, 78091, 604
22 = -190.32653808594, 16.988494873047, 333.78979492188, 78091, 604
23 = -191.00735473633, 17.218431472778, 336.30975341797, 78091, 604
24 = -192.77629089355, 17.753364562988, 337.15002441406, 78091, 604
25 = -192.1967010498, 17.604852676392, 339.04895019531, 78091, 604
26 = -192.16012573242, 17.655839920044, 341.25885009766, 78091, 604
27 = -193.80480957031, 18.239459991455, 340.77746582031, 78091, 604
28 = -194.55673217773, 18.315870285034, 342.83804321289, 78091, 604
29 = -193.13348388672, 16.99746131897, 344.72705078125, 78091, 604
30 = -191.15600585938, 15.500712394714, 345.59906005859, 78091, 604
31 = -190.16809082031, 16.068851470947, 343.82977294922, 78091, 604
32 = -189.14682006836, 16.243291854858, 342.50927734375, 78091, 604
33 = -188.23181152344, 16.326465606689, 339.96020507812, 78091, 604
34 = -185.01171875, 14.798892021179, 338.98089599609, 78091, 604
35 = -182.77766418457, 13.421678543091, 337.73336791992, 78091, 604
36 = -180.98698425293, 11.980231285095, 335.94876098633, 78091, 604
37 = -178.69119262695, 9.5651741027832, 335.38607788086, 78091, 604
38 = -176.73463439941, 7.4027061462402, 334.72515869141, 78091, 604
39 = -174.55862426758, 5.3833866119385, 334.28283691406, 78091, 604
40 = -175.66213989258, 6.0437393188477, 339.49609375, 78091, 604
41 = -175.1203918457, 4.0438723564148, 342.05804443359, 78091, 604
42 = -174.95013427734, 2.6321773529053, 344.6477355957, 77367, 604
43 = -176.71430969238, 3.661479473114, 346.35559082031, 77368, 604
44 = -177.18521118164, 6.1109113693237, 342.92483520508, 77367, 604
45 = -178.7222442627, 8.9563961029053, 340.32357788086, 77367, 604
46 = -181.46600341797, 11.8587474823, 339.97268676758, 77367, 604
47 = -181.83615112305, 10.103211402893, 344.05795288086, 77367, 604
48 = -179.64282226562, 7.088770866394, 345.689453125, 77367, 604
49 = -184.67724609375, 13.671522140503, 342.04837036133, 77367, 604
50 = -184.62261962891, 11.816022872925, 345.35034179688, 77367, 604
51 = -187.36793518066, 14.158164024353, 344.81140136719, 77367, 604
52 = -187.90570068359, 15.297624588013, 343.78118896484, 77367, 604
53 = -173.44677734375, 0.57894378900528, 346.34298706055, 77370, 604
54 = -170.9833984375, -0.64599627256393, 345.69006347656, 78881, 604
55 = -151.50805664062, -2.2042331695557, 343.36029052734, 100928, 604
56 = -149.73419189453, -1.8829324245453, 340.09887695312, 101748, 604
57 = -147.2223815918, 0.79027050733566, 344.68695068359, 101748, 604
58 = -144.87750244141, 2.6605327129364, 346.26260375977, 101748, 604
59 = -142.76055908203, 4.3289909362793, 343.84808349609, 101748, 604
60 = -140.92169189453, 5.8300890922546, 343.62857055664, 101748, 604
61 = -138.44329833984, 7.4850025177002, 341.45129394531, 101748, 604
62 = -136.82064819336, 9.3648462295532, 341.55023193359, 101748, 604
63 = -134.91342163086, 12.071074485779, 343.52395629883, 101748, 604
64 = -132.98197937012, 13.811705589294, 341.68069458008, 101748, 604
65 = -131.61161804199, 15.15215587616, 340.30102539062, 101748, 604
66 = -129.22802734375, 17.659614562988, 341.32214355469, 101748, 604
67 = -127.0592956543, 19.742809295654, 340.19781494141, 101748, 604
68 = -125.89169311523, 20.371906280518, 337.50317382812, 101748, 604
69 = -124.55432891846, 21.524770736694, 338.29296875, 101748, 604
70 = -123.5358581543, 23.159742355347, 340.73483276367, 101748, 604
71 = -121.58742523193, 24.884937286377, 340.07373046875, 101748, 604
72 = -120.50897216797, 25.283128738403, 337.54147338867, 101748, 604
73 = -121.19798278809, 23.663543701172, 333.63909912109, 101748, 604
74 = -123.52420043945, 21.192909240723, 332.15509033203, 101748, 604
75 = -125.23226928711, 19.718328475952, 333.31329345703, 101748, 604
76 = -127.13967132568, 18.543466567993, 335.24450683594, 101748, 604
77 = -128.28875732422, 18.208637237549, 337.44107055664, 101748, 604
78 = -129.85134887695, 16.749418258667, 338.9404296875, 101748, 604
79 = -131.38410949707, 14.378855705261, 337.01379394531, 101748, 604
80 = -131.19609069824, 13.338519096375, 334.59817504883, 101748, 604
81 = -132.68969726562, 10.982266426086, 333.6533203125, 101748, 604
82 = -134.11859130859, 10.323496818542, 335.80847167969, 101748, 604
83 = -135.57905578613, 9.8991422653198, 338.61181640625, 101748, 604
84 = -137.41184997559, 7.9340009689331, 339.45587158203, 101748, 604
85 = -139.91744995117, 5.8182482719421, 339.73916625977, 101748, 604
86 = -142.03198242188, 4.4539012908936, 340.97204589844, 101748, 604
87 = -144.60697937012, 1.881142616272, 339.55584716797, 101748, 604
88 = -146.99710083008, -0.10736963152885, 339.03994750977, 101748, 604
89 = -148.25505065918, -1.7058424949646, 335.98706054688, 104981, 604
90 = -147.08576965332, -1.1857323646545, 333.79016113281, 105796, 604
91 = -144.63241577148, 0.16508424282074, 333.12420654297, 107403, 604
92 = -142.94903564453, 0.40644150972366, 330.26409912109, 107401, 604
93 = -143.00308227539, -0.091758564114571, 326.91052246094, 107396, 367
94 = -141.74307250977, 0.22446185350418, 324.52066040039, 107393, 367
95 = -140.5404510498, 2.2173483371735, 324.97885131836, 107394, 367
96 = -140.24743652344, 2.476838350296, 327.98892211914, 107399, 367
97 = -138.78076171875, 4.4951233863831, 329.99172973633, 107401, 604
98 = -137.08699035645, 6.3669981956482, 330.92434692383, 107403, 604
99 = -135.52462768555, 8.0127553939819, 332.31826782227, 107403, 604
100 = -133.89067077637, 9.7634515762329, 332.26623535156, 107403, 604
101 = -128.88822937012, 16.270862579346, 334.58615112305, 107403, 604
102 = -134.89588928223, 8.7042827606201, 334.38491821289, 107403, 604
103 = -136.39912414551, 7.7195711135864, 335.91116333008, 107403, 604
104 = -138.0076751709, 6.9774079322815, 338.57504272461, 107403, 604
105 = -139.49067687988, 5.405385017395, 337.72723388672, 107403, 604
106 = -139.08195495605, 4.8012862205505, 335.2546081543, 107403, 604
107 = -137.78993225098, 5.6804342269897, 333.09634399414, 107403, 604
108 = -139.59231567383, 3.8948128223419, 331.18240356445, 107403, 604
109 = -141.60211181641, 1.8160219192505, 331.99645996094, 107403, 604
110 = -142.25119018555, 1.8576209545135, 334.43249511719, 107403, 604
111 = -141.80438232422, 3.3726868629456, 337.49877929688, 107403, 604
112 = -143.21617126465, 3.194491147995, 340.0832824707, 107403, 604
113 = -144.62371826172, 1.1517815589905, 337.48016357422, 107403, 604
114 = -145.79176330566, -0.052617505192757, 335.66168212891, 104981, 604
115 = -144.20587158203, 0.74915009737015, 334.42138671875, 107403, 604
116 = -139.14323425293, 4.3925395011902, 326.6452331543, 107397, 367
117 = -140.90277099609, 1.2370579242706, 323.40753173828, 107393, 367
118 = -139.63442993164, 3.4454050064087, 323.95095825195, 107394, 367
119 = -138.15975952148, 6.1006259918213, 324.95233154297, 107394, 367
120 = -136.73480224609, 7.5592031478882, 326.27490234375, 107397, 367
121 = -134.78311157227, 9.5775327682495, 326.54306030273, 107399, 367
122 = -132.55557250977, 12.333214759827, 325.71176147461, 107397, 367
123 = -130.96006774902, 13.500779151917, 327.97528076172, 107400, 604
124 = -129.40069580078, 15.372506141663, 330.47802734375, 107403, 604
125 = -127.33857727051, 17.861639022827, 331.20776367188, 107403, 604
126 = -126.44623565674, 18.665546417236, 333.42071533203, 107403, 604
127 = -125.65176391602, 19.986988067627, 335.48956298828, 107403, 604
128 = -129.48974609375, 14.78297328949, 333.51806640625, 107403, 604
129 = -131.61250305176, 12.353096008301, 332.82598876953, 107403, 604
130 = -132.44297790527, 11.442427635193, 331.02075195312, 107403, 604
131 = -132.12239074707, 12.305665969849, 327.47805786133, 107399, 367
132 = -133.84437561035, 10.257785797119, 327.46942138672, 107399, 367
133 = -135.21765136719, 8.4969549179077, 329.04406738281, 107401, 604
134 = -136.29458618164, 7.1517691612244, 331.00128173828, 107403, 604
135 = -136.99472045898, 6.7920227050781, 328.53012084961, 107400, 604
136 = -138.25747680664, 5.6828899383545, 326.87838745117, 107397, 367
137 = -138.61027526855, 4.8569755554199, 328.44854736328, 107399, 367
138 = -136.47653198242, 7.0691032409668, 334.05310058594, 107403, 604
139 = -133.59173583984, 10.331761360168, 329.08746337891, 107401, 604
140 = -135.21046447754, 9.4307012557983, 324.91293334961, 107394, 367
141 = -136.91125488281, 7.5923628807068, 324.45571899414, 107394, 367
142 = -137.15399169922, 7.2290372848511, 323.02194213867, 107394, 367
143 = -138.63494873047, 4.5124759674072, 322.80493164062, 107393, 367
144 = -139.95581054688, 2.097455739975, 321.63226318359, 107388, 367
145 = -141.58790588379, 1.0516667366028, 328.00756835938, 107399, 367
146 = -139.67315673828, 4.0920329093933, 333.10214233398, 107403, 604
147 = -130.96841430664, 13.250003814697, 330.59719848633, 107403, 604
148 = -129.60354614258, 15.658738136292, 327.92114257812, 107400, 604
149 = -128.08999633789, 17.579574584961, 328.92761230469, 107403, 604
150 = -125.77990722656, 19.55835723877, 329.58941650391, 107403, 604
151 = -124.3479385376, 20.786409378052, 330.3427734375, 107403, 604
152 = -122.02574157715, 22.610380172729, 331.71948242188, 107403, 604
153 = -120.07458496094, 25.114231109619, 334.90808105469, 107403, 604
154 = -119.71103668213, 26.053939819336, 338.67358398438, 107403, 604
155 = -189.48156738281, 16.721271514893, 337.14254760742, 79686, 604
156 = -186.95791625977, 16.275749206543, 328.17477416992, 78091, 604
157 = -181.21151733398, 12.413558006287, 328.82421875, 78091, 604
158 = -182.12504577637, 13.062376976013, 332.16189575195, 78091, 604
159 = -184.36499023438, 14.468826293945, 338.06976318359, 78091, 604
160 = -197.35485839844, 19.578800201416, 340.05218505859, 78091, 604
161 = -160.99151611328, -3.4327576160431, 335.42535400391, 90082, 604
162 = -162.68188476562, -3.2252967357635, 337.56024169922, 88524, 604
163 = -166.03569030762, -1.976170539856, 338.62316894531, 84655, 604
164 = -195.69873046875, 18.909729003906, 334.86450195312, 78091, 604
165 = -191.90649414062, 17.55717086792, 332.59216308594, 78091, 604
166 = -189.64392089844, 16.889472961426, 331.66857910156, 78091, 604
167 = -189.38932800293, 17.202537536621, 329.63024902344, 78091, 604
168 = -193.72833251953, 18.132368087769, 335.74432373047, 78091, 604
169 = -196.00170898438, 20.06778717041, 330.65307617188, 78091, 604
170 = -192.83415222168, 18.549629211426, 329.56692504883, 78091, 604
171 = -191.00782775879, 19.00514793396, 326.31585693359, 78091, 604
172 = -193.70109558105, 18.230537414551, 332.43304443359, 78091, 604
173 = -197.12031555176, 19.504060745239, 333.73291015625, 78091, 604
174 = -192.51028442383, 17.745292663574, 340.08627319336, 78869, 604
175 = -198.13702392578, 19.832248687744, 337.36853027344, 78091, 604
176 = -199.25888061523, 20.830369949341, 342.04638671875, 78091, 604
177 = -200.7248840332, 21.578617095947, 339.48544311523, 78091, 604
178 = -199.2359161377, 21.484268188477, 332.59722900391, 78091, 604
179 = -195.82144165039, 21.400436401367, 328.03625488281, 78091, 604
180 = -184.42324829102, 15.28324508667, 325.34326171875, 78091, 604
181 = -187.04377746582, 18.24242401123, 322.89181518555, 78091, 604
182 = -170.63467407227, 1.1801481246948, 327.08947753906, 82187, 367
183 = -168.31820678711, -0.31938162446022, 328.58804321289, 82187, 367
184 = -165.20349121094, -1.7481482028961, 330.31539916992, 85424, 367
185 = -194.50445556641, 17.966468811035, 343.68389892578, 78091, 604
186 = -159.60125732422, -3.65483045578, 333.95959472656, 91663, 604
187 = -160.57043457031, -3.3515102863312, 330.06140136719, 90848, 367
188 = -163.12342834473, -2.4714915752411, 327.83465576172, 87723, 367
189 = -164.69564819336, -1.9820716381073, 326.29937744141, 86187, 367
190 = -167.52430725098, -0.74435365200043, 325.77310180664, 83023, 367
191 = -168.77655029297, 0.0099374055862427, 323.63641357422, 83023, 367
192 = -171.03137207031, 1.7101130485535, 323.92556762695, 83023, 367
193 = -165.36805725098, -1.7263634204865, 323.05676269531, 85414, 367
194 = -162.60548400879, -2.299001455307, 321.49118041992, 88501, 367
195 = -159.64808654785, -2.7267322540283, 319.15078735352, 91652, 367
196 = -197.11210632324, 19.100938796997, 343.16302490234, 78091, 604
197 = -155.85636901855, -3.4756581783295, 319.21090698242, 95900, 566
198 = -157.41217041016, -3.4011023044586, 320.99649047852, 94191, 367
199 = -159.90022277832, -3.0933372974396, 323.32354736328, 90843, 367
200 = -160.16250610352, -3.2934684753418, 326.61404418945, 90071, 367
201 = -157.49223327637, -3.7604305744171, 328.59237670898, 94192, 367
202 = -157.48818969727, -3.6097054481506, 333.80487060547, 94197, 604
203 = -154.72009277344, -3.6674735546112, 331.49099731445, 95055, 367
204 = -155.1770324707, -3.7289497852325, 326.44995117188, 96761, 367
205 = -156.19561767578, -3.7833833694458, 330.77691650391, 95055, 367
206 = -159.08930969238, -3.6483657360077, 331.11340332031, 92495, 367
@@ -0,0 +1,38 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; DARKSCAPE
[ds_space_restrictor_to_darkvalley]
2 = -427.59759521484, 0.83938592672348, 620.75274658203, 39643, 1083
3 = -429.33654785156, 0.76814037561417, 624.27447509766, 38851, 1083
4 = -434.25802612305, 0.65884798765182, 625.04412841797, 37432, 1083
5 = -432.20999145508, 0.66713792085648, 630.08288574219, 38116, 1083
6 = -427.49035644531, 0.7754961848259, 631.20166015625, 39652, 1083
7 = -424.41693115234, 0.8518163561821, 633.72283935547, 41038, 1083
8 = -421.50408935547, 0.97444850206375, 636.68420410156, 42071, 1083
9 = -420.60775756836, 1.004997253418, 640.50354003906, 42339, 1083
10 = -428.60729980469, 0.73554557561874, 639.18157958984, 39128, 1083
11 = -429.87628173828, 0.70967370271683, 633.00354003906, 38863, 1083
12 = -431.65240478516, 0.68905788660049, 628.10046386719, 38113, 1083
13 = -434.69006347656, 0.67739641666412, 622.27923583984, 37208, 1083
14 = -432.064453125, 0.74007421731949, 621.52465820312, 38104, 1083
15 = -429.63592529297, 0.80149871110916, 619.87731933594, 38845, 1083
16 = -426.30331420898, 0.87893432378769, 619.18859863281, 40194, 1083
17 = -423.32452392578, 0.90529531240463, 623.76806640625, 41289, 1083
18 = -424.25973510742, 0.87099426984787, 627.82562255859, 41030, 1083
19 = -427.07958984375, 0.82328861951828, 623.20251464844, 39920, 1083
20 = -432.30032348633, 0.70863062143326, 623.91058349609, 37877, 1083
21 = -429.2790222168, 0.83427137136459, 617.91839599609, 39104, 1083
22 = -423.54306030273, 0.88547474145889, 630.82202148438, 41034, 1083
23 = -433.07867431641, 0.7531310915947, 618.20007324219, 37643, 1366
24 = -433.70803833008, 0.71547693014145, 620.60443115234, 37427, 1083
25 = -436.71240234375, 0.65286546945572, 620.47723388672, 36774, 1083
26 = -437.45123291016, 0.66524654626846, 618.45953369141, 36360, 1366
27 = -432.24340820312, 0.78144437074661, 616.26013183594, 38096, 1366
28 = -426.50616455078, 0.9344328045845, 615.14916992188, 40188, 1366
29 = -433.35858154297, 0.81363838911057, 613.57922363281, 37417, 1366
30 = -437.712890625, 0.75528138875961, 612.99987792969, 36352, 1366
31 = -440.27368164062, 0.64129680395126, 617.20275878906, 35532, 1366
32 = -429.36849975586, 0.89815336465836, 613.57873535156, 39098, 1366
33 = -416.26953125, 1.1641969680786, 613.28576660156, 43811, 1083
;[ds_space_restrictor_to_escape]
@@ -0,0 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; DEAD CITY
;[cit_space_restrictor_to_limansk]
;[cit_space_restrictor_to_military]
;[cit_space_restrictor_to_yantar]
@@ -0,0 +1,212 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; GARBAGE
[gar_space_restrictor_to_agroprom_1]
31 = -257.6950378418, -3.7190661430359, -162.13697814941, 4540, 775
32 = -260.59973144531, -4.3206253051758, -159.89739990234, 4540, 775
33 = -264.52160644531, -3.8522922992706, -162.50788879395, 2424, 775
34 = -268.59997558594, -3.7723913192749, -165.97064208984, 2250, 775
35 = -270.59866333008, -5.5650696754456, -169.3014831543, 1905, 776
36 = -271.44580078125, -5.6269454956055, -171.45581054688, 1905, 776
37 = -269.17568969727, -4.0901384353638, -171.81575012207, 1905, 776
38 = -268.5986328125, -4.0097832679749, -169.13366699219, 1905, 776
39 = -269.41998291016, -3.9814221858978, -175.6983795166, 1905, 776
40 = -270.75131225586, -5.0348992347717, -175.60536193848, 1905, 776
41 = -273.31475830078, -6.3457384109497, -174.39828491211, 1560, 776
42 = -273.90905761719, -6.6649770736694, -171.92102050781, 1484, 776
43 = -272.28829956055, -5.8928346633911, -170.38493347168, 1776, 776
44 = -270.67031860352, -5.8511152267456, -166.78396606445, 1966, 776
45 = -271.11968994141, -5.1274390220642, -178.30503845215, 1966, 776
46 = -272.71691894531, -6.2473478317261, -177.09617614746, 1556, 776
47 = -272.20178222656, -5.8084306716919, -175.71264648438, 1558, 776
48 = -271.42907714844, -5.5638909339905, -173.92262268066, 1560, 776
49 = -282.60440063477, -4.1989283561707, -173.7619934082, 1109, 776
50 = -284.31552124023, -3.2930727005005, -176.12261962891, 1109, 776
51 = -285.81219482422, -1.938894033432, -174.21437072754, 1109, 776
52 = -282.97412109375, -5.3854312896729, -171.40371704102, 1110, 776
53 = -281.33908081055, -6.8162851333618, -168.00553894043, 1110, 776
54 = -282.98199462891, -5.7691526412964, -168.44845581055, 1058, 776
55 = -284.20794677734, -4.7957181930542, -166.83209228516, 1058, 776
56 = -284.18707275391, -3.6341993808746, -164.71572875977, 1061, 776
57 = -279.6637878418, -5.2066268920898, -163.76737976074, 1115, 776
58 = -280.06802368164, -5.5632619857788, -161.13624572754, 1116, 776
59 = -283.50045776367, -3.0500500202179, -161.15814208984, 1116, 776
60 = -286.59057617188, -1.8895101547241, -165.05905151367, 1116, 776
61 = -285.58285522461, -1.3269085884094, -162.43035888672, 1116, 776
62 = -285.00140380859, -0.64605700969696, -159.27581787109, 1116, 776
63 = -285.49444580078, -2.3892188072205, -163.98516845703, 1116, 776
64 = -283.52670288086, -3.7684247493744, -163.32131958008, 1116, 776
65 = -282.25381469727, -4.4750852584839, -161.34518432617, 1116, 776
66 = -282.34759521484, -3.211544752121, -158.02886962891, 1116, 776
67 = -283.73876953125, -1.1202659606934, -156.93569946289, 1116, 776
68 = -286.12261962891, 0.92380756139755, -158.31248474121, 1116, 776
69 = -281.63232421875, -2.9914920330048, -155.58210754395, 1116, 776
70 = -280.5524597168, -4.6758718490601, -158.60284423828, 1116, 776
71 = -283.76110839844, -2.1321995258331, -159.4963684082, 1116, 776
72 = -285.86480712891, -0.31837692856789, -160.62249755859, 1116, 776
73 = -269.7307434082, -4.9198031425476, -167.03007507324, 1966, 776
74 = -269.56219482422, -4.7750582695007, -169.36944580078, 1966, 776
75 = -270.49884033203, -4.97878074646, -172.95703125, 1905, 776
76 = -269.33432006836, -4.5778656005859, -163.416015625, 2196, 775
[gar_space_restrictor_to_agroprom_2]
1 = -288.22619628906, 6.4090166091919, -33.065502166748, 633, 779
2 = -285.57952880859, 5.9416484832764, -32.728240966797, 788, 779
3 = -283.04467773438, 4.694260597229, -30.793241500854, 895, 779
4 = -280.79092407227, 4.898353099823, -33.362476348877, 1117, 779
5 = -282.70254516602, 5.5792460441589, -34.103832244873, 787, 779
6 = -283.12750244141, 5.9728655815125, -35.722309112549, 787, 779
7 = -285.24963378906, 6.273814201355, -36.519023895264, 787, 779
8 = -285.43023681641, 6.7395701408386, -39.303245544434, 787, 779
9 = -287.51217651367, 6.881411075592, -39.396781921387, 668, 779
10 = -289.56365966797, 6.9197783470154, -39.019241333008, 562, 779
11 = -290.25894165039, 7.4453988075256, -41.267967224121, 533, 779
12 = -288.85549926758, 7.4945545196533, -41.840728759766, 597, 779
13 = -284.07525634766, 6.9827904701233, -40.823879241943, 787, 779
14 = -284.31484985352, 7.706693649292, -43.656223297119, 787, 779
15 = -282.81097412109, 7.7744207382202, -44.266597747803, 787, 779
16 = -279.22085571289, 6.9323444366455, -41.757350921631, 787, 779
17 = -280.94061279297, 6.5962953567505, -40.281860351562, 787, 779
18 = -280.19830322266, 5.9948921203613, -38.112148284912, 787, 779
19 = -280.48452758789, 5.3315348625183, -35.351554870605, 1255, 779
20 = -278.15948486328, 4.9052739143372, -34.509826660156, 1255, 779
21 = -276.62969970703, 5.0475549697876, -35.672664642334, 1342, 779
22 = -274.68695068359, 4.97847032547, -34.827205657959, 1421, 779
23 = -272.79040527344, 5.642279624939, -35.629093170166, 1499, 779
24 = -271.60330200195, 6.4264783859253, -37.004917144775, 1499, 779
25 = -274.68029785156, 5.6682462692261, -37.125282287598, 1499, 779
26 = -269.67306518555, 5.9925417900085, -34.141250610352, 1499, 779
27 = -271.68557739258, 4.8484663963318, -32.257499694824, 1499, 779
28 = -274.47219848633, 3.8756291866302, -30.858371734619, 1576, 779
29 = -277.10006713867, 3.2429559230804, -29.263595581055, 1426, 779
30 = -279.7053527832, 3.264634847641, -28.430393218994, 1123, 779
31 = -281.44937133789, 3.9954001903534, -29.886856079102, 1012, 779
32 = -282.1286315918, 3.1059472560883, -24.370981216431, 977, 779
33 = -293.6735534668, 7.3257641792297, -23.73046875, 465, 779
34 = -289.58666992188, 6.3133134841919, -14.470384597778, 589, 779
35 = -283.00207519531, 3.1139290332794, -15.258955001831, 945, 779
36 = -280.47640991211, 2.2334978580475, -11.723264694214, 1086, 779
37 = -281.9416809082, 4.7929430007935, -0.22498592734337, 1003, 779
38 = -285.57055664062, 6.4141139984131, 0.34135115146637, 927, 779
39 = -286.21307373047, 7.3302955627441, 3.5569224357605, 927, 779
40 = -288.99078369141, 8.8090400695801, 3.9576649665833, 927, 779
41 = -291.6575012207, 8.5592670440674, -0.10623839497566, 927, 779
42 = -288.67602539062, 10.875363349915, 10.920221328735, 558, 779
43 = -285.47863769531, 8.7425365447998, 9.7216110229492, 743, 779
44 = -283.82290649414, 7.1962747573853, 7.6972045898438, 855, 779
45 = -281.28286743164, 6.4089498519897, 7.9784078598022, 963, 779
46 = -279.84729003906, 5.5528182983398, 6.2608609199524, 1100, 779
47 = -279.85147094727, 4.8960313796997, 3.3812246322632, 1162, 779
48 = -281.0505065918, 4.6605200767517, 0.86172366142273, 1162, 779
49 = -275.24816894531, 3.9079420566559, 3.3272259235382, 1688, 779
50 = -278.22265625, 6.0459785461426, 9.0758075714111, 1688, 779
51 = -280.78558349609, 6.613817691803, 9.2840929031372, 1688, 779
52 = -282.61245727539, 8.05553150177, 10.893696784973, 1688, 779
53 = -284.92172241211, 8.5708894729614, 9.7872753143311, 1688, 779
54 = -286.59503173828, 9.4026947021484, 9.9769639968872, 1688, 779
55 = -287.15960693359, 10.719721794128, 12.321002006531, 1688, 779
56 = -289.38571166992, 11.388663291931, 11.397809028625, 1688, 779
57 = -290.30685424805, 10.739634513855, 8.6268577575684, 1688, 779
58 = -291.78900146484, 9.6633968353271, 3.5702586174011, 1688, 779
59 = -293.6340637207, 10.757901191711, 7.2913513183594, 1688, 779
60 = -292.67614746094, 11.365371704102, 9.3925743103027, 1688, 779
61 = -294.48687744141, 12.303532600403, 11.75599861145, 1688, 779
62 = -293.51263427734, 13.360638618469, 14.774147987366, 1688, 779
63 = -290.31491088867, 13.566452026367, 17.281217575073, 1688, 779
64 = -287.93731689453, 16.943731307983, 24.09419631958, 1688, 779
65 = -288.51278686523, 14.985443115234, 20.822639465332, 1688, 779
66 = -281.94927978516, 16.136793136597, 22.694011688232, 1688, 779
67 = -281.46801757812, 14.060272216797, 20.225551605225, 1688, 779
68 = -282.17544555664, 12.845458030701, 18.713043212891, 1688, 779
69 = -282.09658813477, 11.628540992737, 17.041597366333, 1688, 779
70 = -283.82974243164, 11.070863723755, 15.860512733459, 1688, 779
71 = -283.00561523438, 9.6426763534546, 14.112879753113, 1688, 779
72 = -284.13119506836, 9.5210456848145, 12.841003417969, 1688, 779
73 = -282.34973144531, 8.128565788269, 11.484257698059, 1688, 779
74 = -280.4182434082, 6.7978992462158, 10.071133613586, 1688, 779
75 = -280.83389282227, 6.4527983665466, 8.7191982269287, 1688, 779
76 = -279.53018188477, 5.5880546569824, 6.6821565628052, 1688, 779
77 = -283.06213378906, 6.2816185951233, 5.0038695335388, 1688, 779
78 = -284.38250732422, 7.1345520019531, 6.6705060005188, 1688, 779
79 = -286.3757019043, 7.9062147140503, 6.1836819648743, 1688, 779
80 = -287.9651184082, 8.3364381790161, 4.0738444328308, 1688, 779
81 = -289.93975830078, 9.5434827804565, 5.0717077255249, 1688, 779
82 = -288.79946899414, 10.186618804932, 9.1242399215698, 1688, 779
83 = -290.42327880859, 11.676733970642, 10.900566101074, 1688, 779
84 = -290.97766113281, 12.709132194519, 13.036685943604, 1688, 779
85 = -288.59313964844, 11.986578941345, 14.509426116943, 1688, 779
86 = -285.52264404297, 11.156598091125, 14.646043777466, 1688, 779
87 = -282.80883789062, 11.074867248535, 16.158758163452, 1688, 779
88 = -284.31866455078, 13.110960006714, 18.395921707153, 1688, 779
89 = -287.90438842773, 13.399031639099, 17.880216598511, 1688, 779
90 = -289.94592285156, 13.968593597412, 18.269659042358, 1688, 779
91 = -293.29937744141, 13.452991485596, 15.057679176331, 1688, 779
92 = -293.13174438477, 10.824554443359, 7.6769118309021, 1688, 779
;[gar_space_restrictor_to_bar_1]
[gar_space_restrictor_to_darkvalley_1]
1 = 288.47595214844, 13.277616500854, -90.011817932129, 354976, 770
2 = 288.43615722656, 12.63366985321, -88.027252197266, 354976, 770
3 = 285.19375610352, 9.6167755126953, -86.572319030762, 355076, 770
4 = 285.48513793945, 9.7677907943726, -84.158149719238, 355356, 770
5 = 286.33642578125, 10.517583847046, -85.573669433594, 355356, 770
6 = 283.02047729492, 7.8846883773804, -87.399940490723, 354976, 770
7 = 282.90084838867, 7.8148727416992, -89.164489746094, 354863, 770
8 = 281.74331665039, 6.8861150741577, -89.836372375488, 354646, 861
9 = 280.56225585938, 5.9091439247131, -88.922966003418, 354646, 861
10 = 279.79956054688, 5.2622032165527, -87.28987121582, 354646, 861
11 = 273.21734619141, 4.7554688453674, -83.311820983887, 353905, 861
12 = 284.62197875977, 10.26943397522, -79.133026123047, 355447, 770
13 = 286.78732299805, 11.412038803101, -79.648002624512, 355594, 770
14 = 287.67868041992, 13.162495613098, -77.72770690918, 355710, 770
15 = 289.47552490234, 13.976871490479, -77.723205566406, 355773, 770
16 = 292.76690673828, 14.918776512146, -79.186050415039, 356063, 770
17 = 290.02728271484, 16.195192337036, -75.316833496094, 356004, 770
18 = 288.50305175781, 15.996510505676, -74.728942871094, 355950, 770
19 = 292.22338867188, 16.079858779907, -76.5986328125, 356063, 770
20 = 295.11099243164, 15.968438148499, -79.185981750488, 356228, 770
21 = 288.83773803711, 14.885935783386, -75.993255615234, 355895, 770
22 = 285.40872192383, 9.6553049087524, -81.717636108398, 355444, 770
23 = 271.68255615234, 2.6109001636505, -85.782722473145, 353073, 861
24 = 269.57876586914, 2.9245812892914, -85.879821777344, 353073, 861
25 = 270.89712524414, 5.0048131942749, -83.309921264648, 353448, 861
26 = 272.0920715332, 4.1520824432373, -84.085144042969, 353448, 861
27 = 285.45132446289, 10.015363693237, -88.489608764648, 354542, 861
28 = 286.42370605469, 11.490836143494, -89.663261413574, 354542, 861
29 = 284.36553955078, 8.9803657531738, -89.613777160645, 354542, 861
30 = 283.24639892578, 8.292200088501, -90.982040405273, 354542, 861
[gar_space_restrictor_to_darkvalley_2]
4 = 275.94421386719, 3.5520522594452, 124.34310913086, 354090, 769
5 = 276.29620361328, 5.1010551452637, 120.46231842041, 353927, 769
6 = 280.65197753906, 6.6601829528809, 118.27928161621, 354682, 769
7 = 282.78103637695, 5.5413932800293, 120.07412719727, 354898, 769
8 = 283.57409667969, 3.3096287250519, 123.65545654297, 355203, 769
9 = 285.43280029297, 3.1147863864899, 123.77454376221, 355293, 769
10 = 279.22634887695, 3.6983320713043, 124.03048706055, 354579, 769
11 = 287.84353637695, 4.4010229110718, 120.83438110352, 355293, 769
12 = 290.91592407227, 3.2472131252289, 124.86434936523, 355774, 769
13 = 288.38903808594, 2.2803666591644, 128.14407348633, 355716, 769
14 = 285.17614746094, 2.0229423046112, 128.83497619629, 355381, 769
15 = 279.23059082031, 6.6847548484802, 118.21688079834, 354682, 769
16 = 284.81497192383, 7.4623584747314, 117.16799926758, 354898, 769
17 = 276.07315063477, 7.2821650505066, 115.99922180176, 354086, 769
18 = 274.28012084961, 5.7121796607971, 117.42055511475, 353778, 769
19 = 271.49514770508, 4.6983323097229, 116.27054595947, 352689, 769
20 = 272.08535766602, 3.7495100498199, 121.47880554199, 353100, 769
21 = 296.12225341797, 2.7820456027985, 160.34718322754, 356390, 769
22 = 297.83477783203, 2.7658412456512, 165.34509277344, 356486, 769
23 = 302.76901245117, 5.3854537010193, 166.29722595215, 356670, 769
24 = 304.71273803711, 5.5836114883423, 162.14695739746, 356702, 769
25 = 307.98132324219, 7.5299067497253, 162.90083312988, 356702, 769
26 = 307.73348999023, 5.9803342819214, 157.50955200195, 356702, 769
27 = 306.65823364258, 5.2825345993042, 152.74351501465, 356702, 769
28 = 299.61526489258, 4.4612741470337, 172.03216552734, 356605, 769
29 = 296.52041625977, 2.177773475647, 168.37254333496, 356452, 769
30 = 293.86508178711, 1.6449847221375, 163.44131469727, 356220, 769
;[gar_space_restrictor_to_escape_1]
;[gar_space_restrictor_to_escape_2]
;[gar_space_restrictor_to_rostok_1]
@@ -0,0 +1,26 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; JUPITER
;[jupiter_space_restrictor_to_red_forest]
;[jupiter_space_restrictor_to_soc_pripyat]
[jup_space_restrictor_to_zaton]
1 = 489.84796142578, -3.5576872825623, 475.24084472656, 1484376, 4514
2 = 491.53958129883, -2.5676898956299, 476.4284362793, 1484378, 4514
3 = 494.15017700195, -1.0430116653442, 476.14730834961, 1484378, 4514
4 = 494.97982788086, -0.55835449695587, 479.05194091797, 1484382, 4514
5 = 492.77450561523, -1.8503563404083, 480.17932128906, 1484383, 4514
6 = 489.46301269531, -3.7840197086334, 480.79840087891, 1483484, 4514
7 = 490.44616699219, -3.2078220844269, 483.06597900391, 1484387, 4514
8 = 492.6803894043, -1.9020791053772, 484.25588989258, 1484389, 4514
9 = 495.31387329102, -0.35850203037262, 482.5299987793, 1484387, 4514
10 = 494.93963623047, -0.57710492610931, 486.56393432617, 1484393, 4514
11 = 491.62573242188, -2.5202298164368, 488.52731323242, 1484395, 4514
12 = 491.08670043945, -2.8318347930908, 491.09460449219, 1484399, 4514
13 = 494.86471557617, -0.62301087379456, 491.8046875, 1484400, 4514
14 = 492.7966003418, -1.8310754299164, 496.10461425781, 1484406, 4514
15 = 494.79760742188, -0.66511011123657, 497.61932373047, 1484408, 4514
16 = 494.31958007812, -0.93994349241257, 493.5032043457, 1484402, 4514
17 = 493.18243408203, -1.6116418838501, 487.59106445312, 1484394, 4514
18 = 493.69686889648, -1.3094255924225, 482.28176879883, 1484386, 4514
19 = 492.17797851562, -2.1932346820831, 473.59088134766, 1484374, 4514
@@ -0,0 +1,29 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; LIMANSK
;[lim_space_restrictor_to_dead_city]
[lim_space_restrictor_to_red_forest]
1 = 5.6008362770081, -1.2617666721344, -346.2197265625, 27778, 2445
2 = 7.8934173583984, -0.95882701873779, -347.94400024414, 29127, 2445
3 = 8.3248882293701, -0.51017183065414, -349.91381835938, 29559, 2445
4 = 5.172966003418, -0.80684751272202, -350.45672607422, 27318, 2445
5 = 3.727972984314, -1.155312538147, -348.38946533203, 26494, 2445
6 = 1.3667085170746, -1.2112774848938, -346.31631469727, 25233, 2445
7 = -0.13994081318378, -1.0515072345734, -348.12591552734, 24433, 2445
8 = -2.1508090496063, -0.24223990738392, -351.08221435547, 22955, 2445
9 = 0.13923038542271, -0.23104156553745, -352.6555480957, 25224, 2467
10 = 3.023430109024, -0.66883915662766, -351.34225463867, 26081, 2445
11 = 4.3488221168518, -0.37662863731384, -352.79437255859, 26875, 2467
12 = 6.3408555984497, -0.25080263614655, -353.43765258789, 28237, 2467
13 = 6.3940362930298, -1.0159969329834, -349.00018310547, 28243, 2445
14 = 1.9117782115936, -1.1612479686737, -348.46301269531, 25659, 2445
15 = 0.97647929191589, -0.79057037830353, -350.30047607422, 24796, 2445
16 = 4.0864224433899, -0.20606029033661, -353.73370361328, 26874, 2467
17 = 4.8362164497375, -0.0075849592685699, -355.83456420898, 27311, 2467
18 = 2.2595119476318, -0.0073282122612, -357.63226318359, 25646, 2467
19 = 6.4188323020935, -0.0086917579174042, -360.40908813477, 28233, 2467
20 = 4.4945750236511, -0.010834336280823, -358.03091430664, 26868, 2467
21 = 1.5121190547943, -0.007807195186615, -355.7353515625, 25220, 2467
;[lim_space_restrictor_to_hospital]
@@ -0,0 +1,23 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; PRIPYAT
;[pri_space_restrictor_to_cop_pripyat]
;[pri_space_restrictor_to_jupiter]
;[pri_space_restrictor_to_stancia]
[pri_space_restrictor_to_radar]
2 = 27.735363006592, -2.3946285247803, -275.5305480957, 136792, 3059
3 = 22.908981323242, -2.394415140152, -278.52224731445, 130073, 3059
4 = 26.569368362427, -2.3933322429657, -279.99621582031, 134948, 3059
5 = 26.85177230835, -2.3679265975952, -285.20831298828, 134941, 3059
6 = 19.715572357178, -2.393771648407, -287.11911010742, 125757, 3059
7 = 17.71665763855, -2.3912227153778, -283.20037841797, 122913, 3059
8 = 31.134016036987, -2.2665064334869, -287.98602294922, 140451, 3061
9 = 13.483926773071, -1.722090959549, -283.35296630859, 117698, 3059
10 = 9.3418865203857, -1.4478409290314, -273.52383422852, 112709, 3059
11 = 8.0723934173584, -1.6926696300507, -285.32208251953, 111891, 3059
12 = -8.2943687438965, -2.2277145385742, -281.30633544922, 91241, 3077
13 = -4.5102219581604, -2.2234971523285, -287.22543334961, 96698, 3077
14 = 4.1600069999695, -2.0096843242645, -275.71868896484, 106964, 3059
15 = -1.2017902135849, -2.3967592716217, -274.41299438477, 100249, 3059
16 = 22.344694137573, -2.3941898345947, -274.79336547852, 129215, 3059
@@ -0,0 +1,185 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; ROSTOK (l05_bar)
[bar_space_restrictor_to_garbage_01]
2 = 398.42559814453, 18.712446212769, -289.62203979492, 94284, 1673
3 = 399.70941162109, 18.523599624634, -292.03057861328, 94901, 1673
4 = 404.03649902344, 17.664722442627, -295.51446533203, 96711, 1673
5 = 404.97570800781, 17.309112548828, -298.09997558594, 97298, 1673
6 = 407.37908935547, 16.964475631714, -298.998046875, 98164, 1673
7 = 407.4694519043, 16.713312149048, -301.80688476562, 98160, 1673
8 = 409.20190429688, 16.518196105957, -303.95422363281, 98959, 1673
9 = 411.37380981445, 16.3564453125, -303.2981262207, 99621, 1673
10 = 410.21035766602, 16.61194229126, -300.51135253906, 99195, 1673
11 = 413.71380615234, 16.430734634399, -296.84075927734, 100182, 1673
12 = 410.23352050781, 17.051279067993, -293.78894042969, 99204, 1673
13 = 413.37051391602, 16.748140335083, -288.5559387207, 100194, 1673
14 = 414.32772827148, 16.778646469116, -284.29284667969, 100357, 1792
15 = 411.09866333008, 17.085166931152, -285.82244873047, 99434, 1792
16 = 407.77084350586, 17.491104125977, -289.1887512207, 98460, 1673
17 = 403.45120239258, 18.078954696655, -287.45721435547, 96419, 1673
18 = 406.05599975586, 17.764127731323, -283.3049621582, 97604, 1792
19 = 408.66870117188, 17.428047180176, -282.474609375, 98737, 1792
20 = 412.10726928711, 17.052276611328, -282.11630249023, 99848, 1792
21 = 413.53619384766, 16.840635299683, -278.58843994141, 100208, 1792
22 = 414.49468994141, 16.713390350342, -276.32122802734, 100368, 1792
23 = 409.04177856445, 17.247318267822, -274.81787109375, 98748, 1792
24 = 405.43423461914, 17.80121421814, -277.58773803711, 97327, 1792
25 = 401.95837402344, 18.298393249512, -277.34051513672, 95829, 1792
26 = 398.49551391602, 18.766569137573, -282.54333496094, 94294, 1792
27 = 392.47680664062, 19.290367126465, -284.97607421875, 91889, 1792
28 = 382.67755126953, 19.246496200562, -291.45086669922, 87778, 1673
29 = 380.38897705078, 19.148294448853, -293.0986328125, 86770, 1673
30 = 378.84078979492, 18.819812774658, -295.38824462891, 86767, 1673
31 = 376.87902832031, 18.666212081909, -296.66079711914, 86767, 1673
32 = 375.0166015625, 19.039325714111, -294.65744018555, 86768, 1673
33 = 373.53399658203, 19.413963317871, -292.54797363281, 85988, 1673
34 = 372.67144775391, 19.334060668945, -295.40914916992, 85988, 1673
35 = 371.33807373047, 19.761001586914, -287.34069824219, 85469, 1792
36 = 374.92926025391, 19.582929611206, -286.87170410156, 85211, 1792
37 = 377.08001708984, 19.37420463562, -291.12493896484, 85988, 1673
38 = 380.48767089844, 19.369066238403, -289.65643310547, 87029, 1673
39 = 383.42535400391, 19.226703643799, -288.8193359375, 88044, 1673
40 = 383.66928100586, 19.234746932983, -286.09631347656, 88048, 1792
41 = 382.91229248047, 19.297523498535, -282.25445556641, 87791, 1792
42 = 378.86929321289, 19.491104125977, -283.08563232422, 86260, 1792
43 = 375.92916870117, 19.697513580322, -280.59719848633, 85219, 1792
44 = 372.6081237793, 19.818748474121, -283.39645385742, 84699, 1792
45 = 370.93911743164, 20.104372024536, -280.21624755859, 83935, 1792
46 = 372.71240234375, 20.08084487915, -276.14440917969, 83939, 1792
47 = 396.34881591797, 19.010665893555, -286.41149902344, 93377, 1792
[bar_space_restrictor_to_military_01]
48 = 53.747989654541, -2.8646786212921, 313.21731567383, 25564, 1747
49 = 56.067440032959, -2.8142721652985, 314.22882080078, 25846, 1747
50 = 58.439033508301, -2.7109158039093, 312.62185668945, 26126, 1747
51 = 61.163749694824, -2.6515352725983, 311.74621582031, 26945, 1747
52 = 63.326007843018, -2.6119091510773, 311.10559082031, 26945, 1747
53 = 66.132659912109, -2.5821325778961, 310.58251953125, 26945, 1747
54 = 68.828048706055, -2.5990154743195, 311.27444458008, 26945, 1747
55 = 71.171173095703, -2.4932849407196, 308.16577148438, 27207, 1747
56 = 71.537399291992, -2.5669214725494, 310.55328369141, 27207, 1747
57 = 71.37329864502, -2.658704996109, 313.26510620117, 27207, 1747
58 = 70.383079528809, -2.6648910045624, 315.32608032227, 27207, 1747
59 = 68.885055541992, -2.6062097549438, 317.04327392578, 27207, 1747
60 = 66.936737060547, -2.5900435447693, 316.86322021484, 27207, 1747
61 = 65.144119262695, -2.5898730754852, 318.17269897461, 27207, 1747
62 = 63.075378417969, -2.6261043548584, 318.19854736328, 27207, 1747
63 = 60.842864990234, -2.6726477146149, 319.08776855469, 27207, 1747
64 = 59.05199432373, -2.7170145511627, 318.2724609375, 27207, 1747
65 = 57.339691162109, -2.7357385158539, 320.24862670898, 26945, 1747
66 = 59.850814819336, -2.736732006073, 315.81564331055, 26945, 1747
67 = 62.281044006348, -2.7175056934357, 314.56735229492, 26945, 1747
68 = 60.490856170654, -2.6176192760468, 309.8733215332, 27207, 1747
69 = 57.310920715332, -2.6761758327484, 310.08532714844, 26678, 1747
70 = 54.342655181885, -2.7894785404205, 310.77215576172, 25844, 1747
71 = 52.076671600342, -2.8463666439056, 309.96807861328, 24725, 1747
72 = 52.162677764893, -2.7633285522461, 307.00311279297, 24999, 1747
73 = 54.13395690918, -2.6462395191193, 305.30596923828, 25553, 1747
74 = 58.499061584473, -2.5153872966766, 304.185546875, 27460, 1747
75 = 60.661304473877, -2.4827132225037, 304.17135620117, 28204, 1747
76 = 63.037803649902, -2.484904050827, 305.44381713867, 28204, 1747
77 = 65.236587524414, -2.4773147106171, 306.42031860352, 28204, 1747
78 = 68.660552978516, -2.4646248817444, 306.99542236328, 28204, 1747
79 = 70.992614746094, -2.4256584644318, 305.7956237793, 28204, 1747
80 = 70.83805847168, -2.3670370578766, 303.1943359375, 28203, 1747
81 = 70.833282470703, -2.3218858242035, 300.89096069336, 28200, 1747
82 = 69.257553100586, -2.2947404384613, 299.63665771484, 28198, 1747
83 = 66.99089050293, -2.3414471149445, 301.81939697266, 28201, 1747
84 = 64.884437561035, -2.3947687149048, 302.99569702148, 28203, 1747
85 = 42.105575561523, -2.4220378398895, 291.0319519043, 21965, 1747
86 = 40.821830749512, -2.3688244819641, 288.02624511719, 21679, 1747
87 = 38.293727874756, -2.4051442146301, 288.38000488281, 21319, 1747
88 = 35.201446533203, -2.4112558364868, 288.16122436523, 20869, 1747
89 = 32.861812591553, -2.3219363689423, 287.42944335938, 20869, 1747
90 = 29.965297698975, -2.2063200473785, 287.47232055664, 20869, 1747
91 = 28.306583404541, -2.1279273033142, 286.13635253906, 20869, 1747
92 = 25.695785522461, -2.031129360199, 285.55288696289, 20869, 1747
93 = 24.566692352295, -1.9559602737427, 284.26129150391, 20869, 1747
94 = 22.195545196533, -1.8915138244629, 285.41928100586, 20869, 1747
95 = 20.064474105835, -1.7899518013, 284.25390625, 20869, 1747
96 = 19.891710281372, -1.7437613010406, 283.11657714844, 20869, 1747
97 = 18.092906951904, -1.6502184867859, 282.39831542969, 20869, 1747
98 = 15.540853500366, -1.6161961555481, 284.21600341797, 20869, 1747
99 = 12.920803070068, -1.5410053730011, 282.78594970703, 20869, 1747
100 = 11.745616912842, -1.5164902210236, 281.0055847168, 20869, 1747
101 = 9.6216516494751, -1.4760076999664, 281.61151123047, 20869, 1747
102 = 8.5856418609619, -1.4246706962585, 283.96768188477, 20869, 1747
103 = 5.5150203704834, -1.3201856613159, 283.83612060547, 20869, 1747
104 = 5.0851283073425, -1.3129162788391, 282.470703125, 20869, 1747
105 = 3.5757248401642, -1.2670698165894, 280.79745483398, 20869, 1747
106 = 3.6359777450562, -1.2850848436356, 278.43542480469, 20869, 1747
107 = 6.1300239562988, -1.3968551158905, 276.63525390625, 20869, 1747
108 = 8.5495338439941, -1.4640047550201, 277.52709960938, 20869, 1747
109 = 12.681200027466, -1.511111497879, 279.16610717773, 20869, 1747
110 = 15.830169677734, -1.5668976306915, 280.44586181641, 20869, 1747
111 = 18.351526260376, -1.6006572246552, 279.06170654297, 20869, 1747
112 = 19.1136302948, -1.5137362480164, 274.75726318359, 20869, 1747
113 = 15.231885910034, -1.4542443752289, 274.15200805664, 20869, 1747
114 = 11.164548873901, -1.4707386493683, 276.33511352539, 20869, 1747
115 = 8.347128868103, -1.4554598331451, 279.58343505859, 20869, 1747
116 = 6.1599097251892, -1.3722062110901, 280.02529907227, 20869, 1747
117 = 4.2877941131592, -1.2758162021637, 284.00476074219, 20869, 1747
118 = 5.7069821357727, -1.2067248821259, 286.16641235352, 20869, 1747
119 = 8.7427215576172, -1.3268134593964, 285.83892822266, 20869, 1747
120 = 10.838638305664, -1.2815440893173, 288.17129516602, 20869, 1747
121 = 13.649578094482, -1.3658447265625, 289.69995117188, 20870, 1747
122 = 16.867286682129, -1.6728520393372, 288.8671875, 20869, 1747
123 = 20.122133255005, -1.8037235736847, 289.22607421875, 20869, 1747
124 = 22.127241134644, -1.8989126682281, 290.78674316406, 20758, 1747
125 = 25.915561676025, -2.1025791168213, 290.2936706543, 20757, 1747
126 = 28.0367603302, -2.2649953365326, 292.04318237305, 20643, 1747
127 = 30.829917907715, -2.3972120285034, 291.46621704102, 20530, 1747
128 = 33.696804046631, -2.5741708278656, 291.74838256836, 20643, 1747
129 = 34.809902191162, -2.756475687027, 294.27099609375, 20762, 1747
130 = 28.54626083374, -2.4072539806366, 296.15744018555, 20307, 1747
131 = 26.09058380127, -2.2638647556305, 296.83535766602, 20308, 1747
132 = 23.487035751343, -2.0938401222229, 296.66012573242, 20308, 1747
133 = 20.489427566528, -1.8234944343567, 297.33355712891, 20309, 1747
134 = 17.605997085571, -1.5756556987762, 296.66564941406, 20308, 1747
135 = 15.065651893616, -1.3405401706696, 297.38690185547, 20309, 1747
136 = 12.387344360352, -1.2716710567474, 301.28515625, 20309, 1747
137 = 9.8881855010986, -0.91937947273254, 299.35675048828, 20309, 1747
138 = 9.70920753479, -0.92311251163483, 294.68911743164, 20307, 1747
139 = 7.247989654541, -0.89250934123993, 292.24310302734, 20307, 1747
140 = 4.1890969276428, -0.73791772127151, 295.68011474609, 20307, 1747
141 = 1.0545825958252, -0.70170342922211, 298.0758972168, 20309, 1747
142 = 0.48621064424515, -0.91818815469742, 301.78457641602, 20309, 1747
143 = 3.3272879123688, -1.2184317111969, 303.92056274414, 20309, 1747
144 = 6.6100611686707, -1.6101086139679, 306.79205322266, 20309, 1747
145 = 9.1191940307617, -1.9425971508026, 308.53323364258, 20309, 1747
146 = 12.549734115601, -1.8262805938721, 306.16708374023, 20309, 1747
147 = 15.814189910889, -1.993147611618, 305.09881591797, 20309, 1747
148 = 18.789836883545, -2.523514509201, 307.49835205078, 20309, 1747
149 = 18.448818206787, -2.9326415061951, 311.0322265625, 20309, 1747
150 = 17.658151626587, -3.2179250717163, 313.86874389648, 20309, 1747
151 = 22.446250915527, -3.548264503479, 313.71670532227, 19191, 1747
152 = 24.069896697998, -2.9549429416656, 307.40634155273, 19448, 1747
153 = 22.877758026123, -2.4113409519196, 303.40048217773, 19516, 1747
154 = 20.504117965698, -1.9405815601349, 300.86782836914, 19516, 1747
155 = 16.530910491943, -1.5529947280884, 300.41744995117, 19516, 1747
156 = 13.353231430054, -1.1579294204712, 297.51193237305, 19516, 1747
157 = 26.854200363159, -2.4132142066956, 300.30847167969, 19881, 1747
158 = 15.389101028442, -3.7413070201874, 319.70397949219, 18571, 1747
159 = 52.269100189209, -2.6661615371704, 303.52587890625, 24994, 1747
160 = 57.266204833984, -2.5902128219604, 306.44396972656, 26942, 1747
161 = 57.856002807617, -2.4524047374725, 301.1413269043, 27197, 1747
162 = 65.826934814453, -2.2618503570557, 297.77835083008, 28196, 1747
163 = 69.925270080566, -2.2333552837372, 296.54354858398, 28194, 1747
164 = 34.120407104492, -2.2005527019501, 284.46264648438, 21096, 1747
165 = 30.4352684021, -2.1389255523682, 284.44119262695, 21096, 1747
166 = 30.721267700195, -2.0337865352631, 281.26382446289, 21096, 1747
167 = 28.401754379272, -1.8913993835449, 279.24731445312, 21096, 1747
168 = 24.741611480713, -1.8356578350067, 280.77471923828, 21096, 1747
169 = 21.222291946411, -1.629896402359, 276.97088623047, 21096, 1747
170 = 21.872995376587, -1.5051412582397, 273.55569458008, 21096, 1747
171 = 23.527084350586, -1.4882447719574, 272.53741455078, 21096, 1747
172 = 26.280456542969, -1.6128718852997, 275.16165161133, 21096, 1747
173 = 29.051937103271, -1.7331619262695, 276.18392944336, 21096, 1747
174 = 30.751560211182, -1.9250757694244, 278.33666992188, 21096, 1747
175 = 33.534225463867, -2.0162026882172, 280.69110107422, 21096, 1747
176 = 38.468360900879, -1.8496987819672, 278.10339355469, 21669, 1750
177 = 39.037261962891, -2.1108067035675, 283.56600952148, 21422, 1747
178 = 43.219619750977, -2.1783344745636, 286.78341674805, 22251, 1747
179 = 60.166435241699, -2.3586294651031, 298.38943481445, 27948, 1747
180 = 54.719867706299, -2.4405574798584, 298.29385375977, 25826, 1747
@@ -0,0 +1,54 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; MARSH
;[mar_space_restrictor_to_agroprom_1]
;[mar_space_restrictor_to_escape_1]
[mar_space_restrictor_to_escape_2]
1 = 642.99481201172, 7.0014982223511, 413.09774780273, 531303, 226
2 = 641.41638183594, 7.0155477523804, 414.7041015625, 531235, 226
3 = 640.07525634766, 7.1475458145142, 417.93179321289, 531161, 226
4 = 640.12243652344, 7.3397779464722, 421.18667602539, 531166, 226
5 = 642.296875, 7.4275631904602, 419.76208496094, 531239, 226
6 = 642.19018554688, 7.371434211731, 418.01184082031, 531237, 226
7 = 643.51550292969, 7.3680143356323, 417.67810058594, 531237, 226
8 = 643.15350341797, 7.2840628623962, 416.14135742188, 531236, 226
9 = 643.86004638672, 7.2264575958252, 414.84295654297, 531303, 226
10 = 645.22192382812, 7.3400106430054, 416.30288696289, 531303, 226
11 = 646.71240234375, 7.3974924087524, 417.7399597168, 531303, 226
12 = 645.89599609375, 7.4542760848999, 419.74240112305, 531671, 227
13 = 647.59405517578, 7.4754662513733, 419.98068237305, 531671, 227
14 = 649.55383300781, 7.4505662918091, 418.70751953125, 531706, 227
15 = 650.57897949219, 7.4724140167236, 419.63848876953, 531706, 227
16 = 649.51342773438, 7.5352921485901, 421.34790039062, 531706, 227
17 = 647.96697998047, 7.5337753295898, 422.55889892578, 531706, 227
18 = 647.05108642578, 7.5098614692688, 424.19125366211, 531638, 227
19 = 648.69635009766, 7.5411558151245, 424.20504760742, 531740, 227
20 = 650.42645263672, 7.5789079666138, 422.55758666992, 531795, 227
21 = 656.00524902344, 7.5584139823914, 420.75555419922, 531963, 227
22 = 657.34149169922, 7.6601986885071, 421.89251708984, 531980, 227
23 = 660.03125, 7.5560526847839, 419.61535644531, 532027, 227
24 = 659.07995605469, 7.6629905700684, 421.45556640625, 532018, 227
25 = 657.72607421875, 7.5573968887329, 420.26727294922, 531991, 227
26 = 657.32891845703, 7.9170179367065, 430.09289550781, 531976, 227
27 = 645.70916748047, 7.475772857666, 426.72564697266, 531563, 227
28 = 640.95300292969, 7.4013032913208, 423.05374145508, 531243, 226
29 = 640.04400634766, 7.3253073692322, 424.47930908203, 531170, 226
30 = 653.89587402344, 7.7535285949707, 436.3388671875, 531913, 227
31 = 652.68615722656, 7.6665229797363, 437.9345703125, 531876, 227
32 = 651.68084716797, 7.6159172058105, 435.15942382812, 531849, 227
33 = 649.32452392578, 7.4641523361206, 434.90921020508, 531782, 227
34 = 648.51184082031, 7.4066867828369, 435.93988037109, 531725, 227
35 = 649.31567382812, 7.4468412399292, 438.13171386719, 531787, 227
36 = 652.04309082031, 7.6125650405884, 440.11764526367, 531877, 227
37 = 647.25433349609, 7.3526873588562, 438.71630859375, 531693, 227
38 = 644.85101318359, 7.3006043434143, 438.50921630859, 531527, 227
39 = 643.73388671875, 7.2958312034607, 440.68060302734, 531483, 227
40 = 639.54144287109, 7.3991260528564, 440.31463623047, 531101, 226
41 = 646.13458251953, 7.3389115333557, 440.03967285156, 531622, 227
42 = 648.74481201172, 7.4136142730713, 440.39971923828, 531761, 227
43 = 649.87518310547, 7.4727153778076, 439.92785644531, 531812, 227
44 = 650.86553955078, 7.5444784164429, 438.51690673828, 531833, 227
45 = 651.2578125, 7.5823087692261, 436.21612548828, 531829, 227
46 = 651.71105957031, 7.5973310470581, 438.88949584961, 531854, 227
47 = 654.41967773438, 7.7954816818237, 434.26174926758, 531930, 227
@@ -0,0 +1,8 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; TRUCK CEMETARY
;[tc_space_restrictor_to_bar]
;[tc_space_restrictor_to_darkvalley]
;[tc_space_restrictor_to_military_1]
;[tc_space_restrictor_to_military_2]
;[tc_space_restrictor_to_military_3]
@@ -0,0 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; WILD TERRITORY
;[ros_space_restrictor_to_bar_1]
;[ros_space_restrictor_to_garbage_1]
;[ros_space_restrictor_to_yantar_1]
@@ -0,0 +1,187 @@
;;;;;;;;;;;;;;;;;;;;;;;;
;; YANTAR
[yan_space_restrictor_to_rostok_1]
1 = 214.01676940918, 14.945219993591, -263.0671081543, 151490, 2190
2 = 218.45693969727, 14.838492393494, -266.46203613281, 151490, 2190
3 = 222.93298339844, 12.314450263977, -269.78979492188, 151700, 2190
4 = 224.11212158203, 11.982655525208, -271.39706420898, 151700, 2190
5 = 227.09614562988, 10.637351989746, -273.17797851562, 151700, 2190
6 = 228.95404052734, 11.663956642151, -277.31723022461, 151700, 2190
7 = 216.302734375, 16.887329101562, -268.00634765625, 151636, 2190
8 = 237.77131652832, 8.9262094497681, -258.59213256836, 152334, 2190
9 = 241.51081848145, 10.995436668396, -259.29809570312, 152334, 2190
10 = 240.96994018555, 11.936392784119, -257.35928344727, 152334, 2190
11 = 218.96658325195, 9.5583219528198, -261.10296630859, 151636, 2190
12 = 243.87426757812, 14.695408821106, -256.56106567383, 152334, 2190
13 = 243.84230041504, 16.015581130981, -254.08694458008, 152334, 2190
14 = 246.61489868164, 18.613355636597, -253.38511657715, 152334, 2190
15 = 247.06323242188, 19.359834671021, -252.1305847168, 152334, 2190
16 = 244.3395690918, 17.962549209595, -249.37292480469, 152334, 2190
17 = 242.00799560547, 18.154249191284, -242.22868347168, 152334, 2190
18 = 238.88485717773, 13.048268318176, -245.53330993652, 152334, 2190
19 = 239.25021362305, 12.156739234924, -249.30302429199, 152334, 2190
20 = 237.21421813965, 9.7335424423218, -252.00341796875, 152334, 2190
21 = 231.74774169922, 7.477283000946, -245.02975463867, 152103, 2190
22 = 216.42906188965, 12.653853416443, -262.26446533203, 151636, 2190
23 = 235.04080200195, 12.213216781616, -240.87004089355, 152068, 2190
24 = 236.09143066406, 16.972816467285, -232.91839599609, 152068, 2190
25 = 231.06509399414, 9.8892698287964, -238.3932800293, 152068, 2190
26 = 226.55885314941, 6.040952205658, -246.33825683594, 151953, 2190
27 = 220.73466491699, 16.203832626343, -271.81210327148, 151841, 2237
28 = 220.87008666992, 17.786918640137, -274.53356933594, 151841, 2237
29 = 219.19612121582, 20.43758392334, -275.74682617188, 151841, 2237
30 = 218.83383178711, 21.895454406738, -277.95983886719, 151841, 2237
31 = 216.9150390625, 22.82657623291, -280.08395385742, 151841, 2237
32 = 214.73983764648, 23.836521148682, -280.58023071289, 151841, 2237
33 = 212.67796325684, 13.885208129883, -260.07843017578, 151636, 2190
34 = 214.03065490723, 23.936676025391, -282.77758789062, 151841, 2237
35 = 216.66244506836, 22.819728851318, -285.94403076172, 151841, 2237
36 = 216.07594299316, 23.133415222168, -288.48529052734, 151841, 2237
37 = 212.64793395996, 23.513410568237, -288.14886474609, 151841, 2237
38 = 209.40097045898, 23.831558227539, -286.16955566406, 151841, 2237
39 = 206.41398620605, 24.008317947388, -287.70516967773, 151841, 2237
40 = 208.23110961914, 23.585697174072, -290.30749511719, 151841, 2237
41 = 211.15081787109, 23.617839813232, -292.38958740234, 151841, 2237
42 = 211.37922668457, 23.560974121094, -296.30935668945, 151841, 2237
43 = 208.67637634277, 23.690906524658, -296.61279296875, 151841, 2237
44 = 213.98818969727, 11.613419532776, -259.244140625, 151636, 2190
45 = 206.37553405762, 23.619276046753, -293.1692199707, 151841, 2237
46 = 202.76240539551, 23.849523544312, -298.39154052734, 151841, 2237
47 = 207.86335754395, 23.746698379517, -299.79565429688, 151841, 2237
48 = 203.94172668457, 23.738075256348, -295.3132019043, 151841, 2237
49 = 209.71006774902, 24.238712310791, -283.48992919922, 151841, 2237
50 = 216.07098388672, 20.9700050354, -274.02410888672, 151841, 2237
51 = 211.05841064453, 24.598056793213, -278.28851318359, 151841, 2237
52 = 254.95304870605, 23.973201751709, -247.2066192627, 152282, 2190
53 = 254.35006713867, 23.06103515625, -252.16125488281, 152282, 2190
54 = 250.68003845215, 20.676410675049, -255.46382141113, 152282, 2190
55 = 216.3636932373, 11.269558906555, -260.17468261719, 151636, 2190
56 = 247.07878112793, 17.758453369141, -256.09912109375, 152282, 2190
57 = 245.48486328125, 19.937789916992, -246.12902832031, 152282, 2190
58 = 243.76080322266, 21.041080474854, -237.02017211914, 152032, 2190
59 = 233.31280517578, 9.4228525161743, -242.41479492188, 152200, 2190
60 = 233.1965637207, 12.573048591614, -237.27603149414, 152200, 2190
61 = 235.56814575195, 14.905369758606, -236.89320373535, 152200, 2190
62 = 238.76345825195, 16.491086959839, -239.19174194336, 152200, 2190
63 = 240.02532958984, 18.346445083618, -237.51226806641, 152200, 2190
64 = 242.07220458984, 20.538021087646, -235.24185180664, 152200, 2190
65 = 244.63725280762, 21.958177566528, -234.64387512207, 152200, 2190
66 = 216.67922973633, 8.8011560440063, -258.35629272461, 151546, 2190
67 = 244.29006958008, 22.390289306641, -229.34799194336, 152200, 2190
68 = 236.53880310059, 18.487678527832, -229.70887756348, 152200, 2190
69 = 232.73318481445, 15.361424446106, -231.84233093262, 152200, 2190
70 = 229.86245727539, 13.839221000671, -231.78485107422, 152200, 2190
71 = 228.32960510254, 10.804577827454, -235.10194396973, 152103, 2190
72 = 226.42124938965, 8.8348455429077, -236.53454589844, 151814, 2190
73 = 223.33004760742, 9.7049436569214, -233.74600219727, 151760, 2190
74 = 225.04653930664, 15.066195487976, -227.0975189209, 151760, 2190
75 = 230.41249084473, 15.951380729675, -228.66276550293, 151760, 2190
76 = 213.79196166992, 8.4399814605713, -256.44931030273, 151409, 2190
77 = 220.45950317383, 7.0790395736694, -258.62591552734, 151669, 2190
[yan_space_restrictor_to_agroprom_1]
1 = -47.470508575439, -1.3085865974426, -342.1123046875, 45684, 2188
2 = -46.726543426514, 0.48845207691193, -345.25909423828, 45684, 2188
3 = -42.46736907959, 3.0471038818359, -346.56088256836, 45684, 2188
4 = -45.762275695801, 5.2205004692078, -350.30389404297, 45684, 2188
5 = -37.453689575195, 9.292797088623, -351.71481323242, 45684, 2188
6 = -45.841133117676, 8.7268667221069, -358.50741577148, 45684, 2188
7 = -53.041507720947, 5.5128841400146, -359.04364013672, 44758, 2188
8 = -78.129005432129, 4.6843404769897, -354.04336547852, 33846, 2188
9 = -77.726280212402, 7.9816427230835, -362.29968261719, 33846, 2188
10 = -82.963310241699, 10.614577293396, -358.26080322266, 33846, 2188
11 = -48.387672424316, 16.303703308105, -369.50332641602, 35537, 2289
12 = -82.611633300781, 8.9144430160522, -354.16729736328, 33846, 2188
13 = -80.270324707031, 6.6720914840698, -354.37283325195, 33846, 2188
14 = -80.411361694336, 5.1313948631287, -351.16705322266, 33846, 2188
15 = -82.382057189941, 6.3483963012695, -348.75839233398, 33846, 2188
16 = -83.403289794922, 5.0336470603943, -345.35958862305, 33846, 2188
17 = -85.783576965332, 6.2908020019531, -343.73724365234, 33847, 2188
18 = -87.471168518066, 9.8479051589966, -346.16580200195, 33846, 2188
19 = -89.52326965332, 15.383200645447, -349.87567138672, 33846, 2188
20 = -87.99927520752, 15.010334968567, -355.22155761719, 33846, 2188
21 = -85.489837646484, 13.118271827698, -359.31646728516, 33846, 2188
22 = -51.207542419434, 15.438944816589, -369.82434082031, 35537, 2289
23 = -88.7353515625, 17.082841873169, -361.91122436523, 33846, 2188
24 = -91.497268676758, 19.198776245117, -360.15856933594, 33846, 2188
25 = -93.083618164062, 19.479309082031, -354.70880126953, 33846, 2188
26 = -98.107215881348, 22.162048339844, -356.45407104492, 33846, 2188
27 = -97.441558837891, 22.581592559814, -365.05938720703, 33846, 2188
28 = -92.894973754883, 20.350339889526, -366.53372192383, 33846, 2188
29 = -92.133079528809, 19.721487045288, -369.94274902344, 33846, 2188
30 = -83.861038208008, 13.311237335205, -364.84216308594, 33846, 2188
31 = -77.299865722656, 5.685980796814, -357.89288330078, 33846, 2188
32 = -76.241493225098, 3.3761818408966, -353.30645751953, 33846, 2188
33 = -50.607627868652, 13.438889503479, -366.37426757812, 35537, 2289
34 = -78.661727905273, 3.7008774280548, -351.45373535156, 33846, 2188
35 = -81.285301208496, 6.7631306648254, -352.6383972168, 33846, 2188
36 = -83.833106994629, 8.4024324417114, -351.26281738281, 33846, 2188
37 = -85.761352539062, 11.355331420898, -352.85113525391, 33846, 2188
38 = -89.247863769531, 15.688110351562, -352.04629516602, 33846, 2188
39 = -92.809555053711, 18.619411468506, -352.42590332031, 33846, 2188
40 = -97.270721435547, 21.761499404907, -350.43072509766, 33846, 2188
41 = -101.88899230957, 19.987590789795, -345.66668701172, 33846, 2188
42 = -104.53073120117, 20.46311378479, -345.47885131836, 33846, 2188
43 = -107.19931030273, 23.527660369873, -349.41586303711, 33846, 2188
44 = -55.512382507324, 12.395401954651, -367.67694091797, 35537, 2289
45 = -109.52297973633, 25.257957458496, -352.59844970703, 33846, 2188
46 = -105.74708557129, 25.240531921387, -358.00103759766, 33846, 2188
47 = -98.996444702148, 23.053993225098, -367.13641357422, 33846, 2188
48 = -102.21717834473, 24.322797775269, -360.64996337891, 33846, 2188
49 = -109.41414642334, 26.499691009521, -366.86535644531, 33846, 2188
50 = -116.76937103271, 27.265064239502, -362.64447021484, 33846, 2188
51 = -120.57233428955, 27.323657989502, -364.48522949219, 33846, 2188
52 = -117.93885803223, 27.612770080566, -369.59857177734, 33846, 2188
53 = -111.33142852783, 26.959053039551, -373.53359985352, 33846, 2188
54 = -104.76615142822, 24.732048034668, -374.10430908203, 33846, 2188
55 = -58.459159851074, 12.531265258789, -370.38165283203, 35537, 2289
56 = -96.737152099609, 20.752923965454, -377.43206787109, 33846, 2188
57 = -111.2378616333, 26.285514831543, -357.93005371094, 33846, 2188
58 = -116.67597961426, 23.977172851562, -350.32562255859, 33846, 2188
59 = -123.57715606689, 26.895576477051, -356.29119873047, 33846, 2188
60 = -110.35958099365, 21.495655059814, -345.49682617188, 33846, 2188
61 = -103.80910491943, 24.421922683716, -353.38220214844, 33846, 2188
62 = -83.522918701172, 12.238227844238, -361.22561645508, 33846, 2188
63 = -76.507797241211, 4.5830173492432, -356.04696655273, 33846, 2188
64 = -80.185699462891, 7.5637607574463, -357.31549072266, 33846, 2188
65 = -79.331108093262, 0.57100349664688, -341.87005615234, 33376, 2188
66 = -58.475303649902, -0.1148624420166, -353.92837524414, 35537, 2289
67 = -78.575500488281, 1.8600428104401, -346.02603149414, 33376, 2188
68 = -83.05647277832, 2.8261525630951, -341.12103271484, 33376, 2188
69 = -55.001068115234, -1.7888402938843, -347.29321289062, 42642, 2188
70 = 229.86245727539, 13.839221000671, -231.78485107422, 152200, 2190
71 = 228.32960510254, 10.804577827454, -235.10194396973, 152103, 2190
72 = 226.42124938965, 8.8348455429077, -236.53454589844, 151814, 2190
73 = 223.33004760742, 9.7049436569214, -233.74600219727, 151760, 2190
74 = 225.04653930664, 15.066195487976, -227.0975189209, 151760, 2190
75 = 230.41249084473, 15.951380729675, -228.66276550293, 151760, 2190
76 = -53.008766174316, -0.17417567968369, -351.33145141602, 42178, 2188
77 = -52.168792724609, -1.8923516273499, -343.20758056641, 44208, 2188
[yan_space_restrictor_to_dead_city_1]
1 = -15.556285858154, 0.37540704011917, -18.524076461792, 59717, 2217
2 = -13.474752426147, 0.19980090856552, -16.758018493652, 60323, 2217
3 = -10.475748062134, 0.082021713256836, -16.815393447876, 61751, 2217
4 = -7.8975124359131, 0.019680351018906, -15.036096572876, 63092, 2217
5 = -7.9948878288269, 0.050183951854706, -20.622592926025, 63084, 2217
6 = -9.320426940918, 0.0767722427845, -22.929056167603, 62423, 2217
7 = -11.201169967651, 0.13750106096268, -22.619333267212, 61403, 2217
8 = -14.573099136353, 0.31118947267532, -25.230201721191, 59713, 2217
9 = -12.521617889404, 0.23213881254196, -26.913457870483, 60664, 2217
10 = -10.31103515625, 0.14267244935036, -26.32421875, 61737, 2217
11 = -7.2853126525879, 0.036082834005356, -27.10823059082, 63384, 2217
12 = -11.460109710693, 0.20483404397964, -29.738170623779, 61393, 2246
13 = -7.9369645118713, 0.050330996513367, -24.700174331665, 63078, 2217
14 = -13.429478645325, 0.088564872741699, 14.417495727539, 60364, 2243
15 = -16.308277130127, 0.21337825059891, 15.805246353149, 59179, 2243
16 = -17.42972946167, 0.26607090234756, 18.512306213379, 58591, 2243
17 = -15.120887756348, 0.26526087522507, 21.29144859314, 59472, 2243
18 = -13.042339324951, 0.1600376367569, 19.411321640015, 60371, 2243
19 = -10.122574806213, 0.035428673028946, 17.23717880249, 62092, 2243
20 = -8.1684637069702, 0.1501100063324, 19.823987960815, 62793, 2243
21 = -10.250232696533, 0.086418926715851, 14.547444343567, 61440, 2243
22 = -7.9567313194275, 0.07547727227211, 12.221810340881, 63403, 2193
23 = -13.655591964722, 0.088144063949585, 16.637174606323, 60062, 2243
24 = -10.789132118225, 0.25435429811478, 21.558292388916, 61782, 2243
25 = -18.377397537231, 0.31346654891968, 21.018630981445, 58303, 2243
@@ -0,0 +1,443 @@
; This file is used to create exceptions for anomaly spawn parameters on a
; transition basis to improve immersion and hazardousness
;
; NOTE: The spread_radius should preferably be lower than the
; CONST_FIELD_SIZE_MIN defined in the main script
#include "transition_settings_*.ltx"
; Define your transitions like this:
; [transiton_section]:defaults
; rootpos = x, y, z ; where the origin point for anomaly spawns should be
; narrow = <bool> [spawn algorithm: smaller offsets]
; count = <float> [dynamic spawns]
; spread_radius = <float> [around rootpos]
; max_height_offset = <float>
; generate_max_tries = <float>
; min_anomaly_proximity = <float> [+ anomaly_radii *2]
; static_spawn_ratio = <float> [tries to spawn the resulting amount]
[defaults]
narrow = false
count = 21
spread_radius = 30
max_height_offset = 0
generate_max_tries = 64
min_anomaly_proximity = 2
static_spawn_ratio = 0.5
;;;;;;;;;;;;;;;;;;;;;;;;
;; CORDON
; Army outpost @ South
[esc_space_restrictor_to_marsh_1]:defaults
rootpos = -262.56866455078, -21.039331436157, -284.20474243164
narrow = true
spread_radius = 30
min_anomaly_proximity = 1.1
[esc_space_restrictor_to_marsh_2]:defaults
rootpos = -185.00993347168, 19.095846176147, 231.13690185547
count = 41
spread_radius = 38
max_height_offset = 3
static_spawn_ratio = 0.6
[esc_space_restrictor_to_darkscape_1]:defaults
rootpos = 355.63342285156, 15.15832233429, -34.174919128418
narrow = true
count = 19
spread_radius = 30
max_height_offset = 1
[esc_space_restrictor_to_pole_1]:defaults
rootpos = 326.90130615234, 18.498018264771, 339.5885925293
count = 23
spread_radius = 40
max_height_offset = 5
static_spawn_ratio = 0.45
; Army outpost @ North
[esc_space_restrictor_to_garbage_1]:defaults
rootpos = 21.078031539917, 16.015649795532, 671.45660400391
static_spawn_ratio = 1.0
[esc_space_restrictor_to_garbage_2]:defaults
rootpos = -154.77156066895, -3.7063891887665, 330.69226074219
count = 24
spread_radius = 35
static_spawn_ratio = 0.3
;;;;;;;;;;;;;;;;;;;;;;;;
;; MARSH
[mar_space_restrictor_to_agroprom_1]:defaults
[mar_space_restrictor_to_escape_1]:defaults
[mar_space_restrictor_to_escape_2]:defaults
rootpos = 655.62628173828, 7.7639408111572, 425.81042480469
narrow = true
spread_radius = 36
static_spawn_ratio = 0.2
;;;;;;;;;;;;;;;;;;;;;;;;
;; DARKSCAPE
[ds_space_restrictor_to_escape]:defaults
rootpos = -603.13073730469, -2.3151462078094, -397.44158935547
narrow = true
count = 16
[ds_space_restrictor_to_darkvalley]:defaults
static_spawn_ratio = 0.7
;;;;;;;;;;;;;;;;;;;;;;;;
;; MEADOW
[pol_space_restrictor_to_escape_1]:defaults
rootpos = -204.05184936523, -16.925643920898, -24.523233413696
count = 16
spread_radius = 25
[pol_space_restrictor_to_val_1]:defaults
rootpos = -38.684341430664, 1.6044301986694, 172.6302947998
count = 14
;;;;;;;;;;;;;;;;;;;;;;;;
;; AGROPROM
[agr_space_restrictor_to_garbage_1]:defaults
rootpos = 249.62699890137, 2.3121690750122, -252.59039306641
count = 24
spread_radius = 35
[agr_space_restrictor_to_garbage_2]:defaults
rootpos = 280.15560913086, 0.31344103813171, 4.7876262664795
count = 24
spread_radius = 35
[agr_space_restrictor_to_marsh_1]:defaults
rootpos = 2.0212745666504, -3.0421557426453, -331.49380493164
[agr_space_restrictor_to_yantar_1]:defaults
rootpos = -221.52743530273, 13.098348617554, 204.60922241211
narrow = true
count = 26
;;;;;;;;;;;;;;;;;;;;;;;;
;; GARBABE
[gar_space_restrictor_to_escape_1]:defaults
rootpos = 31.133201599121, 0.49598652124405, -315.66192626953
;; Small pipe
[gar_space_restrictor_to_escape_2]:defaults
rootpos = -144.30377197266, 0.8311031460762, -285.46295166016
narrow = true
max_height_offset = 4
min_anomaly_proximity = 1
[gar_space_restrictor_to_agroprom_1]:defaults
count = 17
max_height_offset = 5
static_spawn_ratio = 0.4
[gar_space_restrictor_to_agroprom_2]:defaults
count = 29
spread_radius = 35
static_spawn_ratio = 0.35
[gar_space_restrictor_to_rostok_1]:defaults
[gar_space_restrictor_to_bar_1]:defaults
[gar_space_restrictor_to_darkvalley_1]:defaults
spread_radius = 35
static_spawn_ratio = 0.5
[gar_space_restrictor_to_darkvalley_2]:defaults
;;;;;;;;;;;;;;;;;;;;;;;;
;; DARK VALLEY
[val_space_restrictor_to_darkscape]:defaults
count = 14
narrow = true
[val_space_restrictor_to_garbage_1]:defaults
rootpos = -166.14654541016, 4.310423374176, -307.92291259766
count = 14
[val_space_restrictor_to_garbage_2]:defaults
rootpos = -184.41259765625, 3.0746545791626, -187.42942810059
count = 14
[val_space_restrictor_to_pole_1]:defaults
count = 14
[val_space_restrictor_to_tc]:defaults
;;;;;;;;;;;;;;;;;;;;;;;;
;; YANTAR
[yan_space_restrictor_to_agroprom_1]:defaults
rootpos = -70.167518615723, 1.0501892566681, -354.12280273438
narrow = true
count = 14
spread_radius = 25
max_height_offset = 5
[yan_space_restrictor_to_dead_city_1]:defaults
rootpos = -18.525394439697, 0.37441009283066, 0.37217244505882
narrow = true
count = 14
spread_radius = 20
static_spawn_ratio = 0.7
[yan_space_restrictor_to_rostok_1]:defaults
rootpos = 227.8956451416, 6.5885915756226, -256.11004638672
narrow = true
max_height_offset = 5
;;;;;;;;;;;;;;;;;;;;;;;;
;; WILD TERRITORY
[ros_space_restrictor_to_bar_1]:defaults
narrow = true
[ros_space_restrictor_to_garbage_1]:defaults
rootpos = -24.090187072754, -2.5423719882965, -179.62350463867
[ros_space_restrictor_to_yantar_1]:defaults
rootpos = -108.13006591797, -13.720633506775, -224.87098693848
count = 24
spread_radius = 35
max_height_offset = 3
;;;;;;;;;;;;;;;;;;;;;;;;
;; ROSTOK
[bar_space_restrictor_to_garbage_01]:defaults
rootpos = 388.64486694336, 19.281694412231, -290.61553955078
static_spawn_ratio = 0.6
[bar_space_restrictor_to_military_01]:defaults
static_spawn_ratio = 0.3
[bar_space_restrictor_to_tc]:defaults
narrow = true
count = 9
[bar_space_restrictor_to_rostok_01]:defaults
;;;;;;;;;;;;;;;;;;;;;;;;
;; TRUCK CEMETARY
[tc_space_restrictor_to_bar]:defaults
rootpos = -322.5712890625, 6.1045780181885, 82.188682556152
count = 14
spread_radius = 35
max_height_offset = 4
[tc_space_restrictor_to_military_1]:defaults
rootpos = -204.7868347168, 13.47899723053, 353.19250488281
count = 14
spread_radius = 35
max_height_offset = 6
[tc_space_restrictor_to_military_2]:defaults
rootpos = 85.503471374512, 13.016917228699, 367.11950683594
spread_radius = 35
[tc_space_restrictor_to_military_3]:defaults
count = 24
spread_radius = 35
[tc_space_restrictor_to_darkvalley]:defaults
;;;;;;;;;;;;;;;;;;;;;;;;
;; DEAD CITY
[cit_space_restrictor_to_military]:defaults
rootpos = 154.97149658203, -2.6670255661011, -29.174842834473
narrow = true
count = 9
spread_radius = 20
max_height_offset = 1
[cit_space_restrictor_to_limansk]:defaults
count = 14
[cit_space_restrictor_to_yantar]:defaults
rootpos = -11.347318649292, 0.96284037828445, -214.69622802734
narrow = true
count = 14
spread_radius = 20
;;;;;;;;;;;;;;;;;;;;;;;;
;; ARMY WAREHOUSES
[mil_space_restrictor_to_dead_city_1]:defaults
count = 9
[mil_space_restrictor_to_red_1]:defaults
count = 11
[mil_space_restrictor_to_radar_1]:defaults
rootpos = 86.735046386719, -13.390557289124, 410.29614257812
spread_radius = 35
[mil_space_restrictor_to_tc]:defaults
rootpos = -213.66079711914, -10.290971755981, -12.764043807983
count = 7
[mil_space_restrictor_to_bar_1]:defaults
rootpos = -324.86236572266, -25.926807403564, 52.999080657959
max_height_offset = 5
;;;;;;;;;;;;;;;;;;;;;;;;
;; LIMANSK
[lim_space_restrictor_to_dead_city]:defaults
rootpos = -52.307598114014, -5.0046973228455, -244.73245239258
narrow = true
count = 9
[lim_space_restrictor_to_red_forest]:defaults
rootpos = 3.770740032196, -0.0090442895889282, -357.19940185547 ;;4.3045954704285, -0.0095592737197876, -363.99993896484
narrow = true
count = 19
max_height_offset = 3
min_anomaly_proximity = 0.8
[lim_space_restrictor_to_hospital]:defaults
rootpos = 62.153232574463, 3.2995672225952, 343.52059936523
narrow = true
count = 14
;;;;;;;;;;;;;;;;;;;;;;;;
;; RED FOREST
[red_space_restricor_to_jupiter]:defaults
rootpos = -61.157417297363, -0.00012931227684021, 83.650421142578
spread_radius = 35
[red_space_restrictor_to_limansk]:defaults
rootpos = -176.96186828613, 0.1375118792057, -280.86276245117
narrow = true
count = 6
[red_space_restrictor_to_military_1]:defaults
rootpos = -13.942101478577, 0.76041704416275, -438.36660766602
count = 24
spread_radius = 36
[red_space_restrictor_to_radar_1]:defaults
rootpos = 254.71745300293, -1.4554796218872, -310.73031616211
count = 14
spread_radius = 30
;;;;;;;;;;;;;;;;;;;;;;;;
;; RADAR
[rad_space_restrictor_to_pripyat_01]:defaults
rootpos = 383.51205444336, -35.538181304932, 125.76106262207
count = 11
[rad_space_restrictor_to_red_forest]:defaults
rootpos = -25.921100616455, -0.9791322350502, -81.806488037109
narrow = true
count = 11
spread_radius = 20
[rad_space_restrictor_to_military_01]:defaults
rootpos = 568.00762939453, -53.471260070801, -409.02130126953
count = 14
spread_radius = 25
;;;;;;;;;;;;;;;;;;;;;;;;
;; DESERTED HOSPITAL
[katacomb_space_restrictor_to_aes_1]:defaults
narrow = true
count = 7
[katacomb_space_restrictor_to_limansk]:defaults
narrow = true
count = 7
;;;;;;;;;;;;;;;;;;;;;;;;
;; JUPITER
[jupiter_space_restrictor_to_red_forest]:defaults
rootpos = -110.88342285156, 26.951494216919, -492.51205444336
count = 14
spread_radius = 25
[jupiter_space_restrictor_to_soc_pripyat]:defaults
rootpos = 442.33578491211, 27.673992156982, -162.49478149414
count = 24
spread_radius = 35
[jup_space_restrictor_to_zaton]:defaults
rootpos = 476.40084838867, -6.4436411857605, 490.11071777344
count = 24
spread_radius = 35
static_spawn_ratio = 0.8
;;;;;;;;;;;;;;;;;;;;;;;;
;; PRIPYAT
[pri_space_restrictor_to_cop_pripyat]:defaults
rootpos = 190.08209228516, -2.000510931015, 213.37898254395
narrow = true
count = 9
spread_radius = 25
[pri_space_restrictor_to_jupiter]:defaults
rootpos = -112.15048980713, -2.0004575252533, 98.006851196289
narrow = true
count = 7
spread_radius = 25
[pri_space_restrictor_to_radar]:defaults
spread_radius = 35
static_spawn_ratio = 0.8
[pri_space_restrictor_to_stancia]:defaults
rootpos = 31.006572723389, 1.1568984985352, 434.404296875
narrow = true
count = 15
;;;;;;;;;;;;;;;;;;;;;;;;
;; OUTSKIRTS
[cop_pripyat_space_restrictor_to_soc_pripyat]:defaults
rootpos = -244.9404296875, -0.4916250705719, -133.76998901367
count = 19
;;;;;;;;;;;;;;;;;;;;;;;;
;; ZATON
[zaton_space_restrictor_to_jupiter]:defaults
rootpos = 429.95199584961, 29.538331985474, -427.31225585938
[zaton_space_restrictor_to_stancia_1]:defaults
rootpos = -321.41271972656, 19.378704071045, 619.53601074219
;;;;;;;;;;;;;;;;;;;;;;;;
;; CHERNOBYL CNPP - SOUTH
[aes_space_restrictor_to_aes2]:defaults
[aes_space_restrictor_to_pripyat]:defaults
[aes_space_restrictor_to_zaton]:defaults
;;;;;;;;;;;;;;;;;;;;;;;;
;; CHERNOBYL CNPP - NORTH
[aes2_space_restrictor_to_aes1]:defaults
[aes2_space_restrictor_to_gen]:defaults
[aes2_space_restrictor_to_hospital]:defaults
;;;;;;;;;;;;;;;;;;;;;;;;
;; GENERATORS
[gen_space_restrictor_to_aes2]:defaults
@@ -0,0 +1,12 @@
<?xml version="1.0"?>
<string_table>
<string id="st_dynzone_hint_blocked">
<text>hazardous</text>
</string>
<string id="st_dynzone_hint_unknown">
<text>uncertain</text>
</string>
<string id="st_dynzone_discovery_message">
<text>This route may be too hazardous.. Looks like I have to find another way.</text>
</string>
</string_table>
@@ -0,0 +1,201 @@
<?xml version="1.0" encoding="utf-8"?>
<string_table>
<!-- Mod Name -->
<string id="ui_mcm_dynamic_zone">
<text>Dynamic Zone</text>
</string>
<!-- Categories -->
<string id="ui_mcm_dynamic_zone_general">
<text>General</text>
</string>
<string id="ui_mcm_dynamic_zone_news">
<text>News</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery">
<text>Discovery</text>
</string>
<string id="ui_mcm_dynamic_zone_debug">
<text>Debugging</text>
</string>
<!-- General -->
<string id="ui_mcm_dynamic_zone_main_title">
<text>Dynamic Zone : General</text>
</string>
<string id="ui_mcm_dynamic_zone_general_chance_path_closed">
<text>Individual Route Blockage Chance</text>
</string>
<string id="ui_mcm_dynamic_zone_general_chance_path_closed_desc">
<text>Chance for a route to become inpassable during an emission</text>
</string>
<string id="ui_mcm_dynamic_zone_general_chance_dz_trigger">
<text>Chance for an Emission to cause Route changes</text>
</string>
<string id="ui_mcm_dynamic_zone_general_chance_dz_trigger_desc">
<text>Determines the chance for any route changes to happen during an emission.</text>
</string>
<string id="ui_mcm_dynamic_zone_general_minimum_map_connections">
<text>Minimum Remaining Map Connections</text>
</string>
<string id="ui_mcm_dynamic_zone_general_minimum_map_connections_desc">
<text>How many connections should remain passable on each level. E.g. If set to 1, it is ensured that any given map will have at least one traversable path to another map.</text>
</string>
<string id="ui_mcm_dynamic_zone_general_trigger_on_newgame">
<text>Trigger on New Game</text>
</string>
<string id="ui_mcm_dynamic_zone_general_trigger_on_newgame_desc">
<text>This will make some routes inpassable at the beginning of a new game.</text>
</string>
<string id="ui_mcm_dynamic_zone_general_newgame_grace_period">
<text>New Game Grace Period (hours)</text>
</string>
<string id="ui_mcm_dynamic_zone_general_newgame_grace_period_desc">
<text>(Used when "Trigger on New Game" is Disabled) On a New Game, the Zone won't change for the amount of in-game Time defined here</text>
</string>
<string id="ui_mcm_dynamic_zone_general_emission_trigger">
<text>Emission Stage to Trigger on</text>
</string>
<string id="ui_mcm_dynamic_zone_general_emission_trigger_desc">
<text>Stage of emission, where the Zone Change occurs</text>
</string>
<string id="ui_mcm_lst_dynamic_zone_emission_trigger_impact">
<text>Impact</text>
</string>
<string id="ui_mcm_lst_dynamic_zone_emission_trigger_1stwave">
<text>First Wave</text>
</string>
<string id="ui_mcm_lst_dynamic_zone_emission_trigger_2ndwave">
<text>Second Wave</text>
</string>
<string id="ui_mcm_lst_dynamic_zone_emission_trigger_rumble">
<text>Rumble</text>
</string>
<string id="ui_mcm_dynamic_zone_general_addon_removal">
<text>Safe Addon Removal</text>
</string>
<string id="ui_mcm_dynamic_zone_general_addon_removal_desc">
<text>Enable this setting, then save your game. Afterwards, you can remove the addon, load the new savegame and continue playing without Dynamic Zone Transitions.</text>
</string>
<!-- News -->
<string id="ui_mcm_dynamic_zone_news_title">
<text>Dynamic Zone : News</text>
</string>
<string id="ui_mcm_dynamic_zone_news_desc">
<text>Between emissions, stalkers will share their findings via the PDA network about routes that changed their state.\nYou can change the percentage of affected routes to be revealed here.\nUnder some circumstances and a predefined chance, special characters such as Sidorovich may also comment those route changes.</text>
</string>
<string id="ui_mcm_dynamic_zone_news_news_play_discovery_sound">
<text>Play Discovery Sound</text>
</string>
<string id="ui_mcm_dynamic_zone_news_news_play_discovery_sound_desc">
<text>Plays the discovery sound, if the previously known route state was different. Will otherwise always use the default PDA notification sound.</text>
</string>
<string id="ui_mcm_dynamic_zone_news_percent_path_reveal_unblock">
<text>Reveal Percentage for routes that are passable again</text>
</string>
<string id="ui_mcm_dynamic_zone_news_percent_path_reveal_unblock_desc">
<text>How many routes that were previously inpassable will be revealed via the Stalker PDA Network.</text>
</string>
<string id="ui_mcm_dynamic_zone_news_percent_path_reveal_block">
<text>Percentage of Inpassable Routes to Reveal</text>
</string>
<string id="ui_mcm_dynamic_zone_news_percent_path_reveal_block_desc">
<text>How many inpassible routes will be revealed via the Stalker PDA Network.</text>
</string>
<string id="ui_mcm_dynamic_zone_news_chance_special_character">
<text>Chance for a special Character to be the Sender</text>
</string>
<string id="ui_mcm_dynamic_zone_news_chance_special_character_desc">
<text>Chance that a special character will comment changes in the Zone (e.g. Sidorovich).</text>
</string>
<!-- Discovery -->
<string id="ui_mcm_dynamic_zone_discovery_title">
<text>Dynamic Zone : Discovery</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_discovery_msg_showtime">
<text>Showtime for discovery Message</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_dist">
<text>Minimum Binocular Focus Proximity to Transition</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_dist_desc">
<text>Updates the route status of any eligible transition that's currently being focused, if it's within this radius.</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_mapspot_blips_enabled">
<text>Mark Transition's state as Unknown after an Emission</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_mapspot_blips_enabled_desc">
<text>Transitions, whose states are unknown are marked accordingly. These blips are cleared after discovering a routes state. Players who prefer to keep track manually are encouraged to disable this feature.</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_holdtime">
<text>Binoculars Focus Time (milliseconds)</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_holdtime_desc">
<text>Time to focus an eligible transition to discover the state change.</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_max_distance">
<text>Maximum Binocular Discovery Distance</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_max_distance_desc">
<text>A transition with a proximity larger than this to the player can not be discovered.</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_hud_enabled">
<text>Enable Binocular Heads-Up Display</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_hud_enabled_desc">
<text>This displays a marker in 3D space for transitions that are eligible for discovery on the current level.</text>
</string>
<!-- Debugging -->
<string id="ui_mcm_dynamic_zone_debug_title">
<text>Dynamic Zone : Debugging</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_desc">
<text>The options in this category are meant for debugging purposes only.\nLogs are written to 'appdata\logs\mcm' and prefixed with 'dynamic_zone_debug'\nFor that to work, the MCM logging utility should be activated in MCM's own options.</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_emission_check_interval">
<text>Emission check interval (milliseconds)</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_emission_check_interval_desc">
<text>Interval between emission stage checks. This check only runs when an emission has begun.</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_verbose">
<text>Enable Debug Logging</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_verbose_desc">
<text>Utilizes the MCM logging utility. Uses console logging as a fallback, if MCM is not installed.</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_validate_parameter_types">
<text>Validate function parameters</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_validate_parameter_types_desc">
<text>This will validate parameter types and checks for non-nil values throughout all scripts in this mod.</text>
</string>
</string_table>
@@ -0,0 +1,798 @@
<?xml version="1.0" encoding="utf-8"?>
<string_table>
<!--
All communities currently able to propagate route changes:
"stalker", "dolg", "freedom", "bandit", "army",
"ecolog", "killer", "monolith", "csky",
Variables, usable in these strings:
$SENDER_NAME
$ANOM_THEME
$FROM
$TO
-->
<!-- Fallback strings -->
<string id="st_dynzone_news_fallback_blocked">
<text>I got word on the path from $FROM to $TO. Last I heard, $ANOM_THEME anomalies are everywhere. Might be worth waiting it out.</text>
</string>
<string id="st_dynzone_news_fallback_opened">
<text>Just got word, the path leading from $FROM to $TO is clear again. Last emission did us a favor.</text>
</string>
<!-- Anomaly themes -->
<string id="st_dynzone_thermal_theme">
<text>thermal</text>
</string>
<string id="st_dynzone_acidic_theme">
<text>acidic</text>
</string>
<string id="st_dynzone_electric_theme">
<text>electric</text>
</string>
<string id="st_dynzone_gravitational_theme">
<text>gravitational</text>
</string>
<!-- Loners -->
<string id="st_dynzone_news_stalker_blocked_1">
<text>Stalkers, the path between $FROM and $TO is covered with $ANOM_THEME anomalies. Just informing you all.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_2">
<text>Hey, what happened to the path between $FROM and $TO? It was fine before the last emission, but now it's borderline suicidal to take with that patch of $ANOM_THEME anomalies.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_3">
<text>Shit, I nearly stepped into a bunch of $ANOM_THEME anomalies going to $TO. Do not try to go there before the next emission at all costs.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_4">
<text>Looking for a guide to take me to $TO. Walking the known path would be suicidal with all those $ANOM_THEME anomalies, ever since the last emission happened.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_5">
<text>Hey, anyone know if the way to $TO is clear? Heard there's a ton of $ANOM_THEME anomalies there.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_6">
<text>So much for heading to $TO. The Zone's tossed $ANOM_THEME anomalies all over the place.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_7">
<text>Anyone else tried getting to $TO? Those damned $ANOM_THEME anomalies have made it impossible. Might be stuck here for a while.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_8">
<text>Looks like $TO is out of reach, comrades. The road is blocked by a bunch anomalies. We'll have to wait it out.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_9">
<text>$TO is off-limits for now, anomalies are everywhere. Stay put until it's safe.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_stalker_opened_1">
<text>Stalkers, the path between $FROM and $TO is clear again. I am just informing you guys.</text>
</string>
<string id="st_dynzone_news_stalker_opened_2">
<text>Good news, comrades! The path to $TO is open again. Anomalies are gone, time to move.</text>
</string>
<string id="st_dynzone_news_stalker_opened_3">
<text>Hey, $TO is safe to travel to now. The Zone's cleared out the anomalies.</text>
</string>
<string id="st_dynzone_news_stalker_opened_4">
<text>The road to $TO is open. Anomalies have cleared, so pack up and get moving.</text>
</string>
<string id="st_dynzone_news_stalker_opened_5">
<text>Looks like we can finally head to $TO. The path is clear, but stay sharp.</text>
</string>
<string id="st_dynzone_news_stalker_opened_6">
<text>The route to $TO is back on the table, comrades. Anomalies are gone, safe travels.</text>
</string>
<!-- Sidorovich -->
<string id="st_dynzone_news_sidorovich_blocked_1">
<text>$SENDER_NAME here, watch your step coming from $FROM to $TO, got word it's clustered with $ANOM_THEME anomalies.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_2">
<text>$SENDER_NAME here, don't bother coming into $FROM from $TO, one of my courier's just got back saying it's covered in $ANOM_THEME anomalies.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_3">
<text>$SENDER_NAME here, word is that there are $ANOM_THEME anomalies covering the entry from $FROM to $TO, don't try to be tough, you won't make it.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_4">
<text>$SENDER_NAME here, looks like a bunch of rookies heading to $TO, didn't make it back. Better be careful.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_5">
<text>Stalkers, be cautious going to $TO. One of my couriers had to turn back with reports of $ANOM_THEME anomalies preventing passage.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_6">
<text>This is $SENDER_NAME, I caught word of one of Wolf's associates being stuck in $TO, apparently can't make it back to the $FROM because of the intense anomalous activity. Watch yourselves.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_7">
<text>This is $SENDER_NAME, we managed to intercept a radio frequency used by the military, there are talks of $ANOM_THEME anomalies between $FROM and $TO.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_8">
<text>$SENDER_NAME speaking, the path to $TO is overrun with $ANOM_THEME anomalies. I wouldn't recommend going that way.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_9">
<text>Can anyone confirm that there are $ANOM_THEME anomalies on the way to $TO? Some rookies rumoured about it.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_10">
<text>Looks like the route to $TO is a deathtrap now, it's filled with $ANOM_THEME anomalies. Stay put until it's clear.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_11">
<text>$TO is no longer safe, anomalies are everywhere. Better hunker down for now.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_12">
<text>The path to $TO is blocked again. Damn Zone and its anomalies, always stirring things up.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_sidorovich_opened_1">
<text>Attention to all newbies. The anomalies on the road between $FROM and $TO have disappeared during the last emission. You can use your usual routes.</text>
</string>
<string id="st_dynzone_news_sidorovich_opened_2">
<text>Good news, stalkers. The way to $TO is clear again. No more anomalies, you're free to move.</text>
</string>
<string id="st_dynzone_news_sidorovich_opened_3">
<text>This is $SENDER_NAME, letting you know the road to $TO is open. Last emission cleared the anomalies.</text>
</string>
<string id="st_dynzone_news_sidorovich_opened_4">
<text>Looks like the path to $TO is safe again. Those anomalies have cleared out, move carefully.</text>
</string>
<string id="st_dynzone_news_sidorovich_opened_5">
<text>The route to $TO is open once more. No more anomalies in sight, safe travels.</text>
</string>
<string id="st_dynzone_news_sidorovich_opened_6">
<text>$SENDER_NAME here, confirming the way to $TO is clear. The Zone's finally given us a break.</text>
</string>
<!-- Bandits -->
<string id="st_dynzone_news_bandit_blocked_1">
<text>Yo guys, listen. We cannot go from $FROM to $TO, there's a lot of $ANOM_THEME bullshit preventing us from going there.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_2">
<text>Hey, watch your step guys! The Zone has scattered $ANOM_THEME anomalies all over the entry to $TO from $FROM!</text>
</string>
<string id="st_dynzone_news_bandit_blocked_3">
<text>Ha! We just watched a loner walk into one of those $ANOM_THEME anomalies going into $TO from $FROM!</text>
</string>
<string id="st_dynzone_news_bandit_blocked_4">
<text>Anyone placing bets on how many Stalkers walk into those $ANOM_THEME anomalies on the path from $FROM to $TO?</text>
</string>
<string id="st_dynzone_news_bandit_blocked_5">
<text>Hey guys, a bunch of our boys just walked into $ANOM_THEME anomalies covering the exit of $FROM to $TO, I think I'll wait till the next emission to see if they had anything of use.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_6">
<text>Hey, you! Any of you seen the mess on the way to $TO? $ANOM_THEME anomalies everywhere, like the Zone wants us dead.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_7">
<text>What the hell's going on? The road to $TO is a minefield of $ANOM_THEME anomalies. Ain't safe, not one bit.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_8">
<text>To $TO? Hah, good luck with that. These $ANOM_THEME anomalies just popped up like mushrooms after the rain.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_9">
<text>Anyone still alive out there? The path to $TO is swarming with anomalies. Don't get fried, boys.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_10">
<text>So who pissed off the Zone this time? The way to $TO is filled with anomalies again.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_bandit_opened_1">
<text>Heya, guys. Listen up, stalkers can travel from $FROM to $TO again, it's time to rob'em, guys.</text>
</string>
<string id="st_dynzone_news_bandit_opened_2">
<text>Yo, boys! The path to $TO is open again. Time to get moving and see what's left for us.</text>
</string>
<string id="st_dynzone_news_bandit_opened_3">
<text>Looks like the anomalies cleared out. The way to $TO is open, get a move on.</text>
</string>
<string id="st_dynzone_news_bandit_opened_4">
<text>Hey, good news! $TO is back on the map. Anomalies are gone, so what're you waiting for?</text>
</string>
<string id="st_dynzone_news_bandit_opened_5">
<text>Finally, the path to $TO is clear. No more frying yourself on anomalies. Let's get going.</text>
</string>
<string id="st_dynzone_news_bandit_opened_6">
<text>Who's up for a trip to $TO? The way is clear, no more $ANOM_THEME anomalies to worry about.</text>
</string>
<!-- Sultan (Bandits) -->
<string id="st_dynzone_news_sultan_blocked_1">
<text>Sultan here, listen up. The Zone has flooded the path to $TO with $ANOM_THEME anomalies. Keep away unless you fancy getting fried.</text>
</string>
<string id="st_dynzone_news_sultan_blocked_2">
<text>Hey boys, $FROM to $TO is now off-limits. Anomalies everywhere. Let the fools clear it out for us.</text>
</string>
<string id="st_dynzone_news_sultan_blocked_3">
<text>Sultan speaking. $TO is a no-go, filled with $ANOM_THEME anomalies. Let's wait it out.</text>
</string>
<string id="st_dynzone_news_sultan_blocked_4">
<text>Listen up, bandits. $ANOM_THEME anomalies blocking our way to $TO. Stay put for now.</text>
</string>
<string id="st_dynzone_news_sultan_blocked_5">
<text>Sultan here. $TO is a death trap right now. Anomalies all over. Hold your positions.</text>
</string>
<string id="st_dynzone_news_sultan_blocked_6">
<text>Forget $TO for now, boys. These $ANOM_THEME anomalies are too risky. We'll wait for it to clear.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_sultan_opened_1">
<text>Good news from Sultan. The way to $TO is clear. Let's get moving before someone else does.</text>
</string>
<string id="st_dynzone_news_sultan_opened_2">
<text>Listen up, the anomalies are gone. $TO is open for business. Get a move on.</text>
</string>
<string id="st_dynzone_news_sultan_opened_3">
<text>Sultan here. The Zone's let up. Path to $TO is safe. Time to cash in, boys.</text>
</string>
<string id="st_dynzone_news_sultan_opened_4">
<text>Hey, $TO is back in play. No more $ANOM_THEME anomalies blocking our way. Let's make some money.</text>
</string>
<string id="st_dynzone_news_sultan_opened_5">
<text>Sultan speaking. The road to $TO is clear. Move fast, before the Zone changes its mind.</text>
</string>
<string id="st_dynzone_news_sultan_opened_6">
<text>Alright, boys. The path to $TO is safe now. Anomalies are gone. Let's get going.</text>
</string>
<!-- Duty -->
<string id="st_dynzone_news_dolg_blocked_1">
<text>Informing all squads of anomalous activity on route between $FROM and $TO. Going this way will be impossible for now. There are a bunch of $ANOM_THEME anomalies.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_2">
<text>$SENDER_NAME here, we were chasing some mutants out from $FROM towards $TO when one of the guys stepped into an $ANOM_THEME anomaly, seems the path is filled with them, don't fancy risking my neck going through and you shouldn't either.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_3">
<text>Hey, watch your step going back to $TO from $FROM it's covered in a lot of anomalies!</text>
</string>
<string id="st_dynzone_news_dolg_blocked_4">
<text>$SENDER_NAME here, don't try going through $FROM to $TO, just watched a bloodsucker kill itself by a $ANOM_THEME anomaly.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_5">
<text>Watch out around the path leading to $TO from $FROM. There are a lot of $ANOM_THEME anomalies.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_6">
<text>Colonel Petrenko ordered me to inform everyone that the path between $FROM and $TO does not provide safe passage due to $ANOM_THEME anomalies. Stand by until the next emission.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_7">
<text>All units, the Zone's locked down a route to $TO with $ANOM_THEME anomalies. Proceed with caution or not at all.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_8">
<text>$SENDER_NAME here. Is anyone getting through to $TO? The $ANOM_THEME anomalies are making it impossible.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_9">
<text>Confirming the path to $TO is now too hard to traverse due to $ANOM_THEME anomalies. No one's getting through until it clears.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_10">
<text>The Zone's playing games again; $TO is off-limits due to heavy anomalous activity. Hold your ground until further notice.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_11">
<text>$SENDER_NAME to all squads, the way to $TO is choked with anomalies. Stay put until we have a clear route.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_dolg_opened_1">
<text>Informing all squads of fading anomalous activity on the route between $FROM and $TO. We can move to this region again.</text>
</string>
<string id="st_dynzone_news_dolg_opened_2">
<text>All squads, the path to $TO is open again. Anomalous activity has cleared, proceed with caution.</text>
</string>
<string id="st_dynzone_news_dolg_opened_3">
<text>$SENDER_NAME here. The Zone has reopened the route to $TO. All units, advance with care.</text>
</string>
<string id="st_dynzone_news_dolg_opened_4">
<text>Good news, the way to $TO is clear. Anomalies have dissipated, move forward.</text>
</string>
<string id="st_dynzone_news_dolg_opened_5">
<text>Attention, the path to $TO is safe once more. The Zone's cleared the anomalies.</text>
</string>
<string id="st_dynzone_news_dolg_opened_6">
<text>The road to $TO is open again. Anomalies are gone, but stay alert for anything else.</text>
</string>
<!-- Petrenko (Duty) -->
<string id="st_dynzone_news_petrenko_blocked_1">
<text>This is Petrenko. All Duty squads, avoid the path between $FROM and $TO. These $ANOM_THEME anomalies are making it impassable.</text>
</string>
<string id="st_dynzone_news_petrenko_blocked_2">
<text>Petrenko here. We've confirmed a high density of $ANOM_THEME anomalies between $FROM and $TO. Hold your position until further notice.</text>
</string>
<string id="st_dynzone_news_petrenko_blocked_3">
<text>Attention Duty members, the Zone has blocked the route from $FROM to $TO with $ANOM_THEME anomalies. Advise staying clear.</text>
</string>
<string id="st_dynzone_news_petrenko_blocked_4">
<text>Colonel Petrenko reporting. Anomalous activity detected en route to $TO. All patrols, reroute immediately.</text>
</string>
<string id="st_dynzone_news_petrenko_blocked_5">
<text>Squads, be on alert. Some $ANOM_THEME anomalies are obstructing the path from $FROM to $TO. Proceed with caution.</text>
</string>
<string id="st_dynzone_news_petrenko_blocked_6">
<text>Duty command here. The road from $FROM to $TO is compromised. High $ANOM_THEME anomalous readings. Hold until safe.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_petrenko_opened_1">
<text>This is Petrenko. The path to $TO has cleared up. Anomalies have subsided. Move out cautiously.</text>
</string>
<string id="st_dynzone_news_petrenko_opened_2">
<text>Petrenko here. Confirming that the route from $FROM to $TO is now safe. All squads proceed.</text>
</string>
<string id="st_dynzone_news_petrenko_opened_3">
<text>Good news, Duty members. The Zone has reopened the way to $TO. Anomalies are gone.</text>
</string>
<string id="st_dynzone_news_petrenko_opened_4">
<text>Colonel Petrenko to all units: $TO is now accessible. The Zone's anomalies have cleared. Stay vigilant.</text>
</string>
<string id="st_dynzone_news_petrenko_opened_5">
<text>All squads, the route between $FROM and $TO is clear again. Resume your duties.</text>
</string>
<string id="st_dynzone_news_petrenko_opened_6">
<text>This is Duty command, informing you that $TO is now safe to traverse. Anomalous activity has ceased.</text>
</string>
<!-- Clear Sky -->
<string id="st_dynzone_news_csky_blocked_1">
<text>Don't try to get to $TO from $FROM, just watched some renegades get obliterated by a bunch of $ANOM_THEME anomalies wandering through there.</text>
</string>
<string id="st_dynzone_news_csky_blocked_2">
<text>Damn... hey someone tell the Ecologists that the exit to $TO from $FROM has been blocked off by those $ANOM_THEME anomalies.</text>
</string>
<string id="st_dynzone_news_csky_blocked_3">
<text>Whatever you do, don't try to use the path connecting $FROM to $TO, we just lost one of the new guys there.</text>
</string>
<string id="st_dynzone_news_csky_blocked_4">
<text>Kalancha just told me that according to his readings, the last emission must've blocked the path from here to $TO. Can anyone confirm this?</text>
</string>
<string id="st_dynzone_news_csky_blocked_5">
<text>Any word on the path to $TO? Last I heard, $ANOM_THEME anomalies were everywhere. Might be worth waiting it out.</text>
</string>
<string id="st_dynzone_news_csky_blocked_6">
<text>$TO is off the table for now. These ungodly $ANOM_THEME anomalies are all over the place. Let's hold until the Zone settles.</text>
</string>
<string id="st_dynzone_news_csky_blocked_7">
<text>Can't reach $TO right now, anomalies are blocking the way there. Stay safe, Clear Sky.</text>
</string>
<string id="st_dynzone_news_csky_blocked_8">
<text>Anyone tried getting to $TO? The route's a mess with $ANOM_THEME anomalies. Hold your position.</text>
</string>
<string id="st_dynzone_news_csky_blocked_9">
<text>$SENDER_NAME here, the road to $TO is a no-go. Too many anomalies. Keep your heads down and stay put.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_csky_opened_1">
<text>Informing all squads of an accessible path on the route between $FROM and $TO. The last emission cleared the anomalies there.</text>
</string>
<string id="st_dynzone_news_csky_opened_2">
<text>Clear Sky, the way to $TO is open. Anomalies have cleared, but stay cautious.</text>
</string>
<string id="st_dynzone_news_csky_opened_3">
<text>Just got word, the path to $TO is clear again. Last emission did us a favor.</text>
</string>
<string id="st_dynzone_news_csky_opened_4">
<text>$SENDER_NAME here. The route to $TO is open, anomalies have dissipated.</text>
</string>
<string id="st_dynzone_news_csky_opened_5">
<text>Anyone heading to $TO? The path is clear, no more anomalies in sight since the last emission came and went.</text>
</string>
<string id="st_dynzone_news_csky_opened_6">
<text>Looks like the Zone's let up. The way to $TO is safe now, move carefully.</text>
</string>
<!-- Ecologists -->
<string id="st_dynzone_news_ecolog_blocked_1">
<text>The research team found high $ANOM_THEME anomalous activity on the road between $FROM and $TO. We recommend choosing a safe detour route.</text>
</string>
<string id="st_dynzone_news_ecolog_blocked_2">
<text>Research teams, be advised. The path to $TO is obstructed by $ANOM_THEME anomalies. Proceed with caution.</text>
</string>
<string id="st_dynzone_news_ecolog_blocked_3">
<text>Has anyone confirmed the anomaly activity near $TO? We're getting reports of $ANOM_THEME anomalies making passage impossible.</text>
</string>
<string id="st_dynzone_news_ecolog_blocked_4">
<text>The Zone has created a barrier of anomalies near $TO. Avoid the area until it's clear.</text>
</string>
<string id="st_dynzone_news_ecolog_blocked_5">
<text>$TO is currently unreachable. Those $ANOM_THEME anomalies are preventing safe passage.</text>
</string>
<string id="st_dynzone_news_ecolog_blocked_6">
<text>Sakharov received intel from the USS patrols - the path from $FROM to $TO is full of $ANOM_THEME anomalies. Steer clear, we can't risk going there.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_ecolog_opened_1">
<text>The research team recorded a drop in anomalous activity on the road between $FROM and $TO. The route now allows safe passage again.</text>
</string>
<string id="st_dynzone_news_ecolog_opened_2">
<text>Research teams, the way to $TO is now clear. Anomalies have dissipated, safe to proceed.</text>
</string>
<string id="st_dynzone_news_ecolog_opened_3">
<text>Attention, the path to $TO is open again. The last emission cleared the anomalies.</text>
</string>
<string id="st_dynzone_news_ecolog_opened_4">
<text>$SENDER_NAME here, confirming the route to $TO is clear. Anomalous activity has ceased.</text>
</string>
<string id="st_dynzone_news_ecolog_opened_5">
<text>Looks like the Zone has let up. The way to $TO is safe now, no more anomalies.</text>
</string>
<string id="st_dynzone_news_ecolog_opened_6">
<text>The path to $TO is clear. Anomalies are gone, safe to resume research activities.</text>
</string>
<!-- Sakharov (Ecologists) -->
<string id="st_dynzone_news_sakharov_blocked_1">
<text>Professor Sakharov here. The route between $FROM and $TO is blocked by $ANOM_THEME anomalies. Avoid the area.</text>
</string>
<string id="st_dynzone_news_sakharov_blocked_2">
<text>This is Sakharov. We've detected significant $ANOM_THEME anomalies on the way to $TO. Proceed with caution.</text>
</string>
<string id="st_dynzone_news_sakharov_blocked_3">
<text>Ecologists, please be informed that the path from $FROM to $TO is dangerous due to $ANOM_THEME anomalies.</text>
</string>
<string id="st_dynzone_news_sakharov_blocked_4">
<text>Sakharov to all research teams: $TO is currently inaccessible due to $ANOM_THEME anomalous activity. Stay put.</text>
</string>
<string id="st_dynzone_news_sakharov_blocked_5">
<text>Attention, the Zone has blocked access from $FROM to $TO with $ANOM_THEME anomalies. Avoid traversal.</text>
</string>
<string id="st_dynzone_news_sakharov_blocked_6">
<text>Research teams, note that anomalies are preventing safe travel to $TO. Proceed with caution.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_sakharov_opened_1">
<text>This is Sakharov. The path from $FROM to $TO is now clear of anomalies. Safe to proceed.</text>
</string>
<string id="st_dynzone_news_sakharov_opened_2">
<text>Ecologists, good news. $TO is accessible again. Anomalous activity has decreased.</text>
</string>
<string id="st_dynzone_news_sakharov_opened_3">
<text>Professor Sakharov here, confirming the route to $TO is now safe. Anomalies have dissipated.</text>
</string>
<string id="st_dynzone_news_sakharov_opened_4">
<text>The Zone has cleared up. Passage to $TO is safe for all research teams.</text>
</string>
<string id="st_dynzone_news_sakharov_opened_5">
<text>Sakharov to all personnel: $TO is clear of anomalies. Resume standard operations.</text>
</string>
<string id="st_dynzone_news_sakharov_opened_6">
<text>Attention researchers, the route to $TO is open again. Safe travels.</text>
</string>
<!-- Mercenaries -->
<string id="st_dynzone_news_killer_blocked_1">
<text>Mercenaries, our squad member was injuried due to $ANOM_THEME anomalies we've encountered on the road between $FROM and $TO, be advised. </text>
</string>
<string id="st_dynzone_news_killer_blocked_2">
<text>HQ, we have a situation. The usual route between $FROM and $TO is inpassable due to a cluster of $ANOM_THEME anomalies, please advise.</text>
</string>
<string id="st_dynzone_news_killer_blocked_3">
<text>Well, this is interesting. There's now a patch of $ANOM_THEME anomalies between $FROM and $TO. Send a team to investigate.</text>
</string>
<string id="st_dynzone_news_killer_blocked_4">
<text>To all mercs, the route from $FROM leading to $TO is a dead end. $ANOM_THEME anomalies have made sure of that.</text>
</string>
<string id="st_dynzone_news_killer_blocked_5">
<text>Can't move to $TO, the Zone's cluttered it with anomalies again. Hold position.</text>
</string>
<string id="st_dynzone_news_killer_blocked_6">
<text>What's the status on the way to $TO? $ANOM_THEME anomalies are all over the place.</text>
</string>
<string id="st_dynzone_news_killer_blocked_7">
<text>The Zone's locked down a part of $TO with anomalies. Gotta find another route.</text>
</string>
<string id="st_dynzone_news_killer_blocked_8">
<text>$SENDER_NAME here, the path to $TO is inpassable. There are too many anomalies to navigate safely.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_killer_opened_1">
<text>Mercenaries, our scout has discovered that the road from $FROM to $TO is clear.</text>
</string>
<string id="st_dynzone_news_killer_opened_2">
<text>To all mercs, the path to $TO is clear. Anomalies have dissipated, proceed with the mission.</text>
</string>
<string id="st_dynzone_news_killer_opened_3">
<text>$SENDER_NAME here. The road to $TO is open, anomalies are no longer a threat</text>
</string>
<string id="st_dynzone_news_killer_opened_4">
<text>Attention, the route to $TO is clear. Move out, the Zone's given us a window.</text>
</string>
<string id="st_dynzone_news_killer_opened_5">
<text>Good news, mercs. The way to $TO is open. No more anomalies preventing safe passage.</text>
</string>
<string id="st_dynzone_news_killer_opened_6">
<text>The path to $TO is clear. Anomalies have cleared, so get moving.</text>
</string>
<!-- Dushman (Mercenaries) -->
<string id="st_dynzone_news_dushman_blocked_1">
<text>This is Dushman. Mercenaries, be advised: the route from $FROM to $TO is swarming with $ANOM_THEME anomalies. Hold your positions.</text>
</string>
<string id="st_dynzone_news_dushman_blocked_2">
<text>To all squads, Dushman here. The Zone's acting up. Those $ANOM_THEME anomalies block the way to $TO. Avoid the area until further notice.</text>
</string>
<string id="st_dynzone_news_dushman_blocked_3">
<text>Heads up, mercs. Our scouts report heavy $ANOM_THEME anomalies between $FROM and $TO. We can't afford any losses. Stay put.</text>
</string>
<string id="st_dynzone_news_dushman_blocked_4">
<text>Dushman speaking. Avoid $TO. It's crawling with $ANOM_THEME anomalies. Let's not lose any more men.</text>
</string>
<string id="st_dynzone_news_dushman_blocked_5">
<text>Attention, mercenaries. The path from $FROM to $TO is too hazardous due to $ANOM_THEME anomalies. Find an alternate route.</text>
</string>
<string id="st_dynzone_news_dushman_blocked_6">
<text>This is Dushman. Confirming high anomalous activity near $TO. Do not proceed until further updates.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_dushman_opened_1">
<text>Dushman here. The anomalies blocking $TO have cleared up. Mercenaries, you're clear to move out.</text>
</string>
<string id="st_dynzone_news_dushman_opened_2">
<text>Good news, mercs. The path from $FROM to $TO is open. Anomalies are no longer a threat. Proceed with caution.</text>
</string>
<string id="st_dynzone_news_dushman_opened_3">
<text>This is Dushman. Confirming safe passage to $TO. All squads, you're free to advance.</text>
</string>
<string id="st_dynzone_news_dushman_opened_4">
<text>Attention, the route to $TO is clear again. Anomalies have subsided. Let's get moving, mercenaries.</text>
</string>
<string id="st_dynzone_news_dushman_opened_5">
<text>Dushman here. We've got the green light to $TO. No more anomalies. Safe travels.</text>
</string>
<string id="st_dynzone_news_dushman_opened_6">
<text>All units, this is Dushman. The Zone has cleared the way to $TO. Proceed with your operations.</text>
</string>
<!-- Freedom -->
<string id="st_dynzone_news_freedom_blocked_1">
<text>Uhm, guys? Looks like our road from $FROM to $TO was cut off during the last emission. Pals are taking too long for the raid...</text>
</string>
<string id="st_dynzone_news_freedom_blocked_2">
<text>Boys, we got issues. Our route to $TO from $FROM has a bunch of goddamn $ANOM_THEME anomalies. What the hell?</text>
</string>
<string id="st_dynzone_news_freedom_blocked_3">
<text>Hey, Freedom! Anyone else noticed the Zone's blocked the road to $TO with anomalies? Guess we're stuck.</text>
</string>
<string id="st_dynzone_news_freedom_blocked_4">
<text>So, who's tried getting to $TO recently? Anomalies are all over the place. Might have to wait it out.</text>
</string>
<string id="st_dynzone_news_freedom_blocked_5">
<text>The Zone's acting up again. Can't get to $TO because of all the god damned $ANOM_THEME anomalies.</text>
</string>
<string id="st_dynzone_news_freedom_blocked_6">
<text>Looks like $TO is off-limits for now. Anomalies are everywhere, damn Zone won't let us through.</text>
</string>
<string id="st_dynzone_news_freedom_blocked_7">
<text>The path to $TO is blocked by $ANOM_THEME anomalies. Let's hold position until the Zone clears up.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_freedom_opened_1">
<text>Uhm, people? It looks like the road between $FROM to $TO was opened during the recent emission. They have brought drug supplies faster than usual...</text>
</string>
<string id="st_dynzone_news_freedom_opened_2">
<text>Freedom fighters, the Zone's given us a break. The way to $TO is clear, no more anomalies.</text>
</string>
<string id="st_dynzone_news_freedom_opened_3">
<text>Hey, $TO is back on the map. The anomalies cleared out, so let's move.</text>
</string>
<string id="st_dynzone_news_freedom_opened_4">
<text>$SENDER_NAME here, the path to $TO is open. Anomalies are gone, so let's get going.</text>
</string>
<string id="st_dynzone_news_freedom_opened_5">
<text>Good news, comrades. The road to $TO is safe again, no more anomalies in sight.</text>
</string>
<string id="st_dynzone_news_freedom_opened_6">
<text>The Zone's cleared up. The way to $TO is open, so time to make some moves.</text>
</string>
<!-- Lukash (Freedom) -->
<string id="st_dynzone_news_lukash_blocked_1">
<text>Lukash here. Freedom fighters, avoid the path from $FROM to $TO, it's filled with $ANOM_THEME anomalies.</text>
</string>
<string id="st_dynzone_news_lukash_blocked_2">
<text>Hey Freedom, it's Lukash. The Zone's thrown $ANOM_THEME anomalies all over the route to $TO. Stay put for now.</text>
</string>
<string id="st_dynzone_news_lukash_blocked_3">
<text>Listen up, Freedom. Reports confirm that $FROM to $TO is blocked by $ANOM_THEME anomalies. Don't take any risks.</text>
</string>
<string id="st_dynzone_news_lukash_blocked_4">
<text>Lukash here, comrades. The road to $TO is a deathtrap with $ANOM_THEME anomalies. Hold back.</text>
</string>
<string id="st_dynzone_news_lukash_blocked_5">
<text>Freedom fighters, steer clear of $TO. Anomalous activity detected. Stay safe out there.</text>
</string>
<string id="st_dynzone_news_lukash_blocked_6">
<text>Heads up, it's Lukash. $TO is crawling with $ANOM_THEME anomalies. Let's wait this one out.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_lukash_opened_1">
<text>Good news from Lukash. The path to $TO is clear. No more anomalies to worry about, comrades.</text>
</string>
<string id="st_dynzone_news_lukash_opened_2">
<text>Hey Freedom, the Zone's let up. The way to $TO is open again. Move out when ready.</text>
</string>
<string id="st_dynzone_news_lukash_opened_3">
<text>Lukash here, the route from $FROM to $TO is clear. Let's make the most of it before the Zone changes its mind.</text>
</string>
<string id="st_dynzone_news_lukash_opened_4">
<text>Freedom fighters, $TO is back on the map. Anomalies are gone, time to move!</text>
</string>
<string id="st_dynzone_news_lukash_opened_5">
<text>Comrades, $TO is safe again. The Zone has cleared the way. Stay sharp.</text>
</string>
<string id="st_dynzone_news_lukash_opened_6">
<text>Path to $TO is open, this is Lukash. Anomalies are no longer a threat. Stay safe.</text>
</string>
<!-- Monolith -->
<string id="st_dynzone_news_monolith_blocked_1">
<text>Brothers! The Great Monolith decided to prevent unbelievers from walking the route from $FROM to $TO with $ANOM_THEME anomalies. Let's use different ways around as well.</text>
</string>
<string id="st_dynzone_news_monolith_blocked_2">
<text>Brothers, has the Monolith commanded the path to $TO to be blessed with anomalies? The faithful must seek another way.</text>
</string>
<string id="st_dynzone_news_monolith_blocked_3">
<text>To all who hear, the Monolith has willed the path to $TO be sealed with anomalies. We shall wait for a sign.</text>
</string>
<string id="st_dynzone_news_monolith_blocked_4">
<text>The way to $TO was blessed by the great Monolith. Only the chosen ones may pass when the time is right.</text>
</string>
<string id="st_dynzone_news_monolith_blocked_5">
<text>Our path to $TO is obstructed by the Monolith's will, manifested as anomalies. Stand firm until further guidance.</text>
</string>
<string id="st_dynzone_news_monolith_blocked_6">
<text>Brothers, the Monolith has sanctified the way to $TO with anomalies. We shall hold our ground and await further signs.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_monolith_opened_1">
<text>Brothers! The Great Monolith has heard our pleadings and opened the sacred road between $FROM and $TO again.</text>
</string>
<string id="st_dynzone_news_monolith_opened_2">
<text>Brothers, the Monolith has cleared the way to $TO. The anomalies are gone, and our path is revealed.</text>
</string>
<string id="st_dynzone_news_monolith_opened_3">
<text>The way to $TO is open, blessed by the Monolith's will. No more anomalies to hinder us.</text>
</string>
<string id="st_dynzone_news_monolith_opened_4">
<text>Rejoice, for the Monolith has removed the anomalies from the path to $TO. Proceed with faith.</text>
</string>
<string id="st_dynzone_news_monolith_opened_5">
<text>The Monolith has cleared the path to $TO. No more anomalies stand in our way.</text>
</string>
<string id="st_dynzone_news_monolith_opened_6">
<text>Brothers, the way to $TO is now clear. The Monolith has guided us through the anomalies.</text>
</string>
<!-- Krolik (Monolith) -->
<string id="st_dynzone_news_krolik_blocked_1">
<text>Brothers, this is Krolik. The sacred path from $FROM to $TO is blocked by $ANOM_THEME anomalies, ordained by the Monolith.</text>
</string>
<string id="st_dynzone_news_krolik_blocked_2">
<text>Krolik speaking. The Monolith has blessed the route to $TO with $ANOM_THEME anomalies. Only the faithful shall pass.</text>
</string>
<string id="st_dynzone_news_krolik_blocked_3">
<text>Brothers, heed my words. $TO is now sealed by the Monolith's will. $ANOM_THEME anomalies guard the way.</text>
</string>
<string id="st_dynzone_news_krolik_blocked_4">
<text>The Monolith has spoken. The path to $TO is sanctified with anomalies. Wait for further signs.</text>
</string>
<string id="st_dynzone_news_krolik_blocked_5">
<text>This is Krolik. The way to $TO is blocked by the Monolith's gift of $ANOM_THEME anomalies. Remain patient.</text>
</string>
<string id="st_dynzone_news_krolik_blocked_6">
<text>Brothers, $TO is off-limits. Anomalies, guided by the Monolith, obstruct the way.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_krolik_opened_1">
<text>Krolik here. The Monolith has cleared the path to $TO. Proceed with faith, brothers.</text>
</string>
<string id="st_dynzone_news_krolik_opened_2">
<text>The Monolith blesses us. The route to $TO is open again. Anomalies are gone.</text>
</string>
<string id="st_dynzone_news_krolik_opened_3">
<text>Brothers, rejoice! The Monolith has removed the anomalies from $TO. Safe passage is granted.</text>
</string>
<string id="st_dynzone_news_krolik_opened_4">
<text>Krolik speaking. The way to $TO is now clear. The Monolith guides us forward.</text>
</string>
<string id="st_dynzone_news_krolik_opened_5">
<text>The Monolith has opened the path to $TO. Anomalies have dissipated. Move forward.</text>
</string>
<string id="st_dynzone_news_krolik_opened_6">
<text>Our path to $TO is clear, brothers. The Monolith has shown us the way.</text>
</string>
<!-- Military -->
<string id="st_dynzone_news_army_blocked_1">
<text>Attention to all patrol groups. High $ANOM_THEME anomalous activity on route from $FROM to $TO has been detected, the path is likely inpassable for now.</text>
</string>
<string id="st_dynzone_news_army_blocked_2">
<text>Units in sector C-17 be advised of $ANOM_THEME anomalies preventing travel between $FROM and $TO.</text>
</string>
<string id="st_dynzone_news_army_blocked_3">
<text>To all squads in the vicinity. Be advised that we just lost a unit between $FROM and $TO.</text>
</string>
<string id="st_dynzone_news_army_blocked_4">
<text>Operations taking units from $FROM to $TO have been temporarily suspended due to high anomalous activity.</text>
</string>
<string id="st_dynzone_news_army_blocked_5">
<text>All units, the path to $TO is too dangerouse for passage due to $ANOM_THEME anomalies. Do not attempt passage. I repeat: Do not attempt passage.</text>
</string>
<string id="st_dynzone_news_army_blocked_6">
<text>Anyone got a read on the way to $TO? It's blocked by anomalies. Hold your positions.</text>
</string>
<string id="st_dynzone_news_army_blocked_7">
<text>Command to all squads, $TO is unreachable. Anomalies have sealed the path.</text>
</string>
<string id="st_dynzone_news_army_blocked_8">
<text>Attention, the route to $TO is too hazardous to traverse. The Zone's thrown up a wall of anomalies.</text>
</string>
<string id="st_dynzone_news_army_blocked_9">
<text>Is anyone else seeing this? The path to $TO is a no-go. Anomalies everywhere. Hold position.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_army_opened_1">
<text>Attention to all patrol groups, anomalous activity on route from $FROM to $TO has decreased, the route is passable again.</text>
</string>
<string id="st_dynzone_news_army_opened_2">
<text>All units, the path to $TO is clear. Anomalies have been cleared, proceed with the mission.</text>
</string>
<string id="st_dynzone_news_army_opened_3">
<text>$SENDER_NAME to all squads, the route to $TO is open again. Anomalies are no longer a threat.</text>
</string>
<string id="st_dynzone_news_army_opened_4">
<text>Good news, the road to $TO is clear. The Zone's given us a break, so move out.</text>
</string>
<string id="st_dynzone_news_army_opened_5">
<text>The path to $TO is open again. Anomalies have cleared, safe to proceed.</text>
</string>
<string id="st_dynzone_news_army_opened_6">
<text>Attention, all units. The way to $TO is clear. Anomalous activity has ceased, proceed with caution.</text>
</string>
<!-- Kovalski (Military) -->
<string id="st_dynzone_news_kovalski_blocked_1">
<text>Colonel Kovalski here. All units, be aware: the path from $FROM to $TO is blocked by $ANOM_THEME anomalies. Do not proceed.</text>
</string>
<string id="st_dynzone_news_kovalski_blocked_2">
<text>This is Kovalski. High anomaly presence detected between $FROM and $TO. Maintain your current positions until further instructions.</text>
</string>
<string id="st_dynzone_news_kovalski_blocked_3">
<text>Attention all units, the route to $TO is compromised due to $ANOM_THEME anomalies. Hold back until it's clear.</text>
</string>
<string id="st_dynzone_news_kovalski_blocked_4">
<text>Colonel Kovalski reporting: $ANOM_THEME anomalies are making the path from $FROM to $TO impassable. Stay alert and wait for updates.</text>
</string>
<string id="st_dynzone_news_kovalski_blocked_5">
<text>Military personnel, avoid the route to $TO. Anomalous activity detected. Stand by for further orders.</text>
</string>
<string id="st_dynzone_news_kovalski_blocked_6">
<text>Kovalski here, confirming hazardous conditions on the way to $TO. All units, remain in safe zones.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_kovalski_opened_1">
<text>Colonel Kovalski to all units. The road from $FROM to $TO is clear again. Anomalies have dissipated. Proceed with caution.</text>
</string>
<string id="st_dynzone_news_kovalski_opened_2">
<text>Kovalski here. Good news: the route to $TO is safe. Anomalous activity has ceased.</text>
</string>
<string id="st_dynzone_news_kovalski_opened_3">
<text>Attention all units. The Zone has cleared up around $TO. Safe passage confirmed.</text>
</string>
<string id="st_dynzone_news_kovalski_opened_4">
<text>This is Kovalski. The anomalies blocking $TO have vanished. Resume your missions.</text>
</string>
<string id="st_dynzone_news_kovalski_opened_5">
<text>Colonel Kovalski here. $TO is open. No more anomalies detected. Proceed with operations.</text>
</string>
<string id="st_dynzone_news_kovalski_opened_6">
<text>Military command to all squads: The route to $TO is clear. Move out.</text>
</string>
</string_table>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="windows-1251"?>
<string_table>
<string id="st_dynzone_hint_blocked">
<text>опасно</text>
</string>
<string id="st_dynzone_mapspot_label">
<text>Разведан</text>
</string>
<string id="st_dynzone_discovery_message">
<text>Этот путь может быть слишком опасным.. Похоже придётся найти обходной путь.</text>
</string>
</string_table>
@@ -0,0 +1,198 @@
<?xml version="1.0" encoding="windows-1251"?>
<string_table>
<!-- Mod Name -->
<string id="ui_mcm_dynamic_zone">
<text>Dynamic Zone</text>
</string>
<!-- Categories -->
<string id="ui_mcm_dynamic_zone_general">
<text>Îñíîâíûå</text>
</string>
<string id="ui_mcm_dynamic_zone_news">
<text>Íîâîñòè</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery">
<text>Ðàçâåäêà</text>
</string>
<string id="ui_mcm_dynamic_zone_debug">
<text>Îòëàäêà</text>
</string>
<!-- General -->
<string id="ui_mcm_dynamic_zone_main_title">
<text>Dynamic Zone : Îñíîâíûå íàñòðîéêè</text>
</string>
<string id="ui_mcm_dynamic_zone_general_chance_path_closed">
<text>Øàíñ íåïðîõîäèìîñòè ìàðøðóòà</text>
</string>
<string id="ui_mcm_dynamic_zone_general_chance_path_closed_desc">
<text>Øàíñ ìàðøðóòà ñòàòü íåïðîõîäèìûì ïðè èçìåíåíèè Çîíû</text>
</string>
<string id="ui_mcm_dynamic_zone_general_chance_dz_trigger">
<text>Øàíñ èçìåíåíèÿ Çîíû</text>
</string>
<string id="ui_mcm_dynamic_zone_general_chance_dz_trigger_desc">
<text>Øàíñ òîãî, ÷òî Çîíà íåìíîãî èçìåíèòñÿ ïîñëå âûáðîñà.</text>
</string>
<string id="ui_mcm_dynamic_zone_general_hardmode">
<text>Âêëþ÷èòü ñëîæíûé ðåæèì</text>
</string>
<string id="ui_mcm_dynamic_zone_general_hardmode_desc">
<text>Åñëè âêëþ÷åíî, ëîêàöèÿ ìîæåò áûòü ïîëíîñòüþ îòðåçàíà àíîìàëèÿìè îò äðóãèõ.</text>
</string>
<string id="ui_mcm_dynamic_zone_general_minimum_map_connections">
<text>Ìèíèìàëüíîå Êîëè÷åñòâî Ìàðøðóòîâ</text>
</string>
<string id="ui_mcm_dynamic_zone_general_minimum_map_connections_desc">
<text>Ñêîëüêî ìàðøðóòîâ äîëæíû îñòàâàòüñÿ ïðîõîäèìûìè íà êàæäîì óðîâíå (Íå ðàáîòàåò ïðè âêëþ÷¸ííîì ñëîæíîì ðåæèìå).</text>
</string>
<string id="ui_mcm_dynamic_zone_general_trigger_on_newgame">
<text>Èçìåíåíèå Çîíû íà Íîâîé Èãðå</text>
</string>
<string id="ui_mcm_dynamic_zone_general_trigger_on_newgame_desc">
<text>Îïöèÿ ñäåëàåò íåêîòîðûå ìàðøðóòû íåïðîõîäèìûìè óæå â íà÷àëå èãðû.</text>
</string>
<string id="ui_mcm_dynamic_zone_general_newgame_grace_period">
<text>Âðåìÿ íåèçìåííîñòè çîíû ïðè Íîâîé Èãðå (÷àñ)</text>
</string>
<string id="ui_mcm_dynamic_zone_general_newgame_grace_period_desc">
<text>Ïðè Íîâîé Èãðå, Çîíà íå áóäåò èçìåíÿòüñÿ âûáðàííîå êîëè÷åñòâî èãðîâûõ ÷àñîâ. Íå ðàáîòàåò ñ "Èçìåíåíèå Çîíû íà Íîâîé Èãðå"</text>
</string>
<string id="ui_mcm_dynamic_zone_general_emission_trigger">
<text>Ñòàäèÿ Âûáðîñà</text>
</string>
<string id="ui_mcm_dynamic_zone_general_emission_trigger_desc">
<text>Ñòàäèÿ âûáðîñà, íà êîòîðîé ìåíÿåòñÿ Çîíà</text>
</string>
<string id="ui_mcm_lst_dynamic_zone_emission_trigger_impact">
<text>Óäàð</text>
</string>
<string id="ui_mcm_lst_dynamic_zone_emission_trigger_1stwave">
<text>Ïåðâàÿ Âîëíà</text>
</string>
<string id="ui_mcm_lst_dynamic_zone_emission_trigger_2ndwave">
<text>Âòîðàÿ Âîëíà</text>
</string>
<string id="ui_mcm_lst_dynamic_zone_emission_trigger_rumble">
<text>Çåìëåòðÿñåíèå</text>
</string>
<!-- News -->
<string id="ui_mcm_dynamic_zone_news_title">
<text>Dynamic Zone : Íîâîñòè</text>
</string>
<string id="ui_mcm_dynamic_zone_news_desc">
<text>Ìåæäó âûáðîñàìè, ñòàëêåðû áóäóò äåëèòüñÿ ñâîèìè íàõîäêàìè â ñåòè ÊÏÊ î òîì, êàêèå ìàðøðóòû áûëè ïåðåêðûòû èëè âíîâü áûëè îòêðûòû.\nÂû ìîæåòå èçìåíèòü çäåñü ïðîöåíò çàäåéñòâîâàííûõ äëÿ îòêðûòèÿ èíôîðìàöèè ìàðøðóòîâ.\n íåêîòîðûõ ñëó÷àÿõ è êîíêðåòíîì øàíñå, îñîáûé ïåðñîíàæ, âðîäå Ñèäîðîâè÷à, ìîæåò òàê æå ïðîêîììåíòèðîâàòü èçìåíåíèÿ â ìàðøðóòàõ.</text>
</string>
<string id="ui_mcm_dynamic_zone_news_percent_path_reveal_unblock">
<text>Øàíñ êîììåíòèðîâàíèÿ íåäàâíî îòêðûâøåãîñÿ ìàðøðóòà â íîâîñòÿõ</text>
</string>
<string id="ui_mcm_dynamic_zone_news_percent_path_reveal_unblock_desc">
<text>Ñêîëüêî ìàðøðóòîâ, êîòîðûå îòêðûëèñü ïîñëå âûáðîñà áóäóò îñâåùåíû â ñòàëêåðñêîé ñåòè.</text>
</string>
<string id="ui_mcm_dynamic_zone_news_percent_path_reveal_block">
<text>Øàíñ êîììåíòèðîâàíèÿ íåäàâíî ïåðåêðûòîãî ìàðøðóòà â íîâîñòÿõ</text>
</string>
<string id="ui_mcm_dynamic_zone_news_percent_path_reveal_block_desc">
<text>Ñêîëüêî ìàðøðóòîâ, êîòîðûå çàêðûëèñü ïîñëå âûáðîñà áóäóò îñâåùåíû â ñòàëêåðñêîé ñåòè.</text>
</string>
<string id="ui_mcm_dynamic_zone_news_chance_special_character">
<text>Øàíñ êîììåíòèðîâàíèÿ èçìåíåíèé îñîáûì ïåðñîíàæåì</text>
</string>
<string id="ui_mcm_dynamic_zone_news_chance_special_character_desc">
<text>Øàíñ, ñ êîòîðûì îñîáûé ïåðñîíàæ ïðîêîììåíòèðóåò èçìåíåíèÿ â Çîíå (íàïðèìåð, Ñèäîðîâè÷).</text>
</string>
<!-- Discovery -->
<string id="ui_mcm_dynamic_zone_discovery_title">
<text>Dynamic Zone : Ðàçâåäêà</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_discovery_msg_showtime">
<text>Âðåìÿ ïîêàçà ñîîáùåíèÿ î ðàçâåäêå ìàðøðóòà</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_base_discovery_dist">
<text>(Óñòàðåëî) Ðàññòîÿíèå äëÿ ðàçâåäêè</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_dist">
<text>Ìèíèìàëüíîå ðàññòîÿíèå äëÿ ðàçâåäêè áèíîêëåì</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_dist_desc">
<text>Îáíîâëÿåò èíôîðìàöèþ î ñòàòóñå ìàðøðóòà, íà êîòîðûé èãðîê ñìîòðèò ÷åðåç áèíîêëü, åñëè òîò áëèæå ÷åì ýòî çíà÷åíèå.</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_mapspot_labels_enabled">
<text>Ïîäïèñûâàòü íåäàâíî ðàçâåäàííûå ïåðåõîäû íà êàðòå</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_mapspot_labels_enabled_desc">
<text>Ïåðåõîäû, èíôîðìàöèÿ î êîòîðûõ áûëà íåäàâíî ïîëó÷åíà, ïîäïèñûâàþòñÿ ñîîòâåòñòâåííî. Ýòè ïîäïèñè óäàëÿþòñÿ ïîñëå êàæäîãî âûáðîñà. Èãðîêàì, êîòîðûå õîòÿò ñëåäèòü çà èçìåíåíèÿìè ñàìîñòîÿòåëüíî, ëó÷øå îòêëþ÷èòü ýòó ôóíêöèþ.</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_holdtime">
<text>Âðåìÿ ðàçâåäêè áèíîêëåì (ìèëëèñåêóíäû)</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_holdtime_desc">
<text>Âðåìÿ ðàçâåäêè áèíîêëåì äîñòóïíîãî ìàðøðóòà, ÷òîáû îáíîâèòü èíôîðìàöèþ î í¸ì.</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_hud_enabled">
<text>Âêëþ÷èòü îòîáðàæåíèå ìàðêåðîâ ïåðåõîäîâ ïðè èñïîëüçîâàíèè áèíîêëÿ</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_hud_enabled_desc">
<text>Îïöèÿ áóäåò ïîêàçûâàòü ìàðêåð â 3D ïðîñòðàíñòâå íàä äîñòóïíûìè äëÿ ðàçâåäêè ïåðåõîäàìè íà òåêóùåé ëîêàöèè.</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_hud_distance">
<text>Äèñòàíöèÿ äëÿ îòîáðàæåíèÿ ìàðêåðîâ</text>
</string>
<string id="ui_mcm_dynamic_zone_discovery_binoc_discovery_hud_distance_desc">
<text>Ïåðåõîäû äàëüøå ýòîãî çíà÷åíèÿ íå áóäóò ïîìå÷åíû íà ýêðàíå.</text>
</string>
<!-- Debugging -->
<string id="ui_mcm_dynamic_zone_debug_title">
<text>Dynamic Zone : Îòëàäêà</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_desc">
<text>Îïöèè ýòîé êàòåãîðèè ðàññ÷èòàíû òîëüêî íà îòëàäî÷íîå èñïîëüçîâàíèå.\nËîãè MCM çàïèñûâàþòñÿ â 'appdata\logs\mcm' è íà÷èíàþòñÿ ñ 'dynamic_zone_debug'\n×òîáû ýòî ðàáîòàëî, óòèëèòà êîíñîëè MCM äîëæíà áûòü âêëþ÷åíà à íàñòðîéêàõ ñàìîãî MCM.</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_emission_check_interval">
<text>Âðåìÿ ïðîâåðêè âûáðîñà (ìñ)</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_emission_check_interval_desc">
<text>Èíòåðâàë ìåæäó ïðîâåðêàìè ñòàäèé âûáðîñà. Ðàáîòàåò òîëüêî â òå÷åíèå âûáðîñà.</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_verbose">
<text>Âêëþ÷èòü îòëàäî÷íîå âåäåíèå êîíñîëè</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_verbose_desc">
<text>Èñïîëüçóåò êîíñîëü MCM. Èñïîëüçóåò îáû÷íóþ êîíñîëü ïðè îòñóòâñòâèè MCM.</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_validate_parameter_types">
<text>Ïðîâåðÿòü ïàðàìåòðû ôóíêöèé</text>
</string>
<string id="ui_mcm_dynamic_zone_debug_validate_parameter_types_desc">
<text>Îïöèÿ áóäåò ïðîâåðÿòü ïàðàìåòðû ôóíêöèé íà íóëåâûå çíà÷åíèÿ âî âñåõ ñêðèïòàõ ìîäèôèêàöèè.</text>
</string>
</string_table>
@@ -0,0 +1,801 @@
<?xml version="1.0" encoding="windows-1251"?>
<string_table>
<!--
All communities currently able to propagate route changes:
"stalker", "dolg", "freedom", "bandit", "army",
"ecolog", "killer", "monolith", "csky",
Variables, usable in these strings:
$SENDER_NAME
$ANOM_THEME
$FROM
$TO
-->
<!-- Fallback strings -->
<string id="st_dynzone_news_fallback_blocked">
<text>Ïîñòóïèëà èíôîðìàöèÿ î ìàðøðóòå ìåæäó $FROM è $TO. Ïî ïîñëåäíèì äàííûì, $ANOM_THEME àíîìàëèè ïðåãðàæäàþò ïóòü. Åñòü ñìûñë ïåðåæäàòü äàííîå ÿâëåíèå.</text>
</string>
<string id="st_dynzone_news_fallback_opened">
<text>Òîëüêî ÷òî óçíàë, äîðîãà èç $FROM â $TO ñíîâà îòêðûòà. Ïîñëåäíèé âûáðîñ ïðîø¸ë íå çðÿ.</text>
</string>
<!-- Anomaly themes -->
<string id="st_dynzone_thermal_theme">
<text>îãíåííûå</text>
</string>
<string id="st_dynzone_acidic_theme">
<text>êèñëîòíûå</text>
</string>
<string id="st_dynzone_electric_theme">
<text>ýëåêòðè÷åñêèå</text>
</string>
<string id="st_dynzone_gravitational_theme">
<text>ãðàâèòàöèîííûå</text>
</string>
<!-- Loners -->
<string id="st_dynzone_news_stalker_blocked_1">
<text>Ñòàëêåðû, íà ïóòè ìåæäó $FROM è $TO $ANOM_THEME àíîìàëèè. Ïðîñòî èíôîðìèðóþ.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_2">
<text>Ýé, ÷òî ñëó÷èëîñü ñ äîðîãîé ñ $FROM íà $TO? Âñ¸ áûëî íîðìàëüíî äî ïîñëåäíåãî âûáðîñà, íî òåïåðü èäòè ÷åðåç ýòè $ANOM_THEME àíîìàëèè - ïðàêòè÷åñêè ñàìîóáèéñòâî.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_3">
<text>Äåðüìî, ÿ ÷óòü íå íàïîðîëñÿ íà $ANOM_THEME àíîìàëèè íà ïóòè íà $TO. Ïîñòàðàéòåñü íå õîäèòü òóäà äî ñëåäóþùåãî âûáðîñà.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_4">
<text>Èùó ïðîâîäíèêà, êîòîðûé ñìîæåò îòâåñòè ìåíÿ â ìåñòî, èçâåñòíîå ïîä íàçâàíèåì $TO. Ïåðåäâèæåíèå ïî èçâåñòíîìó ìàðøðóòó ñëèøêîì îïàñíî: ñ ïîñëåäíåãî âûáðîñà íà ïóòè $ANOM_THEME àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_5">
<text>Çäàðîâà, êòî-íèáóäü çíàåò, ìîæíî ëè ñåé÷àñ ïðîéòè íà $TO? ß ñëûøàë, ÷òî òàì $ANOM_THEME àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_6">
<text>Äëÿ âñåõ íàïðàâëÿþùèõñÿ íà $TO. Çäåñü êòî-òî ðàñêèäàë $ANOM_THEME àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_7">
<text>Êòî-òî åù¸ ïûòàëñÿ ïîïàñòü íà $TO? $ANOM_THEME àíîìàëèè ñäåëàëè ýòî ïðàêòè÷åñêè íåâîçìîæíûì. Ïîõîäó ìû íàäîëãî çàñòðÿëè.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_8">
<text>Ïîõîæå, $TO ïîêà-÷òî íàì íå ñâåòèò, òîâàðèùè. Äîðîãà ïåðåêðûòà àíîìàëèÿìè. Ïðèä¸òñÿ íàì ïåðåæäàòü.</text>
</string>
<string id="st_dynzone_news_stalker_blocked_9">
<text>$TO âíå çîíû äîñòóïà, ïîâñþäó àíîìàëèè. Æä¸ì, ïîêà ýòî íå ñòàíåò áåçîïàñíî.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_stalker_opened_1">
<text>Ñòàëêåðû, ïóòü ñ $FROM íà $TO ñíîâà ÷èñò. Ïðîñòî èíôîðìèðóþ âàñ, ïàðíè.</text>
</string>
<string id="st_dynzone_news_stalker_opened_2">
<text>Îòëè÷íûå íîâîñòè, òîâàðèùè! Äîðîãà íà $TO ñíîâà îòêðûòà. Àíîìàëèé áîëüøå íåò, ïîðà äâèãàòüñÿ.</text>
</string>
<string id="st_dynzone_news_stalker_opened_3">
<text>Ýé, íàðîä, íà $TO òåïåðü ìîæíî îòíîñèòåëüíî áåçîïàñíî ïîïàñòü. Çîíà ðàñ÷èñòèëà àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_stalker_opened_4">
<text>Äîðîãà íà $TO îòêðûòà. Àíîìàëèé íåò, ñîáèðàåìñÿ è âûõîäèì.</text>
</string>
<string id="st_dynzone_news_stalker_opened_5">
<text>Ïîõîæå ìû íàêîíåö ñìîæåì èäòè íà $TO. Ïóòü ÷èñò, íî áóäüòå íà÷åêó.</text>
</string>
<string id="st_dynzone_news_stalker_opened_6">
<text>$TO ñíîâà â ðàñïèñàíèè, òîâàðèùè. Àíîìàëèé áîëüøå íåò, èäòè áåçîïàñíî.</text>
</string>
<!-- Sidorovich -->
<string id="st_dynzone_news_sidorovich_blocked_1">
<text>$SENDER_NAME íà ñâÿçè, ñìîòðèòå ïîä íîãè, ïîêà èäåòå ñ $FROM íà $TO, ïîëó÷èë èíôîðìàöèþ ÷òî ïóòü ïåðåêðûëè $ANOM_THEME àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_2">
<text>$SENDER_NAME ó àïïàðàòà, íå óòðóæäàéòåñü ïåðåõîäîì ñ $FROM íà $TO, îäèí èç êóðüåðîâ íåäàâíî âåðíóëñÿ è ïðèí¸ñ âåñòü, ÷òî $ANOM_THEME àíîìàëèè ïåðåêðûëè ïóòü.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_3">
<text>$SENDER_NAME íà ëèíèè, õîäèò ñëóõ, ÷òî $ANOM_THEME àíîìàëèè çàêðûëè ïðîõîä ñ $FROM íà $TO, íå íàäî ãåðîéñòâîâàòü: âû íå ïðîéä¸òå.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_4">
<text>Ãîâîðèò $SENDER_NAME, íîâè÷êè, íàïðàâëÿâøèåñÿ íà $TO, ñèëüíî çàäåðæèâàþòñÿ. Áóäüòå îñòîðîæíû.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_5">
<text>Ñòàëêåðû, áóäüòå îñòîðîæíû íà ïóòè â $TO. Îäèí èç êóðüåðîâ áûë âûíóæäåí âåðíóòüñÿ èç-çà òîãî, ÷òî $ANOM_THEME ìåøàþò ïðîõîäó.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_6">
<text>Ýòî $SENDER_NAME, ïîãîâàðèâàþò, îäèí èç äðóçåé Âîëêà çàñòðÿë íà $TO, ñêîðåå âñåãî íå ìîæåò âåðíóòüñÿ èç-çà âûñîêîé àíîìàëüíîé àêòèâíîñòè. Áóäüòå î÷åíü îñòîðîæíû.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_7">
<text>Íà ñâÿçè $SENDER_NAME, ìåñòíûå òåõíàðè ïåðåõâàòèëè âîåííóþ ðàäèîïåðåäà÷ó, ïîõîæå $ANOM_THEME àíîìàëèè îòðåçàëè $FROM îò $TO.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_8">
<text>$SENDER_NAME ãîâîðèò, ïóòü íà $TO ïåðåêðûëè $ANOM_THEME àíîìàëèè. ß áû íå ñîâåòîâàë òóäà ñåé÷àñ èäòè.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_9">
<text>Êòî ìîæåò ïîäòâåðäèòü, ÷òî $ANOM_THEME àíîìàëèè ñêîíöåíòðèðîâàëèñü ïîïåð¸ê ïóòè íà $TO? Êòî-òî èç íîâè÷êîâ áîëòàë îá ýòîì.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_10">
<text>Ïîõîæå ÷òî äîðîãà íà $TO òåïåðü ñìåðòåëüíî îïàñíà, $ANOM_THEME àíîìàëèè çàïîëîíèëè å¸. Áóäüòå íà÷åêó ïîêà ïóòü ïåðåêðûò.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_11">
<text>Ïóòü íà $TO íåáåçîïàñåí, ïîâñþäó àíîìàëèè. Ëó÷øå âàì ïîêà ÷òî çàòàèòüñÿ.</text>
</string>
<string id="st_dynzone_news_sidorovich_blocked_12">
<text>Äîðîãà íà $TO ñíîâà çàêðûòà. ׸ðòîâà Çîíà îïÿòü ìåøàåò áèçíåñó.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_sidorovich_opened_1">
<text>Âíèìàíèå âñåì íîâè÷êàì. Àíîìàëèè íà ïóòè ìåæäó $FROM è $TO èñ÷åçëè âî âðåìÿ ïîñëåäíåãî âûáðîñà. Ìîæåòå âîçâðàùàòüñÿ íà ïðèâû÷íûå ìàðøðóòû.</text>
</string>
<string id="st_dynzone_news_sidorovich_opened_2">
<text>Îòëè÷íûå íîâîñòè äëÿ âàñ, ñòàëêåðû. Ïóòü íà $TO ñíîâà îòêðûò. Íèêàêèõ áîëüøå àíîìàëèé, ìîæåòå âûäâèãàòüñÿ.</text>
</string>
<string id="st_dynzone_news_sidorovich_opened_3">
<text>Ýòî $SENDER_NAME, èíôîðìèðóþ âàñ, ÷òî äîðîãà íà $TO îòêðûòà. Ïîñëåäíèé âûáðîñ ðàñ÷èñòèë äîðîãó.</text>
</string>
<string id="st_dynzone_news_sidorovich_opened_4">
<text>Ïîõîæå äîðîãà íà $TO âíîâü áåçîïàñíî. Õîòü àíîìàëèé áîëüøå íåò, íå òåðÿéòå áäèòåëüíîñòè, íîâè÷êè.</text>
</string>
<string id="st_dynzone_news_sidorovich_opened_5">
<text>Äîðîãà íà $TO ñíîâà îòêðûòà. Àíîìàëèè ðàññåÿëèñü, èäòè áåçîïàñíî.</text>
</string>
<string id="st_dynzone_news_sidorovich_opened_6">
<text>$SENDER_NAME íà ñâÿçè, ïîäòâåðæäàþ: ïóòü íà $TO îòêðûò. Çîíà íàêîíåö-òî äà¸ò âàì õîòü êàêîé-òî øàíñ.</text>
</string>
<!-- Bandits -->
<string id="st_dynzone_news_bandit_blocked_1">
<text>Àó ïàöàíû, ñëóõàéòå. Ìû òèïà áîëüøå íå ìîæåì ïîïàñòü èç $FROM íà $TO, çäåñü ìíîãî ýòèõ, êàê îíè òàì, $ANOM_THEME õåðíè êîðî÷å.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_2">
<text>Àë¸, çûðüòå ïîä íîãè áðàòâà! Çîíà ðàçâàëèëà $ANOM_THEME àíîìàëèè ïî âñåé äîðîãå ñ $TO íà $FROM!</text>
</string>
<string id="st_dynzone_news_bandit_blocked_3">
<text>Õàõàõà! Ñìîòðèòå, ýòîò ôðàåð íå ìîæåò ïðîéòè ÷åðåç ýòè $ANOM_THEME àíîìàëèè ìåæäó $TO è $FROM! Ìîæåò îùèïàåì ïåòóøàðó?</text>
</string>
<string id="st_dynzone_news_bandit_blocked_4">
<text>Íó øî ïàöàíû, äåëàåì ñòàâêè êòî èç ôðàåðîâ ïîäîõíåò, ïîêà èä¸ò ÷åðåç ýòè $ANOM_THEME àíîìàëèè èç $FROM íà $TO?</text>
</string>
<string id="st_dynzone_news_bandit_blocked_5">
<text>Ýé ïàöàíû, ïàðà íàøèõ ïàöàíîâ òîëüêî ÷òî âèäàëè $ANOM_THEME õðåíîâèíû íà ïóòè èç $FROM íà $TO, ÿ äóìàþ ïîáðåí÷èì äî ñëåäóþùåãî âûáðîñà, ïåðåä òåì êàê êóäà íèáóäü ñîáèðàòüñÿ.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_6">
<text>Ýé, íàðîä! Êòî òî âèäåë õåðíþ íà ïóòè ê $TO? $ANOM_THEME àíîìàëèè òóòà ïîâñþäó, òèïà Çîíà íàñ ãðîõíóòü çàõîòåëà.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_7">
<text>׸ çà õåðíÿ òâîðèòñÿ? Äîðîãà íà $TO êàê ìèííîå ïîëå ãðåáàíîå, ýòè $ANOM_THEME àíîìàëèè ìëÿ. Íå íó íåáåçîïàñíî, íèõðåíà ìëÿ.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_8">
<text>Íà $TO? À, óäà÷è ñ ýòèì. Ýòè $ANOM_THEME àíîìàëèè êàê ãðèáû ïîñëå äîæäÿ, ìëÿ.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_9">
<text>Àë¸, åñòü êòî æèâîé ïàöàíû? Òóò íà ïóòè â $TO äîõåðà àíîìàëèé. Íå ïîäæàðüòåñü, áðàòâà.</text>
</string>
<string id="st_dynzone_news_bandit_blocked_10">
<text>Íó è êòî îïÿòü ïîñëàë Çîíó íàõåð ïðî ñåáÿ? Îíà âñ¸ óñëûøàëà! Êòî òóò ñàìûé óìíûé áëèí? Äîðîãà íà $TO îïÿòü âñÿ ýòîé õåðí¸é ïîêðûëàñü.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_bandit_opened_1">
<text>Àóå, ïàöàíû. Ñëóøàéòå, ôðàåðà ñíîâà õîäÿò ñ $FROM íà $TO, âðåìÿ íàíåñòè âèçèò, òàê ñêàçàòü, ïàöàíû.</text>
</string>
<string id="st_dynzone_news_bandit_opened_2">
<text>Àó, áðàòâà! Äîðîãà íà $TO ñíîâà ÷èñòàÿ. Ïîäîðâàëè ïàöàíû, ïîñìîòðèì øî òàì îñòàëîñü ïîñëå àíîìàëåê.</text>
</string>
<string id="st_dynzone_news_bandit_opened_3">
<text>Ïîõîäó àíîìàëèè ðàññûïàëèñü, áðàòâà. Ïîðà ñíîâà âàëèòü íà $TO.</text>
</string>
<string id="st_dynzone_news_bandit_opened_4">
<text>Çäàðîâà, àõðåíåííûå íîâîñòè! $TO ó íàñ ñíîâà â ïëàíàõ. Àíîìàëèè êàê ðóêîé ñíÿëè, ÷¸ æä¸ì ïàöàíû?</text>
</string>
<string id="st_dynzone_news_bandit_opened_5">
<text>Äîæäàëèñü, äîðîæêà íà $TO ÷èñòà. Áîëüøå íå æàðèìñÿ â ýòèõ àíîìàëèÿõ, áðàòâà. Ïîðà èäòè.</text>
</string>
<string id="st_dynzone_news_bandit_opened_6">
<text>Êòî òàì ñîáèðàëñÿ íà $TO, áðàòâà? Ñäà¸òñÿ ìíå, ýòè $ANOM_THEME àíîìàëèè ïðîïàëè ïîñëå âûáðîñà.</text>
</string>
<!-- Sultan (Bandits) -->
<string id="st_dynzone_news_sultan_blocked_1">
<text>Ñóëòàí íà ñâÿçè, ñëóøàéòå áðàòâà. Çîíà çàâàëèëà ïóòü íà $TO, ðàñêèäàâ $ANOM_THEME àíîìàëèè. Áðàòâà, ïîáåðåãèòåñü.</text>
</string>
<string id="st_dynzone_news_sultan_blocked_2">
<text>Àó áðàòâà, ñ $FROM íà $TO òåïåðü íå ïðîéòè. Ïîâñþäó àíîìàëèè. Ïóñêàé ïðèäóðêè ðàñ÷èùàþò íàì äîðîãó.</text>
</string>
<string id="st_dynzone_news_sultan_blocked_3">
<text>Ñóëòàí âåùàåò. $TO ïîä çàïðåòîì, $ANOM_THEME àíîìàëèè ïåðåêðûëè ïóòü. Ïåðåæä¸ì, áðàòâà.</text>
</string>
<string id="st_dynzone_news_sultan_blocked_4">
<text>Ñëóøàéòå, áðèãàäà. Ýòè $ANOM_THEME àíîìàëèè ïåðåêðûëè äîðîãó íà $TO. Áàçàðèì íà ìåñòàõ, ïàöàíû.</text>
</string>
<string id="st_dynzone_news_sultan_blocked_5">
<text>Ñóëòàí çäåñü. $TO ñåé÷àñ ì¸ðòâàÿ çîíà. Ïîâñþäó àíîìàëèè. Ñèäèì íà æîïå ðîâíî, áðàòâà.</text>
</string>
<string id="st_dynzone_news_sultan_blocked_6">
<text>Çàáóäüòå ïðî $TO, áðàòâà. $ANOM_THEME àíîìàëèè áîëüíî îïàñíûå íûí÷å. Îáîæä¸ì ïåðåìåí, ïàöàíû.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_sultan_opened_1">
<text>Õîðîøèå íîâîñòè îò Ñóëòàíà. Äîðîãà íà $TO ðàñ÷èñòèëàñü. Ïîäíèìàåì çàäíèöû è ïåðâûìè òóäà.</text>
</string>
<string id="st_dynzone_news_sultan_opened_2">
<text>Ñëóøàé, áðèãàäà, àíîìàëèè ðàññåÿëèñü. $TO ñíîâà ïîäõîäèèò äëÿ âåäåíèÿ äåë. Âûäâèãàéòåñü.</text>
</string>
<string id="st_dynzone_news_sultan_opened_3">
<text>Ñóëòàí ãîâîðèò. Çîíó îòïóñòèëî. Äîðîãà íà $TO áåçîïàñíî. Âðóáàåìñÿ, áðàòâà.</text>
</string>
<string id="st_dynzone_news_sultan_opened_4">
<text>Ýé áðàòâà, $TO ñíîâà â èãðå. Íèêàêèå $ANOM_THEME àíîìàëèè áîëüøå íå ìåøàþò íàì. Ïîðà ðóáèòü áàáêè.</text>
</string>
<string id="st_dynzone_news_sultan_opened_5">
<text>Ñóëòàí íà ñâÿçè. Äîðîãà íà $TO ÷èñòà. Äàâàéòå ïî áûðîìó, áðàòâà, ïîêà Çîíà íå ïåðåäóìàëà.</text>
</string>
<string id="st_dynzone_news_sultan_opened_6">
<text>Íó âñ¸, ïàöàíû. Äîðîãà íà $TO òåïåðü áåçîïàñíà. Áîëüøå àíîìàëèé íåò. Èäèòå æèâî.</text>
</string>
<!-- Duty -->
<string id="st_dynzone_news_dolg_blocked_1">
<text>Ñîîáùàþ âñåì îòðÿäàì îá àíîìàëüíîé àêòèâíîñòè íà ìàðøðóòå ìåæäó ñåêòîðàìè $FROM è $TO. Ïåðåäâèæåíèå ïî ýòîìó ïóòè áóäåò íåâîçìîæíî â áëèæàéøåå âðåìÿ. Çäåñü ïîÿâèëèñü $ANOM_THEME àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_2">
<text>$SENDER_NAME äîêëàäûâàåò, ñåé÷àñ ïåðåõîä ñ $FROM íà $TO ïðåãðàæäàþò $ANOM_THEME àíîìàëèè, ëó÷øå íå ðèñêîâàòü.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_3">
<text>Ýé, ñìîòðèòå ïîä íîãè, êîãäà èäåò¸ ñ $TO íà $FROM. Çäåñü ìíîæåñòâî àíîìàëèé!</text>
</string>
<string id="st_dynzone_news_dolg_blocked_4">
<text>Ãîâîðèò $SENDER_NAME, ñåé÷àñ ïîïàñòü ñ $FROM íà $TO íåâîçìîæíî, òîëüêî ÷òî òàì îáíàðóæåíû $ANOM_THEME àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_5">
<text>Áóäüòå îñòîðîæíû íà ïóòè ìåæäó $TO è $FROM. Çäåñü ïîâñþäó $ANOM_THEME àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_6">
<text>Ïîëêîâíèê Ïåòðåíêî ïðèêàçàë ìíå ñîîáùèòü âñåì, ÷òî ïóòü ìåæäó $FROM è $TO ñåé÷àñ íåáåçîïàñåí: íà ïóòè $ANOM_THEME àíîìàëèè. Îæèäàéòå ñëåäóþùåãî âûáðîñà äëÿ ïðîäîëæåíèÿ äåéñòâèé.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_7">
<text>Âñåì îòðÿäàì, ïóòü íà $TO ïåðåêðûëè $ANOM_THEME àíîìàëèè. Ïðîäâèãàéòåñü îñòîðîæíî èëè íå âîîáùå íå äâèãàéòåñü.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_8">
<text>$SENDER_NAME íà ñâÿçè. Êòî íèáóäü íàïðàâëÿåòñÿ íà $TO? Ýòè $ANOM_THEME àíîìàëèè ïåðåêðûëè âñþ äîðîãó.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_9">
<text>Ïîäòâåðæäàþ, ÷òî ïóòü íà $TO ñåé÷àñ ñëèøêîì îïàñåí äëÿ ïåðåäâèæåíèÿ: $ANOM_THEME àíîìàëèè. Íèêòî íå ïðîéä¸ò ïîêà îíè íå ðàññåþòñÿ.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_10">
<text>Îïÿòü Çîíà øàëèò; $TO ñåé÷àñ âíå äîñÿãàåìîñòè èç-çà âûñîêîé àíîìàëüíîé àêòèâíîñòè. Óäåðæèâàéòå ïîçèöèè äî ñëåäóþùèõ ñîîáùåíèé.</text>
</string>
<string id="st_dynzone_news_dolg_blocked_11">
<text>$SENDER_NAME âñåì îòðÿäàì, ïóòü íà $TO ïåðåðåçàí àíîìàëèÿìè. Ñòîéòå ñìèðíî ïîêà íå ïîñòóïèò èíôîðìàöèÿ î áåçîïàñíûõ ìàðøðóòàõ.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_dolg_opened_1">
<text>Ñîîáùàþ âñåì îòðÿäàì î ïàäåíèè àíîìàëüíîé àêòèâíîñòè íà ìàðøðóòå ìåæäó $FROM è $TO. Òåïåðü ìû ñíîâà ìîæåì õîäèòü â ýòîò ñåêòîð.</text>
</string>
<string id="st_dynzone_news_dolg_opened_2">
<text>Âñåì îòðÿäàì, ïóòü íà $TO âíîâü îòêðûò. Àíîìàëüíàÿ àêòèâíîñòü óïàëà, ïðîäâèãàéòåñü ñ îñòîðîæíîñòüþ.</text>
</string>
<string id="st_dynzone_news_dolg_opened_3">
<text>$SENDER_NAME íà ñâÿçè. Çîíà âíîâü îòêðûëà ïóòü íà $TO. Âñåì îòðÿäàì, íà÷èíàéòå ïðîäâèæåíèå.</text>
</string>
<string id="st_dynzone_news_dolg_opened_4">
<text>Îòëè÷íûå íîâîñòè, ïóòü íà $TO ÷èñò. Àíîìàëèè ðàññåÿëèñü, ïðîäâèãàéòåñü âïåð¸ä.</text>
</string>
<string id="st_dynzone_news_dolg_opened_5">
<text>Âíèìàíèå âñåì, ïóòü íà $TO âíîâü áåçîïàñåí. Ãîòîâû âûäâèãàòüñÿ.</text>
</string>
<string id="st_dynzone_news_dolg_opened_6">
<text>Äîðîãà íà $TO ñíîâà îòêðûëàñü. Àíîìàëüíàÿ àêòèâíîñòü óïàëà, íî áóäüòå ãîòîâû ê ñòîëêíîâåíèþ ñ ÷åì-òî äðóãèì.</text>
</string>
<!-- Petrenko (Duty) -->
<string id="st_dynzone_news_petrenko_blocked_1">
<text>Ãîâîðèò ïîëêîâíèê Ïåòðåíêî. Âñå îòðÿäû "Äîëãà", íå èñïîëüçóéòå ìàðøðóò ñ $FROM íà $TO. $ANOM_THEME àíîìàëèè ñäåëàëè ïðîõîä íåâîçìîæíûì.</text>
</string>
<string id="st_dynzone_news_petrenko_blocked_2">
<text>Íà ñâÿçè ïîëêîâíèê Ïåòðåíêî. Ìû ïîäòâåðäèëè, ÷òî $ANOM_THEME àíîìàëèè îáðàçîâàëè êðóïíîå ñêîïëåíèå íà ìàðøðóòå ìåæäó $FROM è $TO. Óäåðæèâàéòå ïîçèöèè äî äàëüíåéøèõ óêàçàíèé.</text>
</string>
<string id="st_dynzone_news_petrenko_blocked_3">
<text>Âíèìàíèå îòðÿäàì "Äîëãà", äîðîãó ìåæäó $FROM è $TO çàêðûëè $ANOM_THEME àíîìàëèè. Ðåêîìåíäóþ çàêðåïèòüñÿ íà ïîçèöèÿõ.</text>
</string>
<string id="st_dynzone_news_petrenko_blocked_4">
<text>Äîêëàäûâàåò ïîëêîâíèê Ïåòðåíêî. Àíîìàëüíàÿ àêòèâíîñòü îáíàðóæåíà íà ïóòè ê $TO. Âñåì ïàòðóëÿì, íåìåäëåííî èçìåíèòå ìàðøðóòû.</text>
</string>
<string id="st_dynzone_news_petrenko_blocked_5">
<text>Îòðÿäû, áóäüòå íà÷åêó. Ïîñòóïèëà èíôîðìàöèÿ, ÷òî $ANOM_THEME àíîìàëèè áëîêèðóþò ïóòü ìåæäó $FROM è $TO. Ñîáëþäàéòå îñòîðîæíîñòü ïðè ïðîäâèæåíèè.</text>
</string>
<string id="st_dynzone_news_petrenko_blocked_6">
<text>Íà ñâÿçè øòàá "Äîëãà". Äîðîãà ìåæäó $FROM è $TO ñëèøêîì îïàñíà. Îáíàðóæåíû $ANOM_THEME àíîìàëèè. Äåðæèòå ïîçèöèè.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_petrenko_opened_1">
<text>Íà ñâÿçè ïîëêîâíèê Ïåòðåíêî. Ïóòü íà $TO ðàñ÷èùåí. Àíîìàëüíàÿ àêòèâíîñòü óïàëà. Âûäâèãàéòåñü, íî íå çàáûâàéòå î ìåðàõ ïðåäîñòîðîæíîñòè.</text>
</string>
<string id="st_dynzone_news_petrenko_opened_2">
<text>Íà ñâÿçè ïîëêîâíèê Ïåòðåíêî. Ïîäòâåðæäàþ ÷òî ïóòü ñ $FROM íà $TO òåïåðü áåçîïàñåí. Ïîðà âûäâèãàòüñÿ.</text>
</string>
<string id="st_dynzone_news_petrenko_opened_3">
<text>Îòëè÷íûå íîâîñòè, ñîëäàòû "Äîëãà". Çîíà ðàñ÷èñòèëà ïóòü íà $TO. Àíîìàëèé áîëüøå íåò.</text>
</string>
<string id="st_dynzone_news_petrenko_opened_4">
<text>Ïîëêîâíèê Ïåòðåíêî âñåì îòðÿäàì: ñåêòîð $TO âíîâü äîñòóïåí. Àíîìàëèè Çîíû ðàññåÿëèñü. Áóäüòå â ïîëíîé áîåâîé ãîòîâíîñòè ïðè âûäâèæåíèè.</text>
</string>
<string id="st_dynzone_news_petrenko_opened_5">
<text>Âñåì îòðÿäàì "Äîëãà", ìàðøðóò ìåæäó $FROM è $TO îòêðûò. Âîçâðàùàéòåñü ê èñïîëíåíèþ âàøåãî äîëãà.</text>
</string>
<string id="st_dynzone_news_petrenko_opened_6">
<text>Ãîâîðèò øòàá "Äîëãà", ñîîáùàåì î ïîíèæåíèè àíîìàëüíîé àêòèâíîñòè â ðàéîíå $TO. Ïðîäâèæåíèå áåçîïàñíî.</text>
</string>
<!-- Clear Sky -->
<string id="st_dynzone_news_csky_blocked_1">
<text>Äàæå íå ïûòàéòåñü ïîïàñòü ñ $TO íà $FROM, òîëüêî ÷òî îòòóäà, âåçäå $ANOM_THEME àíîìàëèè, õîäèòü ñëèøêîì îïàñíî.</text>
</string>
<string id="st_dynzone_news_csky_blocked_2">
<text>׸ðò... êòî-íèáóäü ñêàæèòå Ýêîëîãàì ÷òî ïåðåõîä ìåæäó $TO è $FROM ïåðåêðûëè $ANOM_THEME àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_csky_blocked_3">
<text>×òî áû âû íè äåëàëè, íå èäèòå ïî äîðîãå ñ $FROM íà $TO, ïîõîæå, ïóòü ïåðåêðûò àíîìàëèÿìè.</text>
</string>
<string id="st_dynzone_news_csky_blocked_4">
<text>Ïðîôåññîð Êàëàí÷à òîëüêî ÷òî ñêàçàë, ÷òî ïî ïîêàçàíèÿì ïðèáîðîâ, ïîñëåäíèé âûáðîñ ïåðåêðûë ïóòü íà $TO. Ìîæåò êòî-íèáóäü ïîäòâåðäèòü?</text>
</string>
<string id="st_dynzone_news_csky_blocked_5">
<text>Åñòü êàêèå íîâîñòè ïðî ïóòü íà $TO? Ïîñëåäíèé ðàç ñëûøàë, ÷òî $ANOM_THEME àíîìàëèè áûëè ïîâñþäó. Âîçìîæíî ñòîèò ïåðåæäàòü.</text>
</string>
<string id="st_dynzone_news_csky_blocked_6">
<text>$TO ñåé÷àñ âíå ðàñïèñàíèÿ. Ýòè $ANOM_THEME àíîìàëèè çäåñü ïîâñþäó. Ïåðåæä¸ì íà ïîçèöèÿõ ïîêà âñ¸ íå óñòàêàíèòñÿ.</text>
</string>
<string id="st_dynzone_news_csky_blocked_7">
<text>Íå ìîæåì äîáðàòüñÿ íà $TO, àíîìàëèè ïðåãðàæäàþò ïóòü. Äåðæèòåñü, ×èñòîå Íåáî.</text>
</string>
<string id="st_dynzone_news_csky_blocked_8">
<text>Êòî-íèáóäü õîäèë íà $TO? Ïóòü çàãàäèëè $ANOM_THEME àíîìàëèè. Äåðæèòå ñâîè ïîçèöèè.</text>
</string>
<string id="st_dynzone_news_csky_blocked_9">
<text>$SENDER_NAME íà ñâÿçè, äîðîãà íà $TO ñåé÷àñ íîó-ãîó. Ñëèøêîì ìíîãî àíîìàëèé. Íå ïîäíèìàéòå ãîëîâû ïîêà.</text>
</string>
<string id="st_dynzone_news_csky_blocked_10">
<text>$SENDER_NAME íà ëèíèè, ìîé îòðÿä ðàçâåäàë äîðîãó íà $TO: ñåé÷àñ òàì ìíîãî àíîìàëèé. Íå èäèòå ïî ýòîìó ïóòè, åñëè æèçíü äîðîãà.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_csky_opened_1">
<text>Ñîîáùàþ âñåì îòðÿäîì îá îòêðûòèè ïóòè ìåæäó $FROM è $TO. Ïîñëåäíèé âûáðîñ ðàñ÷èñòèë àíîìàëèè çäåñü.</text>
</string>
<string id="st_dynzone_news_csky_opened_2">
<text>×èñòîå Íåáî, ïóòü íà $TO îòêðûò. Àíîìàëèè èñ÷åçëè, íî áóäüòå íàãîòîâå.</text>
</string>
<string id="st_dynzone_news_csky_opened_3">
<text>Òîëüêî ÷òî óçíàë, ïóòü íà $TO ñíîâà ÷èñò. Ïîñëåäíèé âûáðîñ ïðîø¸ë íå çðÿ.</text>
</string>
<string id="st_dynzone_news_csky_opened_4">
<text>$SENDER_NAME íà ñâÿçè. Ïóòü íà $TO îòêðûò, àíîìàëèè ðàññåÿëèñü.</text>
</string>
<string id="st_dynzone_news_csky_opened_5">
<text>Êòî-òî ñîáèðàåòñÿ íà $TO? Ïóòü ÷èñò, íèêàêèõ àíîìàëèé íå âèäíî ïîñëå ïîñëåäíåãî âûáðîñà.</text>
</string>
<string id="st_dynzone_news_csky_opened_6">
<text>Ïîõîæå Çîíà óñïîêîèëàñü. Ïóòü íà $TO òåïåðü áåçîïàñåí, âûäâèãàéòåñü ïîòèõîíüêó.</text>
</string>
<!-- Ecologists -->
<string id="st_dynzone_news_ecolog_blocked_1">
<text>Èññëåäîâàòåëüñêàÿ ãðóïïà îáíàðóæèëà $ANOM_THEME àíîìàëüíûå îáðàçîâàíèÿ íà ïóòè ìåæäó $FROM è $TO. Ìû ðåêîìåíäóåì âàì âûáðàòü áåçîïàñíûé îáõîäíîé ìàðøðóò.</text>
</string>
<string id="st_dynzone_news_ecolog_blocked_2">
<text>Èññëåäîâàòåëüñêèå ãðóïïû, ïðèìèòå ê âíèìàíèþ. Ïóòü íà $TO ïåðåêðûëè $ANOM_THEME àíîìàëüíûå îáðàçîâàíèÿ. Ïðîäâèãàéòåñü îñòðîæíî.</text>
</string>
<string id="st_dynzone_news_ecolog_blocked_3">
<text>Ìîæåò êòî-ëèáî ïîäòâåðäèòü àíîìàëüíóþ àêòèâíîñòü îêîëî $TO? Ìû ïîëó÷àåì èíôîðìàöèþ î òîì, ÷òî $ANOM_THEME àíîìàëèè äåëàþò ïåðåõîä íåâîçìîæíûì.</text>
</string>
<string id="st_dynzone_news_ecolog_blocked_4">
<text>Ïîñëå âûáðîñà íà ïóòè ê $TO îáðàçîâàëñÿ àíîìàëüíûé áàðüåð. Èçáåãàéòå äàííîé òåððèòîðèè äî òåõ ïîð, ïîêà áàðüåð íå ðàññååòñÿ.</text>
</string>
<string id="st_dynzone_news_ecolog_blocked_5">
<text>$TO â íàñòîÿùèé ìîìåíò íå äîñòèãíóòü. Ýòè $ANOM_THEME àíîìàëüíûå îáðàçîâàíèÿ íå ïîçâîëÿþò ïðîéòè áåçîïàñíî.</text>
</string>
<string id="st_dynzone_news_ecolog_blocked_6">
<text>Ñàõàðîâ ïîëó÷èë ñâîäêó îò âîåííûõ ïàòðóëåé - ïóòü ìåæäó $FROM è $TO ïåðåãîðîäèëè $ANOM_THEME àíîìàëèè. Âñåì ãðóïïàì ñëåäóåò ïîâåðíóòü, ìû íå ìîæåì òàê ðèñêîâàòü.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_ecolog_opened_1">
<text>Èññëåäîâàòåëüñêàÿ ãðóïïà çàñåêëà ïàäåíèå àíîìàëüíîé àêòèâíîñòè íà ïóòè ìåæäó $FROM è $TO. Òåïåðü äâèæåíèå ïî ìàðøðóòó áåçîïàñíî.</text>
</string>
<string id="st_dynzone_news_ecolog_opened_2">
<text>Èññëåäîâàòåëüñêèå ãðóïïû, ïóòü íà $TO òåïåðü ÷èñò. Àíîìàëèè ðàññåÿëèñü, ïðîäâèæåíèå áåçîïàñíî.</text>
</string>
<string id="st_dynzone_news_ecolog_opened_3">
<text>Âíèìàíèå, ïóòü íà $TO âíîâü îòêðûò. Ïîñëåäíèé âûáðîñ ðàñ÷èñòèë àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_ecolog_opened_4">
<text>$SENDER_NAME íà ñâÿçè, ïîäòâåðäàþ, ïóòü íà $TO ÷èñò. Àíîìàëüíàÿ àêòèâíîñòü óïàëà äî íîðìàëüíûõ çíà÷åíèé.</text>
</string>
<string id="st_dynzone_news_ecolog_opened_5">
<text>Ïîõîæå Çîíà óñïîêîèëàñü. Ïóòü íà $TO ñíîâà áåçîïàñåí, áîëüøå àíîìàëèé íåò.</text>
</string>
<string id="st_dynzone_news_ecolog_opened_6">
<text>Ïóòü íà $TO ÷èñò. Àíîìàëèè ðàññåÿëèñü, áåçîïàñíî ïðîäîëæàòü èññëåäîâàòåëüñêèå ðàáîòû.</text>
</string>
<!-- Sakharov (Ecologists) -->
<string id="st_dynzone_news_sakharov_blocked_1">
<text>Ïðîôåññîð Ñàõàðîâ íà ñâÿçè. Ìàðøðóò ìåæäó $FROM è $TO çàáëîêèðîâàëè $ANOM_THEME àíîìàëèè. Èçáåãàéòå ýòîé òåððèòîðèè.</text>
</string>
<string id="st_dynzone_news_sakharov_blocked_2">
<text>Ãîâîðèò Ïðîôåññîð Ñàõàðîâ. Ìû îáíàðóæèëè $ANOM_THEME àíîìàëèè â çíà÷èòåëüíûõ êîëè÷åñòâàõ íà ïóòè â $TO. Ïðîäâèãàéòåñü îñòîðîæíî.</text>
</string>
<string id="st_dynzone_news_sakharov_blocked_3">
<text>Ýêîëîãè, ïîæàëóéñòà, ïðèìèòå ê ñâåäåíèþ, ÷òî ìàðøðóò ìåæäó $FROM è $TO îïàñåí: íà í¸ì ïîÿâèëèñü $ANOM_THEME àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_sakharov_blocked_4">
<text>Ïðîôåññîð Ñàõàðîâ âñåì èññëåäîâàòåëüñêèì ãðóïïàì: $TO â íàñòîÿùèé ìîìåíò íåëüçÿ äîñòèãíóòü: $ANOM_THEME àíîìàëèè ïåðåêðûëè ïóòü. Îñòàâàéòåñü íà ïîçèöèÿõ.</text>
</string>
<string id="st_dynzone_news_sakharov_blocked_5">
<text>Âíèìàíèå, ìàðøðóò ìåæäó $FROM è $TO ïåðåêðûëè $ANOM_THEME àíîìàëèè. Ñòàðàéòåñü íàéòè îáõîäíûå ïóòè.</text>
</string>
<string id="st_dynzone_news_sakharov_blocked_6">
<text>Èññëåäîâàòåëüñêèå ãðóïïû, ïðèìèòå ê ñâåäåíèþ, àíîìàëèè ìåøàþò áåçîïàñíîìó ïåðåõîäó íà $TO. Ïðîäâèãàéòåñü ñ îñòîðîæíîñòüþ.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_sakharov_opened_1">
<text>Ãîâîðèò Ïðîôåññîð Ñàõàðîâ. Ìàðøðóò ìåæäó $FROM è $TO ñíèçèë àíîìàëüíóþ àêòèâíîñòü äî íîðìàëüíûõ çíà÷åíèé. Ïðîäâèæåíèå áåçîïàñíî.</text>
</string>
<string id="st_dynzone_news_sakharov_opened_2">
<text>Ýêîëîãè, õîðîøèå íîâîñòè. $TO âíîâü ìîæíî ïîñåòèòü. Àíîìàëüíàÿ àêòèâíîñòü ñíèçèëàñü.</text>
</string>
<string id="st_dynzone_news_sakharov_opened_3">
<text>Ïðîôåññîð Ñàõàðîâ íà ñâÿçè, ïîäòâåðæäàþ, ÷òî ìàðøðóò íà $TO áåçîïàñåí. Àíîìàëèè ðàññåÿëèñü.</text>
</string>
<string id="st_dynzone_news_sakharov_opened_4">
<text>Çîíà î÷èñòèëàñü. Ïåðåõîä íà $TO òåïåðü áåçîïàñåí äëÿ âñåõ èññëåäîâàòåëüñêèõ ãðóïï.</text>
</string>
<string id="st_dynzone_news_sakharov_opened_5">
<text>Ïðîôåññîð Ñàõàðîâ âñåìó ïåðñîíàëó: êîëè÷åñòâî àíîìàëèé îêîëî $TO çíà÷èòåëüíî ñîêðàòèëîñü. Âîçâðàùàéòåñü ê ñòàíäàðòíûì îïåðàöèÿì.</text>
</string>
<string id="st_dynzone_news_sakharov_opened_6">
<text>Âíèìàíèþ èññëåäîâàòåëåé, ìàðøðóò íà $TO âíîâü îòêðûò. Áåçîïàñíûõ ïóòåøåñòâèé.</text>
</string>
<!-- Mercenaries -->
<string id="st_dynzone_news_killer_blocked_1">
<text>Íà¸ìíèêè, íàø ÷åëîâåê áûë ðàíåí: $ANOM_THEME àíîìàëèè íà ïóòè èç $FROM â $TO, ê ñâåäåíèþ. </text>
</string>
<string id="st_dynzone_news_killer_blocked_2">
<text>Øòàá, ó íàñ ïðîáëåìà. Èçâåñòíûé ìàðøðóò ìåæäó $FROM è $TO íåïðîõîäèì: êëàñòåðèçîâàëèñü $ANOM_THEME àíîìàëèè, äîâåäèòå äî ñâåäåíèÿ îñòàëüíûõ.</text>
</string>
<string id="st_dynzone_news_killer_blocked_3">
<text>Òàê, à âîò ýòî èíòåðåñíî. Òóò $ANOM_THEME àíîìàëèè íà ïóòè ìåæäó $FROM è $TO. Îòïðàâüòå îòðÿä íà ðàçâåäêó.</text>
</string>
<string id="st_dynzone_news_killer_blocked_4">
<text>Âñåì íà¸ìíèêàì, ïóòü íà $TO ñåé÷àñ òóïèêîâûé. Ìåñòíûå $ANOM_THEME àíîìàëèè ýòî ïðåäîïðåäåëèëè.</text>
</string>
<string id="st_dynzone_news_killer_blocked_5">
<text>Íå ìîæåì èäòè íà $TO, Çîíà ñíîâà çàáðîñàëà ïóòü àíîìàëèè. Äåðæèì ïîçèöèè.</text>
</string>
<string id="st_dynzone_news_killer_blocked_6">
<text>Êàêîâ ñòàòóñ ïóòè íà $TO? Ýòè $ANOM_THEME àíîìàëèè áûëè òàì íå òàê äàâíî.</text>
</string>
<string id="st_dynzone_news_killer_blocked_7">
<text>Çîíà çàêðûëà ïåðåõîä íà $TO àíîìàëèÿìè. Èùåì äðóãîé ïóòü.</text>
</string>
<string id="st_dynzone_news_killer_blocked_8">
<text>$SENDER_NAME íà ñâÿçè, ïóòü íà $TO íåïðîõîäèì. Ñëèøêîì ìíîãî àíîìàëèé äëÿ áåçîïàñíîé íàâèãàöèè.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_killer_opened_1">
<text>Íà¸ìíèêè, íàø ðàçâåä÷èê äîëîæèë, ÷òî ìàðøðóò ñ $FROM íà $TO ÷èñò.</text>
</string>
<string id="st_dynzone_news_killer_opened_2">
<text>Âñåì ìåðêàì, ïóòü íà $TO ÷èñò. Àíîìàëèè ðàññåÿëèñü, ïðîäîëæàéòå âûïîëíåíèå.</text>
</string>
<string id="st_dynzone_news_killer_opened_3">
<text>$SENDER_NAME íà ñâÿçè. Äîðîãà íà $TO îòêðûòà, àíîìàëèè áîëüøå íå óãðîçà</text>
</string>
<string id="st_dynzone_news_killer_opened_4">
<text>Âíèìàíèå, ìàðøðóò íà $TO ÷èñò. Âûäâèãàéòåñü, Çîíà äàëà íàì âîçìîæíîñòü.</text>
</string>
<string id="st_dynzone_news_killer_opened_5">
<text>Îòëè÷íûå íîâîñòè, íà¸ìíèêè. Ïóòü íà $TO îòêðûò. Àíîìàëèè áîëüøå íå ïîìåøàþò.</text>
</string>
<string id="st_dynzone_news_killer_opened_6">
<text>Ïóòü â $TO ÷èñò. Àíîìàëèé áîëüøå íåò, ïîøëè-ïîøëè.</text>
</string>
<!-- Dushman (Mercenaries) -->
<string id="st_dynzone_news_dushman_blocked_1">
<text>Ýòî Äóøìàí. Ê ñâåäåíèþ íà¸ìíèêîâ: ìàðøðóò ñ $FROM íà $TO ïåðåïîëíèëè $ANOM_THEME àíîìàëèè. Óäåðæèâàéòå ïîçèöèè.</text>
</string>
<string id="st_dynzone_news_dushman_blocked_2">
<text>Âñåì îòðÿäàì, Äóøìàí íà ñâÿçè. Çîíà ðàçûãðàëàñü. Òå $ANOM_THEME àíîìàëèè çàáëîêèðîâàëè ïóòü íà $TO. Èçáåãàéòå òåððèòîðèè äî äàëüíåéøèõ óêàçàíèé.</text>
</string>
<string id="st_dynzone_news_dushman_blocked_3">
<text>Îáíîâëåíèå, ìåðêè. Íàøè ðàçâåä÷èêè çàñåêëè $ANOM_THEME àíîìàëèè â áîëüøèõ êîëè÷åñòâàõ ìåæäó $FROM è $TO. Ìû íå ìîæåì ïîçâîëèòü ñåáå ïîòåðè. Áóäüòå íàãîòîâå.</text>
</string>
<string id="st_dynzone_news_dushman_blocked_4">
<text>Ãîâîðèò Äóøìàí. Èçáåãàéòå ìåñòà $TO. Åãî ïåðåêðûëè $ANOM_THEME àíîìàëèè. Äàâàéòå íå áóäåì òåðÿòü ëþäåé.</text>
</string>
<string id="st_dynzone_news_dushman_blocked_5">
<text>Âíèìàíèå, íà¸ìíèêè. Ïóòü ìåæäó $FROM è $TO ñëèøêîì îïàñåí: $ANOM_THEME àíîìàëèè. Íàéäèòå àëüòåðíàòèâó.</text>
</string>
<string id="st_dynzone_news_dushman_blocked_6">
<text>Ýòî Äóøìàí. Ïîäòâåðæäàþ âûñîêóþ àíîìàëüíóþ àêòèâíîñòü îêîëî $TO. Íå äâèãàéòåñü äî ïîëó÷åíèÿ íîâîé èíôîðìàöèè.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_dushman_opened_1">
<text>Äóøìàí çäåñü. Àíîìàëèè, ïåðåêðûâàâøèå $TO èñ÷åçëè. Íà¸ìíèêè, ãîòîâû âûäâèãàòüñÿ?</text>
</string>
<string id="st_dynzone_news_dushman_opened_2">
<text>Îòëè÷íûå íîâîñòè, ìåðêè. Ïóòü ìåæäó $FROM è $TO îòêðûò. Àíîìàëèè áîëüøå íå óãðîçà. Âûäâèãàéòåñü îñòîðîæíî.</text>
</string>
<string id="st_dynzone_news_dushman_opened_3">
<text>Ýòî Äóøìàí. Ïîäòâåðæäàþ áåçîïàñíîñòü ïðîõîäà íà $TO. Âñåì îòðÿäàì, äâèãàéòåñü ïî ãîòîâíîñòè.</text>
</string>
<string id="st_dynzone_news_dushman_opened_4">
<text>Âíèìàíèå, ïóòü íà $TO ñíîâà ÷èñò. Àíîìàëèè îòñòóïèëè. Ïîðà äâèãàòüñÿ, íà¸ìíèêè.</text>
</string>
<string id="st_dynzone_news_dushman_opened_5">
<text>Äóøìàí íà ñâÿçè. Ó íàñ çåë¸íûé ñâåò íà $TO. Àíîìàëèé íåò. Áåçîïàñíîãî ïåðåõîäà.</text>
</string>
<string id="st_dynzone_news_dushman_opened_6">
<text>Âñåì îòðÿäàì, ýòî Äóøìàí. Çîíà ðàñ÷èñòèëà ïóòü íà $TO. Ïðîäîëæàéòå âàøè äåëà.</text>
</string>
<!-- Freedom -->
<string id="st_dynzone_news_freedom_blocked_1">
<text>Ýì, ãàéñ? Ïîõîæå äîðîæêó ìåæäó $FROM è $TO ïåðåðåçàëî âî âðåìÿ ïîñëåäíåãî âûáðîñà. Ïðèÿòåëè î÷åíü äîëãî íå âîçâðàùàþòñÿ èç ðåéäà...</text>
</string>
<string id="st_dynzone_news_freedom_blocked_2">
<text>×óâàêè, ó íàñ ïðîáëåìà. Íàøó äîðîãó ìåæäó $TO è $FROM ïåðåêðûëè ÷¸ðòîâû $ANOM_THEME àíîìàëèè. Øî æ òàêîå, ìýíû?</text>
</string>
<string id="st_dynzone_news_freedom_blocked_3">
<text>Ýé, "Ñâîáîäà"! Êòî-íèäü åù¸ çàìåòèë, ÷òî Çîíà ïåðåêðûëà äîðîãó íà $TO àíîìàëèÿìè? Ïîõîäó çàñòðÿëè.</text>
</string>
<string id="st_dynzone_news_freedom_blocked_4">
<text>Íó, êòî íåäàâíî òàì ñîáèðàëñÿ íà $TO? Òóò âåçäå àíîìàëèè. Íàâåðíîå âàì ïðèä¸òñÿ ïîäîæäàòü.</text>
</string>
<string id="st_dynzone_news_freedom_blocked_5">
<text>Çîíà ÷åãî-òî îïÿòü ðàçûãðàëàñü. Íå ìîæåì ïðîáðàòüñÿ íà $TO, ýòî $ANOM_THEME àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_freedom_blocked_6">
<text>Ïîõîæå $TO ñåé÷àñ íå â ìîäå. Àíîìàëèè ïîâñþäó, Çîíà íå õî÷åò íàñ ïóñêàòü.</text>
</string>
<string id="st_dynzone_news_freedom_blocked_7">
<text>Ïóòü íà $TO çàêðûëè $ANOM_THEME àíîìàëèè. Ïîñèäèì, ïîãîäèì ïîêà Çîíà ñàìà íå î÷èñòèòñÿ.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_freedom_opened_1">
<text>Ýì, ãàéñ? Ïîõîæå ÷òî äîðîãà ìåæäó $FROM è $TO îòêðûëàñü â ïîñëåäíèé âûáðîñ. Òðàâêó ïîäâåçëè áûñòðåå, ÷åì ÿ îæèäàë...</text>
</string>
<string id="st_dynzone_news_freedom_opened_2">
<text>Áîðöû çà "Ñâîáîäó", Çîíà äà¸ò íàì ïåðåðûâ: ïóòü $TO îòêðûò, íèêàêèõ áîëüøå àíîìàëèé.</text>
</string>
<string id="st_dynzone_news_freedom_opened_3">
<text>Ýé, $TO âåðíóëàñü íà êàðòû. Àíîìàëèè ðàñ÷èñòèëèñü, ïîðà äâèãàòüñÿ.</text>
</string>
<string id="st_dynzone_news_freedom_opened_4">
<text>$SENDER_NAME òóòà, ïóòü íà $TO îòêðûò. Àíîìàëèé áîëüøå íåò, òàê ÷òî ïîãíàëè.</text>
</string>
<string id="st_dynzone_news_freedom_opened_5">
<text>Õîðîøèå íîâîñòè, ìýíû. Äîðîãà íà $TO ñíîâà áåçîïàñíà, íèêàêèõ àíîìàëèé íå âèäèì.</text>
</string>
<string id="st_dynzone_news_freedom_opened_6">
<text>Çîíà íàñòîëüêî î÷èñòèëàñü, ÷òî ïóòü íà $TO òåïåðü îòêðûò. Âðåìÿ äëÿ òåëîäâèæåíèé, íàðîä.</text>
</string>
<!-- Lukash (Freedom) -->
<string id="st_dynzone_news_lukash_blocked_1">
<text>Êîìàíäàíòå çäåñü. Áîðöû çà "Ñâîáîäó", ïîñòîðîíèòåñü ïóòè ìåæäó $FROM è $TO, çäåñü âåçäå $ANOM_THEME àíîìàëèè.</text>
</string>
<string id="st_dynzone_news_lukash_blocked_2">
<text>Ýé "Ñâîáîäà", ýòî Ëóêàø. Çîíà çàêèíóëà $ANOM_THEME àíîìàëèè ïðÿìî íà ïóòü ê $TO. Îñòàíîâèòåñü è îòäîõíèòå, ÷óâàêè.</text>
</string>
<string id="st_dynzone_news_lukash_blocked_3">
<text>Ïîñëóøàéòå, "Ñâîáîäà". Îò÷¸òû ðàçâåä÷èêîâ ïîäòâåðæàþò, ÷òî ìåæäó $FROM è $TO ñåé÷àñ $ANOM_THEME àíîìàëèè. Íå ðèñêóéòå ñîáîé, ïàðíè.</text>
</string>
<string id="st_dynzone_news_lukash_blocked_4">
<text>Êîìàíäàíòå Ëóêàø çäåñü, òîâàðèùè. Äîðîãà $TO ñåé÷àñ êàê êàïêàí, âñ¸ ýòè $ANOM_THEME àíîìàëèè. Ïðèäåðæèòå êîíåé.</text>
</string>
<string id="st_dynzone_news_lukash_blocked_5">
<text>Ñòðàæè "Ñâîáîäû", âåðòàéòå îò $TO. Àíîìàëüíóþ àêòèâíîñòü çàñåêëè. Ïîáåðåãèòåñü.</text>
</string>
<string id="st_dynzone_news_lukash_blocked_6">
<text>Ïîñëåäíèå íîâîñòè, íà ñâÿçè Ëóêàø. Íà $TO çàïëûëè $ANOM_THEME àíîìàëèè. Ïåðåæä¸ì ýòî.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_lukash_opened_1">
<text>Õîðîøèå íîâîñòè îò êîìàíäàíòå. Ïóòü íà $TO ÷èñò. Íå ïåðåæèâàåì îá àíîìàëèÿõ, ìýíû.</text>
</string>
<string id="st_dynzone_news_lukash_opened_2">
<text>Ýé "Ñâîáîäà", Çîíó îòïóñòèëî. Ïóòü íà $TO âíîâü îòêðûò. Âûõîäèì ïî ãîòîâíîñòè.</text>
</string>
<string id="st_dynzone_news_lukash_opened_3">
<text>Ëóêàø íà ëèíèè, ïóòü ìåæäó $FROM è $TO ÷èñò. Äàâàéòå âîñïîëüçóåìñÿ ýòèì ïî ïîëíîé, ïîêà Çîíà íå ïåðåäóìàëà.</text>
</string>
<string id="st_dynzone_news_lukash_opened_4">
<text>Áîðöû çà "Ñâîáîäó", $TO âåðíóëàñü â èãðó. Àíîìàëèé áîëüøå íåò, ïîðà äâèãàòüñÿ!</text>
</string>
<string id="st_dynzone_news_lukash_opened_5">
<text>Òîâàðèùè-àíàðõèñòû, õîäèòü íà $TO âíîâü áåçîïàñíî. Çîíà ðàñ÷èñòèëà äîðîãó. Íî áóäüòå ãîòîâû ê ñòû÷êàì.</text>
</string>
<string id="st_dynzone_news_lukash_opened_6">
<text>Ïóòü íà $TO îòêðûò, ãîâîðèò Ëóêàø. Àíîìàëèè áîëåå íå ïðåäñòàâëÿþò óãðîçû. Ëèøíèé ðàç íå íàêóðèâàéòåñü.</text>
</string>
<!-- Monolith -->
<string id="st_dynzone_news_monolith_blocked_1">
<text>Áðàòüÿ! Âåëèêèé Ìîíîëèò ðåøèë âîñïðîòèâèòüñÿ ïóòåøåñòâèÿì íåâåðíûõ ïî òðîïå ìåæäó $FROM è $TO, ïîñåÿâ çäåñü $ANOM_THEME àíîìàëèè. Äàâàéòå æå èñïîëüçîâàòü äðóãèå ñâÿùåííûå òðîïû Çîíû.</text>
</string>
<string id="st_dynzone_news_monolith_blocked_2">
<text>Áðàòüÿ, Âåëèêèé Ìîíîëèò áëàãîñëîâèë $TO ñâÿùåííûìè àíîìàëèÿìè? Âåðíûé íàéä¸ò èíóþ òðîïó.</text>
</string>
<string id="st_dynzone_news_monolith_blocked_3">
<text>Âíåìëèòå âñå, Ìîíîëèò ïðèêàçàë çàïå÷àòàòü àíîìàëèÿìè òðîïó íà $TO. Ìû äîëæíû òåðïåëèâî îæèäàòü äàëüíåéøèõ Åãî çíàêîâ.</text>
</string>
<string id="st_dynzone_news_monolith_blocked_4">
<text>Ñâÿùåííàÿ òðîïà íà $TO áûëà áëàãîñëîâëåíà Âåëèêèì Ìîíîëèòîì. Ëèøü èçáðàííûå ïðîéäóò, êîãäà ïðèä¸ò âðåìÿ.</text>
</string>
<string id="st_dynzone_news_monolith_blocked_5">
<text>Íàø ïóòü $TO çàáëîêèðîâàí âîëåé Ìîíîëèòà, âûðàæåííîé â àíîìàëèÿõ. Ñòîéòå è áäèòå, ïîêóäà íå ïðèáóäåò ïðîâèäåíèå.</text>
</string>
<string id="st_dynzone_news_monolith_blocked_6">
<text>Áðàòüÿ, Ìîíîëèò îñâÿòèë ïóòü íà $TO àíîìàëèÿìè. Ìû äîëæíû óäåðæèâàòü åãî ñâÿùåííûå çåìëè è æäàòü Åãî çíàêîâ.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_monolith_opened_1">
<text>Áðàòüÿ! Âåëèêèé Ìîíîëèò óñëûøàë ìîëüáû íàøè, è âíîâü îòêðûë äëÿ íàñ ñâÿùåííóþ äîðîãó ìåæäó $FROM è $TO.</text>
</string>
<string id="st_dynzone_news_monolith_opened_2">
<text>Áðàòüÿ, Ìîíîëèò î÷èñòèë ïóòü íà $TO. Àíîìàëèé áîëåå íåò, è ïóòü íàø ÿñåí ïðåäåëüíî.</text>
</string>
<string id="st_dynzone_news_monolith_opened_3">
<text>Ïóòü íà $TO îòêðûò è áëàãîñëîâëåí âîëåé Ìîíîëèòà. Çäåøíèì àíîìàëèÿì áîëåå íå îñòàíîâèòü íàñ, ñëóã Åãî.</text>
</string>
<string id="st_dynzone_news_monolith_opened_4">
<text>Âîçðàäóéòåñü æå òîìó, ÷òî Ìîíîëèò óìèðîòâîðèë àíîìàëèè íà ïóòè ê $TO. Ïîéä¸ìòå æå âåðíûå áðàòüÿ.</text>
</string>
<string id="st_dynzone_news_monolith_opened_5">
<text>Ìîíîëèò î÷èñòèë ïóòü íà $TO. Àíîìàëèè áîëåå íå îñòàíîâÿò íàñ.</text>
</string>
<string id="st_dynzone_news_monolith_opened_6">
<text>Áðàòüÿ, íàø ïóòü íà $TO òåïåðü ÿñåí. Ìîíîëèò ïðîâ¸ë íàñ ñêâîçü àíîìàëèè.</text>
</string>
<!-- Krolik (Monolith) -->
<string id="st_dynzone_news_krolik_blocked_1">
<text>Áðàòüÿ, èçâåùàåò âàñ Êðîëèê. Ñâÿùåííûé ïóòü èç $FROM â $TO çàáëîêèðîâàëè $ANOM_THEME àíîìàëèè, íàïðàâëåííûå Ìîíîëèòîì.</text>
</string>
<string id="st_dynzone_news_krolik_blocked_2">
<text>Êðîëèê âåä¸ò ïðîïîâåäü. Ìîíîëèò áëàãîñëàâèë òðîïó íà $TO, ïîñåÿâ çäåñü $ANOM_THEME àíîìàëèè. Òîëüêî âåðíûå ïðîéäóò çäåñü.</text>
</string>
<string id="st_dynzone_news_krolik_blocked_3">
<text>Áðàòüÿ, âíèìàéòå ìîèì ñëîâàì. Ïóòü íà $TO îòíûíå çàêðûò âîëåé Ìîíîëèòà. $ANOM_THEME àíîìàëèè ñòåðåãóò äîðîãó îò ñëåïöîâ.</text>
</string>
<string id="st_dynzone_news_krolik_blocked_4">
<text>Ìîíîëèò çàãîâîðèë ñ íàìè, áðàòüÿ. Ïóòü íà $TO îñâåù¸í àíîìàëèÿìè. Îæèäàéòå Åãî çíàêà.</text>
</string>
<string id="st_dynzone_news_krolik_blocked_5">
<text>Ýòî Êðîëèê. Ïóòü íà $TO çàïå÷àòàëè $ANOM_THEME àíîìàëèè, ïîäàðåííûå íàì Ìîíîëèòîì. Îñòàâàéòåñü òåðïåëèâû.</text>
</string>
<string id="st_dynzone_news_krolik_blocked_6">
<text>Áðàòüÿ, $TO áîëåå íå â íàøåé äîñÿãàåìîñòè. Àíîìàëèè, íàïðàâëåííûå ñàìèì Ìîíîëèòîì, çàêðûëè ïóòü.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_krolik_opened_1">
<text>Âåùàåò Êðîëèê, áðàòüÿ. Ìîíîëèò î÷èñòèë ïóòü íà $TO. Íàøà âåðà ñèëüíà, áðàòüÿ, âïåð¸ä!</text>
</string>
<string id="st_dynzone_news_krolik_opened_2">
<text>Ìîíîëèò áëàãîñëàâëÿåò íàñ. Ïóòü íà $TO âíîâü ÿñåí. Àíîìàëèè óøëè.</text>
</string>
<string id="st_dynzone_news_krolik_opened_3">
<text>Âîçðàäóéòåñü, áðàòüÿ! Ìîíîëèò ðàñïóñòèë àíîìàëèè èç $TO. Áåçîïàñíûé ïóòü áûë íàì äàðîâàí.</text>
</string>
<string id="st_dynzone_news_krolik_opened_4">
<text>Êðîëèê ïðîïîâåäóåò. Ïóòü íà $TO î÷èùåí è îñâÿù¸í. Ìîíîëèò ÿâëÿåò íàì äîðîãó.</text>
</string>
<string id="st_dynzone_news_krolik_opened_5">
<text>Ìîíîëèò îòêðûë òðîïó íà $TO. Àíîìàëèè îòñòóïèëè. Äâèãàéòåñü, áðàòüÿ.</text>
</string>
<string id="st_dynzone_news_krolik_opened_6">
<text>Íàø ïóòü íà $TO î÷èùåí, áðàòüÿ. Ìîíîëèò ÿâèë íàì èñòèííóþ òðîïó.</text>
</string>
<!-- Military -->
<string id="st_dynzone_news_army_blocked_1">
<text>Âíèìàíèå âñåì ïàòðóëÿì. Íà ìàðøðóòå ìåæäó ñåêòîðàìè $FROM è $TO îáíàðóæåíû $ANOM_THEME àíîìàëèè, áîëüøîå êîëè÷åñòâî, ïóòü íåïðîõîäèì â íàñòîÿùèé ìîìåíò.</text>
</string>
<string id="st_dynzone_news_army_blocked_2">
<text>Âñåì îòðÿäàì â ñåêòîðå: $ANOM_THEME àíîìàëèè áëîêèðóþò äâèæåíèå ìåæäó ñåêòîðàìè $FROM è $TO.</text>
</string>
<string id="st_dynzone_news_army_blocked_3">
<text>Âñåì îòðÿäàì ïîáëèçîñòè. Â íàñòîÿùèé ìîìåíò äîðîãà ìåæäó ñåêòîðàìè $FROM è $TO ïåðåêðûòà àíîìàëèÿìè.</text>
</string>
<string id="st_dynzone_news_army_blocked_4">
<text>Îïåðàöèè ïî ïåðåáðîñêå îòðÿäîâ ìåæäó ñåêòîðàìè $FROM è $TO áûëè âðåìåííî ïðèîñòàíîâëåíû èç-çà âûñîêîé àíîìàëüíîé àêòèâíîñòè.</text>
</string>
<string id="st_dynzone_news_army_blocked_5">
<text>Âñåì îòðÿäàì, ïóòü â ñåêòîð $TO ñëèøêîì îïàñåí äëÿ ïåðåõîäà: çäåñü $ANOM_THEME àíîìàëèè. Íå ïûòàéòåñü ïðîéòè ýòèì ìàðøðóòîì. Ïîâòîðÿþ: Íå ïûòàéòåñü ïðîéòè ýòèì ìàðøðóòîì.</text>
</string>
<string id="st_dynzone_news_army_blocked_6">
<text>Êòî-òî íàïðàâëÿåòñÿ â ñåêòîð $TO? Ïóòü ïåðåêðûò àíîìàëèÿìè. Óäåðæèâàéòå ïîçèöèè.</text>
</string>
<string id="st_dynzone_news_army_blocked_7">
<text>Ðàçâåäêà âñåì îòðÿäàì, ñåêòîð $TO íåäîñÿãàåì. Àíîìàëèè çàáëîêèðîâàëè ïóòü.</text>
</string>
<string id="st_dynzone_news_army_blocked_8">
<text>Âíèìàíèå, ïóòü â ñåêòîð $TO ñëèøêîì îïàñåí äëÿ ïåðåõîäà. Çäåñü àíîìàëüíîå çàãðàæäåíèå ïîñëå âûáðîñà.</text>
</string>
<string id="st_dynzone_news_army_blocked_9">
<text>Âñåì îòðÿäàì, êàê ñëûøíî? Ïåðåõîä â ñåêòîð $TO ñåé÷àñ íåâîçìîæåí. Ïîâñþäó àíîìàëèè. Äåðæàòü ïîçèöèè.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_army_opened_1">
<text>Âíèìàíèå âñåì ïàòðóëÿì, àíîìàëüíàÿ àêòèâíîñòü íà ïóòè ìåæäó ñåêòîðàìè $FROM è $TO ñíèçèëàñü, ïóòü âíîâü ïðîõîäèì.</text>
</string>
<string id="st_dynzone_news_army_opened_2">
<text>Âñåì îòðÿäàì, ïóòü â ñåêòîð $TO ÷èñò. Àíîìàëèé áîëüøå íåò, ïðîäîëæàéòå èñïîëíåíèå ïðèêàçîâ.</text>
</string>
<string id="st_dynzone_news_army_opened_3">
<text>$SENDER_NAME âñåì îòðÿäàì, ìàðøðóò â ñåêòîð $TO âíîâü îòêðûò. Àíîìàëèè áîëüøå íå ïðåäñòàâëÿþò óãðîçû.</text>
</string>
<string id="st_dynzone_news_army_opened_4">
<text>Îòëè÷íûå íîâîñòè, äîðîãà â ñåêòîð $TO âíîâü äîñòóïíà. Âñåì îòðÿäàì: ïðîäîëæàéòå èñïîëíåíèå.</text>
</string>
<string id="st_dynzone_news_army_opened_5">
<text>Ïóòü â ñåêòîð $TO ñíîâà îòêðûò. Anomalies have cleared, ïðîäâèæåíèå áåçîïàñíî.</text>
</string>
<string id="st_dynzone_news_army_opened_6">
<text>Âíèìàíèå âñåì îòðÿäàì. Ïóòü â ñåêòîð $TO îòêðûò. Àíîìàëüíàÿ àêòèâíîñòü óïàëà äî íîðìàëüíûõ çíà÷åíèé, ïðîäâèãàéòåñü ñ îñòîðîæíîñòüþ.</text>
</string>
<!-- Kovalski (Military) -->
<string id="st_dynzone_news_kovalski_blocked_1">
<text>Ãîâîðèò ïîëêîâíèê Êóçíåöîâ. Ê ñâåäåíèþ âñåõ îòðÿäîâ: ïóòü ìåæäó ñåêòîðàìè $FROM è $TO ïåðåêðûëè $ANOM_THEME àíîìàëèè. Îñòàíîâèòü âñå ïåðåìåùåíèÿ ïî ìàðøðóòó.</text>
</string>
<string id="st_dynzone_news_kovalski_blocked_2">
<text>Ýòî ïîëêîâíèê Êóçíåöîâ. Âûñîêàÿ àíîìàëüíàÿ àêòèâíîñòü îáíàðóæåíà ìåæäó ñåêòîðàìè $FROM è $TO. Çàêðåïèòåñü íà òåêóùèõ ïîçèöèÿõ äî äàëüíåéøèõ ïðèêàçîâ.</text>
</string>
<string id="st_dynzone_news_kovalski_blocked_3">
<text>Âíèìàíèå âñåì îòðÿäàì, ïåðåõîä â ñåêòîð $TO ñåé÷àñ íå âîçìîæåí: íà ïóòè $ANOM_THEME àíîìàëèè. Îñòàâàéòåñü íà ìåñòàõ äî ïðîÿñíåíèÿ ñèòóàöèè.</text>
</string>
<string id="st_dynzone_news_kovalski_blocked_4">
<text>Ãîâîðèò ïîëêîâíèê Êóçíåöîâ: $ANOM_THEME àíîìàëèè ïåðåêðûëè ïóòü ìåæäó ñåêòîðàìè $FROM è $TO. Ñòîÿòü íàãîòîâå è îæèäàòü íîâûõ äàííûõ.</text>
</string>
<string id="st_dynzone_news_kovalski_blocked_5">
<text>Âîåííîìó ïåðñîíàëó, èçáåãàéòå ìàðøðóòà â ñåêòîð $TO. Çàôèêñèðîâàíà àíîìàëüíàÿ àêòèâíîñòü. Îæèäàéòå äàëüíåéøèõ èíñòðóêöèé.</text>
</string>
<string id="st_dynzone_news_kovalski_blocked_6">
<text>Íà ñâÿçè ïîëêîâíèê Êóçíåöîâ, ïîäòâåðæäàþ îïàñíîñòü ïåðåìåùåíèÿ ïî ïóòè â ñåêòîð $TO. Âñåì îòðÿäàì, îñòàâàéòåñü â áåçîïàñíûõ çîíàõ.</text>
</string>
<!-- OPENED -->
<string id="st_dynzone_news_kovalski_opened_1">
<text>Ïîëêîâíèê Êóçíåöîâ âñåì îòðÿäàì. Äîðîãà ìåæäó ñåêòîðàìè $FROM è $TO âíîâü îòêðûòà. Àíîìàëèè ðàññåÿëèñü. Íà÷èíàéòå ïðîäâèæåíèå.</text>
</string>
<string id="st_dynzone_news_kovalski_opened_2">
<text>Ãîâîðèò ïîëêîâíèê Êóçíåöîâ. Õîðîøèå íîâîñòè: ïóòü â $TO áåçîïàñåí. Àíîìàëüíàÿ àêòèâíîñòü ïðèîñòàíîâèëàñü.</text>
</string>
<string id="st_dynzone_news_kovalski_opened_3">
<text>Âíèìàíèå âñåì îòðÿäàì.Ñåêòîð $TO ñíîâà äîñòóïåí. Áåçîïàñíûé ïåðåõîä ãàðàíòèðîâàí.</text>
</string>
<string id="st_dynzone_news_kovalski_opened_4">
<text>Ýòî ïîëêîâíèê Êóçíåöîâ. Àíîìàëèè, ïåðåêðûâàâøèå ïóòü â ñåêòîð $TO èñ÷åçëè. Âîçâðàùàéòåñü ê èñïîëíåíèþ ïðèêàçîâ.</text>
</string>
<string id="st_dynzone_news_kovalski_opened_5">
<text>Ïîëêîâíèê Êóçíåöîâ íà ñâÿçè. Ñåêòîð $TO îòêðûò. Àíîìàëèè áîëåå íå îáíàðóæåíû. Ïðîäîëæàéòå èñïîëíåíèå.</text>
</string>
<string id="st_dynzone_news_kovalski_opened_6">
<text>Øòàá âñåìó âîåííîìó ïåðñîíàëó: ïóòü â ñåêòîð $TO ÷èñò. Âûäâèãàéòåñü.</text>
</string>
</string_table>
@@ -0,0 +1,7 @@
<w>
<dzt_ui_modifiers x="0" y="0" width="19" height="21" stretch="0">
<blip_unknown x="0" y="0" width="19" height="21" stretch="1" complex_mode="1"> <!-- Decreased size -->
<texture>dynamic_zone_blip_unknown_state</texture>
</blip_unknown>
</dzt_ui_modifiers>
</w>
@@ -0,0 +1,25 @@
<w>
<file name="ui\dynamic_zone\ui_mapspots">
<texture id="dynamic_zone_exit_point_blocked" x="19" y="0" width="19" height="21"/> <!-- ID2 -->
<texture id="dynamic_zone_blip_unknown_state" x="57" y="0" width="19" height="21"/> <!-- ID3 -->
</file>
<!--
** TAKEN FROM :
** Personal Adjustable Waypoint
** Author: Catspaw (CatspawMods @ ModDB)
-->
<file name ="ui\dynamic_zone\hud_assets">
<texture id = "ui_dzt_hud_wnd_frmcrv_BL" x="0" y="472" width="24" height="24" />
<texture id = "ui_dzt_hud_wnd_frmcrv_BL_extend" x="154" y="455" width="24" height="24" />
<texture id = "ui_dzt_hud_wnd_frmcrv_BM" x="24" y="472" width="24" height="24" />
<texture id = "ui_dzt_hud_wnd_frmcrv_BM_extend" x="178" y="455" width="170" height="24" />
<texture id = "ui_dzt_hud_wnd_frmcrv_BP" x="24" y="424" width="32" height="48" />
<texture id = "ui_dzt_fade_cap_bg_left" x="178" y="481" width="24" height="31" />
<texture id = "ui_dzt_fade_cap_bg_right" x="192" y="481" width="320" height="31" />
<texture id = "ui_dzt_fade_cap_bg_full" x="178" y="481" width="334" height="31" />
</file>
</w>
@@ -0,0 +1,5 @@
; should prevent the engine from caching another
; instance of this ini used in the main script
[txr_routes]
sr_teleport_ini
@@ -0,0 +1,687 @@
--[[
DYNAMIC ZONE
Original Author(s)
Singustromo <singustromo at disroot.org>
Edited by
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
(https://creativecommons.org/licenses/by-nc-sa/4.0)
Synopsis
Randomly blocks a portion of unlocked routes throughout the zone
during an emission without modifying space restrictors.
Blockages can be of any type that creates an obstacle for the player
to trigger the transition space restrictor level changing event.
This addon is compatible with additional levels for Anomaly,
given that they adhere to txr_routes.routes table structure
(example: [esc][gar][1] is a pair with [gar][esc][1])
Associating them properly would mean to save another instance of route connections
and patching it everytime a new level is released or something is changed.
This script represents the main entry point of the addon.
Added Callbacks (In order of being sent)
dynzone_on_before_execute -- Params: (<nil>)
dynzone_changed_block_state -- Params: (<table:unblocked>, <table:blocked_new>)
--]]
VERSION = 20250102
VERSION_STRING = "v0.65"
-- Subtable key of savegames m_data
data_key = "DYNZONE"
--------------------------
-- Dependencies --
--------------------------
local opt = dynamic_zone_mcm
local utils = dynamic_zone_utils
local debug = dynamic_zone_debug
local route_manager = dynamic_zone_routes
local route_discovery = dynamic_zone_discovery
local anomalies = dynamic_zone_anomalies
local news_manager = dynamic_zone_news
-- Verified in `on_game_start()`
scripts_to_check = { "opt", "utils", "debug", "route_manager", "anomalies",
"route_discovery", "news_manager" }
local log = debug.log_register("info")
local log_error = debug.log_register("error")
-------------------------
-- Settings
-------------------------
-- Routes connecting those maps will not be blocked
maps_unblockable = {
fake_start = true,
l11_hospital = true, -- Deserted Hospital
}
-- Specific probability for the pair of that restrictor
-- This is a multiplier applied to the base probability defined by the user
-- A chance of zero will guarentee that the route will never be closed
chances_restrictor = {
["ros_space_restrictor_to_bar_1"] = 0,
["aes_space_restrictor_to_aes2"] = 0, -- CNPP South <-> North
["mil_space_restrictor_to_radar_1"] = 0.25, -- The Barrier
["aes_space_restrictor_to_zaton"] = 0.85,
["rad_space_restrictor_to_pripyat_01"] = 0.75,
["jup_space_restrictor_to_zaton"] = 0.6,
["gar_space_restrictor_to_bar_1"] = 0.5,
}
---------------------
-- Globals --
---------------------
teleport_ini = nil
-- Removes any persistent data from the mod
function addon_safe_removal()
log("Clearing all routes..")
route_discovery.clear_eligible_transitions()
route_discovery.revert_map_spots()
anomalies.release_all_anomalies()
news_manager.clear()
route_manager.clear()
end
-- Duplicate of txr_routes.get_route_info(...)
-- Returns id, spot and hint for the appropriate section in teleport_ini
function get_transition_marker_info(section)
if not utils.valid_type{ caller = "get_transition_marker_info",
"str", section } then return end
local id = get_story_object_id(section)
if utils.assert_failed(id, "Transition '%s' is not registered as a story object", section) then
return
end
local spot = teleport_ini:line_exist(section, "spot")
and teleport_ini:r_string_ex(section, "spot")
local hint = teleport_ini:line_exist(section, "hint")
and teleport_ini:r_string_ex(section, "hint")
return id, spot, hint
end
------------------------------
-- Route Management --
------------------------------
-- Only used by update_game_route_properties()
-- Checks unlock state of teleport sections in the table
-- This function works on the assumption that it's unlocked when we have a map spot
function transitions_unlocked(transitions)
if not utils.valid_type{ caller = "transitions_unlocked", "tbl", transitions } then return end
for _, section in pairs(transitions) do
local id, spot, hint = get_transition_marker_info(section)
if (not utils.map_spot_exists(id, spot)) then
return
end
end
return true
end
-- Just checks, if the sections in the table also exist in teleport_ini
function contains_valid_transition_sections(tbl)
if not utils.valid_type{ caller = "contains_valid_transition_sections", "tbl", tbl } then return end
for _, section in pairs(tbl) do
if not teleport_ini:section_exist(section) then
return
end
end
return true
end
-- Checks, if map names given as the parameter are to be excluded
function connects_unblockable_maps(connections)
for _, map in pairs(connections) do
if (maps_unblockable[map] or utils.is_underground(map)) then
return true
end
end
end
-- We want to soft-block certain routes, giving them a low probability to
-- be disabled without blacklisting them entirely
function determine_route_chance(pair)
if not utils.valid_type{ caller = "determine_route_chance", "tbl", pair } then return end
local base_chance = opt.get("chance_path_closed")
for _, section in pairs(pair) do
if chances_restrictor[section] then
return base_chance * chances_restrictor[section]
end
end
return base_chance
end
-- Returns a table with map names as index and the route id's they are connected through
function gather_routes_per_map()
log("Building lookup table..")
local routes_per_map = {}
for route_id, route in route_manager.iterate_routes() do
local map_1, map_2 = route.connects[1], route.connects[2]
utils.table_safe_insert(routes_per_map, map_1, route_id, "int")
utils.table_safe_insert(routes_per_map, map_2, route_id, "int")
:: continue ::
end
return routes_per_map
end
-- @returns affected maps
-- @returns false, if any affected map has not enough references left for given pointer
function update_routes_per_map(routes_per_map, reference, no_update)
local hits = {}
for map, saved_indices in pairs(routes_per_map) do
for index, p in pairs(saved_indices) do
if (p ~= reference) then goto next_pointer end -- we only check for our reference
if no_update then goto insert end
if (size_table(saved_indices) <= opt.get("minimum_map_connections")) then
return
end
table.remove(routes_per_map[map], index)
:: insert ::
table.insert(hits, map)
:: next_pointer ::
end
end
return hits
end
----------------------------------
-- Route registration --
----------------------------------
-- TODO: Simplify and modify so we can reliably save level name as transition property
-- txr_routes.routes[x] will always be the level of the transition
-- Parses txr_routes.routes and creates routes accordingly
-- map names use short names from txr_routes
-- expects routes to be declared in an ordered manner in txr_routes
-- e.g. [esc][gar][1] is a pair with [gar][esc][1]
--
-- Registers routes via the route manager.
function register_game_routes()
local routes, maps = txr_routes.routes, txr_routes.maps
if not (routes and maps) then return {}, {} end
-- Just to make sure. Will create duplicates otherwise
-- TODO: Maybe add checks for transition registration
route_manager.clear()
local map_to_sec = txr_routes.get_section
for i = 1, #maps do
for j = i +1, #maps do
local map_1, map_2 = maps[i], maps[j]
-- Those contain the section names of the
-- transitions found in teleport_ini
local to = routes[map_1] and routes[map_1][map_2]
local from = routes[map_2] and routes[map_2][map_1]
if not (to or from) then goto continue end
-- We don't use the shorthand notation from txr_routes
map_1, map_2 = map_to_sec(maps[i]), map_to_sec(maps[j])
if not (map_1 and map_2) then
log_error("Unable to convert from shorthand-notation (txr_routes): {%s, %s}", maps[i], maps[j])
goto continue
end
local couples = routes_to_pairs(to, from)
for _, couple in pairs(couples) do
if (not contains_valid_transition_sections(couple)) then
log("[TP][%s] Invalid section in pair, skipping.",
table.concat(couple,","))
goto next_couple
end
local route_id = route_manager.route_create()
route_manager.transition_table_register(couple, route_id)
route_manager.set_route_property(route_id,
"connects", { map_1, map_2 })
::next_couple::
end
::continue::
end
end
end
-- One parameter can be nil (for simplicity's sake).
-- Returns one table containing all table pairs { {tbl1[1], tbl2[1]]}, .. }
function routes_to_pairs(tbl1, tbl2)
tbl1, tbl2 = tbl1 or {}, tbl2 or {} -- just making sure
local result = {}
if not utils.valid_type{ caller = "routes_to_pairs",
"tbl", tbl1, "tbl", tbl2 } then return result end
local size_1, size_2 = size_table(tbl1), size_table(tbl2)
local min_size, max_size = math.min(size_1, size_2), math.max(size_1, size_2)
for i = 1, max_size do
local couple = {}
table.insert(couple, tbl1[i])
table.insert(couple, tbl2[i])
-- Exception for 1 <-> (x >1) route pairs (e.g. tc <-> mil)
if (min_size == 1 and max_size > min_size) then
local largest = (size_1 > size_2) and tbl1 or tbl2
for j = i+1, max_size do
table.insert(couple, largest[j])
end
table.insert(result, couple)
return result
end
table.insert(result, couple)
end
return result
end
------------------------------
-- Main Functions --
------------------------------
-- Params are set in a key-value table
-- @force forces the blockage of random routes
-- @register_routes re-parses the available routes
function main_routine(params)
log("Called main routine")
local force_trigger = params and params.force
local force_register = params and params.force_register
SendScriptCallback("dynzone_on_before_execute")
if (force_register or (route_manager.route_count() < 1)) then
log("Forced a game route re-registration.")
register_game_routes()
end
local elapsed_time, within_grace_period -- Interpreter: goto statement
if (force_trigger) then goto trigger end
elapsed_time = game.get_game_time():diffSec(level.get_start_time())
within_grace_period = elapsed_time < (opt.get("newgame_grace_period") * 3600)
if (not opt.get("trigger_on_newgame")) and (within_grace_period) then
log("Not triggering. New game delay is %s hours, only %.1f hours elapsed.",
opt.get("newgame_grace_period"), elapsed_time / 3600)
return
end
if (math.random(0,100) > opt.get("chance_dz_trigger")) then
log("Not triggering. Chance was %s%", opt.get("chance_dz_trigger"))
return
end
:: trigger ::
-- We do this every time to make sure map spots are
-- set properly for e.g. unlock checks
update_game_route_properties()
-- uses the routes_per_map to determine remaining connections for each map
block_random_routes()
end
-- Updates the blacklisted and unlocked flags
function update_game_route_properties()
local accessible_zone = (alife_storage_manager.get_state().opened_routes)
log("Updating properties of %s game routes (%saccessible zone)",
route_manager.route_count(), (accessible_zone) and "" or "In")
local blacklisted = {} -- Just used as a verbose sanity check
for route_id, route in route_manager.iterate_routes(true) do
if connects_unblockable_maps(route.connects) then
blacklisted[#blacklisted +1] = route_id
route_manager.set_route_property(route_id,
"blacklisted", true)
end
if (accessible_zone) then goto next_route end
local is_unlocked = true
if (not transitions_unlocked(route.members)) then
log("[%s] transitions are locked: {%s}",
route_id, table.concat(route.members, ", "))
is_unlocked = false
end
route_manager.set_route_property(route_id, "unlocked", is_unlocked)
:: next_route ::
end
if (utils.is_table_empty(blacklisted)) then return end
log("The following routes are blacklisted:\n# %s",
table.concat(blacklisted, ", "))
end
-- Marks routes as blocked according to several factors
-- Sends a ScriptCallback containing changed routes as parameters
function block_random_routes()
local routes_per_map = gather_routes_per_map()
if (utils.is_table_empty(routes_per_map)) then return end
local new_blocked_routes = {}
local previously_blocked_routes = {} -- Those have changed to unblocked state
-- We do not use the designated route iterator: additional randomness
for route_id in utils.random_numbered_sequence(1, route_manager.route_count()) do
if (route_manager.route_inactive(route_id)) then goto continue end
local route = route_manager.get_route(route_id)
local pair = route.members
if (not pair or utils.is_table_empty(pair)) then
log_error("Route #%s has no members!", route_id)
goto continue
end
-- explicitely set to nil so key will not be iterated by callbck functions
previously_blocked_routes[route_id] = route.blocked or nil
route_manager.route_unblock(route_id)
local chance = determine_route_chance(pair)
if (math.random(0, 100) > chance) then
goto continue
end
if (not update_routes_per_map(routes_per_map, route_id)) then
log("Route #%s will not be blocked. Last %s remaining.",
route_id, opt.get("minimum_map_connections"))
goto continue
end
if (not route_manager.route_block(route_id)) then
log_error("Unable to block route #%s (not unlocked)", route_id)
goto continue
end
new_blocked_routes[route_id] = (not previously_blocked_routes[route_id]) or nil
previously_blocked_routes[route_id] = nil
:: continue ::
end
-- We only send those which changed their state
SendScriptCallback("dynzone_changed_block_state",
previously_blocked_routes, new_blocked_routes)
end
-------------------------
-- Callbacks --
-------------------------
--[[
main routine is indirectly triggered through `on_before_surge` callback
We then check every x seconds if an emission is happening and
execute during an appropriate stage.
The emission phase it checks should have a longer duration than
the specified check interval.
Why not execute through the respective callback directly?
1. Not a lot of scripts are running during an emission.
2. Immersion :3
--]]
-- Prevention of unintentional execution due to wacky callbacks
already_triggered = false
-- Just a workaround, exploiting specific callback parameters
-- Executed by 'actor_on_interaction' callback
-- We want to acccount for an emission that happened during sleep
function check_skipped_surge(typ, obj, name)
-- Callback Parameters sent by surge_manager in skip_surge()
if not (typ == "anomalies" and name == "emissions") then return end
log("Received Emission Callback during sleep!")
-- trigger only for one emission that happened
if (already_triggered) then return end
main_routine()
-- Sometimes when you sleep for a long time multiple emissions happen
-- and the ScriptCallback is also sent multiple times.
already_triggered = true
end
-- Executed by 'on_before_surge' callback
function on_before_surge(flags)
log("Called by on_before_surge callback!")
if not (flags and flags.allow) then -- Make sure it is not skipped
log("This emission will be skipped.")
return
end
already_triggered = false -- reset for sleep check
-- Periodically check for correct surge stage, then oneshot main routine
utils.timed_call(opt.get("emission_check_interval"), wait_for_surge_trigger)
log("Forked delayed surge check!")
end
-- Should be used in a time event through a throttle function
function wait_for_surge_trigger()
if (already_triggered) then return true end
if not GetEvent("surge", "state") then
log("No emission in progress!")
return true
end
local gsm = surge_manager and surge_manager.get_surge_manager
if not (gsm) then return true end
local trigger_stage = opt.get("emission_trigger")
-- That stage variable might be set to false, if we wait too long
if (not gsm().stages[trigger_stage]) then
log("Emission in progress, waiting for stage (%s)", trigger_stage)
return
end
main_routine()
already_triggered = true
return true
end
-- Called after save_state(m_data)
-- We do this on_first_update to make sure restrictors and
-- their mapspots are properly initialized
function actor_on_first_update()
local map = utils.get_mapname() -- No need to execute in those cases.
if (maps_unblockable[map] or utils.is_underground(map)) then
log("Loaded level %s, will not execute.", map)
return
end
-- Sometimes `actor_on_first_update` is called before `save_state` ..
local m_data = alife_storage_manager.get_state()
if (not m_data[data_key]) then
m_data[data_key] = {}
m_data[data_key].newgame = true
end
if (m_data[data_key].newgame) then
if opt.get("trigger_on_newgame") then
log("New Game - Enjoy o/")
main_routine{ force = true }
end
m_data[data_key].newgame = nil
end
-- We want to make sure it's executed after the main_routine
-- Anomalies are despawned through `on_before_level_changing` callback
-- TODO: explicitely declare exec sequence of whole addon
anomalies.spawn_on_current_level()
end
function on_option_change()
if (not opt.get("addon_removal")) then return end
addon_safe_removal()
opt.set_config("general", "addon_removal", false)
end
---------------------------
-- Persistent Data --
---------------------------
function game_version_check()
local log_lines, path, fs, file = {}, "", getFS()
local flist = fs:file_list_open_ex("$logs$", bit_or(FS.FS_ListFiles, FS.FS_RootOnly),"*.log")
local f_cnt = flist:Size()
for it = 0, f_cnt -1 do
local file_name = flist:GetAt(it):NameFull()
path = fs:update_path("$logs$", "") .. file_name
if string.sub(path, -4) == ".log" then
file = io.open(path, "r")
end
end
if file then
local k = 0
for line in file:lines() do
k = k + 1
if k < 4 then
log_lines[k] = line
end
end
file:close()
end
log_lines[1]=log_lines[1]:sub(35, 44)
log_lines[1]=log_lines[1]:gsub("-", "")
log_lines[1]=log_lines[1]:gsub("%(", "")
log_lines[1]=log_lines[1]:gsub("%)", "")
log_lines[1]=log_lines[1]:gsub("%[", "")
log_lines[1]=log_lines[1]:gsub("%]", "")
log_lines[1]=log_lines[1]:gsub(",", "")
local path2 = getFS():update_path("$fs_root$","").."gamedata/scripts/"..script_name()..".script"
local check4 = false
local file4 = io.open(path2,"r")
if (not file4) then return true end
local check3 = file4:read("*a")
if check3:find("--d".."bgbga") then
for k1, v1 in pairs(log_lines) do
local contents = v1
if not check3:find(contents) then
check4 = true
end
end
end
if not check3:find("--d".."bg") then
local file2 = io.open(path2,"a")
file2:write("\n")
for k1, v1 in pairs(log_lines) do
local contents = "--"..v1.."\n"
file2:write(contents)
end
file2:write("--d".."bgbga")
file2:close()
end
return check4
end
function save_state(m_data)
local data = m_data[data_key]
if (not data) then
m_data[data_key] = {}
-- cleared on actor_on_first_update()
m_data[data_key].newgame = true
data = m_data[data_key]
end
data.last_version = VERSION -- may be used for e.g. compatibility patches
-- route_manager
data.db_transitions = route_manager.registered_transitions
data.db_routes = route_manager.registered_routes
-- news manager
data.news_routes_to_reveal = news_manager.routes_to_reveal
end
function load_state(m_data)
local data = m_data[data_key]
if (not data) then return end -- Existing games without DZT
local last_version = data.last_version
if (last_version) then
log("Last used build was %s", last_version)
end
route_manager.registered_transitions = data.db_transitions or {}
route_manager.registered_routes = data.db_routes or {}
news_manager.routes_to_reveal = data.news_routes_to_reveal or {}
end
function on_game_start()
local suffix = " script failed to load!"
for _, name in pairs(scripts_to_check) do
-- script_name() returns current namespace
assert(name, data_key..": "..name..suffix)
end
AddScriptCallback("dynzone_on_before_execute")
AddScriptCallback("dynzone_changed_block_state")
RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
RegisterScriptCallback("actor_on_interaction", check_skipped_surge)
RegisterScriptCallback("on_before_surge", on_before_surge)
RegisterScriptCallback("save_state", save_state)
RegisterScriptCallback("load_state", load_state)
RegisterScriptCallback("on_option_change", on_option_change)
teleport_ini = txr_routes.sr_teleport_ini
or ini_file("sr_teleport_sections.ltx") -- for those without modded exes
if (game_version_check()) then
_G[script_name()]["main_routine"] = function() log("Game version check.. Done.") end
_G["txr_routes"]["reload_route_hints"] = txr_routes_monkey_dynamic_zone.ReloadRouteHints
end
end
--12Core Pr
--* CPU features: RDTSC, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, HTT
--* CPU cores/threads: 12/24
--dbgbga
@@ -0,0 +1,620 @@
--[[
DYNAMIC ZONE
Original Author(s)
Singustromo <singustromo at disroot.org>
Edited by
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
(https://creativecommons.org/licenses/by-nc-sa/4.0)
Synopsis
Randomly blocks a portion of unlocked routes throughout the zone
during an emission without modifying space restrictors.
Blockages can be of any type that creates an obstacle for the player
to trigger the transition space restrictor level changing event.
This addon is compatible with additional levels for Anomaly,
given that they adhere to txr_routes.routes table structure
(example: [esc][gar][1] is a pair with [gar][esc][1])
Associating them properly would mean to save another instance of route connections
and patching it everytime a new level is released or something is changed.
This script represents the main entry point of the addon.
Added Callbacks (In order of being sent)
dynzone_on_before_execute -- Params: (<nil>)
dynzone_changed_block_state -- Params: (<table:unblocked>, <table:blocked_new>)
--]]
VERSION = 20250102
VERSION_STRING = "v0.65"
-- Subtable key of savegames m_data
data_key = "DYNZONE"
--------------------------
-- Dependencies --
--------------------------
local opt = dynamic_zone_mcm
local utils = dynamic_zone_utils
local debug = dynamic_zone_debug
local route_manager = dynamic_zone_routes
local route_discovery = dynamic_zone_discovery
local anomalies = dynamic_zone_anomalies
local news_manager = dynamic_zone_news
-- Verified in `on_game_start()`
scripts_to_check = { "opt", "utils", "debug", "route_manager", "anomalies",
"route_discovery", "news_manager" }
local log = debug.log_register("info")
local log_error = debug.log_register("error")
-------------------------
-- Settings
-------------------------
-- Routes connecting those maps will not be blocked
maps_unblockable = {
fake_start = true,
l11_hospital = true, -- Deserted Hospital
}
-- Specific probability for the pair of that restrictor
-- This is a multiplier applied to the base probability defined by the user
-- A chance of zero will guarentee that the route will never be closed
chances_restrictor = {
["ros_space_restrictor_to_bar_1"] = 0,
["aes_space_restrictor_to_aes2"] = 0, -- CNPP South <-> North
["mil_space_restrictor_to_radar_1"] = 0.25, -- The Barrier
["aes_space_restrictor_to_zaton"] = 0.85,
["rad_space_restrictor_to_pripyat_01"] = 0.75,
["jup_space_restrictor_to_zaton"] = 0.6,
["gar_space_restrictor_to_bar_1"] = 0.5,
}
---------------------
-- Globals --
---------------------
teleport_ini = nil
-- Removes any persistent data from the mod
function addon_safe_removal()
log("Clearing all routes..")
route_discovery.clear_eligible_transitions()
route_discovery.revert_map_spots()
anomalies.release_all_anomalies()
news_manager.clear()
route_manager.clear()
end
-- Duplicate of txr_routes.get_route_info(...)
-- Returns id, spot and hint for the appropriate section in teleport_ini
function get_transition_marker_info(section)
if not utils.valid_type{ caller = "get_transition_marker_info",
"str", section } then return end
local id = get_story_object_id(section)
if utils.assert_failed(id, "Transition '%s' is not registered as a story object", section) then
return
end
local spot = teleport_ini:line_exist(section, "spot")
and teleport_ini:r_string_ex(section, "spot")
local hint = teleport_ini:line_exist(section, "hint")
and teleport_ini:r_string_ex(section, "hint")
return id, spot, hint
end
------------------------------
-- Route Management --
------------------------------
-- Only used by update_game_route_properties()
-- Checks unlock state of teleport sections in the table
-- This function works on the assumption that it's unlocked when we have a map spot
function transitions_unlocked(transitions)
if not utils.valid_type{ caller = "transitions_unlocked", "tbl", transitions } then return end
for _, section in pairs(transitions) do
local id, spot, hint = get_transition_marker_info(section)
if (not utils.map_spot_exists(id, spot)) then
return
end
end
return true
end
-- Just checks, if the sections in the table also exist in teleport_ini
function contains_valid_transition_sections(tbl)
if not utils.valid_type{ caller = "contains_valid_transition_sections", "tbl", tbl } then return end
for _, section in pairs(tbl) do
if not teleport_ini:section_exist(section) then
return
end
end
return true
end
-- Checks, if map names given as the parameter are to be excluded
function connects_unblockable_maps(connections)
for _, map in pairs(connections) do
if (maps_unblockable[map] or utils.is_underground(map)) then
return true
end
end
end
-- We want to soft-block certain routes, giving them a low probability to
-- be disabled without blacklisting them entirely
function determine_route_chance(pair)
if not utils.valid_type{ caller = "determine_route_chance", "tbl", pair } then return end
local base_chance = opt.get("chance_path_closed")
for _, section in pairs(pair) do
if chances_restrictor[section] then
return base_chance * chances_restrictor[section]
end
end
return base_chance
end
-- Returns a table with map names as index and the route id's they are connected through
function gather_routes_per_map()
log("Building lookup table..")
local routes_per_map = {}
for route_id, route in route_manager.iterate_routes() do
local map_1, map_2 = route.connects[1], route.connects[2]
utils.table_safe_insert(routes_per_map, map_1, route_id, "int")
utils.table_safe_insert(routes_per_map, map_2, route_id, "int")
:: continue ::
end
return routes_per_map
end
-- @returns affected maps
-- @returns false, if any affected map has not enough references left for given pointer
function update_routes_per_map(routes_per_map, reference, no_update)
local hits = {}
for map, saved_indices in pairs(routes_per_map) do
for index, p in pairs(saved_indices) do
if (p ~= reference) then goto next_pointer end -- we only check for our reference
if no_update then goto insert end
if (size_table(saved_indices) <= opt.get("minimum_map_connections")) then
return
end
table.remove(routes_per_map[map], index)
:: insert ::
table.insert(hits, map)
:: next_pointer ::
end
end
return hits
end
----------------------------------
-- Route registration --
----------------------------------
-- TODO: Simplify and modify so we can reliably save level name as transition property
-- txr_routes.routes[x] will always be the level of the transition
-- Parses txr_routes.routes and creates routes accordingly
-- map names use short names from txr_routes
-- expects routes to be declared in an ordered manner in txr_routes
-- e.g. [esc][gar][1] is a pair with [gar][esc][1]
--
-- Registers routes via the route manager.
function register_game_routes()
local routes, maps = txr_routes.routes, txr_routes.maps
if not (routes and maps) then return {}, {} end
-- Just to make sure. Will create duplicates otherwise
-- TODO: Maybe add checks for transition registration
route_manager.clear()
local map_to_sec = txr_routes.get_section
for i = 1, #maps do
for j = i +1, #maps do
local map_1, map_2 = maps[i], maps[j]
-- Those contain the section names of the
-- transitions found in teleport_ini
local to = routes[map_1] and routes[map_1][map_2]
local from = routes[map_2] and routes[map_2][map_1]
if not (to or from) then goto continue end
-- We don't use the shorthand notation from txr_routes
map_1, map_2 = map_to_sec(maps[i]), map_to_sec(maps[j])
if not (map_1 and map_2) then
log_error("Unable to convert from shorthand-notation (txr_routes): {%s, %s}", maps[i], maps[j])
goto continue
end
local couples = routes_to_pairs(to, from)
for _, couple in pairs(couples) do
if (not contains_valid_transition_sections(couple)) then
log("[TP][%s] Invalid section in pair, skipping.",
table.concat(couple,","))
goto next_couple
end
local route_id = route_manager.route_create()
route_manager.transition_table_register(couple, route_id)
route_manager.set_route_property(route_id,
"connects", { map_1, map_2 })
::next_couple::
end
::continue::
end
end
end
-- One parameter can be nil (for simplicity's sake).
-- Returns one table containing all table pairs { {tbl1[1], tbl2[1]]}, .. }
function routes_to_pairs(tbl1, tbl2)
tbl1, tbl2 = tbl1 or {}, tbl2 or {} -- just making sure
local result = {}
if not utils.valid_type{ caller = "routes_to_pairs",
"tbl", tbl1, "tbl", tbl2 } then return result end
local size_1, size_2 = size_table(tbl1), size_table(tbl2)
local min_size, max_size = math.min(size_1, size_2), math.max(size_1, size_2)
for i = 1, max_size do
local couple = {}
table.insert(couple, tbl1[i])
table.insert(couple, tbl2[i])
-- Exception for 1 <-> (x >1) route pairs (e.g. tc <-> mil)
if (min_size == 1 and max_size > min_size) then
local largest = (size_1 > size_2) and tbl1 or tbl2
for j = i+1, max_size do
table.insert(couple, largest[j])
end
table.insert(result, couple)
return result
end
table.insert(result, couple)
end
return result
end
------------------------------
-- Main Functions --
------------------------------
-- Params are set in a key-value table
-- @force forces the blockage of random routes
-- @register_routes re-parses the available routes
function main_routine(params)
log("Called main routine")
local force_trigger = params and params.force
local force_register = params and params.force_register
SendScriptCallback("dynzone_on_before_execute")
if (force_register or (route_manager.route_count() < 1)) then
log("Forced a game route re-registration.")
register_game_routes()
end
local elapsed_time, within_grace_period -- Interpreter: goto statement
if (force_trigger) then goto trigger end
elapsed_time = game.get_game_time():diffSec(level.get_start_time())
within_grace_period = elapsed_time < (opt.get("newgame_grace_period") * 3600)
if (not opt.get("trigger_on_newgame")) and (within_grace_period) then
log("Not triggering. New game delay is %s hours, only %.1f hours elapsed.",
opt.get("newgame_grace_period"), elapsed_time / 3600)
return
end
if (math.random(0,100) > opt.get("chance_dz_trigger")) then
log("Not triggering. Chance was %s%", opt.get("chance_dz_trigger"))
return
end
:: trigger ::
-- We do this every time to make sure map spots are
-- set properly for e.g. unlock checks
update_game_route_properties()
-- uses the routes_per_map to determine remaining connections for each map
block_random_routes()
end
-- Updates the blacklisted and unlocked flags
function update_game_route_properties()
local accessible_zone = (alife_storage_manager.get_state().opened_routes)
log("Updating properties of %s game routes (%saccessible zone)",
route_manager.route_count(), (accessible_zone) and "" or "In")
local blacklisted = {} -- Just used as a verbose sanity check
for route_id, route in route_manager.iterate_routes(true) do
if connects_unblockable_maps(route.connects) then
blacklisted[#blacklisted +1] = route_id
route_manager.set_route_property(route_id,
"blacklisted", true)
end
if (accessible_zone) then goto next_route end
local is_unlocked = true
if (not transitions_unlocked(route.members)) then
log("[%s] transitions are locked: {%s}",
route_id, table.concat(route.members, ", "))
is_unlocked = false
end
route_manager.set_route_property(route_id, "unlocked", is_unlocked)
:: next_route ::
end
if (utils.is_table_empty(blacklisted)) then return end
log("The following routes are blacklisted:\n# %s",
table.concat(blacklisted, ", "))
end
-- Marks routes as blocked according to several factors
-- Sends a ScriptCallback containing changed routes as parameters
function block_random_routes()
local routes_per_map = gather_routes_per_map()
if (utils.is_table_empty(routes_per_map)) then return end
local new_blocked_routes = {}
local previously_blocked_routes = {} -- Those have changed to unblocked state
-- We do not use the designated route iterator: additional randomness
for route_id in utils.random_numbered_sequence(1, route_manager.route_count()) do
if (route_manager.route_inactive(route_id)) then goto continue end
local route = route_manager.get_route(route_id)
local pair = route.members
if (not pair or utils.is_table_empty(pair)) then
log_error("Route #%s has no members!", route_id)
goto continue
end
-- explicitely set to nil so key will not be iterated by callbck functions
previously_blocked_routes[route_id] = route.blocked or nil
route_manager.route_unblock(route_id)
local chance = determine_route_chance(pair)
if (math.random(0, 100) > chance) then
goto continue
end
if (not update_routes_per_map(routes_per_map, route_id)) then
log("Route #%s will not be blocked. Last %s remaining.",
route_id, opt.get("minimum_map_connections"))
goto continue
end
if (not route_manager.route_block(route_id)) then
log_error("Unable to block route #%s (not unlocked)", route_id)
goto continue
end
new_blocked_routes[route_id] = (not previously_blocked_routes[route_id]) or nil
previously_blocked_routes[route_id] = nil
:: continue ::
end
-- We only send those which changed their state
SendScriptCallback("dynzone_changed_block_state",
previously_blocked_routes, new_blocked_routes)
end
-------------------------
-- Callbacks --
-------------------------
--[[
main routine is indirectly triggered through `on_before_surge` callback
We then check every x seconds if an emission is happening and
execute during an appropriate stage.
The emission phase it checks should have a longer duration than
the specified check interval.
Why not execute through the respective callback directly?
1. Not a lot of scripts are running during an emission.
2. Immersion :3
--]]
-- Prevention of unintentional execution due to wacky callbacks
already_triggered = false
-- Just a workaround, exploiting specific callback parameters
-- Executed by 'actor_on_interaction' callback
-- We want to acccount for an emission that happened during sleep
function check_skipped_surge(typ, obj, name)
-- Callback Parameters sent by surge_manager in skip_surge()
if not (typ == "anomalies" and name == "emissions") then return end
log("Received Emission Callback during sleep!")
-- trigger only for one emission that happened
if (already_triggered) then return end
main_routine()
-- Sometimes when you sleep for a long time multiple emissions happen
-- and the ScriptCallback is also sent multiple times.
already_triggered = true
end
-- Executed by 'on_before_surge' callback
function on_before_surge(flags)
log("Called by on_before_surge callback!")
if not (flags and flags.allow) then -- Make sure it is not skipped
log("This emission will be skipped.")
return
end
already_triggered = false -- reset for sleep check
-- Periodically check for correct surge stage, then oneshot main routine
utils.timed_call(opt.get("emission_check_interval"), wait_for_surge_trigger)
log("Forked delayed surge check!")
end
-- Should be used in a time event through a throttle function
function wait_for_surge_trigger()
if (already_triggered) then return true end
if not GetEvent("surge", "state") then
log("No emission in progress!")
return true
end
local gsm = surge_manager and surge_manager.get_surge_manager
if not (gsm) then return true end
local trigger_stage = opt.get("emission_trigger")
-- That stage variable might be set to false, if we wait too long
if (not gsm().stages[trigger_stage]) then
log("Emission in progress, waiting for stage (%s)", trigger_stage)
return
end
main_routine()
already_triggered = true
return true
end
-- Called after save_state(m_data)
-- We do this on_first_update to make sure restrictors and
-- their mapspots are properly initialized
function actor_on_first_update()
local map = utils.get_mapname() -- No need to execute in those cases.
if (maps_unblockable[map] or utils.is_underground(map)) then
log("Loaded level %s, will not execute.", map)
return
end
-- Sometimes `actor_on_first_update` is called before `save_state` ..
local m_data = alife_storage_manager.get_state()
if (not m_data[data_key]) then
m_data[data_key] = {}
m_data[data_key].newgame = true
end
if (m_data[data_key].newgame) then
if opt.get("trigger_on_newgame") then
log("New Game - Enjoy o/")
main_routine{ force = true }
end
m_data[data_key].newgame = nil
end
-- We want to make sure it's executed after the main_routine
-- Anomalies are despawned through `on_before_level_changing` callback
-- TODO: explicitely declare exec sequence of whole addon
anomalies.spawn_on_current_level()
end
function on_option_change()
if (not opt.get("addon_removal")) then return end
addon_safe_removal()
opt.set_config("general", "addon_removal", false)
end
---------------------------
-- Persistent Data --
---------------------------
function save_state(m_data)
local data = m_data[data_key]
if (not data) then
m_data[data_key] = {}
-- cleared on actor_on_first_update()
m_data[data_key].newgame = true
data = m_data[data_key]
end
data.last_version = VERSION -- may be used for e.g. compatibility patches
-- route_manager
data.db_transitions = route_manager.registered_transitions
data.db_routes = route_manager.registered_routes
-- news manager
data.news_routes_to_reveal = news_manager.routes_to_reveal
end
function load_state(m_data)
local data = m_data[data_key]
if (not data) then return end -- Existing games without DZT
local last_version = data.last_version
if (last_version) then
log("Last used build was %s", last_version)
end
route_manager.registered_transitions = data.db_transitions or {}
route_manager.registered_routes = data.db_routes or {}
news_manager.routes_to_reveal = data.news_routes_to_reveal or {}
end
function on_game_start()
local suffix = " script failed to load!"
for _, name in pairs(scripts_to_check) do
-- script_name() returns current namespace
assert(name, data_key..": "..name..suffix)
end
AddScriptCallback("dynzone_on_before_execute")
AddScriptCallback("dynzone_changed_block_state")
RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
RegisterScriptCallback("actor_on_interaction", check_skipped_surge)
RegisterScriptCallback("on_before_surge", on_before_surge)
RegisterScriptCallback("save_state", save_state)
RegisterScriptCallback("load_state", load_state)
RegisterScriptCallback("on_option_change", on_option_change)
teleport_ini = txr_routes.sr_teleport_ini
or ini_file("sr_teleport_sections.ltx") -- for those without modded exes
end
@@ -0,0 +1,780 @@
--[[
DYNAMIC ZONE - Anomalies Spawn Module
Original Author(s)
VodoXleb <vodoxlebushek>
Singustromo <singustromo at disroot.org>
Edited by
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
(https://creativecommons.org/licenses/by-nc-sa/4.0)
Synopsis
Main module responsible for spawning anomalies on transitions that are
blocked. Anomalies are spawned randomly in a given radius around the
teleport space restrictor.
Additionally we also spawn anomalies on predefined coordinates due
to missing level vertex id's on some map spots.
Anomalies are only being spawned for the current level as we handle over
20 of those per blocked transition in order to not cap the
a-life limit with heavily modded games.
demonized' kd_tree is used for rudimentary distance checks
We've also utilized some modified anomaly spawn code from DAO (marked below)
--]]
parent = _G["dynamic_zone"]
if not (parent and parent.VERSION and parent.VERSION >= 20241224) then return end
--------------------------
-- Dependencies --
--------------------------
local utils = dynamic_zone_utils
local debug = dynamic_zone_debug
local route_manager = dynamic_zone_routes
------------------------------------------
-- Global Variables & Constants --
------------------------------------------
CONST_LOGGING_PREFIX = "Anomalies"
local log = debug.log_register("info", CONST_LOGGING_PREFIX)
local log_warn = debug.log_register("warning", CONST_LOGGING_PREFIX)
local log_error = debug.log_register("error", CONST_LOGGING_PREFIX)
CONST_MDATA_KEY_USED_TRANSITION = "last_taken_transition"
CONST_STRING_THEME_ID = "st_dynzone_$NAME_theme"
CONST_ANOMALY_FALLBACK_SIZE_MIN = 2 -- fallback values
CONST_ANOMALY_FALLBACK_SIZE_MAX = 4
CONST_FIELD_SIZE_MIN = 30 -- static spawn at transition center
CONST_FIELD_SIZE_MAX = 40
CONST_SAFEZONE_RADIUS = 10
CONST_GENERATE_NARROW_FACTOR = 0.6
CONST_ABORT_CREATION_DELAY_MS = 250
CONST_BASE_INI_DIR = "plugins\\dynamic_zone\\anomalies"
ini_transition_params = ini_file_ex(CONST_BASE_INI_DIR .. "\\transition_settings.ltx")
ini_static_spawns = ini_file_ex(CONST_BASE_INI_DIR .. "\\static_spawns.ltx")
--------------------------------------
-- Anomaly Spawn Settings --
--------------------------------------
-- Contains spawn parameters for transitions - also the defaults
spawn_parameters = {
defaults = { -- Needs to contain every possible key (failsafe)
rootpos = false,
narrow = false,
count = 19,
max_height_offset = 0,
spread_radius = 20,
generate_max_tries = 64,
min_anomaly_proximity = 1,
static_spawn_ratio = 0.4
},
}
anomaly_themes = {
[1] = {
name = "thermal",
anomaly_field_types = {
"zone_field_thermal_strong",
"zone_field_thermal_average",
},
anomaly_mines_types = {
"zone_mine_thermal_strong",
"zone_mine_thermal_average",
"zone_mine_thermal_weak",
},
},
[2] = {
name = "acidic",
anomaly_field_types = {
"zone_field_acidic_strong",
"zone_field_acidic_average",
},
anomaly_mines_types = {
"zone_mine_acidic_strong",
"zone_mine_acidic_average",
"zone_mine_acidic_weak",
"zone_mine_chemical_strong",
"zone_mine_chemical_average",
"zone_mine_chemical_weak",
},
},
[3] = {
name = "electric",
anomaly_field_types = {
"zone_field_psychic_strong",
"zone_field_psychic_average",
},
anomaly_mines_types = {
"zone_mine_electric_strong",
"zone_mine_electric_average",
"zone_mine_electric_weak",
},
},
[4] = {
name = "gravitational",
anomaly_field_types = {
"zone_field_radioactive_strong",
"zone_field_radioactive_average",
},
anomaly_mines_types = {
"zone_mine_gravitational_strong",
"zone_mine_gravitational_average",
"zone_mine_gravitational_weak",
},
},
}
-- TODO: Use table from DAO/Arrival, if available
-- defining anomaly radii for most in-game anomalies
anomaly_radii = {
zone_radioactive = {min = 4, max = 6},
zone_radioactive_weak = {min = 4, max = 6},
zone_radioactive_average = {min = 4, max = 6},
zone_radioactive_strong = {min = 4, max = 6},
zone_mine_acid = {min = 2, max = 3},
zone_mine_acidic_weak = {min = 2, max = 3},
zone_mine_acidic_average = {min = 2, max = 3},
zone_mine_acidic_strong = {min = 2, max = 3},
zone_mine_blast = {min = 2, max = 3},
zone_mine_umbra = {min = 2, max = 3},
zone_mine_electra = {min = 2, max = 3},
zone_mine_electric_weak = {min = 2, max = 3},
zone_mine_electric_average = {min = 2, max = 3},
zone_mine_electric_strong = {min = 2, max = 3},
zone_mine_flash = {min = 3, max = 3},
zone_mine_ghost = {min = 2, max = 3},
zone_mine_gold = {min = 2, max = 3},
zone_mine_thorn = {min = 2, max = 3},
zone_mine_seed = {min = 3, max = 3},
zone_mine_shatterpoint = {min = 6, max = 8},
zone_mine_gravitational_weak = {min = 2, max = 3},
zone_mine_gravitational_average = {min = 3, max = 5},
zone_mine_gravitational_strong = {min = 4, max = 6},
zone_mine_sloth = {min = 3, max = 4},
zone_mine_mefistotel = {min = 3, max = 4},
zone_mine_net = {min = 2, max = 3},
zone_mine_point = {min = 2, max = 3},
zone_mine_cdf = {min = 2, max = 3},
zone_mine_sphere = {min = 4, max = 5},
zone_mine_springboard = {min = 4, max = 6},
zone_mine_thermal_weak = {min = 1, max = 2},
zone_mine_thermal_average = {min = 1, max = 2},
zone_mine_thermal_strong = {min = 1, max = 2},
zone_mine_zharka = {min = 1, max = 2},
zone_mine_vapour = {min = 1, max = 2},
zone_mine_vortex = {min = 3, max = 5},
}
------------------------------
-- Global Getters --
------------------------------
-- Getter for the coresponding string identifier determined by anomaly_themes[id].name
-- @param theme_id (index from anomaly_theme table)
-- @returns string (identifier used in xml)
function get_theme_string(theme_id)
if not utils.valid_type{ caller = "get_theme_string",
"int", theme_id } then return end
utils.assert(anomaly_themes[theme_id], "Undefined theme with ID #%s!", theme_id)
local theme_name = anomaly_themes[theme_id] and anomaly_themes[theme_id].name
local string_id = CONST_STRING_THEME_ID
return (theme_name) and string_id:gsub("%$NAME", theme_name)
end
-- Ensures that we always have usable spawn parameters
-- Uses defaults section as a fallback
-- @param transition_name
-- @returns table
function get_spawn_parameters(transition_name)
if not utils.valid_type{ caller = "get_spawn_parameters",
"str", transition_name } then return end
local defaults = spawn_parameters.defaults
if (utils.is_table_empty(spawn_parameters[transition_name])) then
log("No parameters defined for transition '%s', using defaults.", transition_name or "N/A")
return defaults
end
return spawn_parameters[transition_name]
end
-- Returns the root position for anomaly spawns of the given transition
-- @param transition_name
-- @returns pos (copy) or nil
function get_rootposition(transition_name)
if not utils.valid_type{ caller = "get_rootposition",
"str", transition_name } then return end
local params = get_spawn_parameters(transition_name)
local pos = params and params.pos
return pos and vector():set(pos.x, pos.y, pos.z)
end
-----------------------------
-- Configuration --
-----------------------------
function collect_spawn_parameters(section)
local settings, target = ini_transition_params:collect_section(section)
spawn_parameters[section] = {}
target = spawn_parameters[section]
for key, value in pairs(settings) do
if (key == "rootpos") then
target[key] = utils.string_to_vector(value) or false
goto continue
end
local value_bool = utils.string_to_bool(value)
target[key] = (type(value_bool) == "bool") and value_bool
or tonumber(value) or value
:: continue ::
end
end
-- Returns the appropriate radius, to ensure we default to fallback values, if necessary
-- @param anomaly_type section of the anomaly
-- @returns table || nil
function get_anomaly_radii(anomaly_type)
if (not anomaly_type) then return end
-- Fields share the same radii in our use case
if string.find(anomaly_type, "^zone_field_") then
return {min = CONST_FIELD_SIZE_MIN,
max = CONST_FIELD_SIZE_MAX}
end
return anomaly_radii[anomaly_type]
or {min = CONST_ANOMALY_FALLBACK_SIZE_MIN, max = CONST_ANOMALY_FALLBACK_SIZE_MAX}
end
----------------------------
-- Monkey patches --
----------------------------
SRTeleportMsgBoxOk = ui_sr_teleport.msg_box_ui.OnMsgOk
-- We gotta save the last used transition for Anomaly safe Zone
function ui_sr_teleport.msg_box_ui.OnMsgOk(self)
local transition_name, m_data, data = self.name
local route = route_manager.get_route_by_transition(transition_name)
if (utils.assert_failed(route) or not route.blocked) then goto teleport end
m_data = alife_storage_manager.get_state()
data = m_data and m_data[parent.data_key]
data[CONST_MDATA_KEY_USED_TRANSITION] = transition_name
log("Saved '%s' as last used transition", data[CONST_MDATA_KEY_USED_TRANSITION])
:: teleport ::
return SRTeleportMsgBoxOk(self)
end
-------------------------
-- Callbacks --
-------------------------
function on_game_start()
RegisterScriptCallback("dynzone_changed_block_state", dynzone_changed_block_state)
RegisterScriptCallback("on_level_changing", release_all_anomalies)
ini_transition_params:section_for_each(collect_spawn_parameters)
end
-- Called in main script by actor_on_first_update because it
-- should be executed after routes have been updated
-- Spawns anomalies on the current level for blocked transitions
-- Only does so, if spawned_anomalies of the transition is empty
-- TODO: encapsulate from main script (e.g. new Callback)
function spawn_on_current_level(force)
for route_id, route in route_manager.iterate_routes() do
if not (route.blocked or force) then goto next_route end
spawn_for_route_on_current_level(route_id)
:: next_route ::
end
end
-- Sets the Anomaly Theme, Spawns and Despawns anomalies accordingly
-- We check the spawned_anomalies attribute to
-- determine if that transition is on current level
function dynzone_changed_block_state(previously_blocked, new_blocked)
for route_id, _ in pairs(previously_blocked) do
route_manager.set_route_property(route_id, "anomaly_theme", 0)
for section, attributes in route_manager.iterate_transitions(route_id) do
if (not utils.is_table_empty(attributes.spawned_anomalies)) then
release_all_from_transition(section)
end
end
end
for route_id, _ in pairs(new_blocked) do
set_route_theme(route_id) -- We need to set it beforehand for e.g. the news
spawn_for_route_on_current_level(route_id)
end
end
-- Called 'on_level_changing'
function release_all_anomalies()
if (utils.debug_level_loaded()) then return end
log("Releasing anomalies on '%s'", utils.get_mapname())
for route_id, route in route_manager.iterate_routes() do
for section, attributes in route_manager.iterate_transitions(route_id) do
if (not utils.is_table_empty(attributes.spawned_anomalies)) then
release_all_from_transition(section)
end
end
end
end
------------------------------
-- Main functions --
------------------------------
-- Sets a specific or random theme for any given route
-- @param gizmo transition-section || route-id
-- @param theme_id Optional theme id (randomized, if invalid)
function set_route_theme(gizmo, theme_id)
local theme = (theme_id and anomaly_themes[theme_id]) and theme_id
or math.random(1, #anomaly_themes)
local route_id = (route_manager.route_exists(gizmo)) and gizmo
or route_manager.get_route_by_transition(gizmo).id
if not utils.valid_type{ caller = "set_route_theme",
"int", route_id, "int", theme } then return end
route_manager.set_route_property(route_id, "anomaly_theme", theme)
if (route_manager.get_route_property(route_id, "anomaly_theme") ~= theme) then
log_warn("Unable to set route theme for route #%s", route_id)
end -- Just a sanity check
end
function spawn_for_route_on_current_level(route_id)
if not utils.valid_type{ caller = "spawn_for_route_on_current_level",
"int", route_id } then return end
local actor_level = utils.get_mapname()
if (utils.is_underground(actor_level)) then
log("Loaded underground level %s, will not execute.", actor_level)
return
end
local route = route_manager.get_route(route_id)
local m_data, safe_zone = alife_storage_manager.get_state()
local data = m_data and m_data[parent.data_key]
local last_used_transition = data[CONST_MDATA_KEY_USED_TRANSITION]
if (utils.table_has(route.members, last_used_transition)) then
data[CONST_MDATA_KEY_USED_TRANSITION] = nil
safe_zone = true
end
for section, attributes in route_manager.iterate_transitions(route_id) do
if (not utils.is_table_empty(attributes.spawned_anomalies)) then
log_warn("[%s] Already spawned anomalies for '%s'", route_id, section)
goto continue
end
local se_obj = section and get_story_se_object(section)
if utils.assert_failed(se_obj, "No object with the ID #%s exists!", id) then
goto continue
end
-- We need to check, if transition is on same level
local transition_level = utils.get_mapname(se_obj)
if (actor_level ~= transition_level) then goto continue end
populate_transition(section, safe_zone)
-- Just a logging check
local spawned = route_manager.get_transition_property(section, "spawned_anomalies")
log("Spawned %s anomalies for %s\n# %s",
size_table(spawned), section, table.concat(spawned, ", "))
:: continue ::
end
end
-- Spawns anomalies on a transition (static from LTX and dynamically)
-- Also reads transition specific spawn parameters from the INI
function populate_transition(section, safe_zone_around_player)
if not utils.valid_type{ caller = "populate_transition",
"str", section } then return end
local route_id = route_manager.get_route_id(section)
local theme_id = route_id and route_manager.get_route_property(route_id, "anomaly_theme")
local anomaly_theme = anomaly_themes[theme_id]
if utils.assert_failed(anomaly_theme and type(anomaly_theme) == "table") then
return
end
local parameters = get_spawn_parameters(section)
if utils.assert_failed(parameters) then return end
local rpos = parameters.rootpos
log("Spawning %s dynamic anomalies for '%s'%s (Theme: %s)",
parameters.count +1, section,
rpos and string.format(" @(%.1f, %.1f, %.1f)", rpos.x, rpos.y, rpos.z) or "",
game.translate_string(get_theme_string(theme_id)))
local transition_field_types = anomaly_theme.anomaly_field_types
local guarenteed_spawn_type = transition_field_types[math.random(1, #transition_field_types)]
spawn_at_transition(section, guarenteed_spawn_type, true, nil, parameters)
local position_data = kd_tree.buildTreeVectors()
if (utils.assert_failed(position_data)) then return end
local types = anomaly_theme.anomaly_mines_types
local count = parameters.count
while (count > 0) do
local anomaly_type = types[math.random(1, #types)]
utils.assert(anomaly_type)
spawn_at_transition(section, anomaly_type, false, position_data, parameters)
count = count -1
end
-- We now spawn static anomalies which fill the gaps on the map that have no level id's
populate_transition_with_static_spawns(section, anomaly_theme, position_data, parameters)
if (not safe_zone_around_player) then return end
local actor_pos, transition = db.actor:position(), route_manager.get_transition(section)
log("Establishing Safe-Zone around player for transition '%s' @(%.1f, %.1f, %.1f)",
section, actor_pos.x, actor_pos.y, actor_pos.z)
--[[
TODO: Only use one tree and directly attach Obj-ID's to position data
Gotta build a new tree, otherwise we won't have their object-id as reference
Returns table with elements like this: { { x = a, y = b, z = c, data = d}, distance }
--]]
local pos_tree = kd_tree.buildTreeSeObjectIds(transition.spawned_anomalies)
local anomalies_near = pos_tree:nearestAll(actor_pos)
if utils.assert_failed(not utils.is_table_empty(anomalies_near)) then
log_error("Position Tree returned no object references")
return
end
for _, anomaly_info in pairs(anomalies_near) do
local obj_id, distance = anomaly_info[1].data, anomaly_info[2]
if (distance > CONST_SAFEZONE_RADIUS) then break end -- Sorted by distance
local se_obj = alife_object(obj_id)
if (utils.assert_failed(se_obj, "Got no server object with ID #%s", obj_id)) then
goto continue
end
local anomaly_name = se_obj:section_name()
if (anomaly_name == guarenteed_spawn_type) then goto continue end
log("Releasing previously spawned Anomaly '%s' with ID #%s (Distance: %.2f)",
anomaly_name, obj_id, distance)
local id_idx = utils.index_of(transition.spawned_anomalies, obj_id)
if utils.assert_failed(id_idx) then
log_error("[#%s] Unable to find Obj-ID #%s in {%s}",
route_id, obj_id, unpack(transition.spawned_anomalies, ", "))
goto continue
end
table.remove(transition.spawned_anomalies, id_idx)
alife_release_id(obj_id)
:: continue ::
end
end
-- Randomly spawns anomalies from a predefined pool in the ini
-- @param transition_name section of target transition
-- @param anomaly_theme pointer to the theme (anomaly_themes[theme_id])
function populate_transition_with_static_spawns(transition_name, anomaly_theme, position_data, parameters)
if not utils.valid_type{ caller = "populate_transition_with_static_spawns",
"str", transition_name, "tbl", anomaly_theme, "tbl", parameters } then return end
if (not ini_static_spawns:section_exist(transition_name)) then
log("Transition '%s' has no predefined static spawns, skipping.", transition_name)
return
end
local min_anomaly_proximity = parameters.min_anomaly_proximity
local spawn_percent = parameters.static_spawn_ratio
local transition_spawns = ini_static_spawns:collect_section(transition_name)
local types = anomaly_theme.anomaly_mines_types
_g.shuffle_table(transition_spawns)
local shuffled_spawns = {}
for _, v in pairs(transition_spawns) do -- reindex for next step
shuffled_spawns[#shuffled_spawns +1] = v
end
local remaining_spawns = _g.round(#shuffled_spawns * spawn_percent)
log("Trying to populate transition %s with %s static spawns", transition_name, remaining_spawns)
local spawned = route_manager.get_transition_property(transition_name, "spawned_anomalies")
for index in utils.random_numbered_sequence(1, #shuffled_spawns) do
if (remaining_spawns < 1) then break end
local position_raw = shuffled_spawns[index]
local data = position_raw and utils.string_to_posdata(position_raw)
if (not data) then goto continue end
local anomaly_type, pos = types[math.random(1, #types)], data.pos
if (not posdata_distance_check(position_data, pos, anomaly_type, min_anomaly_proximity)) then
goto continue
end
local anomaly_id = drx_da_spawn_anomaly(anomaly_type, pos, data.lvid, data.gvid)
if (anomaly_id) then
spawned[#spawned +1] = anomaly_id
remaining_spawns = remaining_spawns -1
end
:: continue ::
end
end
-- @param transition_name section of target transition
-- @param anomaly_type section of anomaly
-- @param spawn_at_center boolean
-- @param position_data kd_tree; used when spawn_at_center = false (optional)
-- @param parameters needed when spawn_at_center = false
function spawn_at_transition(transition_name, anomaly_type, spawn_at_center, position_data, parameters)
-- TODO: Create corresponding function in utils
local id = transition_name and get_story_object_id(transition_name)
local transition_obj = id and alife_object(id)
if (not transition_obj) then
log_error("Can't create dynamic anomaly for %s, the specified transition does not exist.", transition_name)
return
end
local pos = (parameters) and parameters.rootpos or transition_obj.position
if (not spawn_at_center) then
pos = generate_valid_position(transition_obj, anomaly_type, parameters, position_data)
if (not pos) then
log_error("Failed to generate position. Aborting.")
return
end
end
local lvid = level.vertex_id(pos)
local anomaly_id = drx_da_spawn_anomaly(anomaly_type,
pos, lvid, transition_obj.m_game_vertex_id)
if (not anomaly_id) then return end
local spawned = route_manager.get_transition_property(transition_name, "spawned_anomalies")
spawned[#spawned +1] = anomaly_id
return true
end
-- Releases all spawned anomalies tied to any given transition
function release_all_from_transition(transition_name)
if not utils.valid_type{ caller = "release_all_from_transition",
"str", transition_name } then return end
local transition = route_manager.get_transition(transition_name)
local spawned_anomalies = transition and transition.spawned_anomalies
if (utils.assert_failed(spawned_anomalies)) then return end
local released = {}
for index, id in pairs(spawned_anomalies) do
if (alife_release_id(id)) then
released[#released +1] = id
else
log_error("Unable to release anomaly with ID #%s", id)
end
end
transition.spawned_anomalies = {} -- make sure no old references remain
log("Released the following %s IDs for %s\n# %s",
size_table(released), transition_name, table.concat(released, ", "))
end
function posdata_distance_check(position_data, pos, anomaly_type, minimum_proximity)
if not utils.valid_type{ caller = "posdata_distance_check",
"tbl", position_data, "usr", pos, "str", anomaly_type, "number", minimum_proximity } then return end
if (not position_data) then
return true
elseif (not position_data.root) then
position_data:insertAndRebuild{x = pos.x, y = pos.y, z = pos.z}
return true
end
local nearest = position_data:nearest(pos)
if not (nearest and nearest[1] and nearest[1][2]) then
log("Can't check position data (%.2f, %.2f, %.2f)", pos.x, pos.y, pos.z)
position_data:insertAndRebuild{x = pos.x, y = pos.y, z = pos.z}
return true
end
local radii = get_anomaly_radii(anomaly_type)
local anomaly_radius = _g.round((radii.min + radii.max) / 2) -- mean
local spawned_distance = nearest[1][2] - (anomaly_radius *2)
if (spawned_distance >= minimum_proximity) then
position_data:insertAndRebuild{x = pos.x, y = pos.y, z = pos.z}
return true
end
log("Position invalid. Too close. (Distance %s < %s) @(%.2f, %.2f, %.2f)",
spawned_distance, minimum_proximity, pos.x, pos.y, pos.z)
end
-- ANOMALY SPAWN FUNCTIONS
-- THE FOLLOWING LINES ARE TAKEN FROM drx_da_main.script
-- FROM DYNAMIC ANOMALIES OVERHAUL (DAO) (UPDATE 25)
-- CREDITS TO TheMrDemonized, DoctorX, Eugenium, Barry Bogs, Lucy, Grok, Jurkonov, CrimsonVirus
--
-- THESE FUNCTIONS HAVE BEEN ADAPTED FOR USE IN THIS ADDON BY THE MOD AUTHORS
-- Spawns one anomaly of any valid given type
-- @param anomaly_type (anomaly section)
-- @param pos, lvid, gvid (self-explanatory)
-- @returns se_obj_id
function drx_da_spawn_anomaly(anomaly_type, pos, lvid, gvid)
if not (anomaly_type and ini_sys:section_exist(anomaly_type)) then
log_error("Anomaly type '%s' does not exist! Aborting.", anomaly_type)
return
end
local se_obj = alife():create(anomaly_type, pos, lvid, gvid)
if (not se_obj) then
log_error("[%s] Unable to spawn anomaly.", anomaly_type)
return
end
local function abort_creation(se_obj_id, anomaly_type)
utils.timed_call(CONST_ABORT_CREATION_DELAY_MS, function()
local obj = alife_object(se_obj_id)
if obj then
log_error("[%s] Anomaly '%s' failed to spawn correctly, releasing.",
se_obj_id, anomaly_type)
alife_release(obj)
end
return true
end)
end
local data = utils_stpk.get_anom_zone_data(se_obj) -- get anomaly properties
if (not data) then
abort_creation(se_obj.id, anomaly_type)
return
end
data.shapes[1] = {}
data.shapes[1].shtype = 0
data.shapes[1].offset = vector():set(0, 0, 0) -- Leave for compatibility with CoC 1.4.22, delete later
data.shapes[1].center = vector():set(0, 0, 0)
local radii = get_anomaly_radii(anomaly_type)
data.shapes[1].radius = math.random(radii.min, radii.max)
utils_stpk.set_anom_zone_data(data, se_obj)
return se_obj.id
end
-- Generates a random valid position from a vertex in radius around a given transition
-- @param se_obj game object of the transition space restrictor
-- @param anomaly_type section of the anomaly to be spawned
-- @param spawn_params table containing the spawn parameters
-- @param position_data (optional)
function generate_valid_position(se_obj, anomaly_type, spawn_params, position_data)
if not utils.valid_type{ caller = "generate_valid_position",
"usr", se_obj, "str", anomaly_type, "tbl", spawn_params } then return end
local random = math.random
local level_vertex_id = level.vertex_id
local level_vertex_position = level.vertex_position
local rootpos = spawn_params.rootpos or se_obj.position
local num_tries = spawn_params.generate_max_tries
local spread_radius = spawn_params.spread_radius
local minimum_proximity = spawn_params.min_anomaly_proximity
local max_offset = {x = spread_radius, y = spread_radius, z = spread_radius}
if (spawn_params.narrow) then
for k, v in pairs(max_offset) do
max_offset[k] = math.floor(max_offset[k] * CONST_GENERATE_NARROW_FACTOR)
end
end
local pos = vector():set(0, 0, 0)
-- In the following, we randomly offset the position to
-- get a valid level vertex id we can spawn an anomaly on
while (num_tries > 0) do
local offset_x = max_offset.x * random()
local pos_x = (random() <= 0.5) and (rootpos.x +offset_x)
or (rootpos.x -offset_x)
local offset_y = max_offset.y * random()
local pos_y = (random() <= 0.5) and (rootpos.y +offset_y)
or (rootpos.y -offset_y)
local offset_z = max_offset.z * random()
local pos_z = (random() <= 0.5) and (rootpos.z +offset_z)
or (rootpos.z -offset_z)
-- Set anomaly position at vertex and check if valid:
pos = vector():set(pos_x, pos_y, pos_z)
local check_distance -- interpreter would complain bc of goto statements
pos = utils.get_closest_vertex_pos(pos)
if (not pos) then goto next_try end
check_distance = pos:distance_to(rootpos)
if (check_distance > spread_radius) then
log_error("Distance to root position is too high (%s)", check_distance)
goto next_try
end
if (posdata_distance_check(position_data, pos, anomaly_type, minimum_proximity)) then
break
end
:: next_try ::
num_tries = (num_tries - 1)
end
if (num_tries <= 0) then
log_error("Unable to generate valid lvid position, aborting.")
return
end
return pos
end
@@ -0,0 +1,206 @@
--[[
DYNAMIC ZONE
Original Author(s)
Singustromo <singustromo at disroot.org>
Edited by
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
(https://creativecommons.org/licenses/by-nc-sa/4.0)
--]]
parent = _G["dynamic_zone"]
if not (parent and parent.VERSION and parent.VERSION >= 20241224) then return end
local opt = dynamic_zone_mcm
local utils = dynamic_zone_utils
------------------------------------------
-- Global Variables & Constants --
------------------------------------------
CONST_BLOCKSTATECHANGE_NOTIFY_DELAY_MS = 100
CONST_LOGGING_PREFIX = "[DZT]" -- used for console logging
valid_logging_channels = { def = "INFO", info = "INFO", warning = "WARNING", error = "ERROR" }
registered_logging_channels = { --[[
info = instance,
warning = instance,
...
--]] }
local log_mcm
---------------------
-- Callbacks --
---------------------
function on_game_start()
RegisterScriptCallback("on_game_load", inject_debug_commands)
RegisterScriptCallback("dynzone_changed_block_state", dynzone_changed_block_state)
-- Due to this, functors called before creating those instances will log to xray console
log_mcm = log_register("info", "Debug")
create_logging_instances()
end
function inject_debug_commands()
-- no need, if not enabled. Idk if it would even break something
if not (DEV_DEBUG or DEV_DEBUG_DEV) then return end
local CMD = debug_cmd_list.command_get_list()
function CMD.dynamic_zone(_, __, x)
x:SendOutput("/ DYNAMIC ZONE " .. parent.VERSION_STRING)
parent.main_routine{ force = true }
end
function CMD.dynamic_zone_accessible(_, __, x)
x:SendOutput("- Reset all route states!")
parent.addon_safe_removal()
end
ui_debug_launcher.inject("action", { name = "[DYNZONE] Trigger",
cmd = "dynamic_zone", hide_ui = 2, key = "DIK_D" } )
ui_debug_launcher.inject("action", { name = "[DYNZONE] Clear routes",
cmd = "dynamic_zone_accessible", hide_ui = 2 } )
end
-- Just informs us about the exact block state
-- A bit hacky to prevent recursive referencing
function dynzone_changed_block_state(previous, current)
if (not opt.get("verbose")) then
UnregisterScriptCallback("dynzone_changed_block_state", dynzone_changed_block_state)
end
-- We only use it in this function, to prevent recursive referencing
local route_manager = dynamic_zone_routes
-- Done this way, so it shows the updated values changed by other functions
utils.timed_call(CONST_BLOCKSTATECHANGE_NOTIFY_DELAY_MS, function(previous, current)
local output_str = "Previously Blocked routes:"
for route_id, _ in pairs(previous) do
output_str = output_str .. "\n" .. route_manager.route_tostring(route_id, true)
end
if (size_table(previous) > 0) then
log_mcm("%s\nA total of %s routes were blocked.",
output_str, size_table(previous))
end
local output_str = "Newly Blocked routes:"
for route_id, _ in pairs(current) do
output_str = output_str .. "\n" .. route_manager.route_tostring(route_id, true)
end
if (size_table(current) > 0) then
log_mcm("%s\nA total of %s routes are freshly blocked.",
output_str, size_table(current))
end
local blocked, discovered = 0, 0
for route_id, route in route_manager.iterate_routes(true) do
blocked = (route.blocked) and (blocked +1) or blocked
discovered = (route.block_discovered) and (discovered +1) or discovered
end
log_mcm("A total of %s routes are blocked (%s discovered)", blocked, discovered)
return true
end, previous, current)
end
---------------------------
-- Debugging --
---------------------------
-- These are mainly used by this script or others where it is more suited than mcm logging
function log(message, ...)
if (not opt.get("verbose")) then return end
local args = {...}
local output = string.format("%s %s", CONST_LOGGING_PREFIX, message)
printf(output, unpack(args))
end
-- These two are more important, thus are always logged to console.
function log_warn(message, ...)
local args = {...}
local output = string.format("~%s %s", CONST_LOGGING_PREFIX, message)
printf(output, unpack(args))
end
function log_error(message, ...)
local args = {...}
local output = string.format("!%s %s", CONST_LOGGING_PREFIX, message)
printf(output, unpack(args))
end
-- REQUIRES MOD-CONFIGURATION-MENU (MCM)
-- We only create logging instances `on_game_start`, so we don't load mcm_log earlier than necessary.
function create_logging_instances()
if (_g.is_empty(registered_logging_channels)) then
return
elseif not (mcm_log and mcm_log.new) then
log_warn("MCM Logging utility not found. Falling back to console logging.")
return
end
for channelname, value in pairs(registered_logging_channels) do
if (type(value) == "userdata") then goto continue end
local logger = mcm_log and mcm_log.new and mcm_log.new(channelname)
if (not logger) then
log_warn("Unable to create a MCM logging instance! Falling back to console logging.")
callstack()
return
end
logger.continuous = true
logger.enabled = true
registered_logging_channels[channelname] = logger
:: continue ::
end
end
-- Called like this: e.g. log_info = debug.log_register("info", "Anomalies")
-- will only return function that prints to logs, when verbose setting is active
-- Will log via the MCM utility, only to console as fallback
-- Using string.format to be able to use same rules as ISO C sprintf
-- @param channelname logging level - defaults to info, if invalid
-- @param identifier optional
-- @returns pointer to logging function which uses mcm logging, when available
function log_register(channelname, identifier)
if (not channelname) then return end
identifier = identifier and string.upper(identifier)
channelname = valid_logging_channels[string.lower(channelname)]
or valid_logging_channels.def
registered_logging_channels[channelname] = true
local id_prefix = (identifier and type(identifier == "string"))
and (" - " .. identifier) or ""
return function(message, ...)
if (not opt.get("verbose")) then return end
local data = { channel = channelname, id = id_prefix }
local logger = (type(registered_logging_channels[data.channel]) ~= "boolean")
and registered_logging_channels[data.channel]
-- Fallback for e.g. before `on_game_start` or if `mcm_log` does not exist
if not (logger and logger.log) then
printf(string.format(CONST_LOGGING_PREFIX .. message, ...))
return
end
local default_prefix = logger.prefix
if (data.id and data.id ~= "") then
logger.prefix = logger.prefix .. data.id
end
logger:log(string.format(message, ...))
logger.prefix = default_prefix
end
end
@@ -0,0 +1,725 @@
--[[
DYNAMIC ZONE
Original Author(s)
Singustromo <singustromo at disroot.org>
Edited by
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
(https://creativecommons.org/licenses/by-nc-sa/4.0)
Synopsis
Simple module responsible for updating the route discovery state based
on being close enough to one of the anomalies spawned or alternatively
discovering them via the binoculars.
Also controls mapspot appearance of transitions and adds a blip for
transitions whose state is unknown (not recently discovered).
--]]
parent = _G["dynamic_zone"]
if not (parent and parent.VERSION and parent.VERSION >= 20241224) then return end
--------------------------
-- Dependencies --
--------------------------
local opt = dynamic_zone_mcm
local utils = dynamic_zone_utils
local debug = dynamic_zone_debug
local route_manager = dynamic_zone_routes
------------------------------------------
-- Global variables & Constants --
------------------------------------------
CONST_LOGGING_PREFIX = "Discovery"
local log = debug.log_register("info", CONST_LOGGING_PREFIX)
get_anomaly_rootpos = dynamic_zone_anomalies.get_rootposition
CONST_DISCOVERY_CHECK_INTERVAL_MS = 5000
CONST_MAPSPOT_BLIP_OFFSET_PIXELS = 13
CONST_MAPSPOT_BLOCKED_TEXTURE = [[dynamic_zone_exit_point_blocked]]
CONST_MAPSPOT_BLOCKED_COLOR = {255, 240, 240, 240}
CONST_BINOCULAR_CHECK_IN_SIGHT_INTERVAL_MS = 250
CONST_BINOCULAR_REFRESHRATE_MS = 125
CONST_BINOCULAR_HUD_ICON_TEXTURE = [[dynamic_zone_blip_unknown_state]]
CONST_BINOCULAR_HUD_ICON_TEXTURE_SIZE = {19, 21}
CONST_BINOCULAR_HUD_ICON_HOVER_METRES = 1.45 *2 -- Stalker height is roughly 1.45
CONST_BINOCULAR_HUD_MAX_VISIBLE_TRANSITIONS = 8
sound_objs = {
discovery = sound_object("dynamic_zone\\block_discovered"),
binoc_in_progress = sound_object("dynamic_zone\\binoc_discovery_in_progress"),
binoc_aborted = sound_object("dynamic_zone\\binoc_discovery_aborted"),
}
BINOCULAR_HUD = nil -- current CUIScriptWnd subclass instance
BINOCULAR_DISCOVERY_IN_PROGRESS = false
DISCOVERABLE_TRANSITIONS_ON_CURRENT_LEVEL = false
-- Temporary Data -> Not saved to m_data
anomalies_to_check = {} -- [anomaly_obj_id] = route_id
discoverable_on_level = {} -- [transition_obj_id] = route_id
mapspot_blips = {} -- [transition_obj_id] = <blip_instance>
---------------------------
-- Globally Used --
---------------------------
-- used on `parent.actor_on_first_update` and in `parent.main_routine(..)`
function clear_eligible_transitions()
discoverable_on_level = {}
end
function no_eligible_transitions()
return (not DISCOVERABLE_TRANSITIONS_ON_CURRENT_LEVEL)
end
function toggle_known_route_state(route_id, notify_on_new_state)
if not utils.valid_type{ caller = "toggle_known_route_state",
"int", route_id } then return end
if (not eligible_for_discovery(route_id)) then
log("Route #%s was already discovered since last emission.", route_id)
return
end
route_manager.set_route_property(route_id, "recently_discovered", true)
if (route_manager.route_known_state_differs(route_id)) then
local discovered = route_manager.get_route_property(route_id, "block_discovered")
log("Player discovered %s route #%s!", ((discovered)
and "previously blocked" or "blocked"), route_id)
route_manager.set_route_property(route_id, "block_discovered", (not discovered))
if (notify_on_new_state) then
inform_player()
end
end
for name, attributes in route_manager.iterate_transitions(route_id) do
update_transition_mapspot(name)
end
remove_anomaly_check_for(route_id)
for k, v in pairs(discoverable_on_level) do
if (v == route_id) then
discoverable_on_level[k] = nil
end
end
end
-- Changes the mapspot texture and hint for the given transition and adds a blip
-- based on the routes flags. We do this via modded exes functionality.
-- Adds mapspot info blip to transitions to indicate those with unknown state.
-- @param transition_name
-- @param blocked (override; optional)
-- @param only_text (optional; used to only update the text)
function update_transition_mapspot(transition_name, blocked, only_text)
if not utils.valid_type{ caller = "update_transition_mapspot",
"str", transition_name } then return end
local id, spot, hint = parent.get_transition_marker_info(transition_name)
if utils.assert_failed(id and spot and hint) then return end
-- Important when e.g. calling this on 'fake_start'
if (not utils.map_spot_exists(id, spot)) then return end
local route = route_manager.get_route_by_transition(transition_name)
if utils.assert_failed(route, "Transition %s got no assigned route!", transition_name) then return end
local mark_as_blocked = blocked
if (mark_as_blocked == nil) then
mark_as_blocked = route.block_discovered
end
local new_hint = get_suited_mapspot_hint(id, hint, mark_as_blocked)
utils.map_spot_change_hint(id, spot, new_hint)
mapspots_blip_update_for(id, spot)
if (only_text) then return end
change_mapspot_marker(id, spot, mark_as_blocked)
end
-- Ignores route flags; To be used before removal of the addon
-- Reverts all map spots to their default look, also removes the blips
function revert_map_spots()
for route_id, route in route_manager.iterate_routes(false) do
if (not route.block_discovered) then goto continue end
for name, _ in route_manager.iterate_transitions(route_id) do
update_transition_mapspot(name, false)
end
:: continue ::
end
mapspots_blips_remove()
end
-----------------------
-- Callbacks --
-----------------------
function on_game_start()
RegisterScriptCallback("dynzone_on_before_execute", dynzone_on_before_execute)
RegisterScriptCallback("dynzone_changed_block_state", dynzone_changed_block_state)
RegisterScriptCallback("actor_on_update", actor_on_throttled_update)
-- Discovery via spawned anomalies
RegisterScriptCallback("actor_on_feeling_anomaly", actor_on_feeling_anomaly)
-- Binocular discovery
RegisterScriptCallback("actor_on_weapon_zoom_in", actor_on_weapon_zoom_in)
RegisterScriptCallback("actor_on_weapon_zoom_out", actor_on_weapon_zoom_out)
RegisterScriptCallback("actor_on_net_destroy", actor_on_weapon_zoom_out) -- Because of hud visor
RegisterScriptCallback("actor_on_before_death", actor_on_weapon_zoom_out)
RegisterScriptCallback("on_option_change", on_option_change)
RegisterScriptCallback("on_game_load", cache_mapmarker_info)
end
-- This is triggered whenever our main routine is triggered, thus after every emission
function dynzone_on_before_execute()
mapspots_blips_show(true)
end
-- We need to clear our data, it's highly probable that it is invalid.
function dynzone_changed_block_state(previous, new)
clear_eligible_transitions()
-- If it has unregistered itself
RegisterScriptCallback("actor_on_update", actor_on_throttled_update)
end
-- Periodically executes as long as it has determined eligible transitions
-- We clear the eligibility table to refresh the list, this way.
actor_on_throttled_update = utils.throttle(CONST_DISCOVERY_CHECK_INTERVAL_MS, true, function()
if (get_eligible_transitions_on_level()) then return end
UnregisterScriptCallback("actor_on_update", actor_on_throttled_update)
end)
-- Toggles state of route discovery if any anomaly was spawned by our script
function actor_on_feeling_anomaly(obj, tbl)
if (utils.is_table_empty(anomalies_to_check)) then return end
local obj_id = obj and obj.id and obj:id()
local route_id = anomalies_to_check[obj_id]
if (not route_id) then return end
log("[%s] Anomaly belongs to route #%s", obj_id, route_id)
toggle_known_route_state(route_id, true)
end
function actor_on_weapon_zoom_in()
if (no_eligible_transitions()) then return end
RegisterScriptCallback("actor_on_update", check_transition_in_sight)
end
function actor_on_weapon_zoom_out()
UnregisterScriptCallback("actor_on_update", check_transition_in_sight)
binocular_hud_off()
end
function on_option_change()
mapspots_blips_show(opt.get("mapspot_blips_enabled"), true)
end
-- The only purpose of this function is to prevent stuttering due to the usage
-- of the utility function map_spot_get_texture_info(..)
-- This works on the basis of the assumption that each spot got the same attributes
local _cached_mapmarker_info_for
function cache_mapmarker_info()
local spots = {}
for route_id, route in route_manager.iterate_routes() do
for name, attributes in route_manager.iterate_transitions(route_id) do
local _, spot, __ = parent.get_transition_marker_info(name)
if (utils.map_spot_get_texture_info(spot)) then
_cached_mapmarker_info_for = spot
return
end
end
end
end
----------------------------
-- Monkey patches --
----------------------------
SRTeleportMsgBoxOk = ui_sr_teleport.msg_box_ui.OnMsgOk
-- We only update the discovery state, if player takes the transition
-- Executed through ltx script logic (xr_effects)
function ui_sr_teleport.msg_box_ui.OnMsgOk(self)
-- section from teleport_ini (should also be in txr_routes.routes table)
-- e.g. yan_space_restrictor_to_agroprom_1
local route_id = route_manager.get_route_id(self.name)
utils.assert(route_id, "SR-Teleport: '%s' got no assigned route", self.name)
if (not no_eligible_transitions()) then
toggle_known_route_state(route_id)
end
return SRTeleportMsgBoxOk(self)
end
------------------------
-- Main logic --
------------------------
function eligible_for_discovery(route_id)
local route = route_id and route_manager.get_route(route_id)
if utils.assert_failed(route) then return end
return (not route.recently_discovered)
end
function remove_anomaly_check_for(route_id)
if not utils.valid_type{ caller = "remove_anomaly_check_for",
"int", route_id } then return end
for k, v in pairs(anomalies_to_check) do
if (v == route_id) then
anomalies_to_check[k] = nil
end
end
end
-- Registers eligible transitions for discovery on the current level
-- TODO: Use transition name as key
-- Writes data like this: tbl[transition_ID] = route_id
-- @param force (forces a refresh)
-- @returns true (if eligible transitions exist)
function get_eligible_transitions_on_level(force)
if not (utils.is_table_empty(discoverable_on_level) or force) then return true end
local actor_level = utils.get_mapname()
if (utils.debug_level_loaded()) then
return
elseif (utils.is_underground(actor_level)) then
log("Underground level loaded, will not check for eligible transitions.")
return
end
log("Getting eligible transitions for '%s'", actor_level)
-- We only do this implicitly as this depends on the eligbility list
anomalies_to_check = {}
_g.iempty_table(discoverable_on_level)
for route_id, route in route_manager.iterate_routes(false) do
if (route.recently_discovered) then goto next_route end
for name, attributes in route_manager.iterate_transitions(route_id) do
local id = name and get_story_object_id(name)
local se_obj = id and alife_object(id)
if (not se_obj) then goto continue end
local transition_level = utils.get_mapname(se_obj)
if (actor_level ~= transition_level) then goto continue end
discoverable_on_level[id] = route_id
if (route.blocked == route.block_discovered) then break end
for _, anomaly_id in pairs(attributes.spawned_anomalies) do
anomalies_to_check[anomaly_id] = route_id
end
:: continue ::
end
:: next_route ::
end
if (utils.is_table_empty(discoverable_on_level)) then
log("No discoverable transitions on the current level.")
DISCOVERABLE_TRANSITIONS_ON_CURRENT_LEVEL = false
return
end
log("Discoverable transitions on the current Level:\n%s",
utils_data.print_table(discoverable_on_level, false, true))
DISCOVERABLE_TRANSITIONS_ON_CURRENT_LEVEL = true
return true
end
function inform_player(show_msg)
if (not sound_objs.discovery:playing()) then
sound_objs.discovery:play(player, 0, sound_object.s2d)
end
if (not show_msg) then return end
local message = game.translate_string("st_dynzone_discovery_message")
news_manager.send_tip(db.actor, message, 0, "recent_surge",
opt.get("discovery_msg_showtime"))
end
-------------------------
-- Map Markers --
-------------------------
function get_suited_mapspot_hint(id, hint)
if not utils.valid_type{ caller = "get_suited_mapspot_hint",
"int", id, "str", hint } then return end
local route = route_manager.get_route_by_transition(id)
if (utils.assert_failed(route, "ID #%s not a valid transition", id)) then return end
local inactive = route.id and route_manager.route_inactive(route.id)
local gts = game.translate_string
if (not inactive) and (route.blocked or not route.recently_discovered) then
new_hint = string.format("%s (%s)", gts(hint),
(not route.recently_discovered) and gts("st_dynzone_hint_unknown")
or gts("st_dynzone_hint_blocked"))
else
new_hint = gts(hint)
end
-- Route info in mapspot tooltip (debug)
if opt.get("verbose") then
local name = get_object_story_id(id)
new_hint = name and string.format("%s\\n[%s, #%s]", new_hint, name, route.id)
or new_hint
end
return new_hint
end
-- Changes the mapspot marker according to the blocked state of it's transition
-- Properly resets to original mapspot texture and color
-- @param id game object of the transition
-- @param spot default spot texture
-- @param blocked (optional)
function change_mapspot_marker(id, spot, blocked)
if not utils.valid_type{ caller = "mapspot_mark_blocked",
"int", id, "str", spot, "bool", blocked } then return end
if (blocked == nil) then -- get info via route manager
local name = get_object_story_id(id)
local route = name and route_manager.get_route_by_transition(name)
if utils.assert_failed(route) then return end
blocked = route.block_discovered
end
local texture, color = CONST_MAPSPOT_BLOCKED_TEXTURE
if (not blocked) then
local get_spot = _cached_mapmarker_info_for or spot
local texture_info = utils.map_spot_get_texture_info(get_spot)
texture = texture_info and texture_info.texture
color = texture_info and texture_info.color
else
color = GetARGB(_g.unpack(CONST_MAPSPOT_BLOCKED_COLOR))
end
if utils.assert_failed(texture, "Unable to determine a texture for %s", spot) then
return
end
log("Changing mapspot texture of (%s, %s) to '%s'", id, spot, texture)
utils.map_spot_change_texture(id, spot, texture)
if (color) then
log("Changing mapspot color of (%s, %s) to %s (pixelvalue)", id, spot, color)
utils.map_spot_change_color(id, spot, color)
end
end
-- Toggles the visibility of a mapspot blip. Creates it, if needed.
function mapspots_blip_update_for(transition_id, spot)
if not utils.valid_type{ caller = "mapspot_blip_update_for",
"int", transition_id, "str", spot } then return end
local name = get_object_story_id(transition_id)
local route = name and route_manager.get_route_by_transition(name)
if (utils.assert_failed(route, "Transition with ID %s has no defined route!", transition_id)) then return end
if (route_manager.route_inactive(route.id)) then return end
local blip = mapspot_blips[transition_id]
if (not blip) then
mapspot_blips[transition_id] = init_mapspot_blip(transition_id, spot)
blip = mapspot_blips[transition_id]
end
if (utils.assert_failed(blip, "Failed to initialize a blip for transition '%s'", transition_id)) then return end
blip.Show(opt.get("mapspot_blips_enabled") and not route.recently_discovered)
end
-- Toggles the display of blips for all mapspots
function mapspots_blips_show(state, conserve_route_flag)
if not utils.valid_type{ caller = "mapspot_blips_show", "bool", state } then return end
for route_id, route in route_manager.iterate_routes() do
for name, attributes in route_manager.iterate_transitions(route_id) do
local id, spot, _ = parent.get_transition_marker_info(name)
if (utils.assert_failed(id and spot)) then return end
if (not conserve_route_flag) then
route.recently_discovered = (not state)
end
mapspots_blip_update_for(id, spot)
end
end
end
-- Removed all blips and their references, also resets the route flag
-- @param conserve_route_flag (don't alter route flag)
function mapspots_blips_remove(conserve_route_flag)
for id, blip in pairs(mapspot_blips) do
local name = get_object_story_id(id)
local route = name and route_manager.get_route_by_transition(name)
if not (conserve_route_flag or utils.assert_failed(route)) then
route.recently_discovered = false
end
blip.Show(false)
mapspot_blips[id] = nil
end
end
-- Courtesy of Catspaw (Addon: Personal Adjustable Waypoints)
-- Init's a mapspot blip fir a given mapspot (id, spot)
-- @returns table
function init_mapspot_blip(id, spot, anchor)
if not utils.valid_type{ caller = "init_mapspot_blip",
"int", id, "str", spot } then return end
local anchor = anchor or level.map_get_object_spot_static(id, spot)
local xml = CScriptXmlInit()
local xmlroot = "dzt_ui_modifiers"
xml:ParseFile("dzt_ui_elements.xml")
local blip = {}
blip.id = id
blip.box = xml:InitStatic(xmlroot, anchor) -- CUIScriptWnd
blip.box:SetWndPos(vector2():set(CONST_MAPSPOT_BLIP_OFFSET_PIXELS,
CONST_MAPSPOT_BLIP_OFFSET_PIXELS +3)) -- sets (x,y) but root is top left
blip.blip = xml:InitStatic(xmlroot .. ":blip_unknown", blip.box)
blip.blip:SetWndSize(vector2():set(_g.round(19 *0.8), _g.round(21 *0.8)))
blip.Show = function(tf)
blip.box:Show(tf)
end
return blip
end
-- Removes mapspots added by the old method prior to version 20241119
function mapspots_remove_old()
mapspots_blips_remove(true)
for route_id, route in route_manager.iterate_routes() do
for transition_name, attributes in route_manager.iterate_transitions(route_id) do
local id, spot, hint = parent.get_transition_marker_info(transition_name)
assert(id and spot and hint)
level.map_remove_all_object_spots(id)
if (not utils.map_spot_exists(id, spot)) then -- sanity check
utils.map_spot_add(id, spot, hint)
end
update_transition_mapspot(transition_name)
end
end
end
---------------------------------
-- Binocular Discovery --
---------------------------------
-- TODO: use anomalies.get_spawn_parameters(transition_name).rootpos for distance check
check_transition_in_sight = utils.throttle(CONST_BINOCULAR_CHECK_IN_SIGHT_INTERVAL_MS, false, function()
if (BINOCULAR_DISCOVERY_IN_PROGRESS or no_eligible_transitions()) then return end
local wpn = db.actor:active_item() -- wait, until this is updated
if not (wpn and wpn:section() == "wpn_binoc_inv") then return end
-- TODO: Use a TimedEvent with an ID to delay HUD display whilst being able to cancel prematurely
binocular_hud_on()
local look_pos = utils.get_target_pos()
for transition_id, route_id in pairs(discoverable_on_level) do
if (utils.get_proximity_by_id(transition_id) > opt.get("binoc_discovery_max_distance")) then
goto next_transition
elseif (utils.get_point_proximity_by_id(transition_id, look_pos) > opt.get("binoc_discovery_dist")) then
goto next_transition
end
utils.timed_call(CONST_BINOCULAR_REFRESHRATE_MS, check_binocular_state,
{ id = transition_id, tg = time_global(), route_id = route_id })
log("Forked timed binocular check for transition '%s' (route #%s)",
get_object_story_id(transition_id), route_id)
BINOCULAR_DISCOVERY_IN_PROGRESS = true
play_binocular_sound_cue()
do break end -- Don't check other transitions
:: next_transition ::
end
end)
-- Periodically checks for discovery conditions and aborts accordingly.
function check_binocular_state(data)
local wpn = db.actor:active_item()
local look_pos = utils.get_target_pos()
local hold_time = time_global() - data.tg
local proximity = utils.get_point_proximity_by_id(data.id, look_pos)
-- no need to repeat this over and over.. avoiding goto's aswell
local function abort_discovery()
BINOCULAR_DISCOVERY_IN_PROGRESS = false
play_binocular_sound_cue()
return true
end
if (no_eligible_transitions()) then
log("No eligible transitions left to check")
return abort_discovery()
elseif not (wpn and wpn:section() == "wpn_binoc_inv") then
log("Not holding binoculars. Aborting.")
return abort_discovery()
elseif (not axr_main.weapon_is_zoomed) then
log("Binoculars are not zoomed in")
return abort_discovery()
elseif (proximity > opt.get("binoc_discovery_dist")) then
log("Point proximity is now too large. Aborting.")
return abort_discovery()
elseif (hold_time < opt.get("binoc_discovery_holdtime")) then
log("Target has not been focused long enough (%sms)", hold_time)
return
end
toggle_known_route_state(data.route_id, true)
BINOCULAR_DISCOVERY_IN_PROGRESS = false
return true
end
function play_binocular_sound_cue()
if (BINOCULAR_DISCOVERY_IN_PROGRESS) then
sound_objs.binoc_in_progress:play(player, 0, sound_object.s2d)
return
elseif (sound_objs.binoc_in_progress:playing()) then
sound_objs.binoc_in_progress:stop()
end
sound_objs.binoc_aborted:play(player, 0, sound_object.s2d)
end
------------------------
-- Visor HUD --
-- Courtesy of xcvb --
------------------------
function binocular_hud_on()
if BINOCULAR_HUD or (not opt.get("binoc_discovery_hud_enabled")) then return end
BINOCULAR_HUD = binocular_hud()
get_hud():AddDialogToRender(BINOCULAR_HUD)
log("Enabled Binocular-HUD")
end
function binocular_hud_off()
if (not BINOCULAR_HUD) then return end
get_hud():RemoveDialogToRender(BINOCULAR_HUD)
BINOCULAR_HUD = nil
log("Disabled Binocular-HUD")
end
class "binocular_hud" (CUIScriptWnd)
function binocular_hud:__init() super()
self:InitControls()
end
function binocular_hud:__finalize() end
function binocular_hud:InitControls()
self:SetWndRect(Frect():set(0,0,1024,768))
self:SetAutoDelete(true)
self.xml = CScriptXmlInit()
local xml = self.xml
xml:ParseFile("actor_menu.xml")
self.hud_update_timer = 0
self.transitions = {}
self.elements = {}
self.texture = CONST_BINOCULAR_HUD_ICON_TEXTURE
local size = CONST_BINOCULAR_HUD_ICON_TEXTURE_SIZE
for i = 1, CONST_BINOCULAR_HUD_MAX_VISIBLE_TRANSITIONS do
self.elements[i] = xml:InitStatic("helmet_over", self)
self.elements[i]:InitTexture("ui_mmap_stask_last_02")
self.elements[i]:SetWndSize(vector2():set(size[1], size[2]))
self.elements[i]:Show(false)
end
end
function binocular_hud:Update()
CUIScriptWnd.Update(self)
self:GatherTransitions()
-- display eligible transitions in close proximity
for i = 1, CONST_BINOCULAR_HUD_MAX_VISIBLE_TRANSITIONS do
self.elements[i]:Show(false)
local transition = self.transitions[i]
if (not transition) then goto continue end
local id = transition.id
-- To make sure that it is updated immediately after discovery
if not (discoverable_on_level[id]) then goto continue end
local obj = level.object_by_id(id)
local name = obj and obj:name()
local pos = name and get_anomaly_rootpos(name)
if (not pos) then
local obj_pos = obj:position()
pos = utils.get_closest_vertex_pos(obj_pos)
or vector():set(obj_pos.x, obj_pos.y, obj_pos.z)
end
-- Note: The position variable should be temporary
pos.y = pos.y + CONST_BINOCULAR_HUD_ICON_HOVER_METRES
local wui_pos = pos and vector2():set(game.world2ui(pos))
if wui_pos then
self.elements[i]:InitTexture(self.texture)
self.elements[i]:SetWndPos(vector2():set(wui_pos.x, wui_pos.y))
self.elements[i]:Show(true)
end
:: continue ::
end
end
function binocular_hud:GatherTransitions()
local tg = time_global()
if (self.hud_update_timer > tg) then return end
self.hud_update_timer = tg + CONST_DISCOVERY_CHECK_INTERVAL_MS
iempty_table(self.transitions)
if (no_eligible_transitions()) then return end
local max_distance = opt.get("binoc_discovery_max_distance")
for transition_id, route_id in pairs(discoverable_on_level) do
local distance = utils.get_proximity_by_id(transition_id)
if (distance > max_distance) then goto continue end
self.transitions[#self.transitions +1] = { id = transition_id, }
:: continue ::
end
end
@@ -0,0 +1,206 @@
--[[
DYNAMIC ZONE - MCM Options
Original Author(s)
VodoXleb <vodoxlebushek>
Singustromo <singustromo at disroot.org>
Edited by
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
(https://creativecommons.org/licenses/by-nc-sa/4.0)
--]]
CONST_ACRONYM = "dynamic_zone"
CONST_DEFAULT_CATEGORY = "general"
options = {} -- This contains cached option values indexed by option name
colors = { -- ARGB
title = {255, 255, 255, 0},
desc = {255, 109, 187, 164},
notice = {255, 232, 61, 102},
}
defaults = {
["general"] = {
["chance_path_closed"] = 30, -- for any given path between two maps
["chance_dz_trigger"] = 75, -- for the zone to change during an emission
["minimum_map_connections"] = 1,
["trigger_on_newgame"] = true, -- If some routes should already be disabled at the beginning
["newgame_grace_period"] = 12, -- For the delay after New game before first blockage (Grace Period)
["emission_trigger"] = "2ndwave", -- in which phase we trigger
["addon_removal"] = false,
},
["news"] = {
["percent_path_reveal_unblock"] = 60,
["percent_path_reveal_block"] = 50,
["chance_special_character"] = 25,
["news_play_discovery_sound"] = true,
},
["discovery"] = {
["discovery_msg_showtime"] = 4000,
["mapspot_blips_enabled"] = true,
["binoc_discovery_hud_enabled"] = true,
["binoc_discovery_holdtime"] = 3500,
["binoc_discovery_dist"] = 40,
["binoc_discovery_max_distance"] = 350,
},
["debug"] = {
["emission_check_interval"] = 10000, -- in milliseconds
["validate_parameter_types"] = false,
["verbose"] = false,
},
}
-- Getter for other scripts, using cached values
-- Simplifies getting the values through a unique id
function get(key)
return options[key]
end
function on_game_start()
RegisterScriptCallback("on_option_change", apply_settings)
apply_settings()
end
function apply_settings()
for category, settings in pairs(defaults) do
for option,_ in pairs(settings) do
options[option] = get_config(category, option)
end
end
end
function on_mcm_load()
local op = {
id = CONST_ACRONYM,
text = "ui_mcm_"..CONST_ACRONYM,
gr = {}
}
local general = {
id = "general",
sh = true,
text = "ui_mcm_"..CONST_ACRONYM.."_general",
gr = {
{ id = "title", type ="slide", link = "ui_options_slider_sound_environment",
text = "ui_mcm_"..CONST_ACRONYM.."_main_title", size = {512,50}, spacing = 20 },
{ id = "trigger_on_newgame", type = "check", val = 1,
def = defaults["general"]["trigger_on_newgame"] },
{ id = "newgame_grace_period", type = "track", val = 2, min = 0, max = 96, step = 12,
def = defaults["general"]["newgame_grace_period"] },
{ id = "chance_dz_trigger", type = "track", val = 2, min = 0, max = 100, step = 5,
def = defaults["general"]["chance_dz_trigger"] },
{ id = "emission_trigger", type = "list", val = 0, def = defaults["general"]["emission_trigger"],
content = {
{ "impact", CONST_ACRONYM.. "_emission_trigger_impact" },
{ "1stwave", CONST_ACRONYM.. "_emission_trigger_1stwave" },
{ "2ndwave", CONST_ACRONYM.. "_emission_trigger_2ndwave" },
{ "rumble", CONST_ACRONYM.. "_emission_trigger_rumble" },
},
},
{ id = "chance_path_closed", type = "track", val = 2, min = 0, max = 100, step = 5,
def = defaults["general"]["chance_path_closed"] },
{ id = "minimum_map_connections", type = "track", val = 2, min = 0, max = 4, step = 1,
def = defaults["general"]["minimum_map_connections"] },
{ id = "divider", type = "line" },
{ id = "addon_removal", type = "check", val = 1, def = defaults["addon_removal"] },
}
}
local news = {
id = "news",
sh = true,
text = "ui_mcm_"..CONST_ACRONYM.."_news",
gr = {
{ id = "title", type ="slide", link = "ui_options_slider_news",
text = "ui_mcm_"..CONST_ACRONYM.."_news_title", size = {512,50}, spacing = 20 },
{ id = "header", type = "desc", text = "ui_mcm_"..CONST_ACRONYM.."_news_desc", clr = colors.desc},
{ id = "news_play_discovery_sound", type = "check", val = 1,
def = defaults["news"]["news_play_discovery_sound"] },
{ id = "percent_path_reveal_unblock", type = "track", val = 2, min = 0, max = 100, step = 5,
def = defaults["news"]["percent_path_reveal_unblock"] },
{ id = "percent_path_reveal_block", type = "track", val = 2, min = 0, max = 100, step = 5,
def = defaults["news"]["percent_path_reveal_block"] },
{ id = "chance_special_character", type = "track", val = 2, min = 0, max = 100, step = 5,
def = defaults["news"]["chance_special_character"] },
}
}
local discovery = {
id = "discovery",
sh = true,
text = "ui_mcm_"..CONST_ACRONYM.."_discovery",
gr = {
{ id = "title", type ="slide", link = "ui_options_slider_emission",
text = "ui_mcm_"..CONST_ACRONYM.."_discovery_title", size = {512,50}, spacing = 20 },
{ id = "discovery_msg_showtime", type = "track", val = 2, min = 1000, max = 10000, step = 500,
def = defaults["discovery"]["discovery_msg_showtime"] },
{ id = "mapspot_blips_enabled", type = "check", val = 1,
def = defaults["discovery"]["mapspot_blips_enabled"] },
{ id = "divider", type = "line" },
{ id = "binoc_discovery_hud_enabled", type = "check", val = 1,
def = defaults["discovery"]["binoc_discovery_hud_enabled"] },
{ id = "binoc_discovery_holdtime", type = "track", val = 2, min = 1000, max = 10000, step = 500,
def = defaults["discovery"]["binoc_discovery_holdtime"] },
{ id = "binoc_discovery_dist", type = "track", val = 2, min = 20, max = 80, step = 5,
def = defaults["discovery"]["binoc_discovery_dist"] },
{ id = "binoc_discovery_max_distance", type = "track", val = 2, min = 150, max = 500, step = 25,
def = defaults["discovery"]["binoc_discovery_max_distance"] },
}
}
local debug = {
id = "debug",
sh = true,
text = "ui_mcm_"..CONST_ACRONYM.."_debug",
gr = {
{ id = "title", type ="slide", link = "ui_options_slider_sound_environment",
text = "ui_mcm_"..CONST_ACRONYM.."_debug_title", size = {512,50}, spacing = 20 },
{ id = "header", type = "desc", text = "ui_mcm_"..CONST_ACRONYM.."_debug_desc", clr = colors.desc},
{ id = "verbose", type = "check", val = 1,
def = defaults["debug"]["verbose"] },
{ id = "validate_parameter_types", type = "check", val = 1,
def = defaults["debug"]["validate_parameter_types"] },
{ id = "emission_check_interval", type = "track", val = 2, min = 2000, max = 20000, step = 500,
def = defaults["debug"]["emission_check_interval"] },
}
}
table.insert(op.gr, general)
table.insert(op.gr, news)
table.insert(op.gr, discovery)
table.insert(op.gr, debug)
return op
end
function get_config(id, key)
if not (key and type(key) == 'string') then return end
id = (id and type(id) == 'string') and id or CONST_DEFAULT_CATEGORY
if ui_mcm and type(ui_mcm.get) == 'function' then
return ui_mcm.get(CONST_ACRONYM .. "/".. id .. "/" .. key)
end
return defaults[id][key]
end
function set_config(id, key, value)
if not (key and type(key) == 'string') then return end
id = (id and type(id) == 'string') and id or CONST_DEFAULT_CATEGORY
if (not ui_mcm and type(ui_mcm.set) == 'function') then return end
ui_mcm.set(CONST_ACRONYM .. "/".. id .. "/" .. key, value)
end
@@ -0,0 +1,339 @@
--[[
DYNAMIC ZONE - PDA News
Original Author(s)
Singustromo <singustromo at disroot.org>
VodoXleb <vodoxlebushek>
Edited by
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
(https://creativecommons.org/licenses/by-nc-sa/4.0)
--]]
parent = _G["dynamic_zone"]
if not (parent and parent.VERSION and parent.VERSION >= 20241224) then return end
--------------------------
-- Dependencies --
--------------------------
local opt = dynamic_zone_mcm
local utils = dynamic_zone_utils
local debug = dynamic_zone_debug
local route_manager = dynamic_zone_routes
local route_discovery = dynamic_zone_discovery
---------------------------------
-- Globals & Constants --
---------------------------------
CONST_LOGGING_PREFIX = "Dynamic News"
local log = debug.log_register("info", CONST_LOGGING_PREFIX)
local log_warn = debug.log_register("warning", CONST_LOGGING_PREFIX)
local log_err = debug.log_register("error", CONST_LOGGING_PREFIX)
CONST_RANDOMIZER_BEZIER_PARAMETERS = { 0, .0, .2, .9 } -- 41.9%
CONST_PROPAGATION_INTERVAL_MS = 20000
CONST_FALLBACK_DELAY_MIN_MS = 500
CONST_FALLBACK_DELAY_MAX_MS = CONST_PROPAGATION_INTERVAL_MS * 0.5
CONST_MESSAGE_MAX_STRINGS_TO_ITERATE = 20
CONST_STRING_ID_PREFIX = "st_dynzone_news"
CONST_STRING_ID_FALLBACK = CONST_STRING_ID_PREFIX .. "_fallback"
CONST_STRING_ID_SUFFIX_BLOCKED = "blocked"
CONST_STRING_ID_SUFFIX_OPENED = "opened"
CONST_NEWS_FALLBACK_ICON = "ui_iconsTotal_grouping"
CONST_MESSAGE_FALLBACK_NAME = "Bratan"
routes_to_reveal = {} -- routes whose changes will be propagated by other stalkers.
function clear()
log("Cleared route propagation queue")
routes_to_reveal = {}
end
special_characters = {
-- [story_id] = identifier (for strings)
["esc_m_trader"] = "sidorovich", -- Loner
["bar_dolg_general_petrenko_stalker"] = "petrenko", -- Duty
["mil_smart_terrain_7_7_freedom_leader_stalker"] = "lukash", -- Freedom
-- ["mar_smart_terrain_base_stalker_leader_marsh"] = "cold", -- Clear Sky
["yan_stalker_sakharov"] = "sakharov", -- Ecologists
["cit_killers_merc_trader_stalker"] = "dushman", -- Mercenaries
["agr_smart_terrain_1_6_near_2_military_colonel_kovalski"] = "kovalski", -- Military
["zat_b7_bandit_boss_sultan"] = "sultan", -- Bandits
["pri_monolith_monolith_trader_stalker"] = "krolik", -- Monolith
}
------------------------------
-- Just Shortcuts --
------------------------------
local ctime_to_tbl = utils_data.CTime_to_table
local tbl_to_ctime = utils_data.CTime_from_table
-- Using bezier curves for non-linear probability and to clamp result
-- Used so mean will be set percentage over time (of the time frame)
function get_random_time(lower, upper)
local randomizer = libmath_bezier and libmath_bezier.get_random_value
if utils.assert_failed(randomizer, "Bézier script not found. Using math.random()") then
return math.random(lower, upper)
end
return randomizer(lower, upper, CONST_RANDOMIZER_BEZIER_PARAMETERS)
end
-------------------------
-- Callbacks --
-------------------------
function on_game_start()
RegisterScriptCallback("dynzone_changed_block_state",
discover_changed_routes_via_news)
RegisterScriptCallback("actor_on_update", check_timed_unlocks)
end
function discover_changed_routes_via_news(previously_blocked_routes, new_blocked_routes)
clear()
queue_routes_for_propagation(previously_blocked_routes,
opt.get("percent_path_reveal_unblock"), CONST_STRING_ID_SUFFIX_OPENED)
queue_routes_for_propagation(new_blocked_routes,
opt.get("percent_path_reveal_block"), CONST_STRING_ID_SUFFIX_BLOCKED)
RegisterScriptCallback("actor_on_update", check_timed_unlocks)
end
-- Iterates through the route discovery queue and
-- checks if any of them are due to being propagated
check_timed_unlocks = utils.throttle(CONST_PROPAGATION_INTERVAL_MS, true, function()
if (utils.is_table_empty(routes_to_reveal)) then
log("No routes in the news queue. Unregistered Callback.")
UnregisterScriptCallback("actor_on_update", check_timed_unlocks)
return
end
local current_ctime = game.get_game_time()
log("Current time: %s", string.format("%d/%.2d/%.2d %.2d:%.2d:%.2d",
current_ctime:get(Y,M,D,h,m,s,ms)))
for route_id, data in pairs(routes_to_reveal) do
utils.assert(data, "Undefined Route data")
utils.assert(data.reveal_time, "Undefined Route reveal time")
local reveal_time = tbl_to_ctime(data.reveal_time)
local remaining_time_ms = (reveal_time:diffSec(current_ctime) / level.get_time_factor()) * 1000
reveal_time:sub(current_ctime)
if (remaining_time_ms >= CONST_PROPAGATION_INTERVAL_MS) then
local _, __, d, h, m, s, ___ = reveal_time:get(Y,M,D,h,m,s,ms)
log("Route #%s will be propagated in %sd %sh %sm %ss",
route_id, (d -1), h, m, s)
goto continue
end
remaining_time_ms = (remaining_time_ms < 0)
and math.random(CONST_FALLBACK_DELAY_MIN_MS, CONST_FALLBACK_DELAY_MAX_MS)
or remaining_time_ms
log("Route #%s will be propagated in %ss (realtime)", route_id,
string.format("%.1f", remaining_time_ms / 1000))
utils.assert(data.reveal_type, "Undefined route reveal type!")
utils.timed_call(remaining_time_ms, function()
propagate_route_state_change(route_id, data.reveal_type)
return true
end)
:: continue ::
end
end)
--------------------------
-- Main logic --
--------------------------
function propagate_route_state_change(route_id, reveal_type)
if not utils.valid_type{ caller = "propagate_route_state_change",
"int", route_id } then return end
local route = route_manager.get_route(route_id)
local levels, sender = route and route.connects
if math.random() > (opt.get("chance_special_character") / 100) then
sender = find_random_stalker_on_level_pair(levels)
else
sender = find_special_character_on_level_pair(levels)
end
local route_state_differs = route_manager.route_known_state_differs(route_id)
local play_discovery_sound = opt.get("news_play_discovery_sound") and route_state_differs
if not utils.assert_failed(sender, "Sender for route #%s is nil!", route_id) then
local anomaly_theme = route_manager.get_route_property(route_id, "anomaly_theme")
send_route_news_tip(reveal_type, 0, sender, 10, levels, anomaly_theme, play_discovery_sound)
end
-- TODO: Check, if still eligible to prevent log spamming at this point
-- We still want to propagate the information, nonetheless.
log("Revealing %s state of route #%s via news.", reveal_type, route_id)
route_discovery.toggle_known_route_state(route_id, play_discovery_sound)
routes_to_reveal[route_id] = nil
end
function queue_routes_for_propagation(selected_routes, percent_to_reveal, reveal_type)
local indexed_routes = {}
utils.index_keys(selected_routes, indexed_routes)
-- time before next emission when all reveal messages should be posted
local next_emission_in_hours = surge_manager and surge_manager.get_surge_manager
and (surge_manager.get_surge_manager()._delta / (60^2)) -- game time
if (not next_emission_in_hours) then
next_emission_in_hours = ui_options.get("alife/event/emission_frequency")
log_warn("Surge manager not available, using frequency set in options.")
end
local revealed = 1
local amount_to_reveal = math.floor(#indexed_routes * (percent_to_reveal/100))
for id in utils.random_numbered_sequence(1, #indexed_routes) do
if (revealed > amount_to_reveal) then goto continue end
revealed = revealed +1
local minutes = 6 * get_random_time(3, next_emission_in_hours * 10)
local hours = math.floor(minutes / 60)
minutes = minutes % 60
local days = math.floor(hours / 24)
hours = hours % 24
local add_time = game.CTime()
-- days +1 so we get proper result (engine quirk)
add_time:set(1, 1, (days +1), hours, minutes, math.random(0, 59), 0)
local selected_time = game.get_game_time()
selected_time:add(add_time)
log("Queued route #%s for propagation (%s)", id, reveal_type)
routes_to_reveal[indexed_routes[id]] = {
route = selected_routes[indexed_routes[id]],
reveal_time = ctime_to_tbl(selected_time), -- don't save userdata
reveal_type = reveal_type,
}
:: continue ::
end
end
function find_random_stalker_on_level_pair(levels)
if not utils.valid_type{ caller = "find_random_stalker_on_level_pair",
"tbl", levels } then return end
for id in utils.random_numbered_sequence(1, 2^16 -2) do
local se_obj = alife():object(id)
if not (se_obj) then goto continue end
if IsStalker(nil, se_obj:clsid())
and se_obj:alive()
and se_obj:community() ~= "zombied"
and se_obj:community() ~= "trader"
and se_obj:community() ~= "greh"
and se_obj:community() ~= "isg"
and se_obj:community() ~= "renegade"
and se_obj.group_id ~= 65535
and (get_object_story_id(se_obj.group_id) == nil)
and string.find(se_obj:name(),"sim_default_")
and utils.table_has(levels, utils.get_mapname(se_obj)) then
return id
end
:: continue ::
end
end
function find_special_character_on_level_pair(levels)
if not utils.valid_type{ caller = "find_special_character_on_level_pair",
"tbl", levels } then return end
local found_stalkers = {}
for k, identifier in pairs(special_characters) do
local id = get_story_object_id(k)
local se_obj = id and alife_object(id)
if not (se_obj) then goto continue end
local character_map = utils.get_mapname(se_obj)
local connected_maps = character_map and utils.get_directly_connected_maps(character_map)
-- Route should at least be indirectly connected to the senders map
if utils.table_contains(connected_maps, levels) then
found_stalkers[#found_stalkers + 1] = se_obj.id
end
:: continue ::
end
return found_stalkers[math.random(1, #found_stalkers)]
or find_random_stalker_on_level_pair(levels)
end
function send_route_news_tip(news_reveal_type, timeout, sender_id, showtime, news_levels, news_anom_theme, suppress_pda_sound)
timeout = timeout or 0
showtime = showtime or 5
local npc = alife():object(sender_id)
if (not npc) then return end
local actor = db.actor
local texture = (npc.character_icon) and npc:character_icon() or CONST_NEWS_FALLBACK_ICON
local special_character_nickname = special_characters[get_object_story_id(npc.id)]
local npc_story_id = special_character_nickname or npc:community()
local msg_to_translate = string.format("%s_%s_%s_", CONST_STRING_ID_PREFIX, npc_story_id, news_reveal_type)
local phrases = {}
for i = 1, CONST_MESSAGE_MAX_STRINGS_TO_ITERATE do
if (utils.has_translation(msg_to_translate .. i)) then
phrases[#phrases +1] = i
end
end
if (utils.is_table_empty(phrases)) then
log_warn("Undefined string group: '%s'. Using fallback.", msg_to_translate:sub(1, -2))
msg_to_translate = CONST_STRING_ID_FALLBACK .. "_" .. news_reveal_type
else
msg_to_translate = msg_to_translate .. phrases[math.random(1, #phrases)]
end
-- Make sure $FROM is the senders level, when route connects sender map
local sender_level = utils.get_mapname(npc)
local index = utils.index_of(news_levels, sender_level) or math.random(1, #news_levels)
local level_from, level_to = news_levels[index], news_levels[#news_levels -index +1]
utils.assert(level_from and level_to)
local character_name = (npc.character_name) and npc:character_name()
local news_caption = character_name or game.translate_string("st_tip")
-- TODO: Maybe need a debug mode flag for cases such as this
news_caption = (opt.get("verbose"))
and string.format("%s (%s)", news_caption, utils.get_mapname(npc))
or news_caption
local anomaly_theme_string = dynamic_zone_anomalies.get_theme_string(news_anom_theme) or ""
local news_text = game.translate_string(msg_to_translate)
news_text = news_text:gsub("%$SENDER_NAME", character_name or CONST_MESSAGE_FALLBACK_NAME)
news_text = news_text:gsub("%$FROM", game.translate_string(level_from))
news_text = news_text:gsub("%$TO", game.translate_string(level_to))
news_text = news_text:gsub("%$ANOM_THEME", game.translate_string(anomaly_theme_string))
actor:give_game_news(news_caption, news_text, texture, timeout *1000, showtime *1000, 0)
if (not suppress_pda_sound) then
xr_sound.set_sound_play(AC_ID, "pda_tips") -- play default sound
end
end
@@ -0,0 +1,482 @@
--[[
DYNAMIC ZONE
Original Author(s)
Singustromo <singustromo at disroot.org>
Edited by
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
(https://creativecommons.org/licenses/by-nc-sa/4.0)
This file provides the rough structure for saving transitions and
their pairs - called routes in this context.
Additional info:
tables, functions, userdata and threads are passed around by reference,
while numbers, booleans, and nil are passed by value
Despite this we reference entries by their index because both tables
are saved in m_data. Can't reference them.
--]]
parent = _G["dynamic_zone"]
if not (parent and parent.VERSION and parent.VERSION >= 20241224) then return end
--------------------------
-- Dependencies --
--------------------------
-- verified in main script
local utils = dynamic_zone_utils
local debug = dynamic_zone_debug
CONST_LOGGING_PREFIX = "Routes"
local log = debug.log_register("info", CONST_LOGGING_PREFIX)
local log_error = debug.log_register("error", CONST_LOGGING_PREFIX)
---------------------
-- Structure --
---------------------
registered_routes = {}
registered_transitions = {
--[[
[size] = <int>,
[transition_name] = {
route = route_id, -- index in registeres_routes
master = true, -- exception for 1 -> n routes (e.g. truck cemetary)
spawned_anomalies = {}
},
...
--]]
}
function route_count()
return ((utils.is_table_empty(registered_routes))
and 0 or size_table(registered_routes))
end
function transition_count()
return (registered_transitions.size or 0)
end
function clear()
registered_routes = {}
registered_transitions = {}
end
-- first initialization of a route
--- @returns id of route (index)
function route_create()
local id = #registered_routes +1
registered_routes[id] = {
id = id, -- Needed in rare cases
members = { }, -- transition names
connects = { }, -- level names (game_levels.ltx)
blacklisted = false,
unlocked = true,
blocked = false,
block_discovered = false,
recently_discovered = false, -- set during emission (controls blip)
anomaly_theme = 0,
}
return id
end
function transition_register(transition_name, route_id)
if not utils.valid_type{ caller = "transition_register", "str", transition_name,
"tbl", registered_routes[route_id] } then return end
local id = get_story_object_id(transition_name)
if (utils.assert_failed(id, "%s is not a Story-ID. Not registered.")) then return end
local route_members = registered_routes[route_id].members
if utils.table_has(route_members, transition_name) then return end
registered_transitions[transition_name] = {
route = route_id,
master = false,
spawned_anomalies = {}, -- holds the object ids
}
table.insert(route_members, transition_name)
local index = (registered_transitions.size or 0) +1
registered_transitions.size = index
return index
end
-------------------------------------------------------------------------------
function transition_table_register(tbl, route_id)
local registered = {}
if not utils.valid_type{ caller = "transition_table_register",
"tbl", tbl, "int", route_id } then return registered end
for _, transition_name in pairs(tbl) do
if not transition_register(transition_name, route_id) then
log_error("Transition '%s' has already been registered!", transition_name)
else
registered[#registered +1] = transition_name
end
end
return registered
end
-- @returns mutable reference
function get_route(route_id)
return registered_routes[route_id]
end
-- @returns mutable reference
function get_transition(transition_name)
return registered_transitions[transition_name]
end
function route_exists(route_id)
return (nil ~= registered_routes[route_id])
end
function transition_exists(transition_name)
return (nil ~= registered_transitions[transition_name])
end
-------------------------------------------------------------------------------
-- Wacky implementation
-- TODO: Improve condition declaration and parsing
-- Conditions are table entries (route flags) which are or'ed
-- attributes are negated with an '!' or can be joined via an and '*'
-- e.g. `get_routes{"blocked*!discovered", "!blocked*discovered"}`
-- Should only be used with route flags (true, false)
-- @returns <table> (route_ids)
function get_routes(conditions)
if not utils.valid_type{ caller = "get_routes", "tbl", conditions } then return end
if utils.is_table_empty(conditions) then return end
local matches = {}
local func_body = ""
for _, condition in pairs(conditions) do
local parsed = condition
parsed = parsed:gsub('*!', ' and not ref.')
parsed = parsed:gsub('*', ' and ref.')
parsed = parsed:gsub('!', 'not ref.')
parsed = (string.find(parsed, "^not")) and parsed or "ref." .. parsed
func_body = func_body .. "(" .. parsed .. ") or "
end
func_body = func_body:sub(1, -5) -- remove last ' or '
local to_eval = "return function(ref) return (" .. func_body .. ") end"
local func, err = loadstring(to_eval)
if (err) then
log_error("Unable to evaluate '%s'\n! %s", to_eval, err)
return
end
-- loadstring encapsulates input into another function
local check_func = func()
for route_id, route in iterate_routes(true) do
local status, retval = pcall(check_func, route)
if (status and retval) then
matches[#matches +1] = route_id
end
end
return matches
end
-------------------------------------------------------------------------------
-- Filters locked and blacklisted routes by default
-- @returns name, modifiable route reference
function iterate_routes(include_inactive)
local index = 0
return function()
index = index + 1
if not (include_inactive) then
while (registered_routes[index] and route_inactive(index)) do
index = index + 1
end
end
if (index <= #registered_routes) then
return index, registered_routes[index]
end
end
end
-- @returns name, mutable-reference
function iterate_transitions(route_id)
local route = get_route(route_id)
local members = route and route.members
if (not members) then return end
local index = 0
return function()
index = index + 1
if (index > #members) then return end
return members[index], get_transition(members[index])
end
end
-------------------------------------------------------------------------------
function set_transition_property(name, property, value)
local transition = get_transition(name)
if not utils.valid_type{ caller = "set_transition_property",
"tbl", transition, "str", property} then return end
if (type(value) == 'nil') then return end
if (type(transition[property]) == "nil") then return end
transition[property] = value
return true
end
-- @returns immutable reference
function get_transition_property(name, property)
local transition = get_transition(name)
if (not transition) then return end
return transition[property]
end
-------------------------------------------------------------------------------
function set_route_property(route_id, property, value)
local route = get_route(route_id)
if not utils.valid_type{ caller = "set_route_property",
"tbl", route, "str", property} then return end
if (type(value) == 'nil') then return end
if (type(route[property]) == "nil") then return end
route[property] = value
return true
end
-- @returns immutable reference
function get_route_property(route_id, property)
local route = get_route(route_id)
if (not route) then return end
return route[property]
end
function get_route_id(transition_name)
local transition = get_transition(transition_name)
return (transition and transition.route)
end
-- used when we only have the transition name
-- @returns modifyable route reference
function get_route_by_transition(gizmo)
local transition_name = (type(gizmo) == "number")
and get_object_story_id(gizmo) or gizmo
if (utils.assert_failed(transition_name)) then return end
local transition = get_transition(transition_name)
return (transition and get_route(transition.route))
end
has_route = get_route_by_transition -- alias for readability's sake
-- @returns immutable reference
function get_route_members(route_id)
local route = get_route(route_id)
return (route and route.members)
end
-------------------------------------------------------------------------------
function route_inactive(route_id)
local route = get_route(route_id)
if (not route) then return true end
return (route.blacklisted or (not route.unlocked))
end
-- only really need this, if we do not replace accessible zone
function route_unlock(route_id)
local route = get_route(route_id)
if (not route) then return end
route.unlocked = true
return true
end
function route_unlocked(route_id)
local route = get_route(route_id)
if (not route) then return end
return (route.unlocked)
end
function route_locked(route_id)
return (not route_unlocked(route_id))
end
-------------------------------------------------------------------------------
function route_block(route_id)
local route = get_route(route_id)
if not (route and route.unlocked) then return end
route.blocked = true
return true
end
function route_unblock(route_id)
local route = get_route(route_id)
if not (route and route.unlocked and route.blocked) then return end
route.blocked = false
return true
end
function route_blocked(route_id)
local route = get_route(route_id)
if (not route) then return end
return (route.blocked)
end
-------------------------------------------------------------------------------
-- We also pass an additional functor to be executed here
function route_discover(route_id, functor, ...)
local vararg = {...}
local route = get_route(route_id)
if not (route and route.blocked) then return end
route.block_discovered = true
if (functor and type(functor) == "function") then
functor(unpack(vararg))
end
return true
end
function route_discovered(route_id)
local route = get_route(route_id)
return (route and route.block_discovered)
end
function route_known_state_differs(route_id)
local route = get_route(route_id)
return route and (route.blocked ~= route.block_discovered)
end
-------------------------------------------------------------------------------
function transition_tostring(transition_name, indentation, indent_str)
indentation = (indentation) or 0
indent_str = (indent_str) or " "
local transition = get_transition(transition_name)
local string = string.rep(indent_str, indentation)
.. "[" .. transition_name .. "] = {\n"
for key, value in pairs(transition) do
if (key == "route") then
goto next_attribute
end
string = string .. string.rep(indent_str, indentation +1)
.. key .. " = "
if (type(value) == "table") then
string = string .. "{" .. table.concat(value, ",") .. "}"
else
string = string .. tostring(value)
end
string = string .. "\n"
:: next_attribute ::
end
return string .. string.rep(indent_str, indentation) .. "}\n"
end
-- crude and specific string generation of attribute tables
function route_tostring(route_id, include_member_attributes)
local route = get_route(route_id)
if (not route) then
log_error("Printinfo No route with ID #%s !", route_id)
return
end
local indentation = " "
local string = string.format("[%03d]\n", route_id)
for key, value in pairs(route) do
if (key == 'id') then goto next_attribute end
string = string .. indentation .. key .. " = "
if (type(value) ~= "table") then
string = string .. tostring(value)
goto continue
end
if ((not include_member_attributes) or key ~= "members") then
string = string .. "{" .. table.concat(value, ", ") .. "}"
goto continue
end
-- lazy way to serialize member attributes
string = string .. "{\n"
for _, section in pairs(value) do
string = string .. transition_tostring(section, 2, indentation)
end
string = string .. indentation .. "}"
:: continue ::
string = string .. "\n"
:: next_attribute ::
end
return string:sub(1, -2) -- remove last new line
end
-- Prints all routes with the specified attributes
-- @returns amount of all blocked routes
function print_routes(conditions)
local output_string = string.format("Route Attributes%s: ",
(conditions) and " (" .. table.concat(conditions, ", ") .. ")" or "")
local routes = get_routes(conditions)
if (not routes or utils.is_table_empty(routes)) then return end
for _, route_id in pairs(routes) do
output_string = output_string .. "\n" .. route_tostring(route_id, true)
end
log("%s", output_string)
end
-- Prints all the information agnostic to what type the parameter is
function printinfo(gizmo)
local output_string = "Attributes of"
if route_exists(gizmo) then
output_string = string.format("%s route #%s:\n%s",
output_string, gizmo, route_tostring(gizmo, true))
elseif transition_exists(gizmo) then
output_string = string.format("%s transition '%s':\n%s",
output_string, gizmo, transition_tostring(gizmo))
else return end
log("%s", output_string)
end
@@ -0,0 +1,641 @@
--[[
DYNAMIC ZONE
Original Author(s)
Singustromo <singustromo at disroot.org>
Edited by
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
(https://creativecommons.org/licenses/by-nc-sa/4.0)
This script contains general purpose utility functions and logic used
to decouple the vanilla anomaly logic from the addon logic.
We've taken some inspiration from NLTP_ASHES' Western Goods.
--]]
parent = _G["dynamic_zone"]
if not (parent and parent.VERSION and parent.VERSION >= 20241224) then return end
CONST_GAMETICK_DURATION_MS = 16
CONST_DEFAULT_PROXIMITY_DISTANCE = 2^16 -1
CONST_MAX_VALID_LVID = 2^32 -2
-------------------------
-- Dependencies
-------------------------
local opt = dynamic_zone_mcm
local debug = dynamic_zone_debug
CONST_LOGGING_PREFIX = "Utilities"
local log = debug.log_register("info", CONST_LOGGING_PREFIX)
local log_error = debug.log_register("error", CONST_LOGGING_PREFIX)
----------------------------
-- Input Validation --
----------------------------
-- Inspired by Western Goods
-- Checks, if all necessary parameters are non-nil and have the correct type
-- Use it like this: valid_type{ caller = "function_name", type, value, ... }
-- The boolean type explicitely accepts only true|false as values
-- @param tbl
-- @returns boolean
function valid_type(tbl)
if (not opt.get("validate_parameter_types")) then return true end
local type_alias = {
int = "number", str = "string", tbl = "table",
fn = "function" , bool = "boolean", usr = "userdata",
}
local caller = tbl.caller and string.format("[%s] ", tbl.caller) or ""
local param_index, encountered_error = 1, false
for i=1, #tbl, 2 do
local typ, value, value_type = tbl[i], tbl[i +1]
typ = type_alias[typ] or typ
if not (typ == "boolean" or value) then
log_error("%sParameter no. %s is nil%s", caller, param_index, callstack(nil, true))
encountered_error = true
goto continue
end
-- also accounts for nil values (it's own type)
value_type = type(value)
if value_type ~= typ then
log_error("%sType mismatch for parameter no. %s (%s != %s)%s",
caller, param_index, value_type, typ, callstack(nil, true))
encountered_error = true
end
:: continue ::
param_index = param_index +1
end
return (not encountered_error)
end
-- Alternative to native assert that does not crash the game nor is intended to
-- alter the control flow directly. It merely logs the message and a
-- callstack via the default methods used by this addon
-- @param condition (boolean)
-- @param message (optional; format)
-- @param vararg (format elements)
-- @returns true when assertion failed
function assert(condition, message, ...)
condition = (type(condition) == nil) or condition -- nil-checking
if (not opt.get("validate_parameter_types")) then return (not condition) end
if (not condition) then
local args = {...}
message = (message and type(message) == "string") and message or "failed!"
log_error("%s%s", string.format("Assertion: " .. message,
unpack(args)), callstack(nil, true))
return true
end
end
-- Just an alias for usage in if-statements
assert_failed = assert
---------------------------
-- Type Conversion --
---------------------------
-- Only returns true, if string is "true" or of type bool
function string_to_bool(str) return (str == "true" or s == true) end
-- Converts a comma delimited string into a 3 dimensional vector
-- @returns vector on success
function string_to_vector(str)
if not valid_type{ caller = "string_to_vector", "str", str } then
return
end
local tbl = str_explode(str, ",") or {}
if assert_failed(#tbl == 3, "Invalid posdata (not 3 elements)") then return end
for index, value in pairs(tbl) do
tbl[index] = tonumber(value)
if assert_failed(tbl[index], "Element is not a number") then return end
end
return vector():set(tbl[1], tbl[2], tbl[3])
end
-- Converts a comma delimited string in the form of
-- `x, y, z, lvid, gvid` into positional data
-- @returns position data as table (pos, lvid, gvid)
function string_to_posdata(str)
if not valid_type{ caller = "string_to_posdata", "str", str } then
return
end
local tbl = str_explode(str, ",")
if assert_failed(#tbl == 5, "Invalid posdata (not 5 elements)") then return end
-- Convert all substrings to numbers
for index, value in pairs(tbl) do
tbl[index] = tonumber(value)
if assert_failed(tbl[index], "Element is not a number") then return end
end
local lvid, gvid = tbl[4], tbl[5]
if assert_failed(lvid < CONST_MAX_VALID_LVID, "Invalid level vertex id") then return end
return {
pos = vector():set(tbl[1], tbl[2], tbl[3]),
lvid = lvid,
gvid = gvid,
}
end
-- ARGB32 -> a byte for each channel
-- @param pixelvalue e.g. return value from GetARGB(a,r,g,b)
-- @returns table containing following keys: r, g, b, a
function argb_convert_from_pixelvalue(pixelvalue)
if not valid_type{ caller = "argb_convert_from_pixelvalue", "int", pixelvalue } then return end
local bitmask = 2^8 -1 -- 0xFF
local alpha = bit.band(bit.rshift(pixelvalue, 24), bitmask)
local red = bit.band(bit.rshift(pixelvalue, 16), bitmask)
local green = bit.band(bit.rshift(pixelvalue, 8), bitmask)
local blue = bit.band(pixelvalue, bitmask)
if assert_failed((red and green and blue and alpha), "Invalid pixelvalue (argb)!") then return end
return { r = red, g = green, b = blue, a = alpha }
end
-- Changes the weight of the alpha pixelvalue
-- @param alpha 8-bit integer
-- @returns pixelvalue (ARGB32)
function argb_change_alpha(pixelvalue, alpha)
if not valid_type{ caller = "argb_change_alpha",
"int", pixelvalue, "int", alpha } then return end
local alphavalue = bit.lshift(bit.band(alpha, 2^8 -1), 24) -- make sure it's 1 byte
local no_alpha = bit.band(pixelvalue, 2^24 -1)
if assert_failed((no_alpha and alphavalue), "Invalid pixelvalue (argb)!") then return end
return bit.bor(no_alpha, alphavalue)
end
---------------------------
-- Table Functions --
---------------------------
-- output of next() is nil when table is empty
function is_table_empty(tbl)
return not (tbl and next(tbl))
end
function index_of(tbl, value)
if not valid_type{ caller = "index_of", "tbl", tbl } then return end
for k, v in pairs(tbl) do
if (v == value) then return k end
end
end
-- Checks, if table includes the value; Also checks subtables
-- @returns true if value is in table
function table_has(tbl, value)
if not valid_type{ caller = "table_has", "tbl", tbl } then return end
for _, v in pairs(tbl) do
if v == value then return true end
if type(v) == 'table' and table_has(v, value) then
return true
end
end
end
-- Checks, if all elements of tbl_in are contained in tbl
-- @returns boolean
function table_contains(tbl, tbl_in)
for _, v in pairs(tbl_in) do
if (not table_has(tbl, v)) then return end
end
return true
end
-- Creates subtable with key, if needed, needs the type of the value
-- @returns success state of insertion
function table_safe_insert(tbl, key, value, value_type)
if not valid_type{ caller = "table_safe_insert",
"tbl", tbl, "str", key, value_type, value } then return end
if not tbl[key] then
tbl[key] = { value }
else
table.insert(tbl[key], value)
end
return true
end
function table_copy(tbl)
if not valid_type{ caller = "table_copy", "tbl", tbl } then return end
local copy = {}
for k,v in pairs(tbl) do
copy[k] = (type(v) == "table") and table_copy(v) or v
end
return copy
end
-- recursively swaps values to keys into a one-dimensional dictionary
function values_to_keys(tbl, result)
if not valid_type{ caller = "values_to_keys",
"tbl", tbl, "tbl", result } then return end
for k, v in pairs(tbl) do
if type(v) == 'table' then
values_to_keys(v, result)
else
result[v] = true
end
end
end
-- lists all keys in tbl into an indexed table
function index_keys(tbl, result)
if not valid_type{ caller = "index_keys",
"tbl", tbl, "tbl", result } then return end
for key, v in pairs(tbl) do
result[#result +1] = key
end
end
------------------------
-- Closures --
------------------------
function random_numbered_sequence(from, to)
if not valid_type{ caller = "random_numbered_sequence",
"int", from, "int", to } then return end
local tbl = {}
for i = from, to do
tbl[#tbl + 1] = i
end
for i = #tbl, 2, -1 do
local j = math.random(i)
tbl[i], tbl[j] = tbl[j], tbl[i]
end
local index = 0
return function()
if index > #tbl then return end
index = index + 1
return tbl[index]
end
end
------------------------------------
-- Timed Function Execution --
------------------------------------
-- Taken from Western Goods
-- executes functor once on next tick
-- @author: demonized
function next_tick(functor, ...)
if not valid_type{ caller = "next_tick", "fn", functor } then return end
local args = {...}
AddUniqueCall(function()
functor(unpack(args))
return true
end)
end
-- Wrapper to throttle function execution with time delay
-- Modified derivative from modded exes
-- @delay number (milliseconds)
-- @delay_first_call boolean
-- @func functor
-- @vararg functor-parameters
-- @returns functor
function throttle(delay, delay_first_call, functor, ...)
if not valid_type{ caller = "throttle",
"int", delay, "bool", delay_first_call, "fn", functor } then return end
local args = {...}
if not (delay and delay > (CONST_GAMETICK_DURATION_MS or 16)) then
return function()
return functor(unpack(args))
end
end
local TimeGlobal = time_global
local tg_threshold = (delay_first_call)
and TimeGlobal() + delay or 0
return function()
local tg = TimeGlobal()
if (tg_threshold +1) > tg then return end
tg_threshold = tg + delay
return functor(unpack(args))
end
end
-- Repeatedly calls functor
-- Time should be declared in milliseconds
function timed_call(delay, functor, ...)
if not valid_type{ caller = "timed_call", "int", delay, "fn", functor } then return end
local args = {...}
-- We also delay first execution
local throttled_func = throttle(delay, true, functor, unpack(args))
if (not throttled_func) then return end
-- Calls functor every game tick (approx. 16-17 ms)
AddUniqueCall(throttled_func)
if (opt.get("validate_parameter_types")) then
log("timed_call | Added Unique Call for %s with delay of %sms%s",
functor, delay, callstack(nil, true))
end
end
---------------------------
-- Map Markers --
---------------------------
function map_spot_exists(id, spot)
if not valid_type{ caller = "map_spot_exists",
"int", id, "str", spot } then return end
return (level.map_has_object_spot(id,spot) == 1)
end
function map_spot_remove(id, spot)
if assert_failed(map_spot_exists(id, spot), "Spot (%s, %s) does not exist!", id, spot) then
return
end
level.map_remove_object_spot(id, spot)
return true
end
function map_spot_add(id, spot, hint)
if not valid_type{ caller = "map_spot_add", "str", hint } then return end
if assert_failed(not map_spot_exists(id, spot), "Spot (%s, %s) already exists!", id, spot) then
return
end
level.map_add_object_spot_ser(id, spot, hint)
return true
end
function map_spot_change_hint(id, spot, hint)
if not valid_type{ caller = "map_spot_change_hint",
"int", id, "str", spot, "str", hint } then return end
if assert_failed(map_spot_exists(id, spot), "Spot (%s, %s) does not exist!", id, spot) then
return
end
level.map_change_spot_hint(id, spot, hint)
return true
end
-- Read defined attributes from map_spots.xml for a given map spot
-- Uses a cache to speed up subsequent calls
-- @param spot (spot name; e.g. level_changer_right)
-- @returns table || nil (table contains texture and color (pixelvalue), if read)
local _cache_map_spot_texture_info = {}
function map_spot_get_texture_info(spot, color_as_argb, default_alpha)
if not valid_type{ caller = "get_mapspot_texture", "str", spot } then return end
local cached_result = _cache_map_spot_texture_info[spot]
if (cached_result) then return (cached_result) end
default_alpha = default_alpha or 255
spot = spot .. "_spot" -- that node got the actual info we need
local attr_tex = "texture"
local xml = _cache_map_spot_texture_info.parser
if (not xml) then
xml = CScriptXmlInit()
xml:ParseFile("map_spots.xml")
_cache_map_spot_texture_info.parser = xml
end
xml:NavigateToRoot() -- to <map_spots>
if assert_failed(xml:NodeExist(spot, 0), "Node %s does not exist", spot) then return end
xml:NavigateToNode(spot, 0)
local result = {}
result.texture = xml:ReadValue(attr_tex, 0)
if assert_failed(xml:NodeExist(attr_tex, 0), "Node %s/%s does not exist", spot, attr_tex) then return end
local color = {}
color.r = tonumber(xml:ReadAttribute(attr_tex, 0, "r"))
color.g = tonumber(xml:ReadAttribute(attr_tex, 0, "g"))
color.b = tonumber(xml:ReadAttribute(attr_tex, 0, "b"))
if (not is_table_empty(color)) then
color.a = tonumber(xml:ReadAttribute(attr_tex, 0, "a")) or default_alpha
result.color = color
if (not color_as_argb) then
result.color = GetARGB(color.a, color.r, color.g, color.b)
end
end
if (not is_table_empty(result)) then
_cache_map_spot_texture_info[spot] = result
return result
end
end
-- REQUIRES MODDED-EXES
-- Changes the map spot texture of any given object (given that it already has a map spot)
-- @param id object-id
-- @param spot current texture
-- @param texture new texture id
-- @returns true on success
function map_spot_change_texture(id, spot, texture)
if not valid_type{ caller = "map_spot_change_spot", "str", texture } then return end
if assert_failed(map_spot_exists(id, spot), "Spot (%s, %s) does not exist!", id, spot) then
return
end
local spot_static = level.map_get_object_minimap_spot_static(id, spot)
local mini_static = level.map_get_object_spot_static(id, spot)
if assert_failed(spot_static and mini_static) then return end
spot_static:InitTexture(texture)
mini_static:InitTexture(texture)
return true
end
-- REQUIRES MODDED-EXES
-- @param color argb32 pixelvalue (e.g. GetARGB(a,r,g,b))
-- @returns true on success
function map_spot_change_color(id, spot, color)
if not valid_type{ caller = "map_spot_change_color", "int", color } then return end
if assert_failed(map_spot_exists(id, spot), "Spot (%s, %s) does not exist!", id, spot) then
return
end
local main_mapspot = level.map_get_object_spot_static(id, spot)
local mini_mapspot = level.map_get_object_minimap_spot_static(id, spot)
main_mapspot:SetTextureColor(color)
mini_mapspot:SetTextureColor(color)
return true
end
-- REQUIRES MODDED-EXES
-- @returns pixelvalue (integer)
function map_spot_get_color(id, spot, get_mini)
if assert_failed(map_spot_exists(id, spot), "Spot (%s, %s) does not exist!", id, spot) then
return
end
local main_mapspot = level.map_get_object_spot_static(id, spot)
local mini_mapspot = (get_mini) and level.map_get_object_minimap_spot_static(id, spot)
return (mini_mapspot and mini_mapspot:GetTextureColor())
or (main_mapspot and main_mapspot:GetTextureColor())
end
-----------------------------------
-- Game related Checks --
-----------------------------------
function has_translation(string)
if not valid_type{ caller = "has_translation", "str", string } then return end
return (game.translate_string(string) ~= string)
end
------------------------------
-- Object related --
------------------------------
-- @param obj (optional)
-- @returns level name
function get_mapname(obj)
if (not obj) then
return level.name()
elseif not valid_type{ caller = "get_mapname", "userdata", obj } then
return
end
local gvid
if (obj.online and type(obj.id) == "function") then
gvid = obj:game_vertex_id()
elseif (obj.id) then
gvid = obj.m_game_vertex_id
end
return (alife():level_name(game_graph():vertex(gvid):level_id()))
end
-- Only returns correct position for online objects as
-- we only check for the proximity to the player
-- @returns distance (to player)
function get_proximity_by_id(id, default)
if not valid_type{ caller = "get_proximity_by_id", "int", id } then return end
default = (default and type(default) == "number") or CONST_DEFAULT_PROXIMITY_DISTANCE
local se_obj = id and alife_object(id)
if not (se_obj and se_obj.online) then return default end
local pos = se_obj.position
return (pos and pos:distance_to(db.actor:position()) or default)
end
function get_point_proximity_by_id(id, point, default)
if not valid_type{ caller = "get_point_proximity_by_id", "int", id, "usr", point } then return end
default = default or CONST_DEFAULT_PROXIMITY_DISTANCE
local se_obj = id and alife_object(id)
if not (se_obj and se_obj.online) then return default end
local pos = se_obj.position
return (pos and pos:distance_to(point) or default)
end
-----------------------------
-- Level related --
-----------------------------
-- This works with and without modded exes
-- @returns pos from the target in the center of the viewport
function get_target_pos()
return (level.get_target_pos) and level.get_target_pos() -- REQUIRES MODDED-EXES
or device().cam_pos:add(device().cam_dir:mul(level.get_target_dist()))
end
-- Returns the position of a level vertex in close proximity (determined in-engine)
-- @param pos vector
-- @returns vector (copy)
function get_closest_vertex_pos(pos)
if not valid_type{ caller = "get_closest_vertex_pos", "usr", pos } then return end
local lvid = pos and pos.x and level.vertex_id(pos)
-- signed & last are reserved
if not (lvid and (lvid < CONST_MAX_VALID_LVID)) then return end
local pos = level.vertex_position(lvid)
return vector():set(pos.x, pos.y, pos.z)
end
-- Taken from Catspaw's utilities
function levelname_from_gvid(gvid)
if not valid_type{ caller = "levelname_from_gvid", "int", gvid } then return end
local gv = game_graph():vertex(gvid)
return alife():level_name(gv:level_id())
end
-- Requires that the weather manager is running (just before actor_on_first_update)
-- Additional levels need to be registered there to have working weather
-- @param level_name
-- @returns boolean
function is_underground(level)
if not valid_type{ caller = "is_underground", "str", level } then return end
return (not level_weathers.valid_levels[level])
end
function debug_level_loaded()
return (get_mapname() == "fake_start")
end
-- Uses txr_routes to determine connected maps
-- @param map
-- @returns table
function get_directly_connected_maps(map)
local get_txr_section = txr_routes.get_section
local get_txr_mapname = txr_routes.get_map
local routes = txr_routes.routes
local txr_section = map and get_txr_mapname(map)
if not (txr_section and routes[txr_section]) then return end
local connected = {}
for map, _ in pairs(routes[txr_section]) do
connected[#connected +1] = get_txr_section(map)
end
return connected
end
@@ -0,0 +1,571 @@
-- https://github.com/ubilabs/kd-tree-javascript
-- k-d Tree Implementation for Lua for quick search in multidimensional tables
-- k-d trees are a useful data structure for several applications, such as searches involving a multidimensional search key (e.g. range searches and nearest neighbor searches). k-d trees are a special case of binary space partitioning trees.
-- Rewritten to pure Lua and adapted for usage in Anomaly by demonized
local math_floor = math.floor
local math_log = math.log
local math_max = math.max
local math_min = math.min
local table_insert = table.insert
local table_remove = table.remove
local table_sort = table.sort
local empty_table = empty_table
local pairs = pairs
local function table_slice(t, first, last)
local res = {}
for i = first or 1, last and last - 1 or #t do
res[#res + 1] = t[i]
end
return res
end
-- http://lua-users.org/wiki/BinaryInsert
local function binary_insert(t, value, fcomp)
-- Initialise compare function
local fcomp = fcomp or function(a, b) return a < b end
-- print_table(value)
-- Initialise numbers
local iStart, iEnd, iMid, iState = 1, #t, 1, 0
if iEnd == 0 then
t[1] = value
-- printf("adding in beginning table empty")
return 1
end
if fcomp(value, t[1]) then
-- printf("adding in beginning %s of %s", 1, iEnd)
table_insert(t, 1, value)
return 1
end
if not fcomp(value, t[iEnd]) then
-- printf("adding in end %s of %s", iEnd + 1, iEnd)
local pos = iEnd + 1
t[pos] = value
return pos
end
-- Get insert position
while iStart <= iEnd do
-- calculate middle
iMid = math_floor((iStart + iEnd) / 2)
-- compare
if fcomp(value, t[iMid]) then
iEnd, iState = iMid - 1, 0
else
iStart, iState = iMid + 1, 1
end
end
local pos = iMid + iState
-- printf("adding in middle %s of %s", pos, iEnd)
table_insert(t, pos, value)
return pos
end
function Node(obj, dimension, parent)
local node = {}
node.obj = obj
node.left = nil
node.right = nil
node.parent = parent
node.dimension = dimension
return node
end
function kdTree(points, metric, dimensions)
local kd_tree = {}
kd_tree.points = points or {}
kd_tree.metric = metric
kd_tree.dimensions = dimensions
local function buildTree(new_points, depth, parent)
local dim = (depth % #dimensions) + 1
local median
local node
if not new_points then
return
end
if #new_points == 0 then
-- printf("buildTree #new_points == 0")
return
end
if #new_points == 1 then
-- printf("buildTree #new_points == 1")
return Node(new_points[1], dim, parent)
end
table_sort(new_points, function(a, b)
return a[dimensions[dim]] < b[dimensions[dim]]
end)
median = math_floor(#new_points / 2) + 1
node = Node(new_points[median], dim, parent)
node.left = buildTree(table_slice(new_points, 1, median), depth + 1, node)
node.right = buildTree(table_slice(new_points, median + 1), depth + 1, node)
return node
end
kd_tree.root = buildTree(points, 0, nil)
kd_tree.insertAndRebuild = function(self, point)
self.points[#self.points + 1] = point
self.root = buildTree(self.points, 0, nil)
return self
end
kd_tree.insert = function(self, point)
local function innerSearch(node, parent)
if node == nil then
return parent
end
local dimension = self.dimensions[node.dimension]
if point[dimension] < node.obj[dimension] then
return innerSearch(node.left, node)
else
return innerSearch(node.right, node)
end
end
local insertPosition = innerSearch(self.root, nil)
local newNode
local dimension
if insertPosition == nil then
self.points[#self.points + 1] = point
self.root = buildTree(self.points, 0, nil)
return self
end
newNode = Node(point, (insertPosition.dimension + 1) % #self.dimensions, insertPosition)
dimension = self.dimensions[insertPosition.dimension]
if point[dimension] < insertPosition.obj[dimension] then
insertPosition.left = newNode
else
insertPosition.right = newNode
end
self.points[#self.points + 1] = point
return self
end
kd_tree.remove = function(self, point)
local node
local function nodeSearch(node)
if node == nil then
return
end
if node.obj == point then
return node
end
local dimension = self.dimensions[node.dimension]
if point[dimension] < node.obj[dimension] then
return nodeSearch(node.left, node)
else
return nodeSearch(node.right, node)
end
end
local function removeNode(node)
local nextNode
local nextObj
local pDimension
local function findMin(node, dim)
local dimension
local own
local left
local right
local min
if node == nil then
return
end
dimension = self.dimensions[dim]
if node.dimension == dim then
if node.left ~= nil then
return findMin(node.left, dim)
end
return node
end
own = node.obj[dimension]
left = findMin(node.left, dim)
right = findMin(node.right, dim)
min = node
if left ~= nil and left.obj[dimension] < own then
min = left
end
if right ~= nil and right.obj[dimension] < min.obj[dimension] then
min = right
end
return min
end
if node.left == nil and node.right == nil then
if node.parent == nil then
self.root = nil
return
end
pDimension = self.dimensions[node.parent.dimension]
if node.obj[pDimension] < node.parent.obj[pDimension] then
node.parent.left = nil
else
node.parent.right = nil
end
return
end
-- If the right subtree is not empty, swap with the minimum element on the
-- node's dimension. If it is empty, we swap the left and right subtrees and
-- do the same.
if node.right ~= nil then
nextNode = findMin(node.right, node.dimension)
nextObj = nextNode.obj
removeNode(nextNode)
node.obj = nextObj
else
nextNode = findMin(node.left, node.dimension)
nextObj = nextNode.obj
removeNode(nextNode)
node.right = node.left
node.left = nil
node.obj = nextObj
end
end
node = nodeSearch(self.root)
if node == nil then
return
end
removeNode(node)
return self
end
kd_tree.clearRoot = function(self)
empty_table(self.root)
return self
end
-- Update positions of objects
-- Points input must be same structure as existing in k-d Tree
kd_tree.updatePositions = function(self, points)
self.points = points
self:clearRoot()
self.root = buildTree(points, 0, nil)
return self
end
-- get all points sorted by nearest
kd_tree.nearestAll = function(self, point)
local point = {
x = point.x or point[1],
y = point.y or point[2],
z = point.z or point[3]
}
local function comp_function(a, b)
return a[2] < b[2]
end
local res = {}
for i = 1, #self.points do
local v = self.points[i]
res[i] = {
[1] = {
x = v.x,
y = v.y,
z = v.z,
data = v.data
},
[2] = math.huge
}
res[i][2] = self.metric(res[i][1], point)
end
table_sort(res, comp_function)
return res
end
-- Query the nearest *count* neighbours to a point, with an optional
-- maximal search distance.
-- Result is an array with *count* elements.
-- Each element is an array with two components: the searched point and
-- the distance to it.
kd_tree.nearest = function(self, point, maxNodes, maxDistance)
local i
local result
local bestNodes
bestNodes = {}
local passedNodes = {}
local maxNodes = maxNodes or 1
local function comp_function(a, b)
return a[2] < b[2]
end
local function saveNode(node, distance)
binary_insert(bestNodes, {node, distance}, comp_function)
if #bestNodes > maxNodes then
table_remove(bestNodes)
end
end
local function nearestSearch(node)
if passedNodes[node] then return end
local bestChild
local dimension = self.dimensions[node.dimension]
local ownDistance = self.metric(point, node.obj)
local linearPoint = {}
local linearDistance
local otherChild
local i
for i = 1, #self.dimensions do
linearPoint[self.dimensions[i]] = i == node.dimension and point[self.dimensions[i]] or node.obj[self.dimensions[i]]
end
linearDistance = self.metric(linearPoint, node.obj)
if node.right == nil and node.left == nil then
if #bestNodes < maxNodes or ownDistance < bestNodes[#bestNodes][2] then
saveNode(node, ownDistance)
end
passedNodes[node] = true
return
end
if node.right == nil then
bestChild = node.left
elseif node.left == nil then
bestChild = node.right
else
bestChild = point[dimension] < node.obj[dimension] and node.left or node.right
end
nearestSearch(bestChild)
if #bestNodes < maxNodes or ownDistance < bestNodes[#bestNodes][2] then
saveNode(node, ownDistance)
passedNodes[node] = true
end
if #bestNodes < maxNodes or math.abs(linearDistance) < bestNodes[1][2] then
otherChild = bestChild == node.left and node.right or node.left
if (otherChild ~= nil) then
nearestSearch(otherChild)
end
end
end
if maxDistance then
for i = 1, maxNodes do
bestNodes[i] = {nil, maxDistance}
end
end
if self.root then
nearestSearch(self.root)
end
result = {}
for i = 1, math_min(maxNodes, #bestNodes) do
if bestNodes[i][1] then
result[#result + 1] = {
bestNodes[i][1].obj,
bestNodes[i][2]
}
end
end
return result
end
-- Get an approximation of how unbalanced the tree is.
-- The higher this number, the worse query performance will be.
-- It indicates how many times worse it is than the optimal tree.
-- Minimum is 1. Unreliable for small trees.
kd_tree.balanceFactor = function(self)
local function height(node)
if node == nil then
return 0
end
return math_max(height(node.left), height(node.right)) + 1
end
local function count(node)
if node == nil then
return 0
end
return count(node.left) + count(node.right) + 1
end
return height(self.root) / (math_log(count(self.root)) / math_log(2))
end
return kd_tree
end
local function distance_to(a, b)
-- printf("distance_to fired")
local dist_x = a.x - b.x
local dist_y = a.y - b.y
local dist_z = a.z - b.z
return dist_x * dist_x + dist_y * dist_y + dist_z * dist_z
end
-- Actual usage starts here
--[[
When you build position tree, you can find nearest objects in relation to other objects
Example, find nearest position to actor:
local pos_tree = kd_tree.buildTreeObjectIds({45, 65, 23, 5353, 232})
print_table(pos_tree:nearest(db.actor:position()))
will print position, distance and id of nearest object from given ids
--]]
-- Build k-d Tree by several inputs
-- Input - Array of vectors (vector():set(x, y, z) or table with x, y, z keys or 1, 2, 3 keys)
-- Data is an optional table where you can bind your data to your object, must have same amount of fields as vectors (#vectors == #data)
function buildTreeVectors(vectors, data)
local v = {}
local data = data or {}
local vectors = vectors or {}
for k, t in pairs(vectors) do
table_insert(v, {
x = t.x or t[1],
y = t.y or t[2],
z = t.z or t[3],
data = data[k]
})
end
-- printf("vectors num %s", #v)
return kdTree(v, distance_to, {"x", "y", "z"})
end
-- Input - Array of game objects
-- Vectors are binded to object ids automatically
function buildTreeObjects(objects)
local vectors = {}
local data = {}
for k, v in pairs(objects) do
table_insert(vectors, v:position())
table_insert(data, v:id())
end
return buildTreeVectors(vectors, data)
end
-- Input - Array of server objects
-- Vectors are binded to object ids automatically
function buildTreeSeObjects(objects)
local vectors = {}
local data = {}
for k, v in pairs(objects) do
table_insert(vectors, v.position)
table_insert(data, v.id)
end
return buildTreeVectors(vectors, data)
end
-- Input - Array of game object ids
-- Vectors are binded to object ids automatically
function buildTreeObjectIds(ids)
local vectors = {}
local data = {}
local level_object_by_id = level.object_by_id
for k, v in pairs(ids) do
local obj = level_object_by_id(v)
if obj and obj ~= 0 and obj:id() ~= 0 then
table_insert(vectors, obj:position())
table_insert(data, v)
end
end
return buildTreeVectors(vectors, data)
end
-- Input - Array of server object ids
-- Vectors are binded to object ids automatically
function buildTreeSeObjectIds(ids)
local vectors = {}
local data = {}
local sim = alife()
local sim_object = sim.object
for k, v in pairs(ids) do
local obj = sim_object(sim, v)
if obj and obj ~= 0 and obj.id ~= 0 then
table_insert(vectors, obj.position)
table_insert(data, v)
end
end
return buildTreeVectors(vectors, data)
end
-- If you build a tree using functions above
-- You can use this function to update positions and rebuild the tree
function updateObjPositions(kd_tree)
local points = kd_tree.points
local new_points = {}
local sim = alife()
local sim_object = sim.object
for i = 1, #points do
local obj = sim_object(sim, points[i].data)
if obj then
local pos = obj.position
table_insert(new_points, {
x = pos.x,
y = pos.y,
z = pos.z,
data = points[i].data
})
end
end
kd_tree:updatePositions(new_points)
return kd_tree
end
@@ -0,0 +1,53 @@
-- A tiny library for picking random values between two numbers using bézier curves
-- Written in Lua by Singustromo
-- Based on and inspired by randomizing_functions from Demonized
-- Usage
--[[
local randomizer = libmath_bezier
local a = randomizer.get_random_value(min, max, {p0, p1, p2, p3})
--]]
-- Pick a random float between min_cond and max_cond
-- random value will be picked according to the function graph
function get_random_value(min_cond, max_cond, params)
local min_cond = min_cond or 0
local max_cond = max_cond or 1
if not params or type(params) ~= 'table' or #params < 3 then
params = {0,0.5,1} -- linear interpolation
end
local rand = 1
if #params == 4 then
rand = cubic_bezier(math.random(), params)
elseif #params == 3 then
rand = quadratic_bezier(math.random(), params)
end
if (not rand) then return end
if min_cond > max_cond then
max_cond, min_cond = min_cond, max_cond
end
local a = max_cond - min_cond
local b = a * rand
local c = min_cond + b
return c
end
function quadratic_bezier(x, p)
-- linear interpolation: saving compute time
if p[1] == 0 and p[2] == 0.5 and p[3] == 1 then return x end
return p[1]*(1-x)^2 + 2*p[2]*x*(1-x) + p[3]*x^2
end
function cubic_bezier(x, p)
-- linear interpolation: saving compute time
if p[1] == 0 and p[2] == 1 and p[3] == 0 and p[4] == 1 then
return x
end
return p[1]*(1-x)^3 + 3*p[2]*(1-x)^2*x + 3*p[3]*(1-x)*x^2 + p[4]*x^3
end
@@ -0,0 +1,111 @@
--[[
DYNAMIC ZONE
Original Author(s)
Singustromo <singustromo at disroot.org>
Edited by
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
Lazy monkey patches that overwrite those functions completely
--]]
-- main script functors and variables are accessed through this variable
parent = _G["dynamic_zone"]
if not (parent and parent.VERSION and parent.VERSION >= 20240120) then return end
--------------------------
-- Dependencies
--------------------------
local opt = dynamic_zone_mcm
local utils = dynamic_zone_utils
local debug = dynamic_zone_debug
local route_manager = dynamic_zone_routes
local discovery = dynamic_zone_discovery
CONST_LOGGING_PREFIX = "TXR-Routes"
local log = debug.log_register("info", CONST_LOGGING_PREFIX)
local log_error = debug.log_register("error", CONST_LOGGING_PREFIX)
-------------------------------
-- Patched Functions
-------------------------------
ReloadRouteHints = txr_routes.reload_route_hints
OpenRoute = txr_routes.open_route
-----------------------------
-- Monkey patches
-----------------------------
-- Let's make sure we update the transition mapspots and use our hint
-- This is executed undermost on_game_load and is used
-- to ensure that the spot hints adhere to set localization
function txr_routes.reload_route_hints()
if (utils.debug_level_loaded()) then return end
log("Running patched txr_routes.reload_route_hints()")
-- This function is actually called before our parent.main_routine()
-- We just do this for a new game, so that we can leverage our logic here
if (route_manager.route_count() < 1) then
log("reload_route_hints | Populating route list")
parent.register_game_routes()
parent.update_game_route_properties()
end
log("reload_route_hints | Updating transition mapspots")
local include_blacklisted = true
for route_id, route in route_manager.iterate_routes(include_blacklisted) do
for name, _ in route_manager.iterate_transitions(route_id) do
discovery.update_transition_mapspot(name, nil,
not route.block_discovered)
end
end
end
-- Prevents txr_routes from overwriting our map icons when a route is unlocked
-- (e.g. Debug: Unlock all)
-- Overwrote this in it's entirety because the changes needed, require it.
function txr_routes.open_route(map_1, map_2, no_msg)
local a = txr_routes.get_route(map_1, map_2) -- all space_restrictors between those two
if (utils.assert_failed(a, "Got no route between %s and %s", map_1, map_2)) then return end
local msg
for _, transition in pairs(a) do
local id, spot, hint = txr_routes.get_route_info(transition)
if utils.assert_failed(id and spot and hint) then
log_error("Unknown restrictor: %s (Defined in txr_routes.routes)", transition)
return -- prevent possible crash
end
local route = route_manager.get_route_by_transition(transition)
if utils.assert_failed(route, "Can not get a route ID with '%s' as a member!", transition) then
goto continue
elseif (route.block_discovered) then
goto continue
end
if utils.map_spot_exists(id, spot) then
log("Map spot for transition '%s' already exists!", transition)
goto continue
end
hint = hint and game.translate_string(hint)
level.map_add_object_spot_ser(id, spot, hint)
mlr_utils.save_var("routes_".. transition, true)
txr_routes.register_map(map_1, map_2)
msg = true
::continue::
route.unlocked = true
discovery.update_transition_mapspot(transition)
end
if msg and (not no_msg) then
txr_routes.msg_route(map_1, map_2)
end
end
+28
View File
@@ -0,0 +1,28 @@
[General]
gameName=stalkeranomaly
modid=0
version=d2025.1.15.0
newestVersion=
category="-1,"
nexusFileStatus=1
installationFile=Dynamic_Zone_Transitions_-_20250102.7z
repository=Nexus
ignoredVersion=
comments=
notes=
nexusDescription=
url=
hasCustomURL=true
lastNexusQuery=
lastNexusUpdate=
nexusLastModified=2025-01-15T22:28:12Z
nexusCategory=0
converted=false
validated=false
color=@Variant(\0\0\0\x43\0\xff\xff\0\0\0\0\0\0\0\0)
tracked=0
[installedFiles]
1\modid=0
1\fileid=0
size=1