Return to post
settings
{
main
{
Description: "Path node builder v0.7 CODE: QRD5A Use this tool to create path nodes for your PvE modes. Build project into EXPORT VARS, copy it and paste in your mode. Read more instructions in WORKSHOP SETTINGS"
Description: "Path node builder v0.72 CODE: QRD5A Use this tool to create path nodes for your PvE modes. Build project into EXPORT VARS, copy it and paste in your mode. Read more instructions in WORKSHOP SETTINGS"
}
lobby
{
Max Spectators: 4
Max Team 1 Players: 1
Max Team 2 Players: 1
Max Team 2 Players: 0
Return To Lobby: Never
}
modes
{
Assault
{
enabled maps
{
}
}
Control
{
enabled maps
{
}
}
Escort
{
enabled maps
{
Havana
}
}
Hybrid
{
enabled maps
{
}
}
Team Deathmatch
{
enabled maps
{
}
}
General
{
Enemy Health Bars: Off
Game Mode Start: Manual
Hero Limit: Off
Kill Cam: Off
Kill Feed: Off
Respawn Time Scalar: 0%
Skins: Off
Spawn Health Packs: Disabled
}
}
workshop
{
PLAYER MOVEMENT SPEED: 180
SPAWN ROOM: [2]
SPAWN ROOM: [1]
}
extensions
{
Play More Effects
}
}
variables
{
global:
0: WorkshopSettingInstructions
1: PropertySpawnRoomIndex
2: PropertyPlayerMovementSpeed
3: PropertyBotMovementSpeed
4: PropertyFreeCamera
5: BuilderHudColorCurrent
6: BuilderHudColorBuildMode
7: BuilderHudColorEditMode
8: BuilderHudColorPathFindingMode
9: BuilderMode
10: LoopIterator1
11: LoopIterator2
12: LoopIterator3
13: StringConcatNodeId
14: StringConcatResult
15: StringConcatCountOfElements
16: BuilderRayCastHitPosition
17: BuilderNodePositions
18: BuilderNodeConnections
19: BuilderNodeEffectIdArray
20: BuilderNodeConnectionEffectsId
21: BuilderNodeWorldTextIdArray
22: BuilderSelectedNodeEffectPos
23: BuilderTrySelectNodeInLOS
24: BuilderSelectedNodeId
25: BuilderInnerArray
26: BuilderIsNodeHaveConnection
27: IsBuildingProject
28: BuilderProgressBarValue
29: BuilderProgressBarValueStep
30: BuildProjectEmptySpace
31: BuildProjectNewElementIndex
32: BuildProjectOldElementIndex
33: BuildProjectQueueArray
34: BuildProjectVisitedNodes
35: BuildProjectCurrentNodeId
36: BuildProjectStartNodeId
37: BuildProjectNeighborNodeId
38: PathFindingStartNodeEffectPos
39: PathFindingTargetNodeEffectPos
40: BeamEffects
41: PathFindingStartNodeId
42: PathFindingTargetNodeId
43: PathFindingResultPath
44: PathFindingShortestDistance
45: PathFindingCurrentDistance
46: PathFindingCurrentNodeId
47: PathFindingBotId
48: NodeTriggerRadius
49: PathFindingStartPosition
50: PathFindingTargetPosition
51: DisableInspectorWhileCompiling
125: NodePositions
126: NodeConnections
127: DistanceMatrix
player:
0: BuilderModeInfoHudId
115: BotCancelPathFinding
116: BotLoopIterator1
117: BotTempArray
118: BotTargetPlayer
119: BotTargetPosition
120: BotClosestNodeIdToTarget
121: BotClosestNodeIdToBot
122: BotPrevNodeId
123: BotNextNodeId
124: BotNextNodePosition
125: BotCurrentDistanceToTarget
126: BotShortestDistanceToTarget
127: BotIsPathFinding
}
subroutines
{
0: BuilderSwitchMode
1: BuilderEditModeSelectNode
2: BuilderEditModeDeleteNode
3: BuilderConcatStringConnections
4: BuilderDeleteConnectionsOfNode
5: BuilderConnectDisconnectSelector
6: BuilderConnectNodeBackendLogic
7: BuilderConnectNodeBeamEffect
8: BuilderDisconnectNode
9: BuilderBuildModeCreateNewNode
10: BuilderDeleteAllEffects
11: BuilderBuildProject
12: BuilderOptimizeData
13: BuilderUpdateConnectionIndexes
14: BuilderInitModEffects
15: BuilderBuildPreparedPathNodes
16: BuilderComputeDistanceMatrix
17: BuilderGetClossestNodeIdToCursor
18: PathFindingModeSelectNode
19: PathFindingModeReset
20: DeleteNodeBeams
21: CreateNodeBeams
22: PathFindingGetShortestPath
23: PathFindingCreateBot
24: PathFindingTestBotReset
124: BotStartPathFinding
125: BotGetClosestNodeIdToTarget
126: BotGetNextNodeIdAndPosition
127: BotResetPathFinding
}
rule("=== PATH NODE BUILDER BY HUKUTA94#2589 ===")
{
event
{
Ongoing - Global;
}
actions
{
disabled Disable Inspector Recording;
Create HUD Text(All Players(All Teams), Null, Null, Custom String("PATH NODES BUILDER V{0} BY HUKUTA94#2589", 0.700), Right, -1000,
Create HUD Text(All Players(All Teams), Null, Null, Custom String("PATH NODES BUILDER V{0} BY HUKUTA94#2589", 0.720), Right, -1000,
Color(White), Color(White), Color(White), Visible To, Default Visibility);
}
}
disabled rule("=== EXPORT BLOCK START - COPY THESE RULES AND SUBROUTINES INTO YOUR MODE ===")
disabled rule("")
{
event
{
Ongoing - Global;
}
}
rule("=== EXPORT BLOCK START - COPY THESE RULES AND SUBROUTINES INTO YOUR MODE ===")
{
event
{
Ongoing - Global;
}
}
rule("MAP: WORKSHOP CHAMBER")
{
event
{
Ongoing - Global;
}
conditions
{
Current Map == Map(Workshop Chamber);
}
actions
{
Global.NodePositions = Array(Vector(-0.252, 0.425, -0.037), Vector(15.690, 0.425, 16.016), Vector(-15.527, 0.425, 15.911), Vector(
15.794, 0.425, -15.756), Vector(-15.781, 0.425, -15.775), Vector(-15.802, 0.425, -0.052), Vector(-0.262, 0.425, -15.790),
Vector(15.637, 0.425, -0.001), Vector(0.197, 0.425, 15.665), Vector(-8.102, 0.425, -7.910), Vector(8.013, 0.425, -7.859),
Vector(7.978, 0.425, 8.089), Vector(-8.046, 0.425, 8.175));
Global.NodeConnections = Array(Array(6, 5, 7, 11, 8, 12, 9, 10), Array(7, 11, 8), Array(8, 12, 5), Array(10, 6, 7), Array(9, 6, 5),
Array(2, 12, 9, 4), Array(9, 4, 10, 3), Array(10, 3, 11, 1), Array(1, 11, 12, 2, 0), Array(6, 4, 5, 0), Array(6, 3, 7, 0),
Array(8, 7, 1, 0), Array(2, 5, 8, 0));
Global.DistanceMatrix = Array(Array(9999, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1), Array(2, 9999, 2, 2, 4, 3, 3, 1, 1, 3, 2, 1, 2),
Array(2, 2, 9999, 4, 2, 1, 3, 3, 1, 2, 3, 2, 1), Array(2, 2, 4, 9999, 2, 3, 1, 1, 3, 2, 1, 2, 3), Array(2, 4, 2, 2, 9999, 1, 1,
3, 3, 1, 2, 3, 2), Array(2, 3, 1, 3, 1, 9999, 2, 3, 2, 1, 3, 3, 1), Array(2, 3, 3, 1, 1, 2, 9999, 2, 3, 1, 1, 3, 3), Array(2,
1, 3, 1, 3, 3, 2, 9999, 2, 3, 1, 1, 3), Array(1, 1, 1, 3, 3, 2, 2, 2, 9999, 2, 2, 1, 1), Array(1, 3, 2, 2, 1, 1, 1, 2, 2, 9999,
2, 2, 2), Array(1, 2, 3, 1, 2, 2, 1, 1, 2, 2, 9999, 2, 2), Array(1, 1, 2, 2, 3, 2, 2, 1, 1, 2, 2, 9999, 2), Array(1, 2, 1, 3,
2, 1, 2, 2, 1, 2, 2, 2, 9999));
}
}
rule("MAP: WORKSHOP ISLAND")
{
event
{
Ongoing - Global;
}
conditions
{
Current Map == Map(Workshop Island);
}
actions
{
Global.NodePositions = Array(Vector(-16.004, 0.350, -15.965), Vector(-15.994, 0.350, -0.043), Vector(-15.981, 0.350, 15.908),
Vector(15.941, 0.350, 16.021), Vector(15.980, 0.350, -15.878), Vector(-1.423, 0.350, -16.035), Vector(-1.225, 0.350, 4.747),
Vector(7.259, 0.350, -0.358));
Global.NodeConnections = Array(Array(5, 1, 6), Array(0, 2), Array(3, 1), Array(2, 6, 4), Array(5, 3, 7), Array(4, 0, 7), Array(0,
3, 7), Array(6, 5, 4));
Global.DistanceMatrix = Array(Array(9999, 1, 2, 2, 2, 1, 1, 2), Array(1, 9999, 1, 2, 3, 2, 2, 3), Array(2, 1, 9999, 1, 2, 3, 2, 3),
Array(2, 2, 1, 9999, 1, 2, 1, 2), Array(2, 3, 2, 1, 9999, 1, 2, 1), Array(1, 2, 3, 2, 1, 9999, 2, 1), Array(1, 2, 2, 1, 2, 2,
9999, 1), Array(2, 3, 3, 2, 1, 1, 1, 9999));
}
}
rule("MAP: HAVANA")
{
event
{
Ongoing - Global;
}
conditions
{
Current Map == Map(Havana);
}
actions
{
Global.NodePositions = Array(Vector(113.402, 7.319, -57.302), Vector(147.588, 6.425, -46.749), Vector(136.181, 6.425, -57.159),
Vector(130.189, 6.425, -63.781), Vector(123.305, 6.425, -57.983), Vector(125.678, 6.504, -46.633), Vector(146.311, 9.444,
-61.382), Vector(114.485, 7.471, -46.699), Vector(138.743, 6.425, -32.974), Vector(126.498, 6.425, -39.920), Vector(148.529,
9.425, -28.549), Vector(134.970, 10.396, -27.167), Vector(124.572, 10.434, -34.300), Vector(138.605, 5.359, -18.647), Vector(
119.009, 2.331, -31.024), Vector(121.138, 5.228, -19.933), Vector(126.722, 6.425, -29.505), Vector(102.762, 3.157, -33.609),
Vector(76.030, 7.418, -74.087), Vector(83.720, 9.425, -33.744), Vector(97.439, 7.238, -42.379), Vector(86.252, 12.416,
-47.261), Vector(65.178, 11.425, -73.187), Vector(97.466, 7.269, -50.596), Vector(113.039, 7.424, -37.337), Vector(106.179,
7.450, -46.143), Vector(90.086, 7.411, -44.653), Vector(78.752, 7.418, -62.140), Vector(82.124, 7.428, -44.229), Vector(90.675,
7.231, -51.234), Vector(85.717, 4.692, -63.446), Vector(90.830, 4.330, -70.697), Vector(95.569, 3.646, -79.682), Vector(
102.425, 2.387, -72.817), Vector(81.443, 4.425, -81.648), Vector(70.743, 6.418, -81.495), Vector(69.738, 6.419, -96.344),
Vector(78.682, 5.418, -96.160), Vector(153.887, 18.628, -22.387), Vector(127.586, 12.643, -63.344), Vector(118.911, 13.468,
-58.008), Vector(102.885, 1.092, -56.579), Vector(100.009, 2.967, -67.139), Vector(106.703, 0.465, -44.628), Vector(81.695,
7.418, -52.140), Vector(125.118, 12.445, -57.134));
Global.NodeConnections = Array(Array(4, 7, 41), Array(2, 8, 5, 9), Array(3, 6, 1, 5, 8, 9), Array(2, 4), Array(3, 5, 1), Array(4,
2, 7, 9, 8, 1), Array(2, 39), Array(5, 9, 24, 25, 23), Array(9, 10, 1, 5, 2, 13, 16), Array(5, 7, 8, 1, 2, 16), Array(8, 11),
Array(10, 8, 12), Array(11, 9), Array(8, 15), Array(15, 17), Array(13, 14, 17), Array(8, 14), Array(14, 20, 43), Array(22, 27,
35), Array(21, 28), Array(17, 23, 26, 25, 29, 7), Array(19, 26, 20, 29, 25), Array(18), Array(20, 25, 26, 30, 31, 42, 29, 7),
Array(7, 17, 14), Array(23, 20, 7, 17, 26, 41), Array(20, 23, 25, 28, 29), Array(18, 29, 30), Array(26, 19, 44), Array(27, 26,
23, 20, 30, 31, 42, 44), Array(29, 23, 31, 42, 34), Array(23, 30, 29, 32, 34, 42), Array(33, 31, 34), Array(32, 42, 41), Array(
32, 31, 30, 35, 37), Array(34, 18, 36), Array(35, 34), Array(34), Array(), Array(6, 40, 45), Array(39, 41, 45), Array(42, 43,
33), Array(33, 23, 29, 31, 30, 41), Array(17, 41), Array(29, 27, 28), Array(39, 40, 5, 2, 1, 8));
Global.DistanceMatrix = Array(Array(9999, 2, 3, 2, 1, 2, 4, 1, 3, 2, 4, 5, 6, 4, 3, 4, 3, 3, 5, 5, 3, 6, 6, 2, 2, 2, 3, 4, 4, 3, 3,
3, 3, 2, 4, 5, 6, 5, 0, 5, 6, 1, 2, 2, 4, 6), Array(0, 9999, 1, 2, 2, 1, 2, 2, 1, 1, 2, 3, 4, 2, 3, 3, 2, 4, 6, 6, 4, 7, 7, 3,
3, 3, 4, 5, 5, 4, 4, 4, 5, 5, 5, 6, 7, 6, 0, 3, 4, 4, 4, 5, 5, 4), Array(0, 1, 9999, 1, 2, 1, 1, 2, 1, 1, 2, 3, 4, 2, 3, 3, 2,
4, 6, 6, 4, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4, 4, 5, 5, 5, 6, 7, 6, 0, 2, 3, 4, 4, 5, 5, 3), Array(0, 2, 1, 9999, 1, 2, 2, 3, 2, 2,
3, 4, 5, 3, 4, 4, 3, 5, 7, 7, 5, 8, 8, 4, 4, 4, 5, 6, 6, 5, 5, 5, 6, 6, 6, 7, 8, 7, 0, 3, 4, 5, 5, 6, 6, 4), Array(0, 1, 2, 1,
9999, 1, 3, 2, 2, 2, 3, 4, 5, 3, 4, 4, 3, 4, 6, 6, 4, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4, 4, 5, 5, 5, 6, 7, 6, 0, 4, 5, 4, 4, 5, 5,
5), Array(0, 1, 1, 2, 1, 9999, 2, 1, 1, 1, 2, 3, 4, 2, 3, 3, 2, 3, 5, 5, 3, 6, 6, 2, 2, 2, 3, 4, 4, 3, 3, 3, 4, 4, 4, 5, 6, 5,
0, 3, 4, 3, 3, 4, 4, 4), Array(0, 2, 1, 2, 3, 2, 9999, 3, 2, 2, 3, 4, 5, 3, 4, 4, 3, 5, 7, 7, 5, 8, 8, 4, 4, 4, 5, 6, 6, 5, 5,
5, 5, 4, 6, 7, 8, 7, 0, 1, 2, 3, 4, 4, 6, 2), Array(0, 2, 2, 3, 2, 1, 3, 9999, 2, 1, 3, 4, 5, 3, 2, 3, 2, 2, 4, 4, 2, 5, 5, 1,
1, 1, 2, 3, 3, 2, 2, 2, 3, 3, 3, 4, 5, 4, 0, 4, 5, 2, 2, 3, 3, 5), Array(0, 1, 1, 2, 2, 1, 2, 2, 9999, 1, 1, 2, 3, 1, 2, 2, 1,
3, 6, 6, 4, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4, 4, 5, 5, 5, 6, 7, 6, 0, 3, 4, 4, 4, 4, 5, 4), Array(0, 1, 1, 2, 2, 1, 2, 1, 1, 9999,
2, 3, 4, 2, 2, 3, 1, 3, 5, 5, 3, 6, 6, 2, 2, 2, 3, 4, 4, 3, 3, 3, 4, 4, 4, 5, 6, 5, 0, 3, 4, 3, 3, 4, 4, 4), Array(0, 2, 2, 3,
3, 2, 3, 3, 1, 2, 9999, 1, 2, 2, 3, 3, 2, 4, 7, 7, 5, 8, 8, 4, 4, 4, 5, 6, 6, 5, 5, 5, 6, 6, 6, 7, 8, 7, 0, 4, 5, 5, 5, 5, 6,
5), Array(0, 2, 2, 3, 3, 2, 3, 3, 1, 2, 1, 9999, 1, 2, 3, 3, 2, 4, 7, 7, 5, 8, 8, 4, 4, 4, 5, 6, 6, 5, 5, 5, 6, 6, 6, 7, 8, 7,
0, 4, 5, 5, 5, 5, 6, 5), Array(0, 2, 2, 3, 3, 2, 3, 2, 2, 1, 2, 1, 9999, 3, 3, 4, 2, 4, 6, 6, 4, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4,
4, 5, 5, 5, 6, 7, 6, 0, 4, 5, 4, 4, 5, 5, 5), Array(0, 2, 2, 3, 3, 2, 3, 3, 1, 2, 2, 3, 4, 9999, 2, 1, 2, 2, 6, 6, 3, 7, 7, 4,
4, 4, 4, 5, 5, 4, 5, 5, 6, 5, 6, 7, 8, 7, 0, 4, 5, 4, 5, 3, 5, 5), Array(0, 4, 4, 5, 5, 4, 5, 3, 3, 4, 4, 5, 6, 2, 9999, 1, 4,
1, 5, 5, 2, 6, 6, 3, 4, 3, 3, 4, 4, 3, 4, 4, 5, 4, 5, 6, 7, 6, 0, 6, 7, 3, 4, 2, 4, 7), Array(0, 3, 3, 4, 4, 3, 4, 3, 2, 3, 3,
4, 5, 1, 1, 9999, 3, 1, 5, 5, 2, 6, 6, 3, 4, 3, 3, 4, 4, 3, 4, 4, 5, 4, 5, 6, 7, 6, 0, 5, 6, 3, 4, 2, 4, 6), Array(0, 2, 2, 3,
3, 2, 3, 3, 1, 2, 2, 3, 4, 2, 1, 2, 9999, 2, 6, 6, 3, 7, 7, 4, 4, 4, 4, 5, 5, 4, 5, 5, 6, 5, 6, 7, 8, 7, 0, 4, 5, 4, 5, 3, 5,
5), Array(0, 4, 4, 5, 4, 3, 5, 2, 4, 3, 5, 6, 7, 3, 1, 2, 4, 9999, 4, 4, 1, 5, 5, 2, 3, 2, 2, 3, 3, 2, 3, 3, 4, 3, 4, 5, 6, 5,
0, 6, 7, 2, 3, 1, 3, 7), Array(0, 6, 6, 7, 6, 5, 7, 4, 6, 5, 7, 8, 9, 7, 5, 6, 6, 4, 9999, 5, 3, 6, 1, 3, 5, 4, 3, 1, 4, 2, 2,
3, 3, 4, 2, 1, 2, 3, 0, 8, 9, 4, 3, 5, 3, 9), Array(0, 5, 5, 6, 5, 4, 6, 3, 5, 4, 6, 7, 8, 6, 4, 5, 5, 3, 4, 9999, 2, 1, 5, 3,
4, 2, 2, 3, 1, 2, 3, 3, 4, 4, 4, 5, 6, 5, 0, 7, 8, 3, 3, 4, 2, 8), Array(0, 3, 3, 4, 3, 2, 4, 1, 3, 2, 4, 5, 6, 4, 2, 3, 3, 1,
3, 3, 9999, 4, 4, 1, 2, 1, 1, 2, 2, 1, 2, 2, 3, 3, 3, 4, 5, 4, 0, 5, 6, 2, 2, 2, 2, 6), Array(0, 4, 4, 5, 4, 3, 5, 2, 4, 3, 5,
6, 7, 5, 3, 4, 4, 2, 3, 1, 1, 9999, 4, 2, 3, 1, 1, 2, 2, 1, 2, 2, 3, 3, 3, 4, 5, 4, 0, 6, 7, 2, 2, 3, 2, 7), Array(0, 7, 7, 8,
7, 6, 8, 5, 7, 6, 8, 9, 10, 8, 6, 7, 7, 5, 1, 6, 4, 7, 9999, 4, 6, 5, 4, 2, 5, 3, 3, 4, 4, 5, 3, 2, 3, 4, 0, 9, 10, 5, 4, 6, 4,
10), Array(0, 3, 3, 4, 3, 2, 4, 1, 3, 2, 4, 5, 6, 4, 3, 4, 3, 2, 3, 3, 1, 4, 4, 9999, 2, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 3, 4, 3,
0, 5, 6, 2, 1, 3, 2, 6), Array(0, 3, 3, 4, 3, 2, 4, 1, 3, 2, 4, 5, 6, 3, 1, 2, 3, 1, 5, 5, 2, 6, 6, 2, 9999, 2, 3, 4, 4, 3, 3,
3, 4, 4, 4, 5, 6, 5, 0, 5, 6, 3, 3, 2, 4, 6), Array(0, 3, 3, 4, 3, 2, 4, 1, 3, 2, 4, 5, 6, 4, 2, 3, 3, 1, 4, 3, 1, 4, 5, 1, 2,
9999, 1, 3, 2, 2, 2, 2, 3, 2, 3, 4, 5, 4, 0, 5, 6, 1, 2, 2, 3, 6), Array(0, 4, 4, 5, 4, 3, 5, 2, 4, 3, 5, 6, 7, 5, 3, 4, 4, 2,
3, 2, 1, 3, 4, 1, 3, 1, 9999, 2, 1, 1, 2, 2, 3, 3, 3, 4, 5, 4, 0, 6, 7, 2, 2, 3, 2, 7), Array(0, 5, 5, 6, 5, 4, 6, 3, 5, 4, 6,
7, 8, 6, 4, 5, 5, 3, 1, 4, 2, 5, 2, 2, 4, 3, 2, 9999, 3, 1, 1, 2, 3, 3, 2, 2, 3, 3, 0, 7, 8, 3, 2, 4, 2, 8), Array(0, 5, 5, 6,
5, 4, 6, 3, 5, 4, 6, 7, 8, 6, 4, 5, 5, 3, 3, 1, 2, 2, 4, 2, 4, 2, 1, 2, 9999, 2, 3, 3, 4, 4, 4, 4, 5, 5, 0, 7, 8, 3, 3, 4, 1,
8), Array(0, 4, 4, 5, 4, 3, 5, 2, 4, 3, 5, 6, 7, 5, 3, 4, 4, 2, 2, 3, 1, 4, 3, 1, 3, 2, 1, 1, 2, 9999, 1, 1, 2, 2, 2, 3, 4, 3,
0, 6, 7, 2, 1, 3, 1, 7), Array(0, 4, 4, 5, 4, 3, 5, 2, 4, 3, 5, 6, 7, 5, 4, 5, 4, 3, 3, 4, 2, 5, 4, 1, 3, 2, 2, 2, 3, 1, 9999,
1, 2, 2, 1, 2, 3, 2, 0, 6, 7, 2, 1, 3, 2, 7), Array(0, 4, 4, 5, 4, 3, 5, 2, 4, 3, 5, 6, 7, 5, 4, 5, 4, 3, 3, 4, 2, 5, 4, 1, 3,
2, 2, 2, 3, 1, 1, 9999, 1, 2, 1, 2, 3, 2, 0, 6, 7, 2, 1, 3, 2, 7), Array(0, 5, 5, 6, 5, 4, 6, 3, 5, 4, 6, 7, 8, 6, 5, 6, 5, 4,
3, 5, 3, 6, 4, 2, 4, 3, 3, 3, 4, 2, 2, 1, 9999, 1, 1, 2, 3, 2, 0, 7, 8, 2, 2, 3, 3, 8), Array(0, 5, 5, 6, 5, 4, 6, 3, 5, 4, 6,
7, 8, 6, 4, 5, 5, 3, 4, 5, 3, 6, 5, 2, 4, 3, 3, 3, 4, 2, 2, 2, 1, 9999, 2, 3, 4, 3, 0, 7, 8, 1, 1, 2, 3, 8), Array(0, 5, 5, 6,
5, 4, 6, 3, 5, 4, 6, 7, 8, 6, 5, 6, 5, 4, 2, 5, 3, 6, 3, 2, 4, 3, 3, 3, 4, 2, 1, 1, 1, 2, 9999, 1, 2, 1, 0, 7, 8, 3, 2, 4, 3,
8), Array(0, 6, 6, 7, 6, 5, 7, 4, 6, 5, 7, 8, 9, 7, 6, 7, 6, 5, 1, 6, 4, 7, 2, 3, 5, 4, 4, 2, 5, 3, 2, 2, 2, 3, 1, 9999, 1, 2,
0, 8, 9, 4, 3, 5, 4, 9), Array(0, 6, 6, 7, 6, 5, 7, 4, 6, 5, 7, 8, 9, 7, 6, 7, 6, 5, 2, 6, 4, 7, 3, 3, 5, 4, 4, 3, 5, 3, 2, 2,
2, 3, 1, 1, 9999, 2, 0, 8, 9, 4, 3, 5, 4, 9), Array(0, 6, 6, 7, 6, 5, 7, 4, 6, 5, 7, 8, 9, 7, 6, 7, 6, 5, 3, 6, 4, 7, 4, 3, 5,
4, 4, 4, 5, 3, 2, 2, 2, 3, 1, 2, 3, 9999, 0, 8, 9, 4, 3, 5, 4, 9), Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9999), Array(0, 2, 2, 3, 3, 2, 1, 3, 2, 3, 3, 4, 5, 3, 4, 4, 3, 4,
6, 7, 5, 8, 7, 4, 4, 4, 5, 5, 6, 4, 4, 4, 4, 3, 5, 6, 7, 6, 0, 9999, 1, 2, 3, 3, 5, 1), Array(0, 2, 2, 3, 3, 2, 2, 3, 2, 3, 3,
4, 5, 3, 4, 4, 3, 3, 5, 6, 4, 7, 6, 3, 4, 4, 4, 4, 5, 3, 3, 3, 3, 2, 4, 5, 6, 5, 0, 1, 9999, 1, 2, 2, 4, 1), Array(0, 5, 5, 6,
5, 4, 6, 3, 5, 4, 6, 7, 8, 5, 3, 4, 5, 2, 4, 5, 3, 6, 5, 2, 4, 3, 3, 3, 4, 2, 2, 2, 2, 1, 3, 4, 5, 4, 0, 7, 8, 9999, 1, 1, 3,
8), Array(0, 4, 4, 5, 4, 3, 5, 2, 4, 3, 5, 6, 7, 5, 4, 5, 4, 3, 3, 4, 2, 5, 4, 1, 3, 2, 2, 2, 3, 1, 1, 1, 2, 1, 2, 3, 4, 3, 0,
6, 7, 1, 9999, 2, 2, 7), Array(0, 5, 5, 6, 5, 4, 6, 3, 5, 4, 6, 7, 8, 4, 2, 3, 5, 1, 5, 5, 2, 6, 6, 3, 4, 3, 3, 4, 4, 3, 3, 3,
3, 2, 4, 5, 6, 5, 0, 7, 8, 1, 2, 9999, 4, 8), Array(0, 5, 5, 6, 5, 4, 6, 3, 5, 4, 6, 7, 8, 6, 4, 5, 5, 3, 2, 2, 2, 3, 3, 2, 4,
3, 2, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 0, 7, 8, 3, 2, 4, 9999, 8), Array(0, 1, 1, 2, 2, 1, 2, 2, 1, 2, 2, 3, 4, 2, 3, 3, 2, 4,
6, 6, 4, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4, 4, 4, 3, 5, 6, 7, 6, 0, 1, 1, 2, 3, 3, 5, 9999));
Global.NodePositions = Array(Vector(147.588, 6.425, -46.749), Vector(136.181, 6.425, -57.159), Vector(130.189, 6.425, -63.781),
Vector(123.305, 6.425, -57.983), Vector(125.678, 6.504, -46.633), Vector(146.311, 9.444, -61.382), Vector(114.485, 7.471,
-46.699), Vector(138.743, 6.425, -32.974), Vector(126.498, 6.425, -39.920), Vector(148.529, 9.425, -28.549), Vector(124.572,
10.434, -34.300), Vector(138.605, 5.359, -18.647), Vector(119.009, 2.331, -31.024), Vector(121.138, 5.228, -19.933), Vector(
126.722, 6.425, -29.505), Vector(102.762, 3.157, -33.609), Vector(76.030, 7.418, -74.087), Vector(83.720, 9.425, -33.744),
Vector(97.439, 7.238, -42.379), Vector(86.252, 12.416, -47.261), Vector(65.178, 11.425, -73.187), Vector(97.466, 7.269,
-50.596), Vector(113.039, 7.424, -37.337), Vector(106.179, 7.450, -46.143), Vector(90.086, 7.411, -44.653), Vector(78.752,
7.418, -62.140), Vector(82.124, 7.428, -44.229), Vector(90.675, 7.231, -51.234), Vector(85.717, 4.692, -63.446), Vector(90.830,
4.330, -70.697), Vector(102.425, 2.387, -72.817), Vector(81.443, 4.425, -81.648), Vector(70.743, 6.418, -81.495), Vector(
69.738, 6.419, -96.344), Vector(127.586, 12.643, -63.344), Vector(118.911, 13.468, -58.008), Vector(102.885, 1.092, -56.579),
Vector(100.009, 2.967, -67.139), Vector(106.703, 0.465, -44.628), Vector(81.695, 7.418, -52.140), Vector(126.979, 12.393,
-55.079), Vector(153.720, 18.578, -21.745), Vector(155.301, 18.619, -17.595), Vector(133.043, 10.425, -26.625), Vector(114.646,
7.278, -57.336), Vector(95.160, 3.688, -81.194), Vector(78.456, 5.418, -93.581), Vector(75.455, 5.418, -101.492));
Global.NodeConnections = Array(Array(1, 7, 4, 8), Array(2, 5, 1, 4, 7, 8, 0), Array(1, 3), Array(2, 4, 44), Array(3, 1, 6, 8, 7, 1,
0), Array(1, 34), Array(4, 8, 22, 23, 21, 18, 44), Array(8, 9, 1, 4, 1, 11, 14, 0), Array(4, 6, 7, 1, 1, 14, 0), Array(7, 43),
Array(8, 43), Array(7, 13), Array(13, 15), Array(11, 12, 15), Array(7, 8, 12), Array(12, 18, 38), Array(20, 25, 32), Array(19,
26), Array(15, 21, 24, 23, 27, 6), Array(17, 24, 27, 25), Array(16), Array(18, 23, 24, 28, 29, 37, 27, 6), Array(6, 15, 12),
Array(21, 18, 6, 15, 24, 36), Array(18, 21, 23, 26, 27), Array(16, 27, 28, 39), Array(24, 17, 39), Array(25, 24, 21, 18, 28,
29, 37, 39), Array(27, 21, 29, 37, 31), Array(21, 28, 27, 31, 37, 45), Array(37, 36, 45), Array(29, 28, 32, 45, 46), Array(31,
16, 33), Array(32, 31, 47), Array(5, 35, 40, 1), Array(34, 40, 44), Array(37, 38, 30), Array(30, 21, 27, 29, 28, 36), Array(15,
36), Array(27, 25, 26), Array(6, 4, 1, 7, 1, 34, 35, 0), Array(42), Array(41), Array(7, 9, 10), Array(3, 6, 36), Array(30, 29,
31, 46), Array(31, 45, 47), Array(46, 33));
Global.DistanceMatrix = Array(Array(0, 1, 2, 2, 1, 2, 2, 1, 1, 2, 4, 2, 3, 3, 2, 4, 6, 6, 3, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4, 4, 5, 5,
6, 7, 3, 4, 4, 4, 5, 5, 4, 0, 0, 3, 3, 5, 6, 7), Array(1, 0, 1, 2, 1, 1, 2, 1, 1, 2, 4, 2, 3, 3, 2, 4, 6, 6, 3, 7, 7, 3, 3, 3,
4, 5, 5, 4, 4, 4, 5, 5, 6, 7, 2, 3, 4, 4, 5, 5, 3, 0, 0, 3, 3, 5, 6, 7), Array(2, 1, 0, 1, 2, 2, 3, 2, 2, 3, 5, 3, 4, 4, 3, 5,
7, 7, 4, 8, 8, 4, 4, 4, 5, 6, 6, 5, 5, 5, 4, 6, 7, 8, 3, 4, 3, 4, 4, 6, 4, 0, 0, 4, 2, 5, 6, 7), Array(2, 2, 1, 0, 1, 3, 2, 2,
2, 3, 5, 3, 4, 4, 3, 4, 6, 6, 3, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4, 4, 3, 5, 6, 7, 4, 5, 2, 3, 3, 5, 5, 0, 0, 4, 1, 4, 5, 6), Array(
1, 1, 2, 1, 0, 2, 1, 1, 1, 2, 4, 2, 3, 3, 2, 3, 5, 5, 2, 6, 6, 2, 2, 2, 3, 4, 4, 3, 3, 3, 4, 4, 5, 6, 3, 4, 3, 3, 4, 4, 4, 0,
0, 3, 2, 4, 5, 6), Array(2, 1, 2, 3, 2, 0, 3, 2, 2, 3, 5, 3, 4, 4, 3, 5, 7, 7, 4, 8, 8, 4, 4, 4, 5, 6, 6, 5, 5, 5, 5, 6, 7, 8,
1, 2, 4, 5, 5, 6, 2, 0, 0, 4, 3, 6, 7, 8), Array(2, 2, 3, 2, 1, 3, 0, 2, 1, 3, 5, 3, 2, 3, 2, 2, 4, 4, 1, 5, 5, 1, 1, 1, 2, 3,
3, 2, 2, 2, 3, 3, 4, 5, 4, 5, 2, 2, 3, 3, 5, 0, 0, 4, 1, 3, 4, 5), Array(1, 1, 2, 2, 1, 2, 2, 0, 1, 1, 3, 1, 2, 2, 1, 3, 6, 6,
3, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4, 4, 5, 5, 6, 7, 3, 4, 4, 4, 4, 5, 4, 0, 0, 2, 3, 5, 6, 7), Array(1, 1, 2, 2, 1, 2, 1, 1, 0, 2,
4, 2, 2, 3, 1, 3, 5, 5, 2, 6, 6, 2, 2, 2, 3, 4, 4, 3, 3, 3, 4, 4, 5, 6, 3, 4, 3, 3, 4, 4, 4, 0, 0, 3, 2, 4, 5, 6), Array(2, 2,
3, 3, 2, 3, 3, 1, 2, 0, 2, 2, 3, 3, 2, 4, 7, 7, 4, 8, 8, 4, 4, 4, 5, 6, 6, 5, 5, 5, 6, 6, 7, 8, 4, 5, 5, 5, 5, 6, 5, 0, 0, 1,
4, 6, 7, 8), Array(2, 2, 3, 3, 2, 3, 2, 2, 1, 2, 0, 3, 3, 4, 2, 4, 6, 6, 3, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4, 4, 5, 5, 6, 7, 4, 5,
4, 4, 5, 5, 5, 0, 0, 1, 3, 5, 6, 7), Array(2, 2, 3, 3, 2, 3, 3, 1, 2, 2, 4, 0, 2, 1, 2, 2, 6, 6, 3, 7, 7, 4, 4, 4, 4, 5, 5, 4,
5, 5, 5, 6, 7, 8, 4, 5, 4, 5, 3, 5, 5, 0, 0, 3, 4, 6, 7, 8), Array(4, 4, 5, 5, 4, 5, 3, 3, 4, 4, 6, 2, 0, 1, 4, 1, 5, 5, 2, 6,
6, 3, 4, 3, 3, 4, 4, 3, 4, 4, 4, 5, 6, 7, 6, 7, 3, 4, 2, 4, 7, 0, 0, 5, 4, 5, 6, 7), Array(3, 3, 4, 4, 3, 4, 3, 2, 3, 3, 5, 1,
1, 0, 3, 1, 5, 5, 2, 6, 6, 3, 4, 3, 3, 4, 4, 3, 4, 4, 4, 5, 6, 7, 5, 6, 3, 4, 2, 4, 6, 0, 0, 4, 4, 5, 6, 7), Array(2, 2, 3, 3,
2, 3, 2, 1, 1, 2, 4, 2, 1, 2, 0, 2, 6, 6, 3, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4, 4, 5, 5, 6, 7, 4, 5, 4, 4, 3, 5, 5, 0, 0, 3, 3, 5,
6, 7), Array(4, 4, 5, 4, 3, 5, 2, 4, 3, 5, 7, 3, 1, 2, 4, 0, 4, 4, 1, 5, 5, 2, 3, 2, 2, 3, 3, 2, 3, 3, 3, 4, 5, 6, 6, 7, 2, 3,
1, 3, 7, 0, 0, 6, 3, 4, 5, 6), Array(6, 6, 7, 6, 5, 7, 4, 6, 5, 7, 9, 7, 5, 6, 6, 4, 0, 4, 3, 5, 1, 3, 5, 4, 3, 1, 3, 2, 2, 3,
4, 2, 1, 2, 8, 9, 4, 3, 5, 2, 9, 0, 0, 8, 5, 3, 3, 3), Array(6, 6, 7, 6, 5, 7, 4, 6, 5, 7, 9, 7, 5, 6, 6, 4, 3, 0, 3, 1, 4, 3,
5, 3, 2, 2, 1, 2, 3, 3, 4, 4, 4, 5, 8, 9, 4, 3, 5, 2, 9, 0, 0, 8, 5, 4, 5, 6), Array(3, 3, 4, 3, 2, 4, 1, 3, 2, 4, 6, 4, 2, 3,
3, 1, 3, 3, 0, 4, 4, 1, 2, 1, 1, 2, 2, 1, 2, 2, 3, 3, 4, 5, 5, 6, 2, 2, 2, 2, 6, 0, 0, 5, 2, 3, 4, 5), Array(5, 5, 6, 5, 4, 6,
3, 5, 4, 6, 8, 6, 4, 5, 5, 3, 2, 1, 2, 0, 3, 2, 4, 2, 1, 1, 2, 1, 2, 2, 3, 3, 3, 4, 7, 8, 3, 2, 4, 2, 8, 0, 0, 7, 4, 3, 4, 5),
Array(7, 7, 8, 7, 6, 8, 5, 7, 6, 8, 10, 8, 6, 7, 7, 5, 1, 5, 4, 6, 0, 4, 6, 5, 4, 2, 4, 3, 3, 4, 5, 3, 2, 3, 9, 10, 5, 4, 6, 3,
10, 0, 0, 9, 6, 4, 4, 4), Array(3, 3, 4, 3, 2, 4, 1, 3, 2, 4, 6, 4, 3, 4, 3, 2, 3, 3, 1, 4, 4, 0, 2, 1, 1, 2, 2, 1, 1, 1, 2, 2,
3, 4, 5, 6, 2, 1, 3, 2, 6, 0, 0, 5, 2, 2, 3, 4), Array(3, 3, 4, 3, 2, 4, 1, 3, 2, 4, 6, 3, 1, 2, 3, 1, 5, 5, 2, 6, 6, 2, 0, 2,
3, 4, 4, 3, 3, 3, 4, 4, 5, 6, 5, 6, 3, 3, 2, 4, 6, 0, 0, 5, 2, 4, 5, 6), Array(3, 3, 4, 3, 2, 4, 1, 3, 2, 4, 6, 4, 2, 3, 3, 1,
4, 3, 1, 4, 5, 1, 2, 0, 1, 3, 2, 2, 2, 2, 2, 3, 4, 5, 5, 6, 1, 2, 2, 3, 6, 0, 0, 5, 2, 3, 4, 5), Array(4, 4, 5, 4, 3, 5, 2, 4,
3, 5, 7, 5, 3, 4, 4, 2, 3, 2, 1, 3, 4, 1, 3, 1, 0, 2, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 2, 2, 3, 2, 7, 0, 0, 6, 3, 3, 4, 5), Array(
5, 5, 6, 5, 4, 6, 3, 5, 4, 6, 8, 6, 4, 5, 5, 3, 1, 3, 2, 4, 2, 2, 4, 3, 2, 0, 2, 1, 1, 2, 3, 2, 2, 3, 7, 8, 3, 2, 4, 1, 8, 0,
0, 7, 4, 3, 3, 4), Array(5, 5, 6, 5, 4, 6, 3, 5, 4, 6, 8, 6, 4, 5, 5, 3, 3, 1, 2, 2, 4, 2, 4, 2, 1, 2, 0, 2, 3, 3, 4, 4, 4, 5,
7, 8, 3, 3, 4, 1, 8, 0, 0, 7, 4, 4, 5, 6), Array(4, 4, 5, 4, 3, 5, 2, 4, 3, 5, 7, 5, 3, 4, 4, 2, 2, 3, 1, 4, 3, 1, 3, 2, 1, 1,
2, 0, 1, 1, 2, 2, 3, 4, 6, 7, 2, 1, 3, 1, 7, 0, 0, 6, 3, 2, 3, 4), Array(4, 4, 5, 4, 3, 5, 2, 4, 3, 5, 7, 5, 4, 5, 4, 3, 3, 4,
2, 5, 4, 1, 3, 2, 2, 2, 3, 1, 0, 1, 2, 1, 2, 3, 6, 7, 2, 1, 3, 2, 7, 0, 0, 6, 3, 2, 2, 3), Array(4, 4, 5, 4, 3, 5, 2, 4, 3, 5,
7, 5, 4, 5, 4, 3, 3, 4, 2, 5, 4, 1, 3, 2, 2, 2, 3, 1, 1, 0, 2, 1, 2, 3, 6, 7, 2, 1, 3, 2, 7, 0, 0, 6, 3, 1, 2, 3), Array(5, 5,
6, 5, 4, 6, 3, 5, 4, 6, 8, 6, 4, 5, 5, 3, 4, 5, 3, 6, 5, 2, 4, 3, 3, 3, 4, 2, 2, 2, 0, 2, 3, 4, 7, 8, 1, 1, 2, 3, 8, 0, 0, 7,
4, 1, 2, 3), Array(5, 5, 6, 5, 4, 6, 3, 5, 4, 6, 8, 6, 5, 6, 5, 4, 2, 5, 3, 6, 3, 2, 4, 3, 3, 3, 4, 2, 1, 1, 2, 0, 1, 2, 7, 8,
3, 2, 4, 3, 8, 0, 0, 7, 4, 1, 1, 2), Array(6, 6, 7, 6, 5, 7, 4, 6, 5, 7, 9, 7, 6, 7, 6, 5, 1, 5, 4, 6, 2, 3, 5, 4, 4, 2, 4, 3,
2, 2, 3, 1, 0, 1, 8, 9, 4, 3, 5, 3, 9, 0, 0, 8, 5, 2, 2, 2), Array(6, 6, 7, 6, 5, 7, 4, 6, 5, 7, 9, 7, 6, 7, 6, 5, 2, 6, 4, 7,
3, 3, 5, 4, 4, 3, 5, 3, 2, 2, 3, 1, 1, 0, 8, 9, 4, 3, 5, 4, 9, 0, 0, 8, 5, 2, 2, 1), Array(2, 1, 2, 3, 2, 1, 2, 2, 2, 3, 5, 3,
4, 4, 3, 4, 6, 6, 3, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4, 4, 4, 5, 6, 7, 0, 1, 3, 4, 4, 5, 1, 0, 0, 4, 2, 5, 6, 7), Array(2, 2, 3, 2,
2, 2, 2, 2, 3, 3, 5, 3, 4, 4, 3, 4, 6, 6, 3, 7, 7, 3, 3, 3, 4, 5, 5, 4, 4, 4, 3, 5, 6, 7, 1, 0, 2, 3, 3, 5, 1, 0, 0, 4, 1, 4,
5, 6), Array(5, 5, 6, 5, 4, 6, 3, 5, 4, 6, 8, 5, 3, 4, 5, 2, 4, 5, 3, 6, 5, 2, 4, 3, 3, 3, 4, 2, 2, 2, 1, 3, 4, 5, 7, 8, 0, 1,
1, 3, 8, 0, 0, 7, 4, 2, 3, 4), Array(4, 4, 5, 4, 3, 5, 2, 4, 3, 5, 7, 5, 4, 5, 4, 3, 3, 4, 2, 5, 4, 1, 3, 2, 2, 2, 3, 1, 1, 1,
1, 2, 3, 4, 6, 7, 1, 0, 2, 2, 7, 0, 0, 6, 3, 2, 3, 4), Array(5, 5, 6, 5, 4, 6, 3, 5, 4, 6, 8, 4, 2, 3, 5, 1, 5, 5, 2, 6, 6, 3,
4, 3, 3, 4, 4, 3, 3, 3, 2, 4, 5, 6, 7, 8, 1, 2, 0, 4, 8, 0, 0, 7, 4, 3, 4, 5), Array(5, 5, 6, 5, 4, 6, 3, 5, 4, 6, 8, 6, 4, 5,
5, 3, 2, 2, 2, 3, 3, 2, 4, 3, 2, 1, 1, 1, 2, 2, 3, 3, 3, 4, 7, 8, 3, 2, 4, 0, 8, 0, 0, 7, 4, 3, 4, 5), Array(1, 1, 2, 2, 1, 2,
1, 1, 2, 2, 4, 2, 3, 3, 2, 3, 5, 5, 2, 6, 6, 2, 2, 2, 3, 4, 4, 3, 3, 3, 4, 4, 5, 6, 1, 1, 3, 3, 4, 4, 0, 0, 0, 3, 2, 4, 5, 6),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1), Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1), Array(2, 2, 3, 3, 2, 3, 3, 1, 2, 1, 1, 2, 3, 3, 2, 4, 7, 7, 4, 8, 8, 4, 4, 4, 5, 6, 6, 5, 5, 5, 6, 6, 7, 8, 4,
5, 5, 5, 5, 6, 5, 0, 0, 0, 4, 6, 7, 8), Array(3, 3, 2, 1, 2, 4, 1, 3, 2, 4, 6, 4, 3, 4, 3, 3, 5, 5, 2, 6, 6, 2, 2, 2, 3, 4, 4,
3, 3, 3, 2, 4, 5, 6, 5, 6, 1, 2, 2, 4, 6, 0, 0, 5, 0, 3, 4, 5), Array(5, 5, 6, 5, 4, 6, 3, 5, 4, 6, 8, 6, 5, 6, 5, 4, 3, 5, 3,
6, 4, 2, 4, 3, 3, 3, 4, 2, 2, 1, 1, 1, 2, 3, 7, 8, 2, 2, 3, 3, 8, 0, 0, 7, 4, 0, 1, 2), Array(6, 6, 7, 6, 5, 7, 4, 6, 5, 7, 9,
7, 6, 7, 6, 5, 3, 6, 4, 7, 4, 3, 5, 4, 4, 4, 5, 3, 2, 2, 2, 1, 2, 2, 8, 9, 3, 3, 4, 4, 9, 0, 0, 8, 5, 1, 0, 1), Array(7, 7, 8,
7, 6, 8, 5, 7, 6, 8, 10, 8, 7, 8, 7, 6, 3, 7, 5, 8, 4, 4, 6, 5, 5, 4, 6, 4, 3, 3, 3, 2, 2, 1, 9, 10, 4, 4, 5, 5, 10, 0, 0, 9,
6, 2, 1));
}
}
rule("SUBROUTINE: BOT - RESET PATH FINDING")
{
event
{
Subroutine;
BotResetPathFinding;
}
actions
{
Event Player.BotTargetPlayer = -1;
Event Player.BotTargetPosition = -1;
Event Player.BotPrevNodeId = -1;
Event Player.BotClosestNodeIdToTarget = -1;
Event Player.BotNextNodeId = -1;
Event Player.BotNextNodePosition = -1;
Event Player.BotIsPathFinding = False;
Event Player.BotCancelPathFinding = False;
Stop Throttle In Direction(Event Player);
disabled Stop Facing(Event Player);
Stop Facing(Event Player);
}
}
rule("SUBROUTINE: BOT - START PATH FINDING")
{
event
{
Subroutine;
BotStartPathFinding;
}
actions
{
Abort If(Event Player.BotIsPathFinding == True);
disabled Call Subroutine(BotGetClosestNodeIdToTarget);
Call Subroutine(BotGetNextNodeIdAndPosition);
Start Facing(Event Player, Direction Towards(Position Of(Event Player), Event Player.BotNextNodePosition), 360, To World,
Direction and Turn Rate);
Start Throttle In Direction(Event Player, Direction Towards(Position Of(Event Player), Event Player.BotNextNodePosition), 1,
To World, Replace existing throttle, Direction and Magnitude);
Event Player.BotIsPathFinding = True;
}
}
rule("SUBROUTINE: BOT - GET CLOSEST NODE ID TO TARGET")
{
event
{
Subroutine;
BotGetClosestNodeIdToTarget;
}
actions
{
Event Player.BotTargetPosition = Event Player.BotTargetPlayer != -1 ? Position Of(Event Player.BotTargetPlayer)
: Event Player.BotTargetPosition;
Event Player.BotClosestNodeIdToTarget = Index Of Array Value(Global.NodePositions, Sorted Array(Filtered Array(
Global.NodePositions, Is In Line of Sight(Event Player.BotTargetPosition + Vector(0, 2, 0), Current Array Element,
Barriers Do Not Block LOS) == True), Distance Between(Event Player.BotTargetPosition, Current Array Element))[0]);
}
}
rule("SUBROUTINE: BOT - GET NEXT NODE ID AND POSITION")
{
event
{
Subroutine;
BotGetNextNodeIdAndPosition;
}
actions
{
"BOT JUST START FOLLOW PATH OR LOST NEXT NODE"
If(Event Player.BotPrevNodeId == -1);
Log To Inspector(Custom String("PATH FINDING ({0}): BEGIN PATH FINDING", Event Player));
Event Player.BotClosestNodeIdToBot = Index Of Array Value(Global.NodePositions, Sorted Array(Filtered Array(Global.NodePositions,
Is In Line of Sight(Position Of(Event Player) + Vector(0, 2, 0), Current Array Element, Barriers Do Not Block LOS) == True),
Distance Between(Position Of(Event Player), Current Array Element))[0]);
Call Subroutine(BotGetClosestNodeIdToTarget);
End;
"I. FIND NEXT NODE IN PATH"
Log To Inspector(Custom String("PATH FINDING ({0}): BEGIN FIND NEXT NODE FROM NODE #{1}", Event Player,
Event Player.BotClosestNodeIdToBot));
"ALWAYS UPDATE CLOSEST NODE TO TARGET IF TARGET IS PLAYER (TARGET POSITION CAN CHANGE)"
If(Event Player.BotTargetPlayer != -1);
Event Player.BotTargetPosition = Position Of(Event Player.BotTargetPlayer);
Call Subroutine(BotGetClosestNodeIdToTarget);
Log To Inspector(Custom String("PATH FINDING ({0}): TARGET IS PLAYER {2}, SET TARGET NODE #{1}", Event Player,
Event Player.BotClosestNodeIdToTarget, Event Player.BotTargetPlayer));
End;
"NEXT NODE IS TARGET (DISTANCE TO TARGET NODE = 1)"
If(Global.DistanceMatrix[Event Player.BotClosestNodeIdToBot][Event Player.BotClosestNodeIdToTarget] == 1);
Log To Inspector(Custom String("PATH FINDING ({0}): NEXT NODE #{1} IS TARGET ", Event Player,
Event Player.BotClosestNodeIdToTarget));
Event Player.BotNextNodeId = Event Player.BotClosestNodeIdToTarget;
"CHECK CONNECTIONS OF REACHED NODE"
Else;
Log To Inspector(Custom String("PATH FINDING ({0}): (BEGIN LOOP) CHECK CONNECTIONS FROM NODE #{1} TO TARGET NODE #{2}",
Event Player, Event Player.BotClosestNodeIdToBot, Event Player.BotClosestNodeIdToTarget));
Event Player.BotShortestDistanceToTarget = 999;
Event Player.BotCurrentDistanceToTarget = Event Player.BotShortestDistanceToTarget;
Event Player.BotTempArray = Global.NodeConnections[Event Player.BotClosestNodeIdToBot];
For Player Variable(Event Player, BotLoopIterator1, 0, Count Of(Event Player.BotTempArray), 1);
Event Player.BotCurrentDistanceToTarget = Global.DistanceMatrix[Event Player.BotTempArray[Event Player.BotLoopIterator1]][Event Player.BotClosestNodeIdToTarget];
Log To Inspector(Custom String("PATH FINDING ({0}): NODE #{1}; DISTANCE TO TARGET = {2}", Event Player,
Event Player.BotTempArray[Event Player.BotLoopIterator1], Event Player.BotCurrentDistanceToTarget));
If(Event Player.BotCurrentDistanceToTarget < Event Player.BotShortestDistanceToTarget);
Event Player.BotShortestDistanceToTarget = Event Player.BotCurrentDistanceToTarget;
Event Player.BotNextNodeId = Event Player.BotTempArray[Event Player.BotLoopIterator1];
Log To Inspector(Custom String("PATH FINDING ({0}): SET NEXT NODE #{1}", Event Player, Event Player.BotNextNodeId));
End;
End;
Log To Inspector(Custom String("PATH FINDING ({0}): (END LOOP) NEXT NODE #{1}, DISTANCE TO TARGET NODE = {2}", Event Player,
Event Player.BotNextNodeId, Event Player.BotShortestDistanceToTarget));
End;
"II. AVAILABILITY CHECKING OF NEXT NODE"
Log To Inspector(Custom String("PATH FINDING ({0}): BEGIN AVAILABILITY CHECKING OF NEXT NODE #{1}", Event Player,
Event Player.BotNextNodeId));
"Y-ORD DIFF BETWEEN BOT POS AND NEXT NODE POS"
Log To Inspector(Custom String("PATH FINDING ({0}): Y-ORD DIFF BETWEEN BOT POS AND NEXT NODE POS = {1}", Event Player,
Y Component Of(Position Of(Event Player)) - Y Component Of(Global.NodePositions[Event Player.BotNextNodeId])));
"NEXT NODE IS HIGHER THAN BOT AND BOT DIDN'T REACH CLOSEST NODE"
If(Y Component Of(Position Of(Event Player)) - Y Component Of(Global.NodePositions[Event Player.BotNextNodeId])
< -3 && Event Player.BotPrevNodeId != Event Player.BotClosestNodeIdToBot);
Log To Inspector(Custom String("PATH FINDING ({0}): NEXT NODE {1} IS HIGHER THAN BOT, SET CLOSEST NODE #{2} TO BOT AS NEXT",
Event Player, Event Player.BotNextNodeId, Event Player.BotClosestNodeIdToBot));
Event Player.BotPrevNodeId = Event Player.BotClosestNodeIdToBot;
Event Player.BotNextNodeId = Event Player.BotClosestNodeIdToBot;
"BOT CAN SEE TARGET POSITION AND NEXT NODE IS TARGET"
Else If(
Global.DistanceMatrix[Event Player.BotClosestNodeIdToBot][Event Player.BotClosestNodeIdToTarget] == 1 && Is In Line of Sight(
Position Of(Event Player) + Vector(0, 1.600, 0), Event Player.BotTargetPosition + Vector(0, 2, 0), Barriers Do Not Block LOS));
Log To Inspector(Custom String(
"PATH FINDING ({0}): CAN SEE TARGET POSITION {1} AND DISTANCE TO TARGET NODE = 1, MOVE TO TARGET POSITION", Event Player,
Event Player.BotTargetPosition));
Event Player.BotNextNodePosition = Event Player.BotTargetPosition;
Abort;
"BOT CAN'T SEE NEXT NODE OR NODE IS LOWER THAN BOT"
disabled Else If(Is In Line of Sight(Position Of(Event Player) + Vector(0, 1.600, 0),
Global.NodePositions[Event Player.BotNextNodeId] + Vector(0, 2, 0), Barriers Do Not Block LOS) == False);
"BOT CAN'T SEE NEXT NODE AND PREV NODE != REACHED NODE"
Else If(Is In Line of Sight(Position Of(Event Player) + Vector(0, 1.600, 0),
Global.NodePositions[Event Player.BotNextNodeId] + Vector(0, 2, 0), Barriers Do Not Block LOS)
== False && Event Player.BotPrevNodeId != Event Player.BotClosestNodeIdToBot);
Log To Inspector(Custom String("PATH FINDING ({0}): CAN'T SEE NODE #{1}, SET CLOSEST NODE #{2} AS NEXT", Event Player,
Event Player.BotNextNodeId, Event Player.BotClosestNodeIdToBot));
Event Player.BotPrevNodeId = Event Player.BotClosestNodeIdToBot;
Event Player.BotNextNodeId = Event Player.BotClosestNodeIdToBot;
End;
Event Player.BotNextNodePosition = Global.NodePositions[Event Player.BotNextNodeId];
Log To Inspector(Custom String("PATH FINDING ({0}): MOVE TO NEXT NODE #{1}", Event Player, Event Player.BotNextNodeId));
Log To Inspector(Custom String("PATH FINDING ({0}): END FIND NEXT NODE", Event Player, Event Player.BotNextNodeId));
}
}
rule("SUBROUTINE: BOT - GET CLOSEST NODE ID AND POSITION TO TARGET")
{
event
{
Subroutine;
BotGetClosestNodeIdToTarget;
}
actions
{
Event Player.BotTargetPosition = Event Player.BotTargetPlayer != -1 ? Position Of(Event Player.BotTargetPlayer)
: Event Player.BotTargetPosition;
Event Player.BotClosestNodeIdToTarget = Index Of Array Value(Global.NodePositions, Sorted Array(Filtered Array(
Global.NodePositions, Is In Line of Sight(Event Player.BotTargetPosition + Vector(0, 2, 0), Current Array Element,
Barriers Do Not Block LOS) == True), Distance Between(Event Player.BotTargetPosition, Current Array Element))[0]);
}
}
rule("BOT: PATH FINDING - INIT")
{
event
{
Player Joined Match;
All;
All;
}
conditions
{
Is Dummy Bot(Event Player) == True;
}
actions
{
Call Subroutine(BotResetPathFinding);
}
}
rule("BOT: PATH FINDING - START")
{
event
{
Ongoing - Each Player;
All;
All;
}
conditions
{
Is Dummy Bot(Event Player) == True;
Has Spawned(Event Player) == True;
(Event Player.BotTargetPosition != -1 || Event Player.BotTargetPlayer != -1) == True;
}
actions
{
Start Rule(BotStartPathFinding, Restart Rule);
}
}
rule("BOT: PATH FINDING - REACHED THE NODE")
rule("BOT: PATH FINDING - CANCEL")
{
event
{
Ongoing - Each Player;
All;
All;
}
conditions
{
Is Dummy Bot(Event Player) == True;
Has Spawned(Event Player) == True;
Event Player.BotIsPathFinding == True;
(Event Player.BotClosestNodeIdToTarget >= 0 && Distance Between(Position Of(Event Player), Event Player.BotNextNodePosition)
< 0.850) == True;
Event Player.BotCancelPathFinding == True;
}
actions
{
Event Player.BotPrevNodeId = Event Player.BotNextNodeId;
Event Player.BotClosestNodeIdToBot = Event Player.BotNextNodeId;
Event Player.BotCurrentDistanceToTarget = Distance Between(Position Of(Event Player), Event Player.BotTargetPosition);
Log To Inspector(Custom String("PATH FINDING ({0}): REACHED NODE #{1}", Event Player, Event Player.BotNextNodeId));
"BOT REACHED THE TARGET NODE OR TARGET POSITION"
If(Event Player.BotNextNodeId == Event Player.BotClosestNodeIdToTarget || Event Player.BotCurrentDistanceToTarget <= 0.850);
"BOT DIDN'T REACH TARGET POSITION"
If(Event Player.BotCurrentDistanceToTarget > 0.850);
Event Player.BotNextNodePosition = Event Player.BotTargetPosition;
Skip(5);
End;
"BOT REACHED TARGET POSITION"
Call Subroutine(BotResetPathFinding);
Abort;
End;
"CONTINUE FOLLOW PATH"
Call Subroutine(BotGetNextNodeIdAndPosition);
Start Facing(Event Player, Direction Towards(Position Of(Event Player), Event Player.BotNextNodePosition), 360, To World,
Direction and Turn Rate);
Start Throttle In Direction(Event Player, Direction Towards(Position Of(Event Player), Event Player.BotNextNodePosition), 1,
To World, Replace existing throttle, Direction and Magnitude);
Start Rule(BotResetPathFinding, Restart Rule);
}
}
rule("BOT: PATH FINDING - LOST THE NODE")
{
event
{
Ongoing - Each Player;
All;
All;
}
conditions
{
Is Dummy Bot(Event Player) == True;
Has Spawned(Event Player) == True;
Event Player.BotIsPathFinding == True;
(Is In Line of Sight(Position Of(Event Player) + Vector(0, 1.600, 0), Event Player.BotNextNodePosition + Vector(0, 2.500, 0),
Barriers Do Not Block LOS) == False && Speed Of In Direction(Event Player, Throttle Of(Event Player)) < 2) == True;
}
actions
{
Wait(0.500, Abort When False);
Log To Inspector(Custom String("PATH FINDING ({0}): LOST NEXT NODE FROM SIGHT, BEGIN FIND CLOSEST NODE TO BOT AND NEW NEXT NODE",
Event Player));
"RESET PREV NODE ID TO INFORM BOT THAT IT LOST NEXT NODE"
Event Player.BotPrevNodeId = -1;
"TRY FIND NEW NEXT NODE"
Call Subroutine(BotGetNextNodeIdAndPosition);
Start Facing(Event Player, Direction Towards(Position Of(Event Player), Event Player.BotNextNodeId), 360, To World,
Direction and Turn Rate);
Start Throttle In Direction(Event Player, Direction Towards(Position Of(Event Player), Event Player.BotNextNodePosition), 1,
To World, Replace existing throttle, Direction and Magnitude);
}
}
disabled rule("=== EXPORT BLOCK END ===")
rule("BOT: PATH FINDING - REACHED THE NODE")
{
event
{
Ongoing - Each Player;
All;
All;
}
conditions
{
Is Dummy Bot(Event Player) == True;
Has Spawned(Event Player) == True;
Event Player.BotIsPathFinding == True;
Event Player.BotClosestNodeIdToTarget >= 0;
(Distance Between(Vector(X Component Of(Position Of(Event Player)), 0, Z Component Of(Position Of(Event Player))), Vector(
X Component Of(Event Player.BotNextNodePosition), 0, Z Component Of(Event Player.BotNextNodePosition))) < 0.850) == True;
}
actions
{
Log To Inspector(Custom String("PATH FINDING ({0}): REACHED NODE #{1} OR POSITION {2}", Event Player, Event Player.BotNextNodeId,
Event Player.BotNextNodePosition));
Event Player.BotPrevNodeId = Event Player.BotNextNodeId;
Event Player.BotClosestNodeIdToBot = Event Player.BotNextNodeId;
"BOT'S TARGET IS PLAYER"
If(Event Player.BotTargetPlayer != -1);
Call Subroutine(BotGetClosestNodeIdToTarget);
End;
Event Player.BotCurrentDistanceToTarget = Distance Between(Vector(X Component Of(Position Of(Event Player)), 0, Z Component Of(
Position Of(Event Player))), Vector(X Component Of(Event Player.BotTargetPosition), 0, Z Component Of(
Event Player.BotTargetPosition)));
"BOT REACHED THE TARGET NODE OR TARGET POSITION"
If(Event Player.BotNextNodeId == Event Player.BotClosestNodeIdToTarget || Event Player.BotCurrentDistanceToTarget <= 0.850);
"BOT DIDN'T REACH TARGET POSITION"
If(Event Player.BotCurrentDistanceToTarget > 0.850);
Log To Inspector(Custom String("PATH FINDING ({0}): TARGET IS POSITION #{1}, MOVE TO THIS POSITION", Event Player,
Event Player.BotTargetPosition));
Event Player.BotNextNodePosition = Event Player.BotTargetPosition;
Skip(6);
"BOT REACHED TARGET"
Else;
Call Subroutine(BotResetPathFinding);
Abort;
End;
End;
"CONTINUE FOLLOW PATH"
Call Subroutine(BotGetNextNodeIdAndPosition);
Start Facing(Event Player, Direction Towards(Position Of(Event Player), Event Player.BotNextNodePosition), 360, To World,
Direction and Turn Rate);
Start Throttle In Direction(Event Player, Direction Towards(Position Of(Event Player), Event Player.BotNextNodePosition), 1,
To World, Replace existing throttle, Direction and Magnitude);
}
}
rule("=== EXPORT BLOCK END ===")
{
event
{
Ongoing - Global;
}
}
disabled rule("")
{
event
{
Ongoing - Global;
}
}
rule("GLOBAL: INIT MOD")
{
event
{
Ongoing - Global;
}
actions
{
Global.IsBuildingProject = False;
Global.BuilderNodePositions = Empty Array;
Global.BuilderNodeConnections = Empty Array;
Global.BuilderNodeEffectIdArray = Empty Array;
Global.BuilderNodeWorldTextIdArray = Empty Array;
Global.BuilderNodeConnectionEffectsId = Empty Array;
Global.NodeTriggerRadius = 0.850;
Global.BeamEffects = Empty Array;
Global.NodeTriggerRadius = Workshop Setting Real(Custom String("PATH FINDING"), Custom String("NODE TRIGGER RADIUS"), 0.850, 0.500,
1.500, 0);
Global.DisableInspectorWhileCompiling = Workshop Setting Toggle(Custom String("MOD PROPERTIES"), Custom String(
"DISABLE INSPECTOR WHILE COMPILING (ONLY WRITE RESULT VALUES IN EXPORT VARS)"), True, 0);
Global.PropertySpawnRoomIndex = Workshop Setting Combo(Custom String("MOD PROPERTIES"), Custom String("SPAWN ROOM"), 0, Array(
Custom String("1"), Custom String("2"), Custom String("3")), 0);
Global.PropertyFreeCamera = Workshop Setting Toggle(Custom String("MOD PROPERTIES"), Custom String("FREE FLY CAMERA"), True, 1);
Global.PropertyPlayerMovementSpeed = Workshop Setting Integer(Custom String("MOD PROPERTIES"), Custom String(
"PLAYER MOVEMENT SPEED"), 150, 50, 200, 2);
Global.PropertyBotMovementSpeed = Workshop Setting Integer(Custom String("MOD PROPERTIES"), Custom String(
"TEST BOT MOVEMENT SPEED"), 100, 50, 200, 3);
Start Forcing Spawn Room(All Teams, Global.PropertySpawnRoomIndex);
Create HUD Text(All Players(All Teams), Custom String(""), Null, Null, Left, 0, Color(White), Color(White), Color(White),
Visible To and String, Default Visibility);
"VALUES: \"EDIT\" - EDIT EXISTING NODES; \"BUILD\"- CREATE NEW NODES; \"PATH FINDING\" - TEST COMPUTING PATHS"
Global.BuilderMode = Custom String("PATH FINDING");
Global.BuilderHudColorEditMode = Color(Yellow);
Global.BuilderHudColorBuildMode = Color(Red);
Global.BuilderHudColorPathFindingMode = Color(Purple);
Global.PathFindingStartNodeId = -1;
Global.PathFindingTargetNodeId = -1;
"SELECTED NODE EFFECT"
Call Subroutine(BuilderInitModEffects);
If(Global.NodePositions != Null);
Call Subroutine(BuilderBuildPreparedPathNodes);
End;
}
}
rule("GLOBAL: WORKSHOP SETTINGS INSTRUCTION")
{
event
{
Ongoing - Global;
}
actions
{
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
"1. PLACE NODES AND CONNECT THEM HOW YOU NEED BY USING BUILDER MODES BELOW"), False, -99);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
" 1.1. BUILD MODE - CREATES AND PLACES NEW NODE IN CROSSHAIR'S POSITION"), False, -98);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
" 1.2. EDIT MODE - SELECTS EXISTING NODE AND ALLOWS CONNECT IT TO OTHER NODES"), False, -97);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
" 1.3. PATH FINDING MODE - SETS START AND TARGET NODES TO TEST ROUTE"), False, -96);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
"2. BUILD YOUR PROJECT TO GET EXPORT VARS"), False, -95);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
" 2.1. SWITCH TO BUILD MODE"), False, -94);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
" 2.2. HOLD 'INTERACT' BUTTON A FEW SECONDS TO RUN BUILD PROCESS"), False, -93);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
" 2.3. WAIT WHEN THE PROCESS WILL BE FINISHED"), False, -92);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
" 2.3. OPEN WORKSHOP INSPECTOR AT LAST POSITION AND SELECT 'VARIABLE TARGET' = GLOBAL"), False, -91);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
" 2.4. CLICK (X) BUTTON TO COPY VALUES OF VARS TO CLIPBOARD AND PASTE IT IN ANY TEXT EDITOR"), False, -90);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
" 2.5 DELETE ALL VARS AND ACTIONS EXCEPT NEXT"), False, -89);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
" Global.NodePositions, Global.NodeConnections, Global.DistanceMatrix"), False, -88);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
" 2.6 COPY ALL LINES FROM TEXT EDITOR INTO CLIPBOARD"), False, -87);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
"3. CREATE NEW MAP RULE INSIDE OF 'EXPORT BLOCK' AND PASTE COPIED VALUES FROM CLIPBOARD"), False, -86);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
"4. COPY ALL RULES INSIDE OF 'EXPORT BLOCK' AND PUT THEM IN YOUR GAME MODE"), False, -85);
Global.WorkshopSettingInstructions = Workshop Setting Toggle(Custom String("INSTRUCTIONS - HOW DOES IT WORKS"), Custom String(
"5. PROFIT!"), False, -84);
}
}
rule("SUBROUTINE: INIT MOD EFFECTS")
{
event
{
Subroutine;
BuilderInitModEffects;
}
actions
{
"SELECTED NODE EFFECT"
Global.BuilderSelectedNodeEffectPos = Vector(0, -999, 0);
Create Effect(All Players(All Teams), Sphere, Global.BuilderHudColorEditMode, Global.BuilderSelectedNodeEffectPos,
Global.NodeTriggerRadius, Visible To Position and Radius);
"PATH FINDING EFFECTS"
Global.PathFindingStartNodeEffectPos = Vector(0, -999, 0);
Global.PathFindingTargetNodeEffectPos = Vector(0, -999, 0);
Create Effect(All Players(All Teams), Light Shaft, Global.BuilderHudColorPathFindingMode, Global.PathFindingStartNodeEffectPos,
Global.NodeTriggerRadius, Visible To Position and Radius);
Create Effect(All Players(All Teams), Light Shaft, Global.BuilderHudColorPathFindingMode, Global.PathFindingTargetNodeEffectPos,
Global.NodeTriggerRadius, Visible To Position and Radius);
}
}
disabled rule("=== PLAYER ===")
{
event
{
Ongoing - Global;
}
}
rule("PLAYER: INIT")
{
event
{
Ongoing - Each Player;
All;
All;
}
conditions
{
Is Dummy Bot(Event Player) == False;
Host Player == True;
Has Spawned(Event Player) == True;
}
actions
{
Start Forcing Player To Be Hero(Event Player, Hero(Zenyatta));
Disable Movement Collision With Environment(Event Player, False);
Call Subroutine(BuilderSwitchMode);
disabled Disable Text Chat(Event Player);
disabled Disable Hero HUD(Event Player);
Disable Game Mode HUD(Event Player);
Set Ability 1 Enabled(Event Player, False);
Set Ability 2 Enabled(Event Player, False);
Set Primary Fire Enabled(Event Player, False);
Set Secondary Fire Enabled(Event Player, False);
Set Ultimate Ability Enabled(Event Player, False);
Set Move Speed(Event Player, Global.PropertyPlayerMovementSpeed);
Set Status(Event Player, Null, Phased Out, 9999);
If(Global.PropertyFreeCamera == True);
Set Gravity(Event Player, 0);
Start Accelerating(Event Player, Velocity Of(Event Player) * -1, Speed Of(Event Player) * 2, 10, To World,
Direction Rate and Max Speed);
Set Move Speed(Event Player, Global.PropertyPlayerMovementSpeed * 1.300);
End;
}
}
rule("PLAYER: FREE CAMERA")
{
event
{
Ongoing - Each Player;
All;
All;
}
conditions
{
Global.PropertyFreeCamera == True;
Host Player == True;
Has Spawned(Event Player) == True;
(Is Button Held(Event Player, Button(Jump)) || Is Button Held(Event Player, Button(Crouch))) == True;
}
actions
{
If(Is Button Held(Event Player, Button(Jump)));
Apply Impulse(Event Player, Up, 0.640, To World, Incorporate Contrary Motion);
Wait(False, Ignore Condition);
Loop If Condition Is True;
Else If(Is Button Held(Event Player, Button(Crouch)));
Apply Impulse(Event Player, Down, 0.640, To World, Incorporate Contrary Motion);
Wait(False, Ignore Condition);
Loop If Condition Is True;
End;
}
}
rule("PLAYER: SWITCH BUILDER MODE")
{
event
{
Ongoing - Each Player;
All;
All;
}
conditions
{
Is Dummy Bot(Event Player) == False;
Host Player == True;
Has Spawned(Event Player) == True;
Global.IsBuildingProject == False;
Is Button Held(Event Player, Button(Reload)) == True;
}
actions
{
Call Subroutine(BuilderSwitchMode);
}
}
rule("SUBROUTINE: SWITCH MODE")
{
event
{
Subroutine;
BuilderSwitchMode;
}
actions
{
Destroy HUD Text(Event Player.BuilderModeInfoHudId);
If(Global.BuilderMode == Custom String("PATH FINDING"));
Global.BuilderMode = Custom String("BUILD");
Call Subroutine(PathFindingModeReset);
Global.BuilderHudColorCurrent = Global.BuilderHudColorBuildMode;
Create HUD Text(All Players(All Teams), Custom String("[{0}] - MODE: {1}\r\n{2}", Input Binding String(Button(Reload)),
Global.BuilderMode, Custom String("HOLD {1} - BUILD PROJECT\r\n{0} - CREATE NODE", Input Binding String(Button(Primary Fire)),
Input Binding String(Button(Interact)))), Null, Null, Left, -999, Global.BuilderHudColorCurrent, Color(White), Color(White),
Visible To and String, Default Visibility);
Else If(Global.BuilderMode == Custom String("BUILD"));
Global.BuilderMode = Custom String("EDIT");
Global.BuilderHudColorCurrent = Global.BuilderHudColorEditMode;
Create HUD Text(All Players(All Teams), Custom String("[{0}] - MODE: {1}\r\n{2}", Input Binding String(Button(Reload)),
Global.BuilderMode, Custom String("SELECTED NODE - {0}\r\n{1} - SELECT\r\n{2}",
Global.BuilderSelectedNodeId < 0 ? Custom String("NONE") : Global.BuilderSelectedNodeId, Input Binding String(Button(
Primary Fire)), Custom String("{0} - CONNECT/DISCONNECT\r\n{1} - DELETE", Input Binding String(Button(Secondary Fire)),
Input Binding String(Button(Interact))))), Null, Null, Left, -999, Global.BuilderHudColorCurrent, Color(White), Color(White),
Visible To and String, Default Visibility);
Else If(Global.BuilderMode == Custom String("EDIT"));
Global.BuilderMode = Custom String("PATH FINDING");
Call Subroutine(DeleteNodeBeams);
Global.BuilderHudColorCurrent = Global.BuilderHudColorPathFindingMode;
Create HUD Text(All Players(All Teams), Custom String("[{0}] - MODE: {1}\r\n{2}", Input Binding String(Button(Reload)),
Global.BuilderMode, Custom String("{0} - SET START POS (CLOSEST NODE {1})\r\n{2}", Input Binding String(Button(Primary Fire)),
Global.PathFindingStartNodeId, Custom String("{0} - SET TARGET POS (CLOSEST NODE {1})\r\n{2}", Input Binding String(Button(
Secondary Fire)), Global.PathFindingTargetNodeId, Custom String("{0} - TEST WITH BOT\r\n{1} - BOOP BOT", Input Binding String(
Button(Ultimate)), Input Binding String(Button(Interact)))))), Null, Null, Left, -999, Global.BuilderHudColorCurrent, Color(
White), Color(White), Visible To and String, Default Visibility);
End;
Event Player.BuilderModeInfoHudId = Last Text ID;
Global.BuilderSelectedNodeEffectPos = Vector(0, -999, 0);
Global.BuilderSelectedNodeId = -1;
}
}
rule("SUBROUTINE: GET CLOSSEST NODE ID TO CURSOR")
{
event
{
Subroutine;
BuilderGetClossestNodeIdToCursor;
}
actions
{
"ANY NODE IN LINE OF SIGHT"
Global.BuilderTrySelectNodeInLOS = Filtered Array(Global.BuilderNodePositions, Current Array Element != False && Dot Product(
Facing Direction Of(Event Player), Direction Towards(Eye Position(Event Player), Current Array Element))
>= 0.990 && Is In Line of Sight(Eye Position(Event Player), Current Array Element, Barriers Do Not Block LOS));
If(Global.BuilderTrySelectNodeInLOS != Empty Array);
Global.BuilderTrySelectNodeInLOS = Index Of Array Value(Global.BuilderNodePositions, Global.BuilderTrySelectNodeInLOS[0]);
Else;
Global.BuilderTrySelectNodeInLOS = -1;
End;
}
}
disabled rule("=== EDIT MODE ===")
{
event
{
Ongoing - Global;
}
}
rule("PLAYER: EDIT MODE")
{
event
{
Ongoing - Each Player;
All;
All;
}
conditions
{
Is Dummy Bot(Event Player) == False;
Host Player == True;
Has Spawned(Event Player) == True;
(Is Button Held(Event Player, Button(Primary Fire)) || Is Button Held(Event Player, Button(Secondary Fire)) || Is Button Held(
Event Player, Button(Interact))) == True;
Global.BuilderMode == Custom String("EDIT");
}
actions
{
"ANY NODE IN LINE OF SIGHT"
Call Subroutine(BuilderGetClossestNodeIdToCursor);
"SELECT NODE"
If(Is Button Held(Event Player, Button(Primary Fire)));
Call Subroutine(BuilderEditModeSelectNode);
"CONNECT/DISCONNECT NODE"
Else If(Is Button Held(Event Player, Button(Secondary Fire)) && Global.BuilderSelectedNodeId != -1);
Call Subroutine(BuilderConnectDisconnectSelector);
"DELETE NODE"
Else If(Is Button Held(Event Player, Button(Interact)) && Global.BuilderSelectedNodeId != -1);
Call Subroutine(BuilderEditModeDeleteNode);
End;
}
}
rule("SUBROUTINE: SELECT NODE")
{
event
{
Subroutine;
BuilderEditModeSelectNode;
}
actions
{
If(Global.BuilderTrySelectNodeInLOS != -1);
Global.BuilderSelectedNodeEffectPos = Global.BuilderNodePositions[Global.BuilderTrySelectNodeInLOS];
Else;
Global.BuilderSelectedNodeEffectPos = Vector(0, -999, 0);
Call Subroutine(DeleteNodeBeams);
End;
Global.BuilderSelectedNodeId = Global.BuilderTrySelectNodeInLOS;
Call Subroutine(DeleteNodeBeams);
"DRAW CONNECTED BEAMS"
If(Count Of(Global.BuilderNodeConnections[Global.BuilderSelectedNodeId]) > 0);
Call Subroutine(CreateNodeBeams);
End;
}
}
rule("SUBROUTINE: DELETE NODE")
{
event
{
Subroutine;
BuilderEditModeDeleteNode;
}
actions
{
If(Global.BuilderTrySelectNodeInLOS == -1 || Global.BuilderTrySelectNodeInLOS != Global.BuilderSelectedNodeId);
Small Message(All Players(All Teams), Custom String("LOOK AT NODE {0} TO DELETE IT", Global.BuilderSelectedNodeId));
Abort;
End;
Small Message(All Players(All Teams), Custom String("NODE DELETED"));
Call Subroutine(DeleteNodeBeams);
Play Effect(Event Player, Debuff Impact Sound, Color(White), Event Player, 60);
Destroy Effect(Global.BuilderNodeEffectIdArray[Global.BuilderSelectedNodeId]);
Destroy In-World Text(Global.BuilderNodeWorldTextIdArray[Global.BuilderSelectedNodeId]);
Global.BuilderNodePositions[Global.BuilderTrySelectNodeInLOS] = False;
Global.BuilderSelectedNodeEffectPos = Vector(0, -999, 0);
Call Subroutine(BuilderDeleteConnectionsOfNode);
Global.BuilderSelectedNodeId = -1;
}
}
rule("SUBROUTINE: DELETE ALL CONNECTIONS OF DELETED NODE")
{
event
{
Subroutine;
BuilderDeleteConnectionsOfNode;
}
actions
{
"DELETE ALL CONNECTIONS OF THE DELETED NODE"
For Global Variable(LoopIterator1, 0, Count Of(Global.BuilderNodeConnections[Global.BuilderSelectedNodeId]), 1);
Destroy Effect(
Global.BuilderNodeConnectionEffectsId[Global.BuilderSelectedNodeId][Global.BuilderNodeConnections[Global.BuilderSelectedNodeId][Global.LoopIterator1]]);
End;
"CHECK OTHER NODES FOR CONNECTION WITH DELETED NODE"
For Global Variable(LoopIterator1, 0, Count Of(Global.BuilderNodePositions), 1);
disabled Global.BuilderTrySelectNodeInLOS = Global.BuilderNodeConnections[Global.LoopIterator1][Global.LoopIterator2];
If(Array Contains(Global.BuilderNodeConnections[Global.LoopIterator1], Global.BuilderSelectedNodeId));
"DELETE BEAM EFFECT"
Destroy Effect(Global.BuilderNodeConnectionEffectsId[Global.LoopIterator1][Global.BuilderSelectedNodeId]);
Global.BuilderInnerArray = Global.BuilderNodeConnectionEffectsId[Global.LoopIterator1];
Global.BuilderInnerArray[Global.BuilderSelectedNodeId] = False;
Global.BuilderNodeConnectionEffectsId[Global.LoopIterator1] = Global.BuilderInnerArray;
"REMOVE DELETED NODE FROM CONNECTION ARRAY"
Global.BuilderInnerArray = Global.BuilderNodeConnections[Global.LoopIterator1];
Modify Global Variable(BuilderInnerArray, Remove From Array By Value, Global.BuilderSelectedNodeId);
Global.BuilderNodeConnections[Global.LoopIterator1] = Global.BuilderInnerArray;
"UPDATE IN-WORLD TEXT OF NODE"
Global.StringConcatNodeId = Global.LoopIterator1;
Call Subroutine(BuilderConcatStringConnections);
End;
End;
Global.BuilderNodeConnections[Global.BuilderSelectedNodeId] = False;
Global.BuilderNodeConnectionEffectsId[Global.BuilderSelectedNodeId] = False;
}
}
rule("SUBROUTINE: CONNECT DISCONNECT SELECTOR")
{
event
{
Subroutine;
BuilderConnectDisconnectSelector;
}
actions
{
If(
Global.BuilderSelectedNodeId == -1 || Global.BuilderTrySelectNodeInLOS == -1 || Global.BuilderSelectedNodeId == Global.BuilderTrySelectNodeInLOS);
Small Message(All Players(All Teams), Custom String("LOOK AT OTHER NODE TO CONNECT/DISCONNECT IT"));
Abort;
End;
Global.BuilderIsNodeHaveConnection = Array Contains(Global.BuilderNodeConnections[Global.BuilderSelectedNodeId],
Global.BuilderTrySelectNodeInLOS);
If(!Global.BuilderIsNodeHaveConnection);
Small Message(All Players(All Teams), Custom String("NODE CONNECTED"));
Call Subroutine(BuilderConnectNodeBackendLogic);
Call Subroutine(DeleteNodeBeams);
Call Subroutine(CreateNodeBeams);
Else;
Small Message(All Players(All Teams), Custom String("NODE DISCONNECTED"));
Call Subroutine(BuilderDisconnectNode);
Call Subroutine(DeleteNodeBeams);
Call Subroutine(CreateNodeBeams);
End;
"UPDATE IN-WORLD TEXT OF CONNECTED NODE"
Global.StringConcatNodeId = Global.BuilderSelectedNodeId;
Call Subroutine(BuilderConcatStringConnections);
}
}
rule("SUBROUTINE: CONNECT NODE (BACK-END LOGIC)")
{
event
{
Subroutine;
BuilderConnectNodeBackendLogic;
}
actions
{
"GET CONNECTION ARRAY FOR SELECTED NODE AND ADD NEW CONNECTION"
If(Count Of(Global.BuilderNodeConnections[Global.BuilderSelectedNodeId]) > 0);
Global.BuilderInnerArray = Global.BuilderNodeConnections[Global.BuilderSelectedNodeId];
Modify Global Variable(BuilderInnerArray, Append To Array, Global.BuilderTrySelectNodeInLOS);
"OR CREATE NEW CONNECTION ARRAY FOR SELECTED NODE"
Else;
Global.BuilderInnerArray = Empty Array;
Global.BuilderInnerArray[0] = Global.BuilderTrySelectNodeInLOS;
End;
"ADD CONNECTION ARRAY OF SELECTED NODE IN MATRIX 2X2 OF ALL CONNECTIONS"
Global.BuilderNodeConnections[Global.BuilderSelectedNodeId] = Global.BuilderInnerArray;
Play Effect(All Players(All Teams), Buff Impact Sound, Color(White), Event Player, 60);
Call Subroutine(BuilderConnectNodeBeamEffect);
}
}
rule("SUBROUTINE: CONNECT NODE (BEAM EFFECT)")
{
event
{
Subroutine;
BuilderConnectNodeBeamEffect;
}
actions
{
"'BEAM' EFFECT IS EXIST BETWEEN THESE NODES"
Abort If(Entity Exists(Global.BuilderNodeConnectionEffectsId[Global.BuilderTrySelectNodeInLOS][Global.BuilderSelectedNodeId]));
Abort If(Entity Exists(Global.BuilderNodeConnectionEffectsId[Global.BuilderSelectedNodeId][Global.BuilderTrySelectNodeInLOS]));
"VISUAL EFFECT OF CONNECTION"
Create Beam Effect(All Players(All Teams), Grapple Beam, Global.BuilderNodePositions[Global.BuilderSelectedNodeId],
Global.BuilderNodePositions[Global.BuilderTrySelectNodeInLOS], Color(White), Visible To);
"ARRAY LIKE HASH MAP (KEY : VALUE) - KEY - INDEX OF NODE, VALUE - EFFECT ID"
If(Count Of(Global.BuilderNodeConnectionEffectsId[Global.BuilderSelectedNodeId]) > 0);
Global.BuilderInnerArray = Global.BuilderNodeConnectionEffectsId[Global.BuilderSelectedNodeId];
Else;
Global.BuilderInnerArray = Empty Array;
End;
Global.BuilderInnerArray[Global.BuilderTrySelectNodeInLOS] = Last Created Entity;
"ADD BEAM EFFECT ARRAY IN MATRIX 2X2 OF ALL CONNECTION EFFECTS"
Global.BuilderNodeConnectionEffectsId[Global.BuilderSelectedNodeId] = Global.BuilderInnerArray;
}
}
rule("SUBROUTINE: DISCONNECT NODE")
{
event
{
Subroutine;
BuilderDisconnectNode;
}
actions
{
Play Effect(Event Player, Debuff Impact Sound, Color(White), Event Player, 60);
"GET CONNECTION ARRAY FOR SELECTED NODE"
Global.BuilderInnerArray = Global.BuilderNodeConnections[Global.BuilderSelectedNodeId];
Modify Global Variable(BuilderInnerArray, Remove From Array By Value, Global.BuilderTrySelectNodeInLOS);
"REMOVE CONNECTION ARRAY OF SELECTED NODE IN MATRIX 2X2 OF ALL CONNECTIONS"
Global.BuilderNodeConnections[Global.BuilderSelectedNodeId] = Global.BuilderInnerArray;
"DESTROY BEAM EFFECT"
Abort If(Array Contains(Global.BuilderNodeConnections[Global.BuilderTrySelectNodeInLOS], Global.BuilderSelectedNodeId));
Destroy Effect(Global.BuilderNodeConnectionEffectsId[Global.BuilderSelectedNodeId][Global.BuilderTrySelectNodeInLOS]);
Destroy Effect(Global.BuilderNodeConnectionEffectsId[Global.BuilderTrySelectNodeInLOS][Global.BuilderSelectedNodeId]);
Global.BuilderInnerArray = Global.BuilderNodeConnectionEffectsId[Global.BuilderSelectedNodeId];
Global.BuilderInnerArray[Global.BuilderTrySelectNodeInLOS] = Null;
Global.BuilderNodeConnectionEffectsId[Global.BuilderSelectedNodeId] = Global.BuilderInnerArray;
Global.BuilderInnerArray = Global.BuilderNodeConnectionEffectsId[Global.BuilderTrySelectNodeInLOS];
Global.BuilderInnerArray[Global.BuilderSelectedNodeId] = Null;
Global.BuilderNodeConnectionEffectsId[Global.BuilderTrySelectNodeInLOS] = Global.BuilderInnerArray;
}
}
rule("SUBROUTINE: CONCAT STRING CONNECTIONS")
{
event
{
Subroutine;
BuilderConcatStringConnections;
}
actions
{
Destroy In-World Text(Global.BuilderNodeWorldTextIdArray[Global.StringConcatNodeId]);
Global.StringConcatCountOfElements = Count Of(Global.BuilderNodeConnections[Global.StringConcatNodeId]);
If(Global.StringConcatCountOfElements > 0);
For Global Variable(LoopIterator3, 0, Global.StringConcatCountOfElements, 1);
"FIRST ELEMENT"
If(Global.LoopIterator3 == 0);
Global.StringConcatResult = Custom String("{1}", Null,
Global.BuilderNodeConnections[Global.StringConcatNodeId][Global.LoopIterator3]);
"ADD \",\" SYMBOL BETWEEN ELEMENTS"
Else;
Global.StringConcatResult = Custom String("{0}{2}{1}", Global.StringConcatResult,
Global.BuilderNodeConnections[Global.StringConcatNodeId][Global.LoopIterator3],
Global.LoopIterator3 != Global.StringConcatCountOfElements ? Custom String(", ") : Custom String(" "));
End;
End;
Create In-World Text(All Players(All Teams), Custom String("NODE {0}\r\n[ {1} ]", Global.StringConcatNodeId,
Global.StringConcatResult), Global.BuilderNodePositions[Global.StringConcatNodeId], 1.200, Do Not Clip, Visible To, Color(
White), Default Visibility);
Else;
Create In-World Text(All Players(All Teams), Custom String("NODE {0}", Global.StringConcatNodeId),
Global.BuilderNodePositions[Global.StringConcatNodeId], 1.300, Do Not Clip, Visible To, Color(White), Default Visibility);
End;
Global.BuilderNodeWorldTextIdArray[Global.StringConcatNodeId] = Last Text ID;
}
}
disabled rule("=== BUILD MODE ===")
{
event
{
Ongoing - Global;
}
}
rule("PLAYER: BUILD MODE")
{
event
{
Ongoing - Each Player;
All;
All;
}
conditions
{
Is Dummy Bot(Event Player) == False;
Host Player == True;
Has Spawned(Event Player) == True;
(Is Button Held(Event Player, Button(Primary Fire)) || Is Button Held(Event Player, Button(Interact))) == True;
Global.BuilderMode == Custom String("BUILD");
}
actions
{
"CREATE NEW NODE"
If(Is Button Held(Event Player, Button(Primary Fire)));
Call Subroutine(BuilderBuildModeCreateNewNode);
"OPTIMIZE DATA"
Else If(Is Button Held(Event Player, Button(Interact)));
Create Progress Bar HUD Text(Event Player, Global.BuilderProgressBarValue, Custom String("PREPARING TO BUILD PROJECT"), Top, 1,
Global.BuilderHudColorBuildMode, Global.BuilderHudColorBuildMode, Visible To and Values, Default Visibility);
Global.BuilderProgressBarValue = 0;
Chase Global Variable Over Time(BuilderProgressBarValue, 100, 2, Destination and Duration);
"HOLD BUTTON N SEC TO BEGIN PROCESS"
While(Global.BuilderProgressBarValue != 100);
Wait(0.100, Ignore Condition);
If(Is Button Held(Event Player, Button(Interact)) == False);
Destroy All Progress Bar HUD Text;
Abort;
End;
End;
"RUN BUILD PROJECT"
Destroy All Progress Bar HUD Text;
Call Subroutine(BuilderBuildProject);
End;
}
}
rule("SUBROUTINE: CREATE NEW NODE")
{
event
{
Subroutine;
BuilderBuildModeCreateNewNode;
}
actions
{
Global.BuilderRayCastHitPosition = Ray Cast Hit Position(Eye Position(Event Player), Eye Position(Event Player)
+ Facing Direction Of(Event Player) * 1000, Null, Event Player, False);
"NODE'S OFFSET"
Global.BuilderRayCastHitPosition += Ray Cast Hit Normal(Eye Position(Event Player), Eye Position(Event Player)
+ Facing Direction Of(Event Player) * 999, Null, Event Player, False) * (Global.NodeTriggerRadius / 2);
"OTHER NODE IS VERY CLOSE"
If(Is True For Any(Filtered Array(Global.BuilderNodePositions, Current Array Element != False), Distance Between(
Current Array Element, Global.BuilderRayCastHitPosition) < Global.NodeTriggerRadius * 3));
Small Message(Event Player, Custom String("OTHER NODE VERY CLOSE!"));
Abort;
End;
"CREATE NEW NODE"
Modify Global Variable(BuilderNodePositions, Append To Array, Global.BuilderRayCastHitPosition);
Global.BuilderInnerArray = Empty Array;
Global.BuilderNodeConnections[Index Of Array Value(Global.BuilderNodePositions, Global.BuilderRayCastHitPosition)
] = Global.BuilderInnerArray;
Create Effect(All Players(All Teams), Sphere, Color(Red), Global.BuilderRayCastHitPosition, Global.NodeTriggerRadius, Visible To);
Modify Global Variable(BuilderNodeEffectIdArray, Append To Array, Last Created Entity);
Create In-World Text(All Players(All Teams), Custom String("NODE {0}", Index Of Array Value(Global.BuilderNodePositions,
Global.BuilderRayCastHitPosition)), Global.BuilderRayCastHitPosition, 1.300, Do Not Clip, Visible To, Color(White),
Default Visibility);
Modify Global Variable(BuilderNodeWorldTextIdArray, Append To Array, Last Text ID);
Play Effect(Event Player, Buff Impact Sound, Color(White), Event Player, 60);
}
}
disabled rule("=== BUILD PROJECT ===")
{
event
{
Ongoing - Global;
}
}
rule("SUBROUTINE: BUILD PROJECT")
{
event
{
Subroutine;
BuilderBuildProject;
}
actions
{
"DISABLE INSPECTOR WHILE COMPILING (WRITE RESULT ONLY)"
Skip If(!Global.DisableInspectorWhileCompiling, 1);
Disable Inspector Recording;
"BEGIN COMPILING"
Global.IsBuildingProject = True;
Call Subroutine(BuilderDeleteAllEffects);
Call Subroutine(BuilderOptimizeData);
Wait(0.050, Ignore Condition);
"SELECTED NODE EFFECT"
Call Subroutine(BuilderInitModEffects);
Wait(0.050, Ignore Condition);
Call Subroutine(BuilderBuildPreparedPathNodes);
Call Subroutine(BuilderComputeDistanceMatrix);
Global.IsBuildingProject = False;
Enable Inspector Recording;
}
}
rule("SUBROUTINE: DELETE ALL EFFECTS")
{
event
{
Subroutine;
BuilderDeleteAllEffects;
}
actions
{
Destroy All Effects;
Destroy All In-World Text;
}
}
rule("SUBROUTINE: OPTIMIZE DATA")
{
event
{
Subroutine;
BuilderOptimizeData;
}
actions
{
"PREPARE TO OPTIMAZE DATA"
Destroy All Progress Bar HUD Text;
Global.BuilderProgressBarValue = 0;
Create Progress Bar HUD Text(Event Player, Global.BuilderProgressBarValue, Custom String("OPTIMIZING DATA"), Top, 1, Color(Green),
Color(Green), Visible To and Values, Default Visibility);
Global.BuilderProgressBarValueStep = 100 / Count Of(Global.BuilderNodePositions);
Global.NodePositions = Empty Array;
Global.DistanceMatrix = Empty Array;
Global.NodeConnections = Empty Array;
Global.BuildProjectEmptySpace = 0;
Global.BuildProjectOldElementIndex = 0;
Global.BuildProjectNewElementIndex = 0;
"BEGIN PROCESS"
For Global Variable(LoopIterator1, 0, Count Of(Global.BuilderNodePositions), 1);
Global.BuilderProgressBarValue += Global.BuilderProgressBarValueStep;
"SKIP DELETED NODE (ACCUMULATE SPACE BETWEEN INDEXES)"
If(Global.BuilderNodePositions[Global.LoopIterator1] == False);
Global.BuildProjectEmptySpace += 1;
Continue;
End;
Global.BuildProjectOldElementIndex = Global.LoopIterator1;
Global.BuildProjectNewElementIndex = Global.BuildProjectEmptySpace == 0 ? Global.LoopIterator1 : Global.LoopIterator1 - Global.BuildProjectEmptySpace;
"CONNECTIONS OF CURRENT NODE"
Global.BuilderInnerArray = Global.BuilderNodeConnections[Global.BuildProjectOldElementIndex];
"WRITE ONLY RESULT INTO INSPECTOR"
Enable Inspector Recording;
Global.NodeConnections[Global.BuildProjectNewElementIndex] = Global.BuilderInnerArray;
Modify Global Variable(NodePositions, Append To Array, Global.BuilderNodePositions[Global.BuildProjectOldElementIndex]);
"DISABLE INSPECTOR WHILE COMPILING (WRITE RESULT ONLY)"
Skip If(!Global.DisableInspectorWhileCompiling, 1);
Disable Inspector Recording;
"UPDATE INDEXES IN CONNECTION ARRAY"
If(Global.BuildProjectEmptySpace > 0 && Count Of(Global.NodeConnections) > 1);
Call Subroutine(BuilderUpdateConnectionIndexes);
End;
"ANTI-CRASH DELAY"
Wait(0.020, Ignore Condition);
End;
Destroy All Progress Bar HUD Text;
Enable Inspector Recording;
}
}
rule("SUBROUTINE: UPDATE CONNECTION INDEXES")
{
event
{
Subroutine;
BuilderUpdateConnectionIndexes;
}
actions
{
"UPDATE CONNECTION INDEXES IN FINAL (OPTIMIZED) ARRAY"
For Global Variable(LoopIterator2, 0, Count Of(Global.NodeConnections), 1);
Global.BuilderInnerArray = Global.NodeConnections[Global.LoopIterator2];
For Global Variable(LoopIterator3, 0, Count Of(Global.BuilderInnerArray), 1);
If(Global.BuilderInnerArray[Global.LoopIterator3] == Global.BuildProjectOldElementIndex);
Global.BuilderInnerArray[Global.LoopIterator3] = Global.BuildProjectNewElementIndex;
End;
End;
"WRITE ONLY RESULT INTO INSPECTOR"
Enable Inspector Recording;
Global.NodeConnections[Global.LoopIterator2] = Global.BuilderInnerArray;
"DISABLE INSPECTOR WHILE COMPILING (WRITE RESULT ONLY)"
Skip If(!Global.DisableInspectorWhileCompiling, 1);
Disable Inspector Recording;
End;
"UPDATE NEXT CONNECTION INDEXES IN INPUT ARRAY"
For Global Variable(LoopIterator2, Global.LoopIterator1 + 1, Count Of(Global.BuilderNodeConnections), 1);
Global.BuilderInnerArray = Global.BuilderNodeConnections[Global.LoopIterator2];
For Global Variable(LoopIterator3, 0, Count Of(Global.BuilderInnerArray), 1);
If(Global.BuilderInnerArray[Global.LoopIterator3] == Global.BuildProjectOldElementIndex);
Global.BuilderInnerArray[Global.LoopIterator3] = Global.BuildProjectNewElementIndex;
End;
End;
"WRITE ONLY RESULT INTO INSPECTOR"
Enable Inspector Recording;
Global.BuilderNodeConnections[Global.LoopIterator2] = Global.BuilderInnerArray;
"DISABLE INSPECTOR WHILE COMPILING (WRITE RESULT ONLY)"
Skip If(!Global.DisableInspectorWhileCompiling, 1);
Disable Inspector Recording;
End;
}
}
rule("SUBROUTINE: BUILD PREPARED PATH NODES")
{
event
{
Subroutine;
BuilderBuildPreparedPathNodes;
}
actions
{
Abort If(Count Of(Global.NodePositions) == 0);
Global.BuilderNodeEffectIdArray = Empty Array;
Global.BuilderNodeWorldTextIdArray = Empty Array;
Global.BuilderNodeConnectionEffectsId = Empty Array;
Global.BuilderNodePositions = Global.NodePositions;
Global.BuilderNodeConnections = Empty Array;
"CREATE NODE EFFECTS"
For Global Variable(LoopIterator1, 0, Count Of(Global.NodePositions), 1);
Create Effect(All Players(All Teams), Sphere, Color(Red), Global.NodePositions[Global.LoopIterator1], Global.NodeTriggerRadius,
Visible To);
Modify Global Variable(BuilderNodeEffectIdArray, Append To Array, Last Created Entity);
End;
Wait(0.050, Ignore Condition);
"COPY FROM NodeConnections TO BuilderNodeConnections"
For Global Variable(LoopIterator1, 0, Count Of(Global.NodeConnections), 1);
Global.BuilderInnerArray = Global.NodeConnections[Global.LoopIterator1];
Global.BuilderNodeConnections[Global.LoopIterator1] = Global.BuilderInnerArray;
End;
"ANTI-CRASH DELAY"
Wait(0.030, Ignore Condition);
"CREATE BEAM EFFECTS (CONNECTIONS)"
For Global Variable(LoopIterator1, 0, Count Of(Global.BuilderNodeConnections), 1);
Global.BuilderSelectedNodeId = Global.LoopIterator1;
For Global Variable(LoopIterator2, 0, Count Of(Global.BuilderNodeConnections[Global.LoopIterator1]), 1);
Global.BuilderTrySelectNodeInLOS = Global.BuilderNodeConnections[Global.LoopIterator1][Global.LoopIterator2];
Call Subroutine(BuilderConnectNodeBeamEffect);
End;
End;
"ANTI-CRASH DELAY"
Wait(0.030, Ignore Condition);
"CREATE NODE WORLD TEXTS"
For Global Variable(LoopIterator1, 0, Count Of(Global.NodeConnections), 1);
"UPDATE IN-WORLD TEXT OF CONNECTED NODE"
Global.StringConcatNodeId = Global.LoopIterator1;
Call Subroutine(BuilderConcatStringConnections);
End;
"ANTI-CRASH DELAY"
Wait(0.030, Ignore Condition);
}
}
rule("SUBROUTINE: COMPUTE DISTANCE MATRIX")
{
event
{
Subroutine;
BuilderComputeDistanceMatrix;
}
actions
{
"INIT PROGRESS BAR"
Destroy All Progress Bar HUD Text;
Create Progress Bar HUD Text(All Players(All Teams), Global.BuilderProgressBarValue, Custom String("COMPUTING DISTANCE MATRIX..."),
Top, 1, Color(Purple), Color(Purple), Visible To and Values, Default Visibility);
Global.BuilderProgressBarValue = 0;
Global.BuilderProgressBarValueStep = 100 / Count Of(Global.NodeConnections);
"INIT DISTANCE MATRIX"
"INIT DISTANCE MATRIX SIZE"
Global.DistanceMatrix[Count Of(Global.NodeConnections) - 1] = 0;
"CALCULATE ALL DISTANCES FOR EACH NODE"
For Global Variable(BuildProjectStartNodeId, 0, Count Of(Global.NodeConnections), 1);
"ALL DISTANCES FROM START NODE TO OTHERS"
Global.BuilderInnerArray = Empty Array;
Global.BuilderInnerArray[0] = 0;
"CLEAR QUEUE AND VISITED ARRAYES FOR EACH NODE"
Global.BuildProjectQueueArray = Empty Array;
Global.BuildProjectVisitedNodes = Empty Array;
"PUT THE START NODE IN QUEUE AND MAKE IT VISITED"
Modify Global Variable(BuildProjectQueueArray, Append To Array, Global.BuildProjectStartNodeId);
Modify Global Variable(BuildProjectVisitedNodes, Append To Array, Global.BuildProjectStartNodeId);
"VISIT ALL NODES"
While(Count Of(Global.BuildProjectQueueArray) > 0);
"POP FIRST NODE FROM QUEUE"
Global.BuildProjectCurrentNodeId = Global.BuildProjectQueueArray[0];
Modify Global Variable(BuildProjectQueueArray, Remove From Array By Index, 0);
"VISIT NEIGHBOR NODES"
For Global Variable(LoopIterator1, 0, Count Of(Global.NodeConnections[Global.BuildProjectCurrentNodeId]), 1);
Global.BuildProjectNeighborNodeId = Global.NodeConnections[Global.BuildProjectCurrentNodeId][Global.LoopIterator1];
If(!Array Contains(Global.BuildProjectVisitedNodes, Global.BuildProjectNeighborNodeId));
"ADD NEIGHBOR IN QUEUE AND MARK IT AS VISITED"
Modify Global Variable(BuildProjectQueueArray, Append To Array, Global.BuildProjectNeighborNodeId);
Modify Global Variable(BuildProjectVisitedNodes, Append To Array, Global.BuildProjectNeighborNodeId);
"ACCUMULATE DISTANCE TO NEIGHBOR"
Global.BuilderInnerArray[Global.BuildProjectNeighborNodeId] = Global.BuilderInnerArray[Global.BuildProjectCurrentNodeId] + 1;
End;
End;
"ANTI-CRASH DELAY"
Wait(0.016, Ignore Condition);
End;
"REPLACE ZERO TO INF (9999)"
Global.BuilderInnerArray[Global.BuildProjectStartNodeId] = 9999;
"WRITE ONLY RESULT INTO INSPECTOR"
Enable Inspector Recording;
"ADD RESULT IN DISTANCE MATRIX"
Global.DistanceMatrix[Global.BuildProjectStartNodeId] = Global.BuilderInnerArray;
"DISABLE INSPECTOR WHILE COMPILING (WRITE RESULT ONLY)"
Skip If(!Global.DisableInspectorWhileCompiling, 1);
Disable Inspector Recording;
Global.BuilderProgressBarValue += Global.BuilderProgressBarValueStep;
End;
Destroy All Progress Bar HUD Text;
}
}
disabled rule("=== PATH FINDING MODE ===")
{
event
{
Ongoing - Global;
}
}
rule("PLAYER: PATH FINDING MODE")
{
event
{
Ongoing - Each Player;
All;
All;
}
conditions
{
Is Dummy Bot(Event Player) == False;
Host Player == True;
Has Spawned(Event Player) == True;
(Is Button Held(Event Player, Button(Primary Fire)) || Is Button Held(Event Player, Button(Secondary Fire)) || Is Button Held(
Event Player, Button(Ultimate)) || Is Button Held(Event Player, Button(Interact))) == True;
Global.BuilderMode == Custom String("PATH FINDING");
}
actions
{
"SET START OR TARGET NODE"
If(Is Button Held(Event Player, Button(Primary Fire)) || Is Button Held(Event Player, Button(Secondary Fire)));
Call Subroutine(PathFindingModeSelectNode);
"CREATE TEST BOT"
Else If(Is Button Held(Event Player, Button(Ultimate)));
If(Global.PathFindingStartNodeId != -1 && Global.PathFindingTargetNodeId != -1);
Call Subroutine(PathFindingCreateBot);
End;
"BOOP TEST BOT"
Else If(Is Button Held(Event Player, Button(Interact)));
Apply Impulse(Global.PathFindingBotId, Vector(X Component Of(Facing Direction Of(Event Player)), 0.200, Z Component Of(
Facing Direction Of(Event Player))), 20, To World, Cancel Contrary Motion);
End;
}
}
rule("SUBROUTINE: PATH FINDING SELECT NODE")
{
event
{
Subroutine;
PathFindingModeSelectNode;
}
actions
{
disabled Abort If(Global.BuilderTrySelectNodeInLOS == -1);
Global.BuilderRayCastHitPosition = Ray Cast Hit Position(Eye Position(Event Player), Eye Position(Event Player)
+ Facing Direction Of(Event Player) * 999, Null, Event Player, False);
"SET START NODE"
If(Is Button Held(Event Player, Button(Primary Fire)));
Global.PathFindingStartNodeId = Index Of Array Value(Global.NodePositions, Sorted Array(Filtered Array(Global.NodePositions,
Is In Line of Sight(Global.BuilderRayCastHitPosition + Vector(0, 2, 0), Current Array Element, Barriers Do Not Block LOS)
== True), Distance Between(Global.BuilderRayCastHitPosition, Current Array Element))[0]);
Global.PathFindingStartPosition = Global.BuilderRayCastHitPosition;
Global.PathFindingStartNodeEffectPos = Global.PathFindingStartPosition;
"SET TARGET NODE"
Else If(Is Button Held(Event Player, Button(Secondary Fire)));
Global.PathFindingTargetNodeId = Index Of Array Value(Global.NodePositions, Sorted Array(Filtered Array(Global.NodePositions,
Is In Line of Sight(Global.BuilderRayCastHitPosition + Vector(0, 2, 0), Current Array Element, Barriers Do Not Block LOS)
== True), Distance Between(Global.BuilderRayCastHitPosition, Current Array Element))[0]);
Global.PathFindingTargetPosition = Global.BuilderRayCastHitPosition;
Global.PathFindingTargetNodeEffectPos = Global.PathFindingTargetPosition;
End;
"DRAW PATH"
If(Global.PathFindingStartNodeId != -1 && Global.PathFindingTargetNodeId != -1);
Call Subroutine(PathFindingGetShortestPath);
Call Subroutine(DeleteNodeBeams);
Call Subroutine(CreateNodeBeams);
"CLEAR PATH"
Else If(Global.PathFindingStartNodeId == -1 || Global.PathFindingTargetNodeId == -1);
Call Subroutine(DeleteNodeBeams);
End;
}
}
disabled rule("SUBROUTINE: PATH FINDING SELECT NODE !!!OLD")
{
event
{
Subroutine;
PathFindingModeSelectNode;
}
actions
{
disabled Abort If(Global.BuilderTrySelectNodeInLOS == -1);
"SET START NODE"
If(Is Button Held(Event Player, Button(Primary Fire)));
Global.PathFindingStartPosition = Ray Cast Hit Position(Eye Position(Event Player), Eye Position(Event Player)
+ Facing Direction Of(Event Player) * 999, Null, Event Player, False);
Global.PathFindingStartNodeId = Global.BuilderTrySelectNodeInLOS;
"BIND EFFECT TO NODE"
disabled Global.PathFindingStartNodeEffectPos = Global.NodePositions[Global.BuilderTrySelectNodeInLOS];
"BIND EFFECT TO RAY CAST POS"
Global.PathFindingStartNodeEffectPos = Global.PathFindingStartPosition;
If(Global.PathFindingStartNodeId == Global.PathFindingTargetNodeId);
Global.PathFindingTargetNodeId = -1;
Global.PathFindingTargetNodeEffectPos = Vector(0, -999, 0);
End;
"SET TARGET NODE"
Else If(Is Button Held(Event Player, Button(Secondary Fire)));
Global.PathFindingTargetPosition = Ray Cast Hit Position(Eye Position(Event Player), Eye Position(Event Player)
+ Facing Direction Of(Event Player) * 999, Null, Event Player, False);
Global.PathFindingTargetNodeId = Global.BuilderTrySelectNodeInLOS;
"BIND EFFECT TO NODE"
disabled Global.PathFindingTargetNodeEffectPos = Global.NodePositions[Global.BuilderTrySelectNodeInLOS];
"BIND EFFECT TO RAY CAST POS"
Global.PathFindingTargetNodeEffectPos = Global.PathFindingTargetPosition;
If(Global.PathFindingTargetNodeId == Global.PathFindingStartNodeId);
Global.PathFindingStartNodeId = -1;
Global.PathFindingStartNodeEffectPos = Vector(0, -999, 0);
End;
End;
"DRAW PATH"
If(Global.PathFindingStartNodeId != -1 && Global.PathFindingTargetNodeId != -1);
Call Subroutine(PathFindingGetShortestPath);
Call Subroutine(DeleteNodeBeams);
Call Subroutine(CreateNodeBeams);
"CLEAR PATH"
Else If(Global.PathFindingStartNodeId == -1 || Global.PathFindingTargetNodeId == -1);
Call Subroutine(DeleteNodeBeams);
End;
}
}
rule("SUBROUTINE: PATH FINDING MODE RESET")
{
event
{
Subroutine;
PathFindingModeReset;
}
actions
{
Global.PathFindingStartNodeId = -1;
Global.PathFindingTargetNodeId = -1;
Global.PathFindingStartNodeEffectPos = Vector(0, -999, 0);
Global.PathFindingTargetNodeEffectPos = Vector(0, -999, 0);
Call Subroutine(DeleteNodeBeams);
}
}
rule("SUBROUTINE: DELETE NODE BEAM EFFECTS")
{
event
{
Subroutine;
DeleteNodeBeams;
}
actions
{
If(Count Of(Global.BeamEffects) > 0);
For Global Variable(LoopIterator1, 0, Count Of(Global.BeamEffects), 1);
Destroy Effect(Global.BeamEffects[Global.LoopIterator1]);
End;
Global.BeamEffects = Empty Array;
End;
}
}
rule("SUBROUTINE: CREATE NODE BEAM EFFECTS")
{
event
{
Subroutine;
CreateNodeBeams;
}
actions
{
If(Global.BuilderMode == Custom String("PATH FINDING"));
For Global Variable(LoopIterator1, 0, Count Of(Global.PathFindingResultPath) - 1, 1);
Create Beam Effect(All Players(All Teams), Bad Beam, Global.NodePositions[Global.PathFindingResultPath[Global.LoopIterator1]],
Global.NodePositions[Global.PathFindingResultPath[Global.LoopIterator1 + 1]], Global.BuilderHudColorCurrent, Visible To);
Modify Global Variable(BeamEffects, Append To Array, Last Created Entity);
End;
Else If(Global.BuilderMode == Custom String("EDIT"));
For Global Variable(LoopIterator1, 0, Count Of(Global.BuilderNodeConnections[Global.BuilderSelectedNodeId]), 1);
Create Beam Effect(All Players(All Teams), Good Beam, Global.BuilderNodePositions[Global.BuilderSelectedNodeId],
Global.BuilderNodePositions[Global.BuilderNodeConnections[Global.BuilderSelectedNodeId][Global.LoopIterator1]],
Global.BuilderHudColorEditMode, Visible To);
Modify Global Variable(BeamEffects, Append To Array, Last Created Entity);
End;
End;
}
}
rule("SUBROUTINE: PATH FINDING GET SHORTEST PATH")
{
event
{
Subroutine;
PathFindingGetShortestPath;
}
actions
{
Global.PathFindingResultPath = Empty Array;
Global.BuildProjectVisitedNodes = Empty Array;
Global.PathFindingCurrentNodeId = Global.PathFindingStartNodeId;
While(Global.PathFindingCurrentNodeId != Global.PathFindingTargetNodeId);
Modify Global Variable(PathFindingResultPath, Append To Array, Global.PathFindingCurrentNodeId);
Global.PathFindingShortestDistance = 999;
Global.BuilderInnerArray = Global.NodeConnections[Global.PathFindingCurrentNodeId];
For Global Variable(LoopIterator1, 0, Count Of(Global.BuilderInnerArray), 1);
If(Array Contains(Global.PathFindingResultPath, Global.BuilderInnerArray[Global.LoopIterator1]));
Continue;
Else If(Global.BuilderInnerArray[Global.LoopIterator1] == Global.PathFindingTargetNodeId);
Modify Global Variable(PathFindingResultPath, Append To Array, Global.PathFindingTargetNodeId);
Global.PathFindingCurrentNodeId = Global.PathFindingTargetNodeId;
Break;
End;
Global.PathFindingCurrentDistance = Global.DistanceMatrix[Global.BuilderInnerArray[Global.LoopIterator1]][Global.PathFindingTargetNodeId];
If(Global.PathFindingCurrentDistance < Global.PathFindingShortestDistance);
Global.PathFindingShortestDistance = Global.PathFindingCurrentDistance;
Global.PathFindingCurrentNodeId = Global.BuilderInnerArray[Global.LoopIterator1];
End;
End;
"IMPOSSIBLE TO REACH TARGET NODE"
If(Count Of(Global.PathFindingResultPath) > 1 && Global.PathFindingResultPath[Count Of(Global.PathFindingResultPath)
- 1] == Global.PathFindingResultPath[Count Of(Global.PathFindingResultPath) - 2]);
Small Message(All Players(All Teams), Custom String("IMPOSSIBLE TO REACH TARGET NODE {0}", Global.PathFindingTargetNodeId));
Global.PathFindingResultPath = Empty Array;
Abort;
End;
"ANTI-CRASH DELAY"
Wait(0.016, Ignore Condition);
End;
}
}
rule("SUBROUTINE: PATH FINDING CREATE TEST BOT")
{
event
{
Subroutine;
PathFindingCreateBot;
}
actions
{
If(!Entity Exists(Global.PathFindingBotId));
Create Dummy Bot(Random Value In Array(All Heroes), Opposite Team Of(Team Of(Event Player)), -1, Global.PathFindingStartPosition,
Vector(0, 0, 0));
Global.PathFindingBotId = Last Created Entity;
Set Move Speed(Global.PathFindingBotId, Global.PropertyBotMovementSpeed);
Start Forcing Dummy Bot Name(Global.PathFindingBotId, Custom String("TEST BOT"));
Else;
Start Forcing Player To Be Hero(Global.PathFindingBotId, Random Value In Array(All Heroes));
Teleport(Global.PathFindingBotId, Global.PathFindingStartPosition);
End;
Call Subroutine(PathFindingTestBotReset);
"ANTI-BUG DELAY"
Wait(0.100, Ignore Condition);
Global.PathFindingBotId.BotTargetPosition = Global.PathFindingTargetPosition;
disabled Global.PathFindingBotId.BotTargetPlayer = Event Player;
}
}
disabled rule("=== TEST BOT ===")
{
event
{
Ongoing - Global;
}
}
rule("BOT: INIT")
{
event
{
Player Joined Match;
All;
All;
}
conditions
{
Is Dummy Bot(Event Player) == True;
}
actions
{
Call Subroutine(BotResetPathFinding);
"LINE OF SIGHT TO NEXT NODE"
Create Beam Effect(All Players(All Teams), Good Beam, Update Every Frame(Position Of(Event Player) + Vector(0, 1.600, 0)),
Update Every Frame(Event Player.BotNextNodePosition + Vector(0, 2, 0)), Color(Green), Visible To Position and Radius);
"Y DIFF BETWEEN BOT POS AND NODE POS"
Create Beam Effect(All Players(All Teams), Good Beam, Update Every Frame(Position Of(Event Player)), Update Every Frame(
Position Of(Event Player) + Vector(0, 2, 0)), Color(Red), Visible To Position and Radius);
Create HUD Text(All Players(All Teams), Custom String("TEST BOT INFO\r\nCLOSEST NODE: {0}\r\nCLOSEST NODE IN LOS: {1}\r\n{2}",
Index Of Array Value(Global.NodePositions, Sorted Array(Global.NodePositions, Distance Between(Position Of(Event Player),
Current Array Element))[0]), Index Of Array Value(Global.NodePositions, Sorted Array(Filtered Array(Global.NodePositions,
Is In Line of Sight(Eye Position(Event Player), Current Array Element, Barriers Do Not Block LOS) == True), Distance Between(
Position Of(Event Player), Current Array Element))[0]), Custom String("PREV NODE {0}\r\nNEXT NODE {1}\r\n{2}",
Global.PathFindingBotId.BotPrevNodeId, Global.PathFindingBotId.BotNextNodeId, Custom String(
"TARGET NODE {0}\r\nY DIFF {1}\r\nSEE NEXT NODE {2}", Event Player.BotClosestNodeIdToTarget, Y Component Of(Position Of(
Event Player)) - Y Component Of(Global.NodePositions[Event Player.BotNextNodeId]), Is In Line of Sight(Position Of(
Event Player) + Vector(0, 1.600, 0), Global.NodePositions[Event Player.BotNextNodeId] + Vector(0, 2, 0),
Barriers Do Not Block LOS)))), Null, Null, Right, -1, Color(Purple), Color(White), Color(White), Visible To and String,
Default Visibility);
}
}
rule("SUBROUTINE: TEST BOT RESET")
{
event
{
Subroutine;
PathFindingTestBotReset;
}
actions
{
Global.PathFindingBotId.BotTargetPlayer = -1;
Global.PathFindingBotId.BotTargetPosition = -1;
Global.PathFindingBotId.BotPrevNodeId = -1;
Global.PathFindingBotId.BotClosestNodeIdToTarget = -1;
Global.PathFindingBotId.BotNextNodeId = -1;
Global.PathFindingBotId.BotNextNodePosition = -1;
Global.PathFindingBotId.BotIsPathFinding = False;
Stop Facing(Global.PathFindingBotId);
Stop Throttle In Direction(Global.PathFindingBotId);
}
}