Created lane feature that should be backwards compatible with non-lane features
This commit is contained in:
+410
-35
@@ -406,8 +406,8 @@
|
|||||||
"type": 3
|
"type": 3
|
||||||
},
|
},
|
||||||
"seed": 1626473245,
|
"seed": 1626473245,
|
||||||
"version": 468,
|
"version": 469,
|
||||||
"versionNonce": 1827077469,
|
"versionNonce": 874232424,
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
"boundElements": [
|
"boundElements": [
|
||||||
{
|
{
|
||||||
@@ -417,13 +417,9 @@
|
|||||||
{
|
{
|
||||||
"id": "kIqbCgtXKr5-2qhRSYTAa",
|
"id": "kIqbCgtXKr5-2qhRSYTAa",
|
||||||
"type": "arrow"
|
"type": "arrow"
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "0CY7kgHkgaXEMGTFJiv2H",
|
|
||||||
"type": "arrow"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"updated": 1787318071712,
|
"updated": 1787406477137,
|
||||||
"link": null,
|
"link": null,
|
||||||
"locked": false
|
"locked": false
|
||||||
},
|
},
|
||||||
@@ -633,11 +629,11 @@
|
|||||||
"type": 2
|
"type": 2
|
||||||
},
|
},
|
||||||
"seed": 2125327475,
|
"seed": 2125327475,
|
||||||
"version": 36,
|
"version": 40,
|
||||||
"versionNonce": 1265229288,
|
"versionNonce": 1013087493,
|
||||||
"isDeleted": true,
|
"isDeleted": true,
|
||||||
"boundElements": [],
|
"boundElements": [],
|
||||||
"updated": 1787403270962,
|
"updated": 1787675736572,
|
||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"points": [
|
"points": [
|
||||||
@@ -773,8 +769,8 @@
|
|||||||
"type": 3
|
"type": 3
|
||||||
},
|
},
|
||||||
"seed": 1931784787,
|
"seed": 1931784787,
|
||||||
"version": 595,
|
"version": 597,
|
||||||
"versionNonce": 648660125,
|
"versionNonce": 196807877,
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
"boundElements": [
|
"boundElements": [
|
||||||
{
|
{
|
||||||
@@ -786,15 +782,15 @@
|
|||||||
"type": "arrow"
|
"type": "arrow"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "0CY7kgHkgaXEMGTFJiv2H",
|
"id": "Q8b54GQSVn5ZBrXMwYjN7",
|
||||||
"type": "arrow"
|
"type": "arrow"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "Q8b54GQSVn5ZBrXMwYjN7",
|
"id": "MwTn5dJVKPmeTHOM-q3f9",
|
||||||
"type": "arrow"
|
"type": "arrow"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"updated": 1787318161674,
|
"updated": 1787675772937,
|
||||||
"link": null,
|
"link": null,
|
||||||
"locked": false
|
"locked": false
|
||||||
},
|
},
|
||||||
@@ -1488,11 +1484,11 @@
|
|||||||
"type": 2
|
"type": 2
|
||||||
},
|
},
|
||||||
"seed": 536727613,
|
"seed": 536727613,
|
||||||
"version": 139,
|
"version": 140,
|
||||||
"versionNonce": 1741218173,
|
"versionNonce": 399876888,
|
||||||
"isDeleted": false,
|
"isDeleted": true,
|
||||||
"boundElements": [],
|
"boundElements": [],
|
||||||
"updated": 1787318074593,
|
"updated": 1787406477136,
|
||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"points": [
|
"points": [
|
||||||
@@ -1772,8 +1768,8 @@
|
|||||||
"type": 3
|
"type": 3
|
||||||
},
|
},
|
||||||
"seed": 1971420499,
|
"seed": 1971420499,
|
||||||
"version": 285,
|
"version": 286,
|
||||||
"versionNonce": 598897235,
|
"versionNonce": 142740965,
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
"boundElements": [
|
"boundElements": [
|
||||||
{
|
{
|
||||||
@@ -1783,9 +1779,13 @@
|
|||||||
{
|
{
|
||||||
"id": "w6_Fv5GP_VEFqSQMXy25N",
|
"id": "w6_Fv5GP_VEFqSQMXy25N",
|
||||||
"type": "arrow"
|
"type": "arrow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "o3WprJN3wZEDcHw1DiFYr",
|
||||||
|
"type": "arrow"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"updated": 1787318114912,
|
"updated": 1787675785325,
|
||||||
"link": null,
|
"link": null,
|
||||||
"locked": false
|
"locked": false
|
||||||
},
|
},
|
||||||
@@ -1889,7 +1889,7 @@
|
|||||||
"id": "qO3tWw8uDrdY-GSL5hbG7",
|
"id": "qO3tWw8uDrdY-GSL5hbG7",
|
||||||
"type": "rectangle",
|
"type": "rectangle",
|
||||||
"x": 1611.9167066751852,
|
"x": 1611.9167066751852,
|
||||||
"y": 1250.2170926328931,
|
"y": 1206.2170926328931,
|
||||||
"width": 144,
|
"width": 144,
|
||||||
"height": 99,
|
"height": 99,
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@@ -1907,8 +1907,8 @@
|
|||||||
"type": 3
|
"type": 3
|
||||||
},
|
},
|
||||||
"seed": 2008474461,
|
"seed": 2008474461,
|
||||||
"version": 330,
|
"version": 502,
|
||||||
"versionNonce": 2001596957,
|
"versionNonce": 72829003,
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
"boundElements": [
|
"boundElements": [
|
||||||
{
|
{
|
||||||
@@ -1918,9 +1918,13 @@
|
|||||||
{
|
{
|
||||||
"id": "Q8b54GQSVn5ZBrXMwYjN7",
|
"id": "Q8b54GQSVn5ZBrXMwYjN7",
|
||||||
"type": "arrow"
|
"type": "arrow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Z4Fy52Fl_c9lXHJlrhd9g",
|
||||||
|
"type": "arrow"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"updated": 1787318163603,
|
"updated": 1787675800613,
|
||||||
"link": null,
|
"link": null,
|
||||||
"locked": false
|
"locked": false
|
||||||
},
|
},
|
||||||
@@ -1928,7 +1932,7 @@
|
|||||||
"id": "EFDaczSk3yi8gn2b8hoI_",
|
"id": "EFDaczSk3yi8gn2b8hoI_",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"x": 1632.626736277236,
|
"x": 1632.626736277236,
|
||||||
"y": 1287.2170926328931,
|
"y": 1243.2170926328931,
|
||||||
"width": 102.57994079589844,
|
"width": 102.57994079589844,
|
||||||
"height": 25,
|
"height": 25,
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
@@ -1944,11 +1948,11 @@
|
|||||||
"index": "ag",
|
"index": "ag",
|
||||||
"roundness": null,
|
"roundness": null,
|
||||||
"seed": 958164925,
|
"seed": 958164925,
|
||||||
"version": 298,
|
"version": 467,
|
||||||
"versionNonce": 374795869,
|
"versionNonce": 328458027,
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
"boundElements": [],
|
"boundElements": [],
|
||||||
"updated": 1787318158139,
|
"updated": 1787675761637,
|
||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"text": "STAGE C5",
|
"text": "STAGE C5",
|
||||||
@@ -1967,7 +1971,7 @@
|
|||||||
"x": 1449.9192687785321,
|
"x": 1449.9192687785321,
|
||||||
"y": 980.5000000000001,
|
"y": 980.5000000000001,
|
||||||
"width": 155.99743789665308,
|
"width": 155.99743789665308,
|
||||||
"height": 315.1857377213224,
|
"height": 273.41807104570137,
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"strokeColor": "#ffffff",
|
"strokeColor": "#ffffff",
|
||||||
"backgroundColor": "#1971c2",
|
"backgroundColor": "#1971c2",
|
||||||
@@ -1983,11 +1987,11 @@
|
|||||||
"type": 2
|
"type": 2
|
||||||
},
|
},
|
||||||
"seed": 935284605,
|
"seed": 935284605,
|
||||||
"version": 184,
|
"version": 353,
|
||||||
"versionNonce": 822381789,
|
"versionNonce": 667206091,
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
"boundElements": [],
|
"boundElements": [],
|
||||||
"updated": 1787318165497,
|
"updated": 1787675761637,
|
||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"points": [
|
"points": [
|
||||||
@@ -2001,7 +2005,7 @@
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
155.99743789665308,
|
155.99743789665308,
|
||||||
315.1857377213224
|
273.41807104570137
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"startBinding": {
|
"startBinding": {
|
||||||
@@ -2022,6 +2026,377 @@
|
|||||||
},
|
},
|
||||||
"startArrowhead": null,
|
"startArrowhead": null,
|
||||||
"endArrowhead": "arrow",
|
"endArrowhead": "arrow",
|
||||||
|
"elbowed": false,
|
||||||
|
"moveMidPointsWithElement": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "oIXVKbkqP10kd7HsX3Ma8",
|
||||||
|
"type": "rectangle",
|
||||||
|
"x": 1845.5,
|
||||||
|
"y": 878,
|
||||||
|
"width": 144,
|
||||||
|
"height": 99,
|
||||||
|
"angle": 0,
|
||||||
|
"strokeColor": "#1e1e1e",
|
||||||
|
"backgroundColor": "#e8590c",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"groupIds": [],
|
||||||
|
"frameId": null,
|
||||||
|
"index": "ai",
|
||||||
|
"roundness": {
|
||||||
|
"type": 3
|
||||||
|
},
|
||||||
|
"seed": 1637710309,
|
||||||
|
"version": 783,
|
||||||
|
"versionNonce": 1692360869,
|
||||||
|
"isDeleted": false,
|
||||||
|
"boundElements": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"id": "7AVtQifmKK8XdbWOLnM1M"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "MwTn5dJVKPmeTHOM-q3f9",
|
||||||
|
"type": "arrow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "o3WprJN3wZEDcHw1DiFYr",
|
||||||
|
"type": "arrow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Z4Fy52Fl_c9lXHJlrhd9g",
|
||||||
|
"type": "arrow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"updated": 1787675805417,
|
||||||
|
"link": null,
|
||||||
|
"locked": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7AVtQifmKK8XdbWOLnM1M",
|
||||||
|
"type": "text",
|
||||||
|
"x": 1872.2800216674805,
|
||||||
|
"y": 915,
|
||||||
|
"width": 90.43995666503906,
|
||||||
|
"height": 25,
|
||||||
|
"angle": 0,
|
||||||
|
"strokeColor": "#ffffff",
|
||||||
|
"backgroundColor": "#96f2d7",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"groupIds": [],
|
||||||
|
"frameId": null,
|
||||||
|
"index": "aj",
|
||||||
|
"roundness": null,
|
||||||
|
"seed": 1576990021,
|
||||||
|
"version": 739,
|
||||||
|
"versionNonce": 761448939,
|
||||||
|
"isDeleted": false,
|
||||||
|
"boundElements": [],
|
||||||
|
"updated": 1787675780472,
|
||||||
|
"link": null,
|
||||||
|
"locked": false,
|
||||||
|
"text": "STAGE 6",
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 5,
|
||||||
|
"textAlign": "center",
|
||||||
|
"verticalAlign": "middle",
|
||||||
|
"containerId": "oIXVKbkqP10kd7HsX3Ma8",
|
||||||
|
"originalText": "STAGE 6",
|
||||||
|
"autoResize": true,
|
||||||
|
"lineHeight": 1.25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "MwTn5dJVKPmeTHOM-q3f9",
|
||||||
|
"type": "arrow",
|
||||||
|
"x": 1497,
|
||||||
|
"y": 925.0522131170663,
|
||||||
|
"width": 342.5,
|
||||||
|
"height": 2.4153737658673435,
|
||||||
|
"angle": 0,
|
||||||
|
"strokeColor": "#ffffff",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"groupIds": [],
|
||||||
|
"frameId": null,
|
||||||
|
"index": "ak",
|
||||||
|
"roundness": {
|
||||||
|
"type": 2
|
||||||
|
},
|
||||||
|
"seed": 1633560229,
|
||||||
|
"version": 99,
|
||||||
|
"versionNonce": 1709724811,
|
||||||
|
"isDeleted": false,
|
||||||
|
"boundElements": null,
|
||||||
|
"updated": 1787675780472,
|
||||||
|
"link": null,
|
||||||
|
"locked": false,
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
342.5,
|
||||||
|
2.4153737658673435
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"startBinding": {
|
||||||
|
"elementId": "UoiunLPIaAwLLJTJGcSj8",
|
||||||
|
"mode": "orbit",
|
||||||
|
"fixedPoint": [
|
||||||
|
1,
|
||||||
|
0.5001
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"endBinding": {
|
||||||
|
"elementId": "oIXVKbkqP10kd7HsX3Ma8",
|
||||||
|
"mode": "orbit",
|
||||||
|
"fixedPoint": [
|
||||||
|
0,
|
||||||
|
0.5001
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow",
|
||||||
|
"elbowed": false,
|
||||||
|
"moveMidPointsWithElement": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "o3WprJN3wZEDcHw1DiFYr",
|
||||||
|
"type": "arrow",
|
||||||
|
"x": 1755.5,
|
||||||
|
"y": 765.5,
|
||||||
|
"width": 84.00000000000023,
|
||||||
|
"height": 141.54545454545473,
|
||||||
|
"angle": 0,
|
||||||
|
"strokeColor": "#ffffff",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"groupIds": [],
|
||||||
|
"frameId": null,
|
||||||
|
"index": "al",
|
||||||
|
"roundness": {
|
||||||
|
"type": 2
|
||||||
|
},
|
||||||
|
"seed": 68654021,
|
||||||
|
"version": 179,
|
||||||
|
"versionNonce": 1367219755,
|
||||||
|
"isDeleted": false,
|
||||||
|
"boundElements": [],
|
||||||
|
"updated": 1787675789610,
|
||||||
|
"link": null,
|
||||||
|
"locked": false,
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
43,
|
||||||
|
33
|
||||||
|
],
|
||||||
|
[
|
||||||
|
42,
|
||||||
|
132
|
||||||
|
],
|
||||||
|
[
|
||||||
|
84.00000000000023,
|
||||||
|
141.54545454545473
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"startBinding": {
|
||||||
|
"elementId": "Dug48Ksr7mdITJ1CSQdgJ",
|
||||||
|
"mode": "inside",
|
||||||
|
"fixedPoint": [
|
||||||
|
0.9971062036445457,
|
||||||
|
0.47830856212545203
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"endBinding": {
|
||||||
|
"elementId": "oIXVKbkqP10kd7HsX3Ma8",
|
||||||
|
"mode": "orbit",
|
||||||
|
"fixedPoint": [
|
||||||
|
0.45884773662551637,
|
||||||
|
0.45884773662551726
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow",
|
||||||
|
"elbowed": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "GPK9crZA0GMljhRqF5HDa",
|
||||||
|
"type": "text",
|
||||||
|
"x": 1794.2073421171517,
|
||||||
|
"y": 835.5194758205485,
|
||||||
|
"width": 8,
|
||||||
|
"height": 25,
|
||||||
|
"angle": 0,
|
||||||
|
"strokeColor": "#ffffff",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"groupIds": [],
|
||||||
|
"frameId": null,
|
||||||
|
"index": "am",
|
||||||
|
"roundness": null,
|
||||||
|
"seed": 1055479941,
|
||||||
|
"version": 3,
|
||||||
|
"versionNonce": 1276059851,
|
||||||
|
"isDeleted": true,
|
||||||
|
"boundElements": null,
|
||||||
|
"updated": 1787675789610,
|
||||||
|
"link": null,
|
||||||
|
"locked": false,
|
||||||
|
"text": "",
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 5,
|
||||||
|
"textAlign": "center",
|
||||||
|
"verticalAlign": "middle",
|
||||||
|
"containerId": "o3WprJN3wZEDcHw1DiFYr",
|
||||||
|
"originalText": "",
|
||||||
|
"autoResize": true,
|
||||||
|
"lineHeight": 1.25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v_3ygDgE5RD8LQhGEvhTX",
|
||||||
|
"type": "arrow",
|
||||||
|
"x": 1662.1960283823262,
|
||||||
|
"y": 1200.2170926328931,
|
||||||
|
"width": 128.30397161767382,
|
||||||
|
"height": 194.71709263289313,
|
||||||
|
"angle": 0,
|
||||||
|
"strokeColor": "#ffffff",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"groupIds": [],
|
||||||
|
"frameId": null,
|
||||||
|
"index": "an",
|
||||||
|
"roundness": {
|
||||||
|
"type": 2
|
||||||
|
},
|
||||||
|
"seed": 1602252997,
|
||||||
|
"version": 261,
|
||||||
|
"versionNonce": 1283832069,
|
||||||
|
"isDeleted": true,
|
||||||
|
"boundElements": null,
|
||||||
|
"updated": 1787675799132,
|
||||||
|
"link": null,
|
||||||
|
"locked": false,
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
128.30397161767382,
|
||||||
|
-194.71709263289313
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"startBinding": {
|
||||||
|
"elementId": "qO3tWw8uDrdY-GSL5hbG7",
|
||||||
|
"mode": "orbit",
|
||||||
|
"fixedPoint": [
|
||||||
|
0.2207233413264886,
|
||||||
|
0.22072334132648888
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"endBinding": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow",
|
||||||
|
"elbowed": false,
|
||||||
|
"fixedSegments": null,
|
||||||
|
"startIsSpecial": null,
|
||||||
|
"endIsSpecial": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Z4Fy52Fl_c9lXHJlrhd9g",
|
||||||
|
"type": "arrow",
|
||||||
|
"x": 1761.9167066751852,
|
||||||
|
"y": 1248.0538669619218,
|
||||||
|
"width": 78.55616398479242,
|
||||||
|
"height": 286.26754389891505,
|
||||||
|
"angle": 0,
|
||||||
|
"strokeColor": "#ffffff",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"groupIds": [],
|
||||||
|
"frameId": null,
|
||||||
|
"index": "ao",
|
||||||
|
"roundness": {
|
||||||
|
"type": 2
|
||||||
|
},
|
||||||
|
"seed": 1569002603,
|
||||||
|
"version": 382,
|
||||||
|
"versionNonce": 2105101093,
|
||||||
|
"isDeleted": false,
|
||||||
|
"boundElements": null,
|
||||||
|
"updated": 1787675810843,
|
||||||
|
"link": null,
|
||||||
|
"locked": false,
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
28.583293324814804,
|
||||||
|
-36.55386696192181
|
||||||
|
],
|
||||||
|
[
|
||||||
|
4.583293324814804,
|
||||||
|
-269.5538669619218
|
||||||
|
],
|
||||||
|
[
|
||||||
|
78.55616398479242,
|
||||||
|
-286.26754389891505
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"startBinding": {
|
||||||
|
"elementId": "qO3tWw8uDrdY-GSL5hbG7",
|
||||||
|
"mode": "orbit",
|
||||||
|
"fixedPoint": [
|
||||||
|
1,
|
||||||
|
0.5001
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"endBinding": {
|
||||||
|
"elementId": "oIXVKbkqP10kd7HsX3Ma8",
|
||||||
|
"mode": "orbit",
|
||||||
|
"fixedPoint": [
|
||||||
|
0.24597691208358835,
|
||||||
|
0.7540230879164157
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow",
|
||||||
"elbowed": false
|
"elbowed": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ local MissionCompleteListeners = {}
|
|||||||
---@class SpearheadAPIInternal
|
---@class SpearheadAPIInternal
|
||||||
---@field notifyMissionComplete fun(zone_name: string)
|
---@field notifyMissionComplete fun(zone_name: string)
|
||||||
|
|
||||||
|
|
||||||
---@type FullSpearheadAPI
|
---@type FullSpearheadAPI
|
||||||
SpearheadAPI = {
|
SpearheadAPI = {
|
||||||
Stages = {
|
Stages = {
|
||||||
@@ -25,12 +24,12 @@ SpearheadAPI = {
|
|||||||
getCurrentStage = function()
|
getCurrentStage = function()
|
||||||
return GlobalStageManager.getCurrentStage() or nil
|
return GlobalStageManager.getCurrentStage() or nil
|
||||||
end,
|
end,
|
||||||
isStageComplete = function(stageNumber)
|
isStageComplete = function(stageNumber, stageLaneIdentifier)
|
||||||
if type(stageNumber) ~= "number" then
|
if type(stageNumber) ~= "number" then
|
||||||
return false, "stageNumber " .. stageNumber .. " is not a valid number"
|
return false, "stageNumber " .. stageNumber .. " is not a valid number"
|
||||||
end
|
end
|
||||||
|
|
||||||
local isComplete = GlobalStageManager.isStageComplete(stageNumber)
|
local isComplete = GlobalStageManager.isStageComplete(stageNumber, stageLaneIdentifier)
|
||||||
if isComplete == nil then
|
if isComplete == nil then
|
||||||
return nil, "no stage found with number " .. stageNumber
|
return nil, "no stage found with number " .. stageNumber
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ SpearheadAPI = SpearheadAPI
|
|||||||
---@class SpearheadStagesAPI
|
---@class SpearheadStagesAPI
|
||||||
---@field changeStage fun(stageNumber: number): boolean, string @Changes the active stage of spearhead. <br/> All other stages will change based on the normal logic. (CAP, BLUE etc.)
|
---@field changeStage fun(stageNumber: number): boolean, string @Changes the active stage of spearhead. <br/> All other stages will change based on the normal logic. (CAP, BLUE etc.)
|
||||||
---@field getCurrentStage fun(): number | nil @Returns the current stange number <br/> Returns nil when the stagenumber was not set before ever, which means Spearhead was not started.
|
---@field getCurrentStage fun(): number | nil @Returns the current stange number <br/> Returns nil when the stagenumber was not set before ever, which means Spearhead was not started.
|
||||||
---@field isStageComplete fun(stageNumber: number): boolean | nil, string @returns whether a stage (by index) is complete. <br/> @param stageNumber number <br/> @return boolean | nil <br/> @return string
|
---@field isStageComplete fun(stageNumber: number, stageLaneIdentifier: string?): boolean | nil, string @returns whether a stage (by index) is complete. <br/> @param stageNumber number <br/> @param stageLaneIdentifier string? nil for default lane <br/> @return boolean | nil <br/> @return string
|
||||||
|
|
||||||
---@class OnMissionCompleteListener
|
---@class OnMissionCompleteListener
|
||||||
---@field onMissionComplete fun(self: OnMissionCompleteListener, zone_name: string) @Called when a mission is completed. @return void
|
---@field onMissionComplete fun(self: OnMissionCompleteListener, zone_name: string) @Called when a mission is completed. @return void
|
||||||
@@ -14,4 +14,3 @@ SpearheadAPI = SpearheadAPI
|
|||||||
---@class MissionAPI
|
---@class MissionAPI
|
||||||
---@field addOnMissionCompleteListener fun(listener: OnMissionCompleteListener) @Adds a listener to the mission. <br/> @param listener OnMissionCompleteListener <br/> @return void
|
---@field addOnMissionCompleteListener fun(listener: OnMissionCompleteListener) @Adds a listener to the mission. <br/> @param listener OnMissionCompleteListener <br/> @return void
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@class OnStageChangedListener
|
---@class OnStageChangedListener
|
||||||
---@field OnStageNumberChanged fun(self:OnStageChangedListener, number:integer)
|
---@field OnStageNumberChanged fun(self:OnStageChangedListener, number:integer, laneIdentifier:string?)
|
||||||
|
|
||||||
do -- STAGE NUMBER CHANGED
|
do -- STAGE NUMBER CHANGED
|
||||||
local OnStageNumberChangedListeners = {}
|
local OnStageNumberChangedListeners = {}
|
||||||
@@ -37,17 +37,11 @@ do
|
|||||||
---Add a stage zone number changed listener
|
---Add a stage zone number changed listener
|
||||||
---@param listener OnStageChangedListener object with function OnStageNumberChanged(self, number)
|
---@param listener OnStageChangedListener object with function OnStageNumberChanged(self, number)
|
||||||
SpearheadEvents.AddStageNumberChangedListener = function(listener)
|
SpearheadEvents.AddStageNumberChangedListener = function(listener)
|
||||||
table.insert(OnStageNumberChangedListeners, listener)
|
if type(listener) ~= "table" or type(listener.OnStageNumberChanged) ~= "function" then
|
||||||
end
|
warn("Event handler not of type table/object with function OnStageNumberChanged(self, number)")
|
||||||
|
|
||||||
---Add a stage zone number changed listener
|
|
||||||
---@param handler function function(number)
|
|
||||||
SpearheadEvents.AddStageNumberChangedHandler = function(handler)
|
|
||||||
if type(handler) ~= "function" then
|
|
||||||
warn("Event handler not of type function, did you mean to use listener?")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
table.insert(OnStageNumberChangedHandlers, handler)
|
table.insert(OnStageNumberChangedListeners, listener)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class OnStageNumberChangeCompleteListener
|
---@class OnStageNumberChangeCompleteListener
|
||||||
@@ -64,14 +58,15 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param newStageNumber number
|
---@param newStageNumber number
|
||||||
SpearheadEvents.PublishStageNumberChanged = function(newStageNumber)
|
---@param laneIdentifier string?
|
||||||
|
SpearheadEvents.PublishStageNumberChanged = function(newStageNumber, laneIdentifier)
|
||||||
pcall(function ()
|
pcall(function ()
|
||||||
Persistence.SetActiveStage(newStageNumber)
|
Persistence.SetActiveStage(newStageNumber)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
for _, callable in pairs(OnStageNumberChangedListeners) do
|
for _, callable in pairs(OnStageNumberChangedListeners) do
|
||||||
local succ, err = pcall(function()
|
local succ, err = pcall(function()
|
||||||
callable:OnStageNumberChanged(newStageNumber)
|
callable:OnStageNumberChanged(newStageNumber, laneIdentifier)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
logError(err)
|
logError(err)
|
||||||
@@ -79,7 +74,7 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
for _, callable in pairs(OnStageNumberChangedHandlers) do
|
for _, callable in pairs(OnStageNumberChangedHandlers) do
|
||||||
local succ, err = pcall(callable, newStageNumber)
|
local succ, err = pcall(callable, newStageNumber, laneIdentifier)
|
||||||
if err then
|
if err then
|
||||||
logError(err)
|
logError(err)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,17 +8,8 @@ local ExtraStage = require("classes.stageClasses.Stages.ExtraStage")
|
|||||||
local PrimaryStage = require("classes.stageClasses.Stages.PrimaryStage")
|
local PrimaryStage = require("classes.stageClasses.Stages.PrimaryStage")
|
||||||
local WaitingStage = require("classes.stageClasses.Stages.WaitingStage")
|
local WaitingStage = require("classes.stageClasses.Stages.WaitingStage")
|
||||||
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
||||||
|
local StageRepository = require("classes.stageClasses.StageRepository")
|
||||||
local StagesByName = {}
|
local StageLane = require("classes.stageClasses.StageLane")
|
||||||
|
|
||||||
---@type table<string, Array<Stage>>
|
|
||||||
local StagesByIndex = {}
|
|
||||||
|
|
||||||
---@type table<string, Array<Stage>>
|
|
||||||
local SideStageByIndex = {}
|
|
||||||
|
|
||||||
---@type table<string, Array<WaitingStage>>
|
|
||||||
local WaitingStagesByIndex = {}
|
|
||||||
|
|
||||||
local currentStage = -99
|
local currentStage = -99
|
||||||
|
|
||||||
@@ -26,25 +17,37 @@ local currentStage = -99
|
|||||||
---@field private database Database
|
---@field private database Database
|
||||||
---@field private logger Logger
|
---@field private logger Logger
|
||||||
---@field private stageConfig StageConfig
|
---@field private stageConfig StageConfig
|
||||||
|
---@field private _stageRepository StageRepository
|
||||||
---@field private _missionCommandsHelper MissionCommandsHelper
|
---@field private _missionCommandsHelper MissionCommandsHelper
|
||||||
local GlobalStageManager = {}
|
local GlobalStageManager = {}
|
||||||
GlobalStageManager.__index = GlobalStageManager
|
GlobalStageManager.__index = GlobalStageManager
|
||||||
|
|
||||||
GlobalStageManager.getCurrentStage = function() return currentStage end
|
GlobalStageManager.getCurrentStage = function() return currentStage end
|
||||||
|
|
||||||
|
---@type GlobalStageManager
|
||||||
|
local singletonInstance = nil
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param database Database
|
---@param database Database
|
||||||
---@param stageConfig StageConfig
|
---@param stageConfig StageConfig
|
||||||
---@param logLevel LogLevel
|
---@param logLevel LogLevel
|
||||||
---@param spawnManager SpawnManager
|
---@param spawnManager SpawnManager
|
||||||
---@return nil
|
---@return GlobalStageManager
|
||||||
function GlobalStageManager.NewAndStart(database, stageConfig, logLevel, spawnManager)
|
function GlobalStageManager.NewAndStart(database, stageConfig, logLevel, spawnManager)
|
||||||
|
|
||||||
|
if singletonInstance ~= nil then
|
||||||
|
return singletonInstance
|
||||||
|
end
|
||||||
|
|
||||||
local logger = Logger.new("StageManager", logLevel)
|
local logger = Logger.new("StageManager", logLevel)
|
||||||
logger:info("Using Stage Log Level: " .. logLevel)
|
logger:info("Using Stage Log Level: " .. logLevel)
|
||||||
local self = setmetatable({}, GlobalStageManager)
|
local self = setmetatable({}, GlobalStageManager)
|
||||||
|
singletonInstance = self
|
||||||
|
|
||||||
self.database = database
|
self.database = database
|
||||||
self.stageConfig = stageConfig
|
self.stageConfig = stageConfig
|
||||||
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate()
|
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate()
|
||||||
|
self._stageRepository = StageRepository.new()
|
||||||
|
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
if stageConfig.isAutoStages ~= true then
|
if stageConfig.isAutoStages ~= true then
|
||||||
@@ -55,161 +58,222 @@ function GlobalStageManager.NewAndStart(database, stageConfig, logLevel, spawnMa
|
|||||||
|
|
||||||
for _, stageName in pairs(database:getStagezoneNames()) do
|
for _, stageName in pairs(database:getStagezoneNames()) do
|
||||||
logger:debug("Found stage zone with name: " .. stageName)
|
logger:debug("Found stage zone with name: " .. stageName)
|
||||||
|
|
||||||
|
local parseResult = self:ParseStageName(stageName)
|
||||||
|
if parseResult.isValid == false then
|
||||||
|
logger:warn("Stage zone with name " .. stageName .. " is not valid: " .. parseResult.invalidReason)
|
||||||
|
else
|
||||||
|
local initData = {
|
||||||
|
stageZoneName = parseResult.stageZoneName,
|
||||||
|
stageNumber = parseResult.orderNumber,
|
||||||
|
stageDisplayName = parseResult.stageDisplayName,
|
||||||
|
stageLaneIdentifier = parseResult.stageLaneIdentifier
|
||||||
|
}
|
||||||
|
|
||||||
if Util.startswith(stageName, "missionstage", true) then
|
if parseResult.stageType == "PrimaryStage" then
|
||||||
local valid = true
|
local stage = PrimaryStage.New(database, stageConfig, logger, initData, spawnManager)
|
||||||
local split = Util.split_string(stageName, "_")
|
|
||||||
if Util.tableLength(split) < 2 then
|
|
||||||
MissionEditorWarnings.Add("Stage zone with name " .. stageName .. " does not have a order number or valid format")
|
|
||||||
valid = false
|
|
||||||
end
|
|
||||||
|
|
||||||
if Util.tableLength(split) < 3 then
|
stage:AddStageCompleteListener(self)
|
||||||
MissionEditorWarnings.Add("Stage zone with name " .. stageName .. " does not have a stage name")
|
self._stageRepository:AddStage(stage)
|
||||||
end
|
elseif parseResult.stageType == "ExtraStage" then
|
||||||
|
local stage = ExtraStage.New(database, stageConfig, logger, initData, spawnManager)
|
||||||
local orderNumber = nil
|
stage:AddStageCompleteListener(self)
|
||||||
local isSideStage = false
|
self._stageRepository:AddStage(stage)
|
||||||
if valid == true then
|
elseif parseResult.stageType == "WaitingStage" then
|
||||||
local orderNumberString = string.lower(split[2])
|
local waitingStage = WaitingStage.New(database, stageConfig, logger, initData, parseResult.waitingStageSeconds, spawnManager)
|
||||||
if Util.startswith(orderNumberString, "x") == true then
|
waitingStage:AddStageCompleteListener(self)
|
||||||
isSideStage = true
|
self._stageRepository:AddStage(waitingStage)
|
||||||
|
|
||||||
orderNumberString = string.gsub(orderNumberString, "x", "")
|
|
||||||
orderNumber = tonumber(orderNumberString)
|
|
||||||
else
|
|
||||||
orderNumber = tonumber(split[2])
|
|
||||||
end
|
|
||||||
|
|
||||||
if orderNumber == nil then
|
|
||||||
MissionEditorWarnings.Add("Stage zone with name " .. stageName .. " does not have a valid order number : " .. split[2])
|
|
||||||
valid = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local stageDisplayName = split[3]
|
|
||||||
local stagelogger = Logger.new(stageName, logLevel)
|
|
||||||
if valid == true and orderNumber then
|
|
||||||
|
|
||||||
---@type StageInitData
|
|
||||||
local initData = {
|
|
||||||
stageDisplayName = stageDisplayName,
|
|
||||||
stageNumber = orderNumber,
|
|
||||||
stageZoneName = stageName,
|
|
||||||
}
|
|
||||||
|
|
||||||
if isSideStage == true then
|
|
||||||
local stage = ExtraStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
|
||||||
stage:AddStageCompleteListener(self)
|
|
||||||
|
|
||||||
if SideStageByIndex[tostring(orderNumber)] == nil then SideStageByIndex[tostring(orderNumber)] = {} end
|
|
||||||
table.insert(SideStageByIndex[tostring(orderNumber)], stage)
|
|
||||||
else
|
|
||||||
local stage = PrimaryStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
|
||||||
stage:AddStageCompleteListener(self)
|
|
||||||
|
|
||||||
if StagesByIndex[tostring(orderNumber)] == nil then StagesByIndex[tostring(orderNumber)] = {} end
|
|
||||||
table.insert(StagesByIndex[tostring(orderNumber)], stage)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if Util.startswith(stageName, "waitingstage", true) then
|
|
||||||
local valid = true
|
|
||||||
|
|
||||||
local split = Util.split_string(stageName, "_")
|
|
||||||
|
|
||||||
if Util.tableLength(split) < 3 then
|
|
||||||
MissionEditorWarnings.Add("Stage zone with name " .. stageName .. " does not have a order number or valid format")
|
|
||||||
valid = false
|
|
||||||
end
|
|
||||||
|
|
||||||
if valid == true then
|
|
||||||
local stageIndexString = split[2]
|
|
||||||
local stageIndex = tonumber(stageIndexString)
|
|
||||||
|
|
||||||
if not stageIndex then
|
|
||||||
MissionEditorWarnings.Add("Stage zone with name " .. stageName .. " does not have a valid order number")
|
|
||||||
valid = false
|
|
||||||
end
|
|
||||||
|
|
||||||
local waitingSecondsString = split[3]
|
|
||||||
local waitingSeconds = tonumber(waitingSecondsString)
|
|
||||||
if not waitingSeconds then
|
|
||||||
MissionEditorWarnings.Add("Waiting Stage zone with name " .. stageName .. " does not have a valid amount of seconds parameter")
|
|
||||||
valid = false
|
|
||||||
end
|
|
||||||
|
|
||||||
if valid == true then
|
|
||||||
local stagelogger = Logger.new(stageName, logLevel)
|
|
||||||
|
|
||||||
---@type WaitingStageInitData
|
|
||||||
local initData = {
|
|
||||||
stageDisplayName = "Waiting Stage " .. stageIndex,
|
|
||||||
stageNumber = stageIndex or -99,
|
|
||||||
stageZoneName = stageName,
|
|
||||||
waitingSeconds = waitingSeconds --[[@as integer]]
|
|
||||||
}
|
|
||||||
local waitingStage = WaitingStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
|
||||||
|
|
||||||
if WaitingStagesByIndex[tostring(stageIndex)] == nil then
|
|
||||||
WaitingStagesByIndex[tostring(stageIndex)] = {}
|
|
||||||
end
|
|
||||||
table.insert(WaitingStagesByIndex[tostring(stageIndex)], waitingStage)
|
|
||||||
|
|
||||||
waitingStage:AddStageCompleteListener(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
singletonInstance = self
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@class StageNameParseResult
|
||||||
|
---@field isValid boolean
|
||||||
|
---@field orderNumber integer
|
||||||
|
---@field stageLaneIdentifier string?
|
||||||
|
---@field stageDisplayName string
|
||||||
|
---@field stageZoneName string
|
||||||
|
---@field stageType StageType
|
||||||
|
---@field invalidReason string?
|
||||||
|
---@field waitingStageSeconds integer?
|
||||||
|
|
||||||
|
---@param self GlobalStageManager
|
||||||
|
---@param stageName string
|
||||||
|
---@return StageNameParseResult
|
||||||
|
function GlobalStageManager:ParseStageName(stageName)
|
||||||
|
|
||||||
|
local split = Util.split_string(stageName, "_")
|
||||||
|
|
||||||
|
if Util.tableLength(split) < 3 then
|
||||||
|
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " does not have a order number or valid format" }
|
||||||
|
end
|
||||||
|
|
||||||
|
local typePart = string.lower(split[1])
|
||||||
|
|
||||||
|
if typePart == "missionstage" then
|
||||||
|
|
||||||
|
local orderNumberString = string.lower(split[2])
|
||||||
|
---@type StageType
|
||||||
|
local stageType = "PrimaryStage"
|
||||||
|
if Util.endsWith(orderNumberString, "x", true) == true then
|
||||||
|
stageType = "ExtraStage"
|
||||||
|
orderNumberString = orderNumberString:sub(1, -1)
|
||||||
|
end
|
||||||
|
local stageLaneIdentifier = nil
|
||||||
|
local first = orderNumberString:sub(1, 1)
|
||||||
|
if tonumber(first) == nil then -- first character is the lane identifier only if it's not a number
|
||||||
|
stageLaneIdentifier = string.lower(first)
|
||||||
|
|
||||||
|
orderNumberString = orderNumberString:sub(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
local orderNumber = tonumber(orderNumberString)
|
||||||
|
if orderNumber == nil then
|
||||||
|
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " does not have a valid order number : " .. orderNumberString }
|
||||||
|
end
|
||||||
|
|
||||||
|
local stageDisplayName = split[3]
|
||||||
|
---@type StageNameParseResult
|
||||||
|
local result = {
|
||||||
|
isValid = true,
|
||||||
|
orderNumber = orderNumber,
|
||||||
|
stageLaneIdentifier = stageLaneIdentifier,
|
||||||
|
stageDisplayName = stageDisplayName,
|
||||||
|
stageZoneName = stageName,
|
||||||
|
stageType = stageType
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
elseif typePart == "waitingstage" then
|
||||||
|
|
||||||
|
local stageType = "WaitingStage"
|
||||||
|
local orderNumberString = split[2]
|
||||||
|
local orderNumber = tonumber(orderNumberString)
|
||||||
|
if orderNumber == nil then
|
||||||
|
return { isValid = false, invalidReason = "Waiting Stage zone with name " .. stageName .. " does not have a valid order number : " .. orderNumberString }
|
||||||
|
end
|
||||||
|
|
||||||
|
local waitingSecondsString = split[3]
|
||||||
|
local waitingSeconds = tonumber(waitingSecondsString)
|
||||||
|
if waitingSeconds == nil then
|
||||||
|
return { isValid = false, invalidReason = "Waiting Stage zone with name " .. stageName .. " does not have a valid amount of seconds parameter : " .. waitingSecondsString }
|
||||||
|
end
|
||||||
|
|
||||||
|
local stageDisplayName = "Waiting Stage " .. orderNumber
|
||||||
|
|
||||||
|
---@type StageNameParseResult
|
||||||
|
local result = {
|
||||||
|
isValid = true,
|
||||||
|
orderNumber = orderNumber,
|
||||||
|
stageLaneIdentifier = nil,
|
||||||
|
stageDisplayName = stageDisplayName,
|
||||||
|
stageZoneName = stageName,
|
||||||
|
stageType = stageType,
|
||||||
|
waitingStageSeconds = waitingSeconds
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
|
||||||
|
end
|
||||||
|
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " has an unrecognized type: " .. typePart }
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param stage Stage
|
||||||
function GlobalStageManager:OnStageComplete(stage)
|
function GlobalStageManager:OnStageComplete(stage)
|
||||||
self.logger:debug("Receiving stage complete event from: " .. stage.zoneName)
|
self.logger:debug("Receiving stage complete event from: " .. stage.zoneName)
|
||||||
|
|
||||||
local anyIncomplete = false
|
local stageIndex = stage:GetStageIndex()
|
||||||
self.logger:debug("Checking stages for index: " .. tostring(currentStage))
|
local laneIdentifier = stage:GetStageLaneIdentifier()
|
||||||
for index, stage in pairs(StagesByIndex[tostring(currentStage)]) do
|
|
||||||
if stage:IsComplete() == false then
|
local stageLane = self._stageRepository:getStageLane(laneIdentifier)
|
||||||
anyIncomplete = true
|
if not stageLane or not stageLane:IsCurrentStageIndexComplete() then
|
||||||
self.logger:debug("Need to wait for Stage " .. stage.zoneName .. " to be completed")
|
self.logger:debug("Stage lane " .. (laneIdentifier or "default") .. " is not complete for stage index " .. stageIndex)
|
||||||
else
|
return
|
||||||
self.logger:debug("Stage verified to be completed: " .. stage.zoneName)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if anyIncomplete == false and self.stageConfig.isAutoStages == true then
|
|
||||||
|
|
||||||
-- CHECK WAITING STAGES
|
local nextStageIndex = stageIndex + 1
|
||||||
local nextStage = currentStage + 1
|
|
||||||
|
Events.PublishStageNumberChanged(nextStageIndex, laneIdentifier)
|
||||||
if WaitingStagesByIndex[tostring(nextStage)] then
|
stageLane:SetActiveStageIndex(nextStageIndex)
|
||||||
for _, waitingStage in pairs(WaitingStagesByIndex[tostring(nextStage)]) do
|
|
||||||
if waitingStage:IsActive() == false then
|
if stageLane:IsDefaultStageLane() then
|
||||||
waitingStage:ActivateStage()
|
-- COMPLETION IN THE DEFAULT LANE
|
||||||
|
|
||||||
|
-- 1. Check if any lane is at status "BetweenChapters" and the next chapter start is "next stage index"
|
||||||
|
|
||||||
|
local allLanes = self._stageRepository:getAllStageLanes()
|
||||||
|
for _, lane in ipairs(allLanes) do
|
||||||
|
if lane:GetStageLaneIdentifier() ~= StageLane.DefaultLaneKey and lane:GetStageLaneState() == "InChapter" then
|
||||||
|
local nextChapterStart = lane:GetNextChapterStart()
|
||||||
|
if nextChapterStart == nextStageIndex then
|
||||||
|
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is at chapter start for next stage index " .. nextStageIndex)
|
||||||
|
Events.PublishStageNumberChanged(nextStageIndex, lane:GetStageLaneIdentifier())
|
||||||
|
lane:SetActiveStageIndex(nextStageIndex)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
else
|
||||||
local anyWaiting = false
|
-- COMPLETION IN A SIDE LANE
|
||||||
if WaitingStagesByIndex[tostring(nextStage)] then
|
|
||||||
for _, waitingStage in pairs(WaitingStagesByIndex[tostring(nextStage)]) do
|
-- 1. Check if the default lane is at status "BetweenChapters"
|
||||||
if waitingStage:IsComplete() == false then
|
local defaultStageLane = self._stageRepository:getStageLane(StageLane.DefaultLaneKey)
|
||||||
anyWaiting = true
|
if defaultStageLane and defaultStageLane:GetStageLaneState() == "BetweenChapters" then
|
||||||
|
local nextChapterStart = defaultStageLane:GetNextChapterStart()
|
||||||
|
if nextChapterStart == nextStageIndex then
|
||||||
|
|
||||||
|
-- 2. Check if all side lanes are at or beyond the next chapter starts
|
||||||
|
local allLanes = self._stageRepository:getAllStageLanes()
|
||||||
|
local allSideLanesReady = true
|
||||||
|
for _, lane in ipairs(allLanes) do
|
||||||
|
if lane:GetStageLaneIdentifier() ~= StageLane.DefaultLaneKey then
|
||||||
|
-- Check if the lane is at or beyond the next chapter starts when "InChapter" eq "Active"
|
||||||
|
if lane:GetStageLaneState() == "InChapter" and lane:GetActiveStageIndex() < nextStageIndex then
|
||||||
|
allSideLanesReady = false
|
||||||
|
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is not ready for next stage index " .. nextStageIndex)
|
||||||
|
break
|
||||||
|
|
||||||
|
-- When in between chapters, check if the next chapter start is less than the next stage index, meaning there is still stages to be completed before the main lane can be activated again
|
||||||
|
elseif lane:GetStageLaneState() == "BetweenChapters" then
|
||||||
|
local nextChapter = lane:GetNextChapterStart()
|
||||||
|
if nextChapter and nextChapter < nextStageIndex then
|
||||||
|
allSideLanesReady = false
|
||||||
|
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is not ready for next stage index " .. nextStageIndex)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if allSideLanesReady then
|
||||||
|
self.logger:debug("All side lanes are ready for next stage index " .. nextStageIndex .. ", activating default lane")
|
||||||
|
Events.PublishStageNumberChanged(nextStageIndex, nil)
|
||||||
|
defaultStageLane:SetActiveStageIndex(nextStageIndex)
|
||||||
|
else
|
||||||
|
self.logger:debug("Not all side lanes are ready for next stage index " .. nextStageIndex .. ", default lane will not be activated")
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if anyWaiting == false then
|
|
||||||
local newStageNumber = currentStage + 1
|
|
||||||
self.logger:debug("Setting next stage to: " .. tostring(newStageNumber))
|
|
||||||
Events.PublishStageNumberChanged(newStageNumber)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param stageNumber number
|
||||||
|
---@param stageLaneIdentifier string?
|
||||||
|
---@return boolean?
|
||||||
|
function GlobalStageManager:IsStageComplete(stageNumber, stageLaneIdentifier)
|
||||||
|
local stageLane = self._stageRepository:getStageLane(stageLaneIdentifier)
|
||||||
|
if not stageLane then
|
||||||
|
self.logger:warn("Stage lane " .. (stageLaneIdentifier or "default") .. " does not exist")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return stageLane:IsStageIndexComplete(stageNumber)
|
||||||
|
end
|
||||||
|
|
||||||
---@public
|
---@public
|
||||||
function GlobalStageManager:OnStageNumberChanged(stageNumber)
|
function GlobalStageManager:OnStageNumberChanged(stageNumber)
|
||||||
self.logger:debug("Stage number changed to: " .. tostring(stageNumber))
|
self.logger:debug("Stage number changed to: " .. tostring(stageNumber))
|
||||||
@@ -252,67 +316,176 @@ function GlobalStageManager:UpdateDrawings(stageNumber)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
GlobalStageManager.printFullOverview = function ()
|
function GlobalStageManager:PrintMermaidStage()
|
||||||
|
local lanes = self._stageRepository:getAllStageLanes()
|
||||||
|
|
||||||
local logger = Logger.new("StageOverview", "INFO")
|
local nodes = {}
|
||||||
logger:info("Stage overview:")
|
local edges = {}
|
||||||
|
local stageIndicesByLane = {} -- Track all stage indices per lane
|
||||||
local max = 0
|
local mainLaneId = "default"
|
||||||
local lines = {}
|
|
||||||
for stageIndex, stages in pairs(StagesByIndex) do
|
-- Build nodes and collect all stage indices per lane
|
||||||
|
for _, lane in ipairs(lanes) do
|
||||||
|
local laneId = lane:GetStageLaneIdentifier() or "default"
|
||||||
|
local stageIndices = lane:GetAllStageIndices()
|
||||||
|
stageIndicesByLane[laneId] = stageIndices
|
||||||
|
|
||||||
local totalStrike = 0
|
-- Create nodes for each stage index in this lane
|
||||||
local totalbai = 0
|
for _, stageIndex in ipairs(stageIndices) do
|
||||||
local totaldead = 0
|
local stages = lane:GetStagesAtIndex(stageIndex)
|
||||||
local totalMissions = 0
|
|
||||||
local totalCas = 0
|
|
||||||
|
|
||||||
for _, stage in pairs(stages) do
|
|
||||||
|
|
||||||
local strike, dead, bai, cas = stage:GetStageStats()
|
if stages then
|
||||||
|
for _, stage in ipairs(stages) do
|
||||||
totalStrike = totalStrike + strike
|
local nodeId = laneId .. "_" .. stageIndex
|
||||||
totalbai = totalbai + bai
|
local stageType = stage:GetStageType()
|
||||||
totaldead = totaldead + dead
|
local label = stage.stageName or stage.zoneName
|
||||||
totalCas = totalCas + cas
|
|
||||||
totalMissions = totalMissions + strike + dead + bai + cas
|
-- Different node shapes for different stage types
|
||||||
end
|
local nodeShape = "["
|
||||||
|
local nodeEnd = "]"
|
||||||
local index = tonumber(stageIndex)
|
if stageType == "ExtraStage" then
|
||||||
if index then
|
nodeShape = "(["
|
||||||
if index > max then
|
nodeEnd = "])"
|
||||||
max = index
|
elseif stageType == "WaitingStage" then
|
||||||
|
nodeShape = "[["
|
||||||
|
nodeEnd = "]]"
|
||||||
|
end
|
||||||
|
|
||||||
|
nodes[nodeId] = string.format(' %s%s"%s (S%d)"%s',
|
||||||
|
nodeId, nodeShape, label, stageIndex, nodeEnd)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
lines[index] ="Stage# " .. tostring(stageIndex).. " | " .. totalStrike .. " strikes | " .. totaldead .. " dead | " .. totalbai .. " BAI | " .. totalCas .. " CAS | Total:" .. totalMissions
|
|
||||||
else
|
|
||||||
logger:warn("Stage index is not a number: " .. stageIndex)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, max do
|
-- Add edges for sequential stages within the same lane
|
||||||
if lines[i] then
|
for laneId, stageIndices in pairs(stageIndicesByLane) do
|
||||||
logger:info(lines[i])
|
for i = 1, #stageIndices - 1 do
|
||||||
|
local fromIdx = stageIndices[i]
|
||||||
|
local toIdx = stageIndices[i + 1]
|
||||||
|
local fromNodeId = laneId .. "_" .. fromIdx
|
||||||
|
local toNodeId = laneId .. "_" .. toIdx
|
||||||
|
|
||||||
|
-- Check if this is a chapter boundary (gap)
|
||||||
|
local isChapter = false
|
||||||
|
for _, lane in ipairs(lanes) do
|
||||||
|
local normalizedLaneId = lane:GetStageLaneIdentifier() or "default"
|
||||||
|
if normalizedLaneId == laneId then
|
||||||
|
isChapter = lane:IsChapterStart(toIdx)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local label = isChapter and "|chapter|" or ""
|
||||||
|
table.insert(edges, string.format(' %s -->%s %s', fromNodeId, label, toNodeId))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Get main lane reference
|
||||||
|
local mainStageLane = nil
|
||||||
|
for _, lane in ipairs(lanes) do
|
||||||
|
if lane:IsDefaultStageLane() then
|
||||||
|
mainStageLane = lane
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add dependencies from DEFAULT lane to SIDE lanes at chapter starts
|
||||||
|
-- Side lanes activate when main reaches a chapter start index for that side lane
|
||||||
|
if mainStageLane then
|
||||||
|
for _, lane in ipairs(lanes) do
|
||||||
|
if lane:IsDefaultStageLane() == false then
|
||||||
|
local sideId = lane:GetStageLaneIdentifier()
|
||||||
|
local sideIndices = stageIndicesByLane[sideId]
|
||||||
|
|
||||||
|
-- For each stage in the side lane
|
||||||
|
for _, stageIdx in ipairs(sideIndices) do
|
||||||
|
-- Check if this is a chapter start in the side lane
|
||||||
|
if lane:IsChapterStart(stageIdx) then
|
||||||
|
local fromNodeId = mainLaneId .. "_" .. stageIdx
|
||||||
|
local toNodeId = sideId .. "_" .. stageIdx
|
||||||
|
-- Side lane activates when main lane reaches this chapter start
|
||||||
|
table.insert(edges, string.format(' %s -->|unlock| %s', fromNodeId, toNodeId))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add dependencies from SIDE lanes gating the MAIN lane at chapter boundaries
|
||||||
|
-- Main cannot advance to the next chapter until ALL side lanes are at or above that chapter index
|
||||||
|
if mainStageLane then
|
||||||
|
local mainIndices = stageIndicesByLane[mainLaneId]
|
||||||
|
|
||||||
|
-- For each chapter start in main lane (skip first one)
|
||||||
|
for i = 2, #mainIndices do
|
||||||
|
local nextIdx = mainIndices[i]
|
||||||
|
|
||||||
|
-- Check if nextIdx is a chapter start (there's a gap before it)
|
||||||
|
if mainStageLane:IsChapterStart(nextIdx) then
|
||||||
|
-- Before main can progress to nextIdx, all side lanes must be at >= nextIdx
|
||||||
|
for _, lane in ipairs(lanes) do
|
||||||
|
if lane:IsDefaultStageLane() == false then
|
||||||
|
local sideId = lane:GetStageLaneIdentifier()
|
||||||
|
local sideIndices = stageIndicesByLane[sideId]
|
||||||
|
|
||||||
|
-- Find the appropriate gate node for this side lane
|
||||||
|
-- Use first stage >= nextIdx if it exists, otherwise use the highest stage
|
||||||
|
local gateStageIdx = nil
|
||||||
|
|
||||||
|
for _, idx in ipairs(sideIndices) do
|
||||||
|
if idx >= nextIdx then
|
||||||
|
gateStageIdx = idx
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If no stage >= nextIdx, use the highest stage in this lane
|
||||||
|
if gateStageIdx == nil and #sideIndices > 0 then
|
||||||
|
gateStageIdx = sideIndices[#sideIndices]
|
||||||
|
end
|
||||||
|
|
||||||
|
if gateStageIdx then
|
||||||
|
local fromNodeId = sideId .. "_" .. gateStageIdx
|
||||||
|
local toNodeId = mainLaneId .. "_" .. nextIdx
|
||||||
|
table.insert(edges, string.format(' %s -->|gate| %s', fromNodeId, toNodeId))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Build complete Mermaid diagram
|
||||||
|
local diagramLines = {"graph TD"}
|
||||||
|
for _, nodeStr in pairs(nodes) do
|
||||||
|
table.insert(diagramLines, nodeStr)
|
||||||
|
end
|
||||||
|
for _, edgeStr in pairs(edges) do
|
||||||
|
table.insert(diagramLines, edgeStr)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Print as single multi-line message
|
||||||
|
local diagram = "========== STAGE FLOW DIAGRAM ==========\n" .. table.concat(diagramLines, "\n") .. "\n========== END DIAGRAM =========="
|
||||||
|
self.logger:info(diagram)
|
||||||
end
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param stageNumber number
|
---@param stageNumber number
|
||||||
|
---@param stageLaneIdentifier string? nil for default lan
|
||||||
---@return boolean | nil
|
---@return boolean | nil
|
||||||
GlobalStageManager.isStageComplete = function (stageNumber)
|
GlobalStageManager.isStageComplete = function (stageNumber, stageLaneIdentifier)
|
||||||
|
|
||||||
local stageIndex = tostring(stageNumber)
|
|
||||||
|
|
||||||
if StagesByIndex[stageIndex] == nil then return nil end
|
|
||||||
|
|
||||||
for _, stage in ipairs(StagesByIndex[stageIndex]) do
|
if singletonInstance == nil then
|
||||||
if stage:IsComplete() == false then
|
Logger.new("StageManager", "INFO"):warn("GlobalStageManager.isStageComplete called before GlobalStageManager was initialized. Returning nil")
|
||||||
return false
|
return nil
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
if stageLaneIdentifier then
|
||||||
|
stageLaneIdentifier = string.lower(stageLaneIdentifier)
|
||||||
|
end
|
||||||
|
|
||||||
|
return singletonInstance:IsStageComplete(stageNumber, stageLaneIdentifier)
|
||||||
end
|
end
|
||||||
|
|
||||||
return GlobalStageManager
|
return GlobalStageManager
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
|
||||||
|
|
||||||
|
---@class StageLane
|
||||||
|
---@field private _isDefaultStageLane boolean
|
||||||
|
---@field private _stageLaneIdentifier string
|
||||||
|
---@field private _activeStageIndex number
|
||||||
|
---@field private _stagesInLaneByIndex table<number, Array<Stage>>
|
||||||
|
---@field private _chapterStarts table<number, boolean>?
|
||||||
|
---@field private _stageLaneState StageLaneState
|
||||||
|
---@field private _maxStageIndex number
|
||||||
|
local StageLane = {}
|
||||||
|
StageLane.__index = StageLane
|
||||||
|
|
||||||
|
---@alias StageLaneState
|
||||||
|
---| "InChapter"
|
||||||
|
---| "BetweenChapters"
|
||||||
|
---| "Completed"
|
||||||
|
|
||||||
|
StageLane.DefaultLaneKey = nil
|
||||||
|
|
||||||
|
function StageLane.New(laneIdentifier)
|
||||||
|
|
||||||
|
if not laneIdentifier then
|
||||||
|
laneIdentifier = StageLane.DefaultLaneKey
|
||||||
|
end
|
||||||
|
|
||||||
|
local self = setmetatable({}, { __index = StageLane }) --[[@as StageLane]]
|
||||||
|
self._isDefaultStageLane = laneIdentifier == StageLane.DefaultLaneKey
|
||||||
|
self._stageLaneIdentifier = laneIdentifier
|
||||||
|
self._activeStageIndex = nil
|
||||||
|
self._stagesInLaneByIndex = {}
|
||||||
|
self._chapterStarts = nil
|
||||||
|
self._stageLaneState = "BetweenChapters"
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param stage Stage
|
||||||
|
function StageLane:AddStage(stage)
|
||||||
|
local stageIndex = stage:GetStageIndex()
|
||||||
|
if not self._stagesInLaneByIndex[stageIndex] then
|
||||||
|
self._stagesInLaneByIndex[stageIndex] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self._maxStageIndex or stageIndex > self._maxStageIndex then
|
||||||
|
self._maxStageIndex = stageIndex
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(self._stagesInLaneByIndex[stageIndex], stage)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param stageNumber number
|
||||||
|
---@return boolean?
|
||||||
|
function StageLane:IsStageIndexComplete(stageNumber)
|
||||||
|
local stages = self._stagesInLaneByIndex[stageNumber]
|
||||||
|
if not stages then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, stage in ipairs(stages) do
|
||||||
|
if not stage:IsComplete() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return boolean
|
||||||
|
function StageLane:IsCurrentStageIndexComplete()
|
||||||
|
return self:IsStageIndexComplete(self._activeStageIndex) == true
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return string?
|
||||||
|
function StageLane:GetStageLaneIdentifier()
|
||||||
|
return self._stageLaneIdentifier
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return boolean
|
||||||
|
function StageLane:IsDefaultStageLane()
|
||||||
|
return self._isDefaultStageLane
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return number
|
||||||
|
function StageLane:GetActiveStageIndex()
|
||||||
|
return self._activeStageIndex
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param stageNumber number
|
||||||
|
function StageLane:SetActiveStageIndex(stageNumber)
|
||||||
|
|
||||||
|
if self._stagesInLaneByIndex[stageNumber] == nil then
|
||||||
|
self._stageLaneState = "BetweenChapters" -- stage number is not in this lane, so we are between chapters
|
||||||
|
elseif stageNumber > self._maxStageIndex then
|
||||||
|
self._stageLaneState = "Completed" -- stage number is beyond the max stage index
|
||||||
|
else
|
||||||
|
self._stageLaneState = "InChapter"
|
||||||
|
end
|
||||||
|
|
||||||
|
self._activeStageIndex = stageNumber
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return StageLaneState
|
||||||
|
function StageLane:GetStageLaneState()
|
||||||
|
return self._stageLaneState
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Checks if the given stage number is a chapter start. <br>
|
||||||
|
--- Chapter starts are the first StageIndex after a gap in stage numbers. <br>
|
||||||
|
--- For example, if the stage numbers are 1, 2, 3, 5, 6, 7, then stage number 5 is a chapter start because there is a gap between 3 and 5. <br>
|
||||||
|
---@param stageNumber number
|
||||||
|
function StageLane:IsChapterStart(stageNumber)
|
||||||
|
|
||||||
|
if self._chapterStarts == nil then
|
||||||
|
self:FillChapterStarts()
|
||||||
|
end
|
||||||
|
|
||||||
|
return self._chapterStarts[tostring(stageNumber)] == true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- fills chapter starts, chapter starts are where there's a gap in between stage numbers.
|
||||||
|
--- The first stage in a lane is always a chapter start.
|
||||||
|
---@private
|
||||||
|
function StageLane:FillChapterStarts()
|
||||||
|
|
||||||
|
local previousIndex = nil
|
||||||
|
local stageIndices = {}
|
||||||
|
for stageIndex, _ in pairs(self._stagesInLaneByIndex) do
|
||||||
|
table.insert(stageIndices, tonumber(stageIndex))
|
||||||
|
end
|
||||||
|
table.sort(stageIndices)
|
||||||
|
|
||||||
|
self._chapterStarts = self._chapterStarts or {}
|
||||||
|
for _, stageIndex in ipairs(stageIndices) do
|
||||||
|
if previousIndex == nil then
|
||||||
|
-- First stage is always a chapter start
|
||||||
|
self._chapterStarts[tostring(stageIndex)] = true
|
||||||
|
elseif stageIndex > previousIndex + 1 then
|
||||||
|
-- Gap before this stage means it's a chapter start
|
||||||
|
self._chapterStarts[tostring(stageIndex)] = true
|
||||||
|
else
|
||||||
|
-- Consecutive stage, not a chapter start
|
||||||
|
self._chapterStarts[tostring(stageIndex)] = false
|
||||||
|
end
|
||||||
|
previousIndex = stageIndex
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return Array<number>
|
||||||
|
function StageLane:GetAllStageIndices()
|
||||||
|
local indices = {}
|
||||||
|
for stageIndex, _ in pairs(self._stagesInLaneByIndex) do
|
||||||
|
table.insert(indices, tonumber(stageIndex))
|
||||||
|
end
|
||||||
|
table.sort(indices)
|
||||||
|
return indices
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param stageIndex number
|
||||||
|
---@return Array<Stage>?
|
||||||
|
function StageLane:GetStagesAtIndex(stageIndex)
|
||||||
|
return self._stagesInLaneByIndex[stageIndex]
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return number?
|
||||||
|
function StageLane:GetNextChapterStart()
|
||||||
|
if self._chapterStarts == nil then
|
||||||
|
self:FillChapterStarts()
|
||||||
|
end
|
||||||
|
|
||||||
|
for stageIndex, _ in pairs(self._stagesInLaneByIndex) do
|
||||||
|
if tonumber(stageIndex) > self._activeStageIndex and self._chapterStarts[tostring(stageIndex)] == true then
|
||||||
|
return tonumber(stageIndex)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return StageLane
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
local StageLane = require("classes.stageClasses.StageLane")
|
||||||
|
|
||||||
|
---@class StageRepository
|
||||||
|
---@field private StageLanes table<string, StageLane>
|
||||||
|
local StageRepository = {}
|
||||||
|
StageRepository.__index = StageRepository
|
||||||
|
|
||||||
|
---@return StageRepository
|
||||||
|
function StageRepository.new()
|
||||||
|
local self = setmetatable({}, StageRepository)
|
||||||
|
self.StageLanes = {}
|
||||||
|
self.StageLanes[tostring(StageLane.DefaultLaneKey)] = StageLane.New(StageLane.DefaultLaneKey)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---@param laneName string? `nil` for default lane
|
||||||
|
---@return StageLane?
|
||||||
|
function StageRepository:getStageLane(laneName)
|
||||||
|
if not laneName then
|
||||||
|
laneName = StageLane.DefaultLaneKey
|
||||||
|
end
|
||||||
|
return self.StageLanes[tostring(laneName)]
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return Array<StageLane>
|
||||||
|
function StageRepository:getAllStageLanes()
|
||||||
|
local lanes = {}
|
||||||
|
for _, lane in pairs(self.StageLanes) do
|
||||||
|
table.insert(lanes, lane)
|
||||||
|
end
|
||||||
|
return lanes
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param stage Stage
|
||||||
|
function StageRepository:AddStage(stage)
|
||||||
|
|
||||||
|
local stageLaneIdentifier = stage:GetStageLaneIdentifier() or StageLane.DefaultLaneKey
|
||||||
|
|
||||||
|
if self.StageLanes[tostring(stageLaneIdentifier)] == nil then
|
||||||
|
self.StageLanes[tostring(stageLaneIdentifier)] = StageLane.New(stageLaneIdentifier)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.StageLanes[tostring(stageLaneIdentifier)]:AddStage(stage)
|
||||||
|
end
|
||||||
|
|
||||||
|
return StageRepository
|
||||||
@@ -19,6 +19,11 @@ local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelpe
|
|||||||
---| "BLUE"
|
---| "BLUE"
|
||||||
---| "GRAY"
|
---| "GRAY"
|
||||||
|
|
||||||
|
---@alias StageType
|
||||||
|
---| "PrimaryStage"
|
||||||
|
---| "ExtraStage"
|
||||||
|
---| "WaitingStage"
|
||||||
|
|
||||||
--- @class StageData
|
--- @class StageData
|
||||||
--- @field stageBriefing string?
|
--- @field stageBriefing string?
|
||||||
--- @field missionsByCode table<string, Mission>
|
--- @field missionsByCode table<string, Mission>
|
||||||
@@ -33,9 +38,11 @@ local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelpe
|
|||||||
--- @field supplyHubs Array<SupplyHub>
|
--- @field supplyHubs Array<SupplyHub>
|
||||||
|
|
||||||
--- @class StageInitData
|
--- @class StageInitData
|
||||||
|
--- @field type StageType
|
||||||
--- @field stageZoneName string
|
--- @field stageZoneName string
|
||||||
--- @field stageNumber integer
|
--- @field stageNumber integer
|
||||||
--- @field stageDisplayName string
|
--- @field stageDisplayName string
|
||||||
|
--- @field stageLaneIdentifier string?
|
||||||
|
|
||||||
|
|
||||||
--- @class StageCompleteListener
|
--- @class StageCompleteListener
|
||||||
@@ -45,6 +52,8 @@ local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelpe
|
|||||||
--- @field zoneName string
|
--- @field zoneName string
|
||||||
--- @field stageName string?
|
--- @field stageName string?
|
||||||
--- @field stageNumber number
|
--- @field stageNumber number
|
||||||
|
--- @field protected _stageLaneIdentifier string?
|
||||||
|
--- @field protected _stageType StageType
|
||||||
--- @field protected _currentStageState CurrentStageState
|
--- @field protected _currentStageState CurrentStageState
|
||||||
--- @field protected _missionCommandsHelper MissionCommandsHelper
|
--- @field protected _missionCommandsHelper MissionCommandsHelper
|
||||||
--- @field protected _missionPriority MissionPriority
|
--- @field protected _missionPriority MissionPriority
|
||||||
@@ -86,15 +95,22 @@ Stage.StageColors = {
|
|||||||
---@param initData StageInitData
|
---@param initData StageInitData
|
||||||
---@param missionPriority MissionPriority
|
---@param missionPriority MissionPriority
|
||||||
---@param spawnManager SpawnManager
|
---@param spawnManager SpawnManager
|
||||||
|
---@param stageType StageType
|
||||||
---@return Stage
|
---@return Stage
|
||||||
function Stage:superNew(database, stageConfig, logger, initData, missionPriority, spawnManager)
|
function Stage:superNew(database, stageConfig, logger, initData, stageType, missionPriority, spawnManager)
|
||||||
|
|
||||||
logger:debug("[BaseStage] Initiating stage with name: " .. initData.stageZoneName)
|
logger:debug("[BaseStage] Initiating stage with name: " .. initData.stageZoneName)
|
||||||
self._currentStageState = Stage.CurrentStageState.INACTIVE
|
self._currentStageState = Stage.CurrentStageState.INACTIVE
|
||||||
self.zoneName = initData.stageZoneName
|
self.zoneName = initData.stageZoneName
|
||||||
self.stageNumber = initData.stageNumber
|
self.stageNumber = initData.stageNumber
|
||||||
|
if initData.stageLaneIdentifier then
|
||||||
|
self._stageLaneIdentifier = string.lower(initData.stageLaneIdentifier)
|
||||||
|
else
|
||||||
|
self._stageLaneIdentifier = nil
|
||||||
|
end
|
||||||
self.stageName = initData.stageDisplayName
|
self.stageName = initData.stageDisplayName
|
||||||
self._currentStageState = Stage.CurrentStageState.INACTIVE
|
self._currentStageState = Stage.CurrentStageState.INACTIVE
|
||||||
|
self._stageType = stageType
|
||||||
|
|
||||||
self.OnPostStageComplete = nil
|
self.OnPostStageComplete = nil
|
||||||
self.OnPostBlueActivated = nil
|
self.OnPostBlueActivated = nil
|
||||||
@@ -298,6 +314,21 @@ function Stage:IsActive()
|
|||||||
return self._currentStageState == Stage.CurrentStageState.ACTIVE
|
return self._currentStageState == Stage.CurrentStageState.ACTIVE
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return StageType
|
||||||
|
function Stage:GetStageType()
|
||||||
|
return self._stageType
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return string?
|
||||||
|
function Stage:GetStageLaneIdentifier()
|
||||||
|
return self._stageLaneIdentifier
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return number
|
||||||
|
function Stage:GetStageIndex()
|
||||||
|
return self.stageNumber
|
||||||
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
function Stage:CheckAndUpdateSelf()
|
function Stage:CheckAndUpdateSelf()
|
||||||
self._logger:debug("Checking on Stage: " .. self.zoneName)
|
self._logger:debug("Checking on Stage: " .. self.zoneName)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ function ExtraStage.New(database, stageConfig, logger, initData, spawnManager)
|
|||||||
setmetatable(ExtraStage, Stage)
|
setmetatable(ExtraStage, Stage)
|
||||||
|
|
||||||
local self = setmetatable({}, { __index = ExtraStage }) --[[@as ExtraStage]]
|
local self = setmetatable({}, { __index = ExtraStage }) --[[@as ExtraStage]]
|
||||||
self:superNew(database, stageConfig, logger, initData, "secondary", spawnManager)
|
self:superNew(database, stageConfig, logger, initData, "ExtraStage", "secondary", spawnManager)
|
||||||
|
|
||||||
self.OnPostBlueActivated = function (selfStage)
|
self.OnPostBlueActivated = function (selfStage)
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ function PrimaryStage.New(database, stageConfig, logger, initData, spawnManager)
|
|||||||
setmetatable(PrimaryStage, Stage)
|
setmetatable(PrimaryStage, Stage)
|
||||||
|
|
||||||
local self = setmetatable({}, { __index = PrimaryStage }) --[[@as PrimaryStage]]
|
local self = setmetatable({}, { __index = PrimaryStage }) --[[@as PrimaryStage]]
|
||||||
self:superNew(database, stageConfig, logger, initData, "primary", spawnManager)
|
self:superNew(database, stageConfig, logger, initData, "PrimaryStage", "primary", spawnManager)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,28 +4,24 @@ local Stage = require("classes.stageClasses.Stages.BaseStage.Stage")
|
|||||||
---@field private _waitTimeSeconds integer
|
---@field private _waitTimeSeconds integer
|
||||||
---@field private _startTime number
|
---@field private _startTime number
|
||||||
local WaitingStage = {}
|
local WaitingStage = {}
|
||||||
|
|
||||||
WaitingStage.__index = WaitingStage
|
WaitingStage.__index = WaitingStage
|
||||||
|
|
||||||
---@class WaitingStageInitData : StageInitData
|
|
||||||
---@field waitingSeconds integer
|
|
||||||
local WaitingStageInitData = {}
|
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param database Database
|
---@param database Database
|
||||||
---@param stageConfig StageConfig
|
---@param stageConfig StageConfig
|
||||||
---@param logger any
|
---@param logger any
|
||||||
---@param initData WaitingStageInitData
|
---@param initData StageInitData
|
||||||
---@param spawnManager SpawnManager
|
---@param spawnManager SpawnManager
|
||||||
|
---@param waitingSeconds integer
|
||||||
---@return WaitingStage
|
---@return WaitingStage
|
||||||
function WaitingStage.New(database, stageConfig, logger, initData, spawnManager)
|
function WaitingStage.New(database, stageConfig, logger, initData, waitingSeconds, spawnManager)
|
||||||
setmetatable(WaitingStage, Stage)
|
setmetatable(WaitingStage, Stage)
|
||||||
|
|
||||||
local self = setmetatable({}, { __index = WaitingStage }) --[[@as WaitingStage]]
|
local self = setmetatable({}, { __index = WaitingStage }) --[[@as WaitingStage]]
|
||||||
self:superNew(database, stageConfig, logger, initData, "none", spawnManager)
|
self:superNew(database, stageConfig, logger, initData, "WaitingStage", "none", spawnManager)
|
||||||
|
|
||||||
self._waitTimeSeconds = 5
|
self._waitTimeSeconds = 5
|
||||||
if initData.waitingSeconds and initData.waitingSeconds > 5 then self._waitTimeSeconds = initData.waitingSeconds end
|
if waitingSeconds and waitingSeconds > 5 then self._waitTimeSeconds = waitingSeconds end
|
||||||
self._startTime = nil
|
self._startTime = nil
|
||||||
|
|
||||||
self.CheckContinuousAsync = function (selfA, time)
|
self.CheckContinuousAsync = function (selfA, time)
|
||||||
|
|||||||
@@ -128,6 +128,14 @@ do -- INIT UTIL
|
|||||||
return str:find('^' .. findable) ~= nil
|
return str:find('^' .. findable) ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
UTIL.endsWith = function(str, findable, ignoreCase)
|
||||||
|
if ignoreCase == true then
|
||||||
|
return string.lower(str):find(string.lower(findable) .. '$') ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return str:find(findable .. '$') ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param str string
|
---@param str string
|
||||||
---@param findable string
|
---@param findable string
|
||||||
|
|||||||
+2
-2
@@ -54,7 +54,7 @@ local detectionLogger = Logger.new("DetectionManager", defaultLogLevel)
|
|||||||
local detectionManager = DetectionManager.New(detectionLogger)
|
local detectionManager = DetectionManager.New(detectionLogger)
|
||||||
|
|
||||||
GlobalCapManager.start(databaseManager, capConfig, detectionManager, stageConfig, defaultLogLevel, spawnManager)
|
GlobalCapManager.start(databaseManager, capConfig, detectionManager, stageConfig, defaultLogLevel, spawnManager)
|
||||||
GlobalStageManager.NewAndStart(databaseManager, stageConfig, defaultLogLevel, spawnManager)
|
local globalStageManager = GlobalStageManager.NewAndStart(databaseManager, stageConfig, defaultLogLevel, spawnManager)
|
||||||
GlobalFleetManager.start(databaseManager)
|
GlobalFleetManager.start(databaseManager)
|
||||||
|
|
||||||
local SetStageDelayed = function(number, time)
|
local SetStageDelayed = function(number, time)
|
||||||
@@ -70,5 +70,5 @@ standardLogger:info("Spearhead Initialisation duration: " .. tostring(duration)
|
|||||||
|
|
||||||
local missionEditorWarningsLogger = Logger.new("MissionEditorWarnings", defaultLogLevel)
|
local missionEditorWarningsLogger = Logger.new("MissionEditorWarnings", defaultLogLevel)
|
||||||
MissionEditorWarnings.WriteAll(missionEditorWarningsLogger)
|
MissionEditorWarnings.WriteAll(missionEditorWarningsLogger)
|
||||||
GlobalStageManager:printFullOverview()
|
globalStageManager:PrintMermaidStage()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user