├── Images
├── AoeShapes.png
└── DllLocation.png
├── Linqpad
├── Examples
│ ├── ForcedMovement
│ │ ├── AwayWithTheeDemo.linq
│ │ ├── KnockbackDemo.linq
│ │ └── TerrainDemo.linq
│ ├── MechanicRecursion
│ │ ├── ExaflareDemo.linq
│ │ └── InnocenceAoeDemo.linq
│ ├── RotationDemo.linq
│ ├── SimpleAoeDemo.linq
│ ├── TargetedAoeDemo.linq
│ └── TowerDemo.linq
└── MechanicSets
│ ├── AnnihilationDemo.linq
│ ├── BlackfireDemo.linq
│ ├── CircleProgramDemo.linq
│ ├── CloudOfDarknessDemo.linq
│ ├── FellruinDemo.linq
│ ├── Grand Octet.linq
│ ├── HeavensfallDemo.linq
│ ├── LightRampantDemo.linq
│ ├── LightRampantDemo2.linq
│ ├── LightRampantDemo3.linq
│ ├── LimitCutDemo.linq
│ ├── Quickmarch.linq
│ ├── RunDeltaDemo.linq
│ ├── RunSigmaDemo.linq
│ ├── SuppressionDemo.linq
│ ├── TenstrikeDemo.linq
│ ├── UcobAddsDemo.linq
│ ├── WormholeDemo.linq
│ ├── WrathOfTheHeavensDemo.linq
│ └── WyrmholeDemo.linq
├── Mechanics
├── AwayWithTheeDemo.json
├── ExaflareDemo.json
├── InnocenceAoeDemo.json
├── KnockbackDemo.json
├── RotationDemo.json
├── SimpleAoeDemo.json
├── TargetedAoeDemo.json
├── TerrainDemo.json
└── TowerDemo.json
└── README.md
/Images/AoeShapes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiv-stats/xiv-sim-documentation/f93f01c62219755ddd470db3393e15fdda29dd57/Images/AoeShapes.png
--------------------------------------------------------------------------------
/Images/DllLocation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiv-stats/xiv-sim-documentation/f93f01c62219755ddd470db3393e15fdda29dd57/Images/DllLocation.png
--------------------------------------------------------------------------------
/Linqpad/Examples/ForcedMovement/AwayWithTheeDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "AwayWithTheeDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-documentation";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "DrawIn",
17 | new MechanicProperties
18 | {
19 | visible = true,
20 | collisionShapeParams = new Vector4(0.3f, 360),
21 | colorHtml = "#d800ff99",
22 | mechanic = new ExecuteMultipleEvents
23 | {
24 | events = new List
25 | {
26 | new WaitEvent { timeToWait = 1 },
27 | new ApplyEffectToTargetOnly {
28 | effects = new List
29 | {
30 | new KnockbackEffect { knockbackDistance = 1, isDrawIn = true, additionalKnockbackSpeed = 5 },
31 | }
32 | },
33 | }
34 | }
35 | }
36 | },
37 | {
38 | "DrawInLeft",
39 | new MechanicProperties
40 | {
41 | visible = false,
42 | mechanic = new ExecuteMultipleEvents
43 | {
44 | events = new List
45 | {
46 | new ApplyEffectToTargetOnly { effect = new ApplyStatusEffect { referenceStatusName = "Stun" } },
47 | new SpawnTargetedEvents { referenceMechanicName = "DrawIn", isPositionRelative = true, isRotationRelative = true, spawnOnTarget = true, position = new Vector2(-3, 0), targetingScheme = new TargetExistingTarget() }
48 | }
49 | },
50 | }
51 | },
52 | {
53 | "LeftWithThee",
54 | new MechanicProperties
55 | {
56 | visible = false,
57 | mechanic = new ExecuteMultipleEvents
58 | {
59 | events = new List {
60 | new ApplyEffectToTargetOnly { effect = new ApplyStatusEffect { referenceStatusName = "LeftWithThee" } },
61 | new SpawnVisualObject
62 | {
63 | textureFilePath = "Mechanics/Resources/Mark1.png",
64 | colorHtml = "#d800ff",
65 | visualDuration = 5,
66 | spawnOnPlayer = true,
67 | relativePosition = new Vector3(-3, 0.6f, 0),
68 | scale = new Vector3(0.8f, 0.8f, 1),
69 | isBillboard = true
70 | },
71 | new SpawnVisualObject
72 | {
73 | textureFilePath = "Mechanics/Resources/LimitCut-1.png",
74 | colorHtml = "#d800ff99",
75 | visualDuration = 5,
76 | spawnOnPlayer = true,
77 | relativePosition = new Vector3(-3, 0.1f, 0),
78 | eulerAngles = new Vector3(90, 0, 0),
79 | },
80 | }
81 | }
82 | }
83 | }
84 | };
85 |
86 |
87 | mechanicData.referenceStatusProperties = new Dictionary
88 | {
89 | {
90 | "LeftWithThee",
91 | new SpawnMechanicOnExpire
92 | {
93 | statusIconPath = "Mechanics/Resources/LeftWithThee.png",
94 | statusName = "Larboard With Thee",
95 | statusDescription = "When this effect ends, you will be spawned and forcibly moved leftwards.",
96 | duration = 5,
97 | referenceMechanicName = "DrawInLeft"
98 | }
99 | },
100 | {
101 | "Stun",
102 | new StatusEffectData
103 | {
104 | statusIconPath = "Mechanics/Resources/Stun.png",
105 | statusName = "Stun",
106 | statusDescription = "Unable to execute actions.",
107 | duration = 3f,
108 | disableType = DisableType.Movement | DisableType.Actions
109 | }
110 | },
111 | };
112 |
113 | mechanicData.mechanicEvents = new List
114 | {
115 | new SpawnVisualObject
116 | {
117 | textureFilePath = "Mechanics/Resources/ArenaSquare4x4.png",
118 | visualDuration = float.PositiveInfinity,
119 | relativePosition = new Vector3(0, -0.001f, 0),
120 | eulerAngles = new Vector3(90, 0, 0),
121 | scale = new Vector3(15.8637f, 15.8637f, 1),
122 | },
123 | new SpawnTargetedEvents { referenceMechanicName = "LeftWithThee", targetingScheme = new TargetAllPlayers() },
124 | };
125 |
126 | var resultText = mechanicData.ToString();
127 |
128 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
129 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
130 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
131 |
132 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/Examples/ForcedMovement/KnockbackDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "KnockbackDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-documentation";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "Knockback",
17 | new MechanicProperties
18 | {
19 | collisionShape = CollisionShape.Round,
20 | collisionShapeParams = new Vector4(3, 360),
21 | colorHtml = "#ff9600",
22 | mechanic = new ExecuteMultipleEvents
23 | {
24 | events = new List
25 | {
26 | new WaitEvent { timeToWait = 3 },
27 | new ApplyEffectToPlayers {
28 | effects = new List
29 | {
30 | new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Knockback" },
31 | new KnockbackEffect { knockbackDistance = 3, canArmsLength = true },
32 | }
33 | }
34 | }
35 | }
36 | }
37 | },
38 | {
39 | "DrawIn",
40 | new MechanicProperties
41 | {
42 | collisionShape = CollisionShape.Round,
43 | collisionShapeParams = new Vector4(3, 360),
44 | colorHtml = "#0078ff",
45 | mechanic = new ExecuteMultipleEvents
46 | {
47 | events = new List
48 | {
49 | new WaitEvent { timeToWait = 3 },
50 | new ApplyEffectToPlayers {
51 | effects = new List
52 | {
53 | new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Draw In" },
54 | new KnockbackEffect { knockbackDistance = 1, isDrawIn = true, additionalKnockbackSpeed = 5 },
55 | }
56 | }
57 | }
58 | }
59 | }
60 | },
61 | };
62 |
63 | mechanicData.mechanicEvents = new List
64 | {
65 | new SpawnMechanicEvent { referenceMechanicName = "Knockback", position = new Vector2(-2, 0) },
66 | new SpawnMechanicEvent { referenceMechanicName = "DrawIn", position = new Vector2(2, 0) }
67 | };
68 |
69 | var resultText = mechanicData.ToString();
70 |
71 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
72 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
73 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
74 |
75 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/Examples/ForcedMovement/TerrainDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "TerrainDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-documentation";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "Knockback",
17 | new MechanicProperties
18 | {
19 | collisionShape = CollisionShape.Round,
20 | collisionShapeParams = new Vector4(3, 360),
21 | colorHtml = "#ff9600",
22 | mechanic = new ExecuteMultipleEvents
23 | {
24 | events = new List
25 | {
26 | new WaitEvent { timeToWait = 3 },
27 | new ApplyEffectToPlayers {
28 | effects = new List
29 | {
30 | new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Knockback" },
31 | new KnockbackEffect { knockbackDistance = 20 },
32 | }
33 | }
34 | }
35 | }
36 | }
37 | },
38 | {
39 | "Wall",
40 | new MechanicProperties
41 | {
42 | collisionShape = CollisionShape.Rectangle,
43 | collisionShapeParams = new Vector4(10, 3),
44 | colorHtml = "#0078ff",
45 | mechanic = new WaitEvent { timeToWait = float.PositiveInfinity },
46 | isTerrain = true
47 | }
48 | },
49 | };
50 |
51 | mechanicData.mechanicEvents = new List
52 | {
53 | new SpawnMechanicEvent { referenceMechanicName = "Knockback", position = new Vector2(-2, 0) },
54 | new SpawnMechanicEvent { referenceMechanicName = "Wall", position = new Vector2(4, -5) },
55 | };
56 |
57 | var resultText = mechanicData.ToString();
58 |
59 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
60 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
61 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
62 |
63 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/Examples/MechanicRecursion/ExaflareDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "ExaflareDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-documentation";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "Exaflare",
17 | new MechanicProperties
18 | {
19 | collisionShape = CollisionShape.Round,
20 | collisionShapeParams = new Vector4(1, 360),
21 | colorHtml = "#ff9600",
22 | mechanic = new ExecuteMultipleEvents
23 | {
24 | events = new List
25 | {
26 | new WaitEvent { timeToWait = 2 },
27 | new CheckMechanicDepth {
28 | expressionFormat = "{0} < 5",
29 | successEvent = new SpawnMechanicEvent { referenceMechanicName = "Exaflare", isPositionRelative = true, isRotationRelative = true, position = new Vector2(0, 1.5f) }
30 | },
31 | new WaitEvent { timeToWait = 1 },
32 | new ApplyEffectToPlayers {
33 | effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Exaflare" }
34 | }
35 | }
36 | }
37 | }
38 | },
39 | };
40 |
41 | mechanicData.mechanicEvents = new List
42 | {
43 | new SpawnMechanicEvent { referenceMechanicName = "Exaflare", position = new Vector3(0, 3) },
44 | new SpawnMechanicEvent { referenceMechanicName = "Exaflare", position = new Vector3(3, 0), rotation = 90 },
45 | new SpawnMechanicEvent { referenceMechanicName = "Exaflare", position = new Vector3(0, -3), rotation = 180 },
46 | new SpawnMechanicEvent { referenceMechanicName = "Exaflare", position = new Vector3(-3, 0), rotation = 270 },
47 | };
48 |
49 | var resultText = mechanicData.ToString();
50 |
51 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
52 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
53 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
54 |
55 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/Examples/MechanicRecursion/InnocenceAoeDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "InnocenceAoeDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-documentation";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "Donut Cone",
17 | new MechanicProperties
18 | {
19 | collisionShape = CollisionShape.Round,
20 | collisionShapeParams = new Vector4(5, 120, 3),
21 | colorHtml = "#ff9600",
22 | mechanic = new ExecuteMultipleEvents
23 | {
24 | events = new List
25 | {
26 | new WaitEvent { timeToWait = 3 },
27 | new ApplyEffectToPlayers {
28 | effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Innocence Aoe" }
29 | }
30 | }
31 | }
32 | }
33 | },
34 | {
35 | "Donut Cone Offset",
36 | new MechanicProperties
37 | {
38 | visible = false,
39 | mechanic = new ExecuteMultipleEvents
40 | {
41 | events = new List
42 | {
43 | new SpawnMechanicEvent
44 | {
45 | referenceMechanicName = "Donut Cone",
46 | isPositionRelative = true,
47 | isRotationRelative = true,
48 | position = new Vector3(4, 0),
49 | rotation = -30
50 | },
51 | new WaitEvent { timeToWait = 2 },
52 | new SpawnMechanicEvent { referenceMechanicName = "Donut Cone Offset", isPositionRelative = true, isRotationRelative = true, rotation = -25 }
53 | }
54 | }
55 | }
56 | }
57 | };
58 |
59 | mechanicData.mechanicEvents = new List
60 | {
61 | new SpawnMechanicEvent { referenceMechanicName = "Donut Cone Offset", position = new Vector2(0, 0) },
62 | new SpawnMechanicEvent { referenceMechanicName = "Donut Cone Offset", position = new Vector2(0, 0), rotation = 180 },
63 | };
64 |
65 | var resultText = mechanicData.ToString();
66 |
67 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
68 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
69 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
70 |
71 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/Examples/RotationDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "RotationDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-documentation";
10 |
11 |
12 | var planetVisual = new SpawnVisualObject
13 | {
14 | textureFilePath = "Mechanics/Resources/Cat.png",
15 | visualDuration = 6,
16 | colorHtml = "#b429bd",
17 | isBillboard = true,
18 | relativePosition = new Vector3(0, 1.5f, 0),
19 | scale = new Vector3(2, 2, 2),
20 | };
21 |
22 | var platformRotateVisuals = new List();
23 |
24 | for (int i = 0; i < 50; i++)
25 | {
26 | var angle = 360f/ 50 * i;
27 | var rads = angle * Mathf.Deg2Rad;
28 |
29 | platformRotateVisuals.Add(new SpawnVisualObject
30 | {
31 | textureFilePath = "Mechanics/Resources/Arrow.png",
32 | visualDuration = 5,
33 | colorHtml = "#2579bd",
34 | relativePosition = new Vector3(Mathf.Cos(rads), 0, Mathf.Sin(rads)) * 8 + Vector3.up,
35 | eulerAngles = new Vector3(0, 90 - angle , 0),
36 | scale = new Vector3(1, 1, 1),
37 | });
38 | }
39 |
40 | var mechanicData = new MechanicData();
41 | mechanicData.referenceMechanicProperties = new Dictionary
42 | {
43 | {
44 | "ArenaBoundary",
45 | new MechanicProperties
46 | {
47 | collisionShape = CollisionShape.Round,
48 | collisionShapeParams = new Vector4(25, 360, 7),
49 | colorHtml = "#8800FF",
50 | persistentTickInterval = 0.2f,
51 | persistentMechanic = new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 9999999, damageType = "TrueDamage" } },
52 | }
53 | },
54 | {
55 | "Explosion",
56 | new MechanicProperties
57 | {
58 | collisionShape = CollisionShape.Round,
59 | collisionShapeParams = new Vector4(12, 360),
60 | colorHtml = "#ff9600",
61 | mechanic = new ExecuteMultipleEvents
62 | {
63 | events = new List
64 | {
65 | new WaitEvent { timeToWait = 0.5f },
66 | new ApplyEffectToPlayers {
67 | effect = new DamageEffect { damageAmount = 30000, damageType = "Damage", name = "CAT-Astrophe" }
68 | }
69 | }
70 | }
71 | }
72 | },
73 | {
74 | "SnakeAOE",
75 | new MechanicProperties
76 | {
77 | collisionShape = CollisionShape.Rectangle,
78 | collisionShapeParams = new Vector4(14, 3.5f),
79 | colorHtml = "#ff9600",
80 | mechanic = new ExecuteMultipleEvents
81 | {
82 | events = new List
83 | {
84 | new WaitEvent { timeToWait = 1 },
85 | new ApplyEffectToPlayers {
86 | effect = new DamageEffect { damageAmount = 30000, damageType = "Damage", name = "Snake" }
87 | }
88 | }
89 | }
90 | }
91 | },
92 | {
93 | "SpawnPlanets",
94 | new MechanicProperties
95 | {
96 | visible = false,
97 | mechanic = new ExecuteMultipleEvents
98 | {
99 | events = new List
100 | {
101 | new SpawnEnemy {
102 | enemyName = "Doomed Stars",
103 | textureFilePath = "Mechanics/Resources/Cat.png",
104 | maxHp = 35000000,
105 | hitboxSize = 1,
106 | referenceMechanicName = "SlowPlanet",
107 | visualScale = Vector3.zero,
108 | isTargetable = false,
109 | showInEnemyList = false,
110 | },
111 | new SpawnEnemy {
112 | enemyName = "Doomed Stars",
113 | textureFilePath = "Mechanics/Resources/Cat.png",
114 | maxHp = 35000000,
115 | hitboxSize = 1,
116 | referenceMechanicName = "FastPlanet",
117 | visualScale = Vector3.zero,
118 | isTargetable = false,
119 | showInEnemyList = false,
120 | },
121 | new WaitEvent { timeToWait = 5.5f },
122 | new SpawnMechanicEvent { referenceMechanicName = "Explosion", position = new Vector2(7, 0) },
123 | }
124 | }
125 | }
126 | },
127 | {
128 | "SpawnSnakes",
129 | new MechanicProperties
130 | {
131 | visible = false,
132 | mechanic = new ExecuteMultipleEvents
133 | {
134 | events = new List
135 | {
136 | new SpawnEnemy {
137 | enemyName = "Snake",
138 | textureFilePath = "Mechanics/Resources/Snake.png",
139 | maxHp = 35000000,
140 | hitboxSize = 1,
141 | referenceMechanicName = "Snake",
142 | visualScale = Vector3.zero,
143 | isTargetable = true,
144 | showInEnemyList = false,
145 | position = new Vector2(0f, 0.01f),
146 | rotation = 90
147 | }
148 | }
149 | }
150 | }
151 | },
152 | {
153 | "Snake",
154 | new MechanicProperties
155 | {
156 | visible = false,
157 | mechanic = new ExecuteMultipleEvents
158 | {
159 | events = new List
160 | {
161 | new SpawnVisualObject
162 | {
163 | textureFilePath = "Mechanics/Resources/Snake.png",
164 | visualDuration = 7.5f,
165 | colorHtml = "#2529bd",
166 | relativePosition = new Vector3(5.25f, 1, -1.75f),
167 | eulerAngles = new Vector3(0, 180, 0),
168 | isRotationRelative = true,
169 | scale = new Vector3(2, 2, 2),
170 | },
171 | new SpawnVisualObject
172 | {
173 | textureFilePath = "Mechanics/Resources/Snake.png",
174 | visualDuration = 7.5f,
175 | colorHtml = "#2529bd",
176 | relativePosition = new Vector3(5.25f, 1, 5.25f),
177 | eulerAngles = new Vector3(0, 180, 0),
178 | isRotationRelative = true,
179 | scale = new Vector3(2, 2, 2),
180 | },
181 | new WaitEvent { timeToWait = 4 },
182 | new SetEnemyMovementPath { path = new CircleMovementPath { radius = 0.01f, degreesPerSecond = -30, startAngle = 90} },
183 | new WaitEvent { timeToWait = 3.05f },
184 | new SpawnMechanicEvent { referenceMechanicName = "SnakeAOE", position = new Vector2(7, -1.75f), rotation = -90, isPositionRelative = true, isRotationRelative = true },
185 | new SpawnMechanicEvent { referenceMechanicName = "SnakeAOE", position = new Vector2(7, 5.25f), rotation = -90, isPositionRelative = true, isRotationRelative = true },
186 | }
187 | }
188 | }
189 | },
190 | {
191 | "SlowPlanet",
192 | new MechanicProperties
193 | {
194 | visible = false,
195 | mechanic = new ExecuteMultipleEvents
196 | {
197 | events = new List
198 | {
199 | new SetEnemyMovementPath { path = new CircleMovementPath { radius = 7.5f, degreesPerSecond = 0, startAngle = -90} },
200 | planetVisual,
201 | new WaitEvent { timeToWait = 1 },
202 | new SetEnemyMovementPath { path = new CircleMovementPath { radius = 7.5f, degreesPerSecond = 18, startAngle = -90} },
203 | new WaitEvent { timeToWait = 5 },
204 | }
205 | }
206 | }
207 | },
208 | {
209 | "FastPlanet",
210 | new MechanicProperties
211 | {
212 | visible = false,
213 | mechanic = new ExecuteMultipleEvents
214 | {
215 | events = new List
216 | {
217 | new SetEnemyMovementPath { path = new CircleMovementPath { radius = 7.5f, degreesPerSecond = 0, startAngle = 180} },
218 | planetVisual,
219 | new WaitEvent { timeToWait = 1 },
220 | new SetEnemyMovementPath { path = new CircleMovementPath { radius = 7.5f, degreesPerSecond = 36, startAngle = 180} },
221 | new WaitEvent { timeToWait = 5 },
222 | }
223 | }
224 | }
225 | },
226 | {
227 | "StunPlayers",
228 | new MechanicProperties
229 | {
230 | visible = false,
231 | mechanic = new ApplyEffectToTargetOnly { effect = new ApplyStatusEffect { referenceStatusName = "Stun" } }
232 | }
233 | }
234 | };
235 |
236 | mechanicData.referenceStatusProperties = new Dictionary
237 | {
238 | {
239 | "Stun",
240 | new StatusEffectData
241 | {
242 | statusIconPath = "Mechanics/Resources/Stun.png",
243 | statusName = "Bind",
244 | statusDescription = "Unable to move.",
245 | duration = 5f,
246 | disableType = DisableType.Movement
247 | }
248 | },
249 | };
250 |
251 | mechanicData.mechanicEvents = new List
252 | {
253 | new SpawnMechanicEvent { referenceMechanicName = "ArenaBoundary" },
254 | new SpawnVisualObject
255 | {
256 | textureFilePath = "Mechanics/Resources/ArenaSquare4x4.png",
257 | visualDuration = float.PositiveInfinity,
258 | relativePosition = new Vector3(0, -0.001f, 0),
259 | eulerAngles = new Vector3(90, 0, 0),
260 | scale = new Vector3(18f, 18, 1),
261 | },
262 | new ExecuteMultipleEvents
263 | {
264 | events = new List
265 | {
266 | new SpawnMechanicEvent { referenceMechanicName = "SpawnPlanets" },
267 | new SpawnMechanicEvent { referenceMechanicName = "SpawnSnakes" },
268 |
269 | new WaitEvent { timeToWait = 2 },
270 | new ExecuteMultipleEventsParallel { events = platformRotateVisuals },
271 |
272 | new WaitEvent { timeToWait = 2 },
273 | new SpawnTargetedEvents { referenceMechanicName = "StunPlayers", targetingScheme = new TargetAllPlayers() },
274 | }
275 | }
276 | };
277 |
278 | var resultText = mechanicData.ToString();
279 |
280 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
281 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
282 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
283 |
284 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/Examples/SimpleAoeDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "SimpleAoeDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-documentation";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "Circle",
17 | new MechanicProperties
18 | {
19 | collisionShape = CollisionShape.Round,
20 | collisionShapeParams = new Vector4(1, 360),
21 | colorHtml = "#ff9600",
22 | mechanic = new ExecuteMultipleEvents
23 | {
24 | events = new List
25 | {
26 | new WaitEvent { timeToWait = 3 },
27 | new ApplyEffectToPlayers {
28 | effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Circle Aoe" }
29 | }
30 | }
31 | }
32 | }
33 | },
34 | {
35 | "Cone",
36 | new MechanicProperties
37 | {
38 | collisionShape = CollisionShape.Round,
39 | collisionShapeParams = new Vector4(1, 120),
40 | colorHtml = "#ff9600",
41 | mechanic = new ExecuteMultipleEvents
42 | {
43 | events = new List
44 | {
45 | new WaitEvent { timeToWait = 3 },
46 | new ApplyEffectToPlayers {
47 | effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Cone Aoe" }
48 | }
49 | }
50 | }
51 | }
52 | },
53 | {
54 | "Donut",
55 | new MechanicProperties
56 | {
57 | collisionShape = CollisionShape.Round,
58 | collisionShapeParams = new Vector4(2, 360, 1),
59 | colorHtml = "#ff9600",
60 | mechanic = new ExecuteMultipleEvents
61 | {
62 | events = new List
63 | {
64 | new WaitEvent { timeToWait = 3 },
65 | new ApplyEffectToPlayers {
66 | effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Donut Aoe" }
67 | }
68 | }
69 | }
70 | }
71 | },
72 | {
73 | "Donut Cone",
74 | new MechanicProperties
75 | {
76 | collisionShape = CollisionShape.Round,
77 | collisionShapeParams = new Vector4(2, 120, 1),
78 | colorHtml = "#ff9600",
79 | mechanic = new ExecuteMultipleEvents
80 | {
81 | events = new List
82 | {
83 | new WaitEvent { timeToWait = 3 },
84 | new ApplyEffectToPlayers {
85 | effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Donut Cone Aoe" }
86 | }
87 | }
88 | }
89 | }
90 | },
91 | {
92 | "Rectangle",
93 | new MechanicProperties
94 | {
95 | collisionShape = CollisionShape.Rectangle,
96 | collisionShapeParams = new Vector4(10, 1),
97 | colorHtml = "#ff9600",
98 | mechanic = new ExecuteMultipleEvents
99 | {
100 | events = new List
101 | {
102 | new WaitEvent { timeToWait = 3 },
103 | new ApplyEffectToPlayers {
104 | effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Rectangle Aoe" }
105 | }
106 | }
107 | }
108 | }
109 | },
110 | };
111 |
112 | mechanicData.mechanicEvents = new List
113 | {
114 | new SpawnMechanicEvent { referenceMechanicName = "Circle" },
115 | new SpawnMechanicEvent { referenceMechanicName = "Cone", position = new Vector2(2, 0) },
116 | new SpawnMechanicEvent { referenceMechanicName = "Donut", position = new Vector2(6, 0) },
117 | new SpawnMechanicEvent { referenceMechanicName = "Donut Cone", position = new Vector2(10, 0) },
118 | new SpawnMechanicEvent { referenceMechanicName = "Rectangle", position = new Vector2(0, 4), rotation = 90 },
119 | };
120 |
121 | var resultText = mechanicData.ToString();
122 |
123 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
124 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
125 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
126 |
127 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/Examples/TargetedAoeDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "TargetedAoeDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-documentation";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "TargetedCircle",
17 | new MechanicProperties
18 | {
19 | collisionShape = CollisionShape.Round,
20 | collisionShapeParams = new Vector4(1, 360),
21 | colorHtml = "#ff9600",
22 | isTargeted = true,
23 | followSpeed = 10000,
24 | mechanic = new ExecuteMultipleEvents
25 | {
26 | events = new List
27 | {
28 | new WaitEvent { timeToWait = 15 },
29 | new ApplyEffectToPlayers {
30 | effect = new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Circle Aoe" }
31 | },
32 | }
33 | },
34 | }
35 | },
36 | {
37 | "AimedRectangle",
38 | new MechanicProperties
39 | {
40 | collisionShape = CollisionShape.Rectangle,
41 | collisionShapeParams = new Vector4(50, 1),
42 | colorHtml = "#0196ff",
43 | isTargeted = true,
44 | mechanic = new ExecuteMultipleEvents
45 | {
46 | events = new List
47 | {
48 | new WaitEvent { timeToWait = 15 },
49 | new ApplyEffectToPlayers {
50 | effect = new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Rectangle Aoe" }
51 | },
52 | }
53 | },
54 | }
55 | },
56 | };
57 |
58 | mechanicData.mechanicEvents = new List
59 | {
60 | new SpawnTargetedEvents { referenceMechanicName = "TargetedCircle", targetingScheme = new TargetAllPlayers() },
61 | new SpawnTargetedEvents { referenceMechanicName = "AimedRectangle", targetingScheme = new TargetAllPlayers() }
62 | };
63 |
64 | var resultText = mechanicData.ToString();
65 |
66 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
67 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
68 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
69 |
70 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/Examples/TowerDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "TowerDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-documentation";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "Aoe-Green",
17 | new MechanicProperties
18 | {
19 | colorHtml = "#00ff00",
20 | }
21 | },
22 | {
23 | "Tower",
24 | new MechanicProperties
25 | {
26 | collisionShape = CollisionShape.Round,
27 | collisionShapeParams = new Vector4(1, 360),
28 | colorHtml = "#ff9600",
29 | mechanic = new ExecuteMultipleEvents
30 | {
31 | events = new List
32 | {
33 | new WaitEvent { timeToWait = 5 },
34 | new ApplyEffectToPlayers {
35 | effect = new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Tower" }
36 | },
37 | new CheckNumberOfPlayers {
38 | expressionFormat = "{0} = 1",
39 | failEvent = new SpawnMechanicEvent { referenceMechanicName = "TowerFailed", isPositionRelative = true }
40 | },
41 | }
42 | },
43 | persistentTickInterval = 0.1f,
44 | persistentMechanic = new CheckNumberOfPlayers {
45 | expressionFormat = "{0} = 1",
46 | successEvent = new ModifyMechanicEvent { referenceMechanicName = "Aoe-Green" },
47 | failEvent = new ModifyMechanicEvent { referenceMechanicName = "Tower" }
48 | },
49 | }
50 | },
51 | {
52 | "TowerFailed",
53 | new MechanicProperties
54 | {
55 | collisionShape = CollisionShape.Round,
56 | collisionShapeParams = new Vector4(3, 360),
57 | colorHtml = "#ff0000",
58 | mechanic = new ExecuteMultipleEvents
59 | {
60 | events = new List
61 | {
62 | new WaitEvent { timeToWait = 0.2f },
63 | new ApplyEffectToPlayers {
64 | effect = new DamageEffect { damageAmount = 9999999, damageType = "TrueDamage", name = "TowerFailed" }
65 | }
66 | }
67 | }
68 | }
69 | }
70 | };
71 |
72 | mechanicData.mechanicEvents = new List
73 | {
74 | new SpawnMechanicEvent { referenceMechanicName = "Tower" },
75 | };
76 |
77 | var resultText = mechanicData.ToString();
78 |
79 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
80 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
81 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
82 |
83 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/MechanicSets/BlackfireDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "BlackfireDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-mechanics";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "SnapshotDive",
17 | new MechanicProperties
18 | {
19 | isTargeted = false,
20 | }
21 | },
22 | {
23 | "SetVisible",
24 | new MechanicProperties
25 | {
26 | visible = true
27 | }
28 | },
29 | {
30 | "BahamutMechanics",
31 | new MechanicProperties
32 | {
33 | collisionShape = CollisionShape.Rectangle,
34 | collisionShapeParams = new Vector4(14, 4),
35 | colorHtml = "#0a4d8b",
36 | visible = false,
37 | isTargeted = true,
38 | mechanic = new ExecuteMultipleEvents
39 | {
40 | events = new List
41 | {
42 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Bahamut.png", colorHtml = "#0a4d8b", visualDuration = 5, relativePosition = Vector3.up, scale = new Vector3(1, 1, 1), eulerAngles = new Vector3(0, 180, 0), isRotationRelative = true },
43 | new WaitEvent { timeToWait = 2 },
44 | new ModifyMechanicEvent { referenceMechanicName = "SnapshotDive" },
45 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Mark1.png", colorHtml = "#0a4d8b", visualDuration = 4, spawnOnPlayer = true, relativePosition = Vector3.up, scale = new Vector3(1, 1, 1), isBillboard = true },
46 | new WaitEvent { timeToWait = 3.8f },
47 | new ModifyMechanicEvent { referenceMechanicName = "SetVisible" },
48 | new WaitEvent { timeToWait = 0.2f },
49 | new ApplyEffectToPlayers {
50 | effects = new List {
51 | new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Megaflare Dive" },
52 | new KnockbackEffect { knockbackDistance = 10 },
53 | }
54 | },
55 | new SpawnMechanicEvent { referenceMechanicName = "BahamutMechanics2" }
56 | }
57 | }
58 | }
59 | },
60 | {
61 | "BahamutMechanics2",
62 | new MechanicProperties {
63 | visible = false,
64 | mechanic = new ExecuteMultipleEvents
65 | {
66 | events = new List
67 | {
68 | new WaitEvent { timeToWait = 3 },
69 | new ReshufflePlayerIds(),
70 | new SpawnTargetedEvents { referenceMechanicName = "MegaflareTarget", targetingScheme =
71 | new UnionTargetingSchemes {
72 | targetingSchemes = new List {
73 | new TargetSpecificPlayerIdsByClass {classType = PlayerClassType.Tank, targetIds = new List{0} },
74 | new TargetSpecificPlayerIdsByClass {classType = PlayerClassType.Healer, targetIds = new List{0} },
75 | new TargetSpecificPlayerIdsByClass {classType = PlayerClassType.Dps, targetIds = new List{0, 1} },
76 | }
77 | }
78 | },
79 | new SpawnTargetedEvents
80 | {
81 | referenceMechanicName = "MegaflareStack",
82 | targetingScheme = new TargetRandomPlayers
83 | {
84 | numTargets = 0, // Get all players in a random order
85 | targetCondition = new CheckPlayerStatus { statusName = "MegaflareMark" }, // Filter to only players marked by megaflare
86 | totalTargetsNeeded = 1, // Select one of the players to place the stack on
87 | }
88 | },
89 | }
90 | }
91 | }
92 | },
93 | {
94 | "NaelMechanics",
95 | new MechanicProperties
96 | {
97 | visible = false,
98 | mechanic = new ExecuteMultipleEvents
99 | {
100 | events = new List
101 | {
102 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Nael.png", colorHtml = "#a917bf", visualDuration = float.PositiveInfinity, relativePosition = Vector3.up, scale = new Vector3(1, 1, 1), eulerAngles = new Vector3(0, 180, 0), isRotationRelative = true },
103 | new WaitEvent { timeToWait = 4.9f },
104 | new SpawnTargetedEvents { referenceMechanicName = "Stack", spawnOnTarget = true, isPositionRelative = true, targetingScheme = new TargetRandomPlayers() },
105 | new WaitEvent { timeToWait = 8 },
106 | new SpawnTargetedEvents { referenceMechanicName = "Hypernova", spawnOnTarget = true, isPositionRelative = true, targetingScheme = new TargetRandomPlayers() },
107 | new WaitEvent { timeToWait = 1.6f },
108 | new SpawnTargetedEvents { referenceMechanicName = "Hypernova", spawnOnTarget = true, isPositionRelative = true, targetingScheme = new TargetRandomPlayers() },
109 | new WaitEvent { timeToWait = 1.6f },
110 | new SpawnTargetedEvents { referenceMechanicName = "Hypernova", spawnOnTarget = true, isPositionRelative = true, targetingScheme = new TargetRandomPlayers() },
111 | new WaitEvent { timeToWait = 1.6f },
112 | new SpawnTargetedEvents { referenceMechanicName = "Hypernova", spawnOnTarget = true, isPositionRelative = true, targetingScheme = new TargetRandomPlayers() },
113 | }
114 | }
115 | }
116 | },
117 | {
118 | "Stack",
119 | new MechanicProperties
120 | {
121 | collisionShape = CollisionShape.Round,
122 | collisionShapeParams = new Vector4(1.4f, 360),
123 | colorHtml = "#ff60ab",
124 | mechanic = new ExecuteMultipleEvents
125 | {
126 | events = new List
127 | {
128 | new WaitEvent { timeToWait = 0.2f },
129 | new ApplyEffectToPlayers {
130 | effect = new DamageEffect { damageAmount = 700000, damageType = "Damage", name = "Thermionic Beam", maxStackAmount = 8 }
131 | }
132 | }
133 | }
134 | }
135 | },
136 | {
137 | "Hypernova",
138 | new MechanicProperties
139 | {
140 | collisionShape = CollisionShape.Round,
141 | collisionShapeParams = new Vector4(1.5f, 360),
142 | colorHtml = "#352a43",
143 | mechanic = new ExecuteMultipleEvents
144 | {
145 | events = new List
146 | {
147 | new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Hypernova" } },
148 | new WaitEvent { timeToWait = 10 },
149 | }
150 | },
151 |
152 | persistentTickInterval = 0.3f,
153 | persistentActivationDelay = 2,
154 | persistentMechanic = new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 999999, damageType = "Damage", name = "Bleed" } },
155 | }
156 | },
157 | {
158 | "TwinMechanics",
159 | new MechanicProperties
160 | {
161 | visible = false,
162 | mechanic = new ExecuteMultipleEvents
163 | {
164 | events = new List
165 | {
166 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Twintania.png", colorHtml = "#067743", visualDuration = float.PositiveInfinity, relativePosition = Vector3.up, scale = new Vector3(1, 1, 1), eulerAngles = new Vector3(0, 180, 0), isRotationRelative = true },
167 | new WaitEvent { timeToWait = 2 },
168 | new SpawnTargetedEvents { referenceMechanicName = "Liquid Hell", spawnOnTarget = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List { 0 } } },
169 | new WaitEvent { timeToWait = 1.2f },
170 | new SpawnTargetedEvents { referenceMechanicName = "Liquid Hell", spawnOnTarget = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List { 0 } } },
171 | new WaitEvent { timeToWait = 1.2f },
172 | new SpawnTargetedEvents { referenceMechanicName = "Liquid Hell", spawnOnTarget = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List { 0 } } },
173 | new WaitEvent { timeToWait = 1.2f },
174 | new SpawnTargetedEvents { referenceMechanicName = "Liquid Hell", spawnOnTarget = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List { 0 } } },
175 | new WaitEvent { timeToWait = 1.2f },
176 | new SpawnTargetedEvents { referenceMechanicName = "Liquid Hell", spawnOnTarget = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List { 0 } } },
177 | }
178 | }
179 | }
180 | },
181 | {
182 | "Liquid Hell",
183 | new MechanicProperties
184 | {
185 | collisionShape = CollisionShape.Round,
186 | collisionShapeParams = new Vector4(2, 360),
187 | colorHtml = "#ff7200",
188 | mechanic = new ExecuteMultipleEvents
189 | {
190 | events = new List
191 | {
192 | new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Liquid Hell" } },
193 | new WaitEvent { timeToWait = 12 },
194 | }
195 | },
196 | persistentTickInterval = 0.3f,
197 | persistentActivationDelay = 3,
198 | persistentMechanic = new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 999999, damageType = "Damage", name = "Burns" } },
199 | }
200 | },
201 | {
202 | "MegaflareTarget",
203 | new MechanicProperties
204 | {
205 | visible = false,
206 | mechanic = new ExecuteMultipleEvents
207 | {
208 | events = new List
209 | {
210 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Mark1.png", colorHtml = "#ff4200", visualDuration = 4, spawnOnPlayer = true, relativePosition = Vector3.up * 0.8f, scale = new Vector3(0.5f, 0.5f, 1), isBillboard = true },
211 | new ApplyEffectToTargetOnly { effect = new ApplyStatusEffect { referenceStatusName = "MegaflareMark" } }
212 | }
213 | },
214 | }
215 | },
216 | {
217 | "MegaflareStack",
218 | new MechanicProperties
219 | {
220 | collisionShape = CollisionShape.Round,
221 | collisionShapeParams = new Vector4(1.68f, 360),
222 | colorHtml = "#ff4200",
223 | isTargeted = true,
224 | followSpeed = 10000,
225 | visible = false,
226 | mechanic = new ExecuteMultipleEvents
227 | {
228 | events = new List
229 | {
230 | new WaitEvent { timeToWait = 5 },
231 | new ModifyMechanicEvent { referenceMechanicName = "SetVisible" },
232 | new ApplyEffectToPlayers {
233 | condition = new CheckPlayerStatus { statusName = "MegaflareMark" },
234 | effect = new DamageEffect { damageAmount = 350000, damageType = "Damage", name = "Megaflare", maxStackAmount = 4 },
235 | failedConditionEffect = new DamageEffect { damageAmount = 200000, damageType = "Damage", name = "Megaflare" },
236 | },
237 | }
238 | }
239 | }
240 | },
241 | {
242 | "SpawnTowers",
243 | new MechanicProperties
244 | {
245 | visible = false,
246 | mechanic = new ExecuteMultipleEvents
247 | {
248 | events = new List
249 | {
250 | new SpawnMechanicEvent { referenceMechanicName = "Tower", isPositionRelative = true, isRotationRelative = true, position = new Vector2(3.5f, 0) },
251 | new SpawnMechanicEvent { referenceMechanicName = "Tower", isPositionRelative = true, isRotationRelative = true, position = new Vector2(-3.5f, 0) },
252 | new SpawnMechanicEvent { referenceMechanicName = "Tower", isPositionRelative = true, isRotationRelative = true, position = new Vector2(0, 3.5f) },
253 | new SpawnMechanicEvent { referenceMechanicName = "Tower", isPositionRelative = true, isRotationRelative = true, position = new Vector2(0, -3.5f) }
254 | }
255 | }
256 | }
257 | },
258 | {
259 | "Tower Fail",
260 | new MechanicProperties
261 | {
262 | collisionShape = CollisionShape.Round,
263 | collisionShapeParams = new Vector4(50, 360),
264 | colorHtml = "#FF0000",
265 | mechanic = new ExecuteMultipleEvents
266 | {
267 | events = new List
268 | {
269 | new WaitEvent { timeToWait = 0.2f },
270 | new ApplyEffectToPlayers {
271 | effect = new DamageEffect { damageAmount = 9999999, damageType = "Damage", name = "Tower Failed" }
272 | }
273 | }
274 | }
275 | }
276 | },
277 | {
278 | "Tower",
279 | new MechanicProperties
280 | {
281 | collisionShape = CollisionShape.Round,
282 | collisionShapeParams = new Vector4(1, 360),
283 | colorHtml = "#FFFF00",
284 | mechanic = new ExecuteMultipleEvents
285 | {
286 | events = new List
287 | {
288 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Tower.png", colorHtml = "#FFFF00", visualDuration = 8, relativePosition = Vector3.up, scale = new Vector3(1, 1.8876f, 1) * 0.6f, eulerAngles = new Vector3(0, 0, 0) },
289 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Tower.png", colorHtml = "#FFFF00", visualDuration = 8, relativePosition = Vector3.up, scale = new Vector3(1, 1.8876f, 1) * 0.6f, eulerAngles = new Vector3(0, 90, 0) },
290 | new WaitEvent { timeToWait = 8 },
291 | new CheckNumberOfPlayers
292 | {
293 | expressionFormat = "{0} >= 1",
294 | failEvent = new SpawnMechanicEvent { referenceMechanicName = "Tower Fail", isPositionRelative = true }
295 | },
296 | new ApplyEffectToPlayers {
297 | effect = new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Megaflare" }
298 | }
299 | }
300 | }
301 | }
302 | },
303 | {
304 | "ArenaBoundary",
305 | new MechanicProperties
306 | {
307 | collisionShape = CollisionShape.Round,
308 | collisionShapeParams = new Vector4(25, 360, 7),
309 | colorHtml = "#8800FF",
310 | persistentTickInterval = 0.2f,
311 | persistentMechanic = new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 9999999, damageType = "TrueDamage" } },
312 | }
313 | },
314 | {
315 | "SpawnBosses",
316 | new MechanicProperties
317 | {
318 | visible = false,
319 | mechanic = new ExecuteMultipleEvents
320 | {
321 | events = new List
322 | {
323 | new WaitEvent { timeToWait = 2 },
324 | new SpawnTargetedEvents { referenceMechanicName = "BahamutMechanics", position = new Vector2(0, 7), isPositionRelative = true, isRotationRelative = true, targetingScheme = new TargetRandomPlayers() },
325 | new SpawnMechanicEvent { referenceMechanicName = "TwinMechanics", position = new Vector2(-5, -5), isPositionRelative = true, isRotationRelative = true, rotation = 60 },
326 | new SpawnMechanicEvent { referenceMechanicName = "NaelMechanics", position = new Vector2(5, -5), isPositionRelative = true, isRotationRelative = true, rotation = -60 },
327 | new WaitEvent { timeToWait = 8 },
328 | new SpawnMechanicEvent { referenceMechanicName = "SpawnTowers", isRotationRelative = true },
329 | }
330 | }
331 | }
332 | },
333 | {
334 | "SpawnBossesB",
335 | new MechanicProperties
336 | {
337 | visible = false,
338 | mechanic = new ExecuteMultipleEvents
339 | {
340 | events = new List
341 | {
342 | new WaitEvent { timeToWait = 2 },
343 | new SpawnTargetedEvents { referenceMechanicName = "BahamutMechanics", position = new Vector2(0, 7), isPositionRelative = true, isRotationRelative = true, targetingScheme = new TargetRandomPlayers() },
344 | new SpawnMechanicEvent { referenceMechanicName = "NaelMechanics", position = new Vector2(-5, -5), isPositionRelative = true, isRotationRelative = true, rotation = 60 },
345 | new SpawnMechanicEvent { referenceMechanicName = "TwinMechanics", position = new Vector2(5, -5), isPositionRelative = true, isRotationRelative = true, rotation = -60 },
346 | new WaitEvent { timeToWait = 8 },
347 | new SpawnMechanicEvent { referenceMechanicName = "SpawnTowers", isRotationRelative = true },
348 | }
349 | }
350 | }
351 | },
352 | };
353 |
354 | mechanicData.referenceStatusProperties = new Dictionary
355 | {
356 | {
357 | "MegaflareMark",
358 | new StatusEffectData
359 | {
360 | statusName = "MegaflareMark",
361 | statusDescription = "Chosen to share the Megaflare stack.",
362 | duration = 7,
363 | }
364 | }
365 | };
366 |
367 | mechanicData.mechanicPools = new Dictionary>
368 | {
369 | {
370 | "BossPool",
371 | new List {
372 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses" },
373 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = 45 },
374 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = 90 },
375 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = 135 },
376 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = 180 },
377 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = 225 },
378 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = 270 },
379 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = 315 },
380 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBossesB" },
381 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBossesB", rotation = 45 },
382 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBossesB", rotation = 90 },
383 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBossesB", rotation = 135 },
384 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBossesB", rotation = 180 },
385 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBossesB", rotation = 225 },
386 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBossesB", rotation = 270 },
387 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBossesB", rotation = 315 },
388 | }
389 | }
390 | };
391 |
392 | mechanicData.mechanicEvents = new List
393 | {
394 | new SpawnVisualObject
395 | {
396 | textureFilePath = "Mechanics/Resources/ArenaCircle.png",
397 | visualDuration = float.PositiveInfinity,
398 | relativePosition = new Vector3(0, -0.001f, 0),
399 | eulerAngles = new Vector3(90, 0, 0),
400 | scale = new Vector3(15.8637f, 15.8637f, 1),
401 | },
402 | new SpawnMechanicEvent { referenceMechanicName = "ArenaBoundary" },
403 | new ExecuteRandomEvents { mechanicPoolName = "BossPool" }
404 | };
405 |
406 | var resultText = mechanicData.ToString();
407 |
408 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
409 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
410 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
411 |
412 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/MechanicSets/CircleProgramDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "CircleProgramDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-mechanics";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "OmegaMechanics",
17 | new MechanicProperties
18 | {
19 | visible = false,
20 | mechanic = new ExecuteMultipleEvents
21 | {
22 | events = new List
23 | {
24 | new WaitForAggro(),
25 | new WaitEvent { timeToWait = 3 },
26 | new StartCastBar { castName = "Circle Program", duration = 5},
27 | new WaitEvent { timeToWait = 5 },
28 | new SpawnTargetedEvents { referenceMechanicName = "AutoAttack", targetingScheme = new TargetNthHighestAggro() },
29 | new SpawnTargetedEvents {referenceMechanicName = "Looper-1", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {0, 1} } },
30 | new SpawnTargetedEvents {referenceMechanicName = "Looper-2", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {2, 3} } },
31 | new SpawnTargetedEvents {referenceMechanicName = "Looper-3", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {4, 5} } },
32 | new SpawnTargetedEvents {referenceMechanicName = "Looper-4", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {6, 7} } },
33 | new ReshufflePlayerIds(),
34 | new WaitEvent { timeToWait = 3 },
35 | new SpawnTargetedEvents { referenceMechanicName = "AutoAttack", targetingScheme = new TargetNthHighestAggro() },
36 | new WaitEvent { timeToWait = 1 },
37 | new ExecuteRandomEvents { mechanicPoolName = "Towers-Pool" },
38 | new WaitEvent { timeToWait = 1 },
39 | new SpawnTethersToPlayers { referenceTetherName = "Blaster", tetherOffset = new Vector3(0, 1, 0), targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {0, 1} } },
40 | new StartCastBar { castName = "Blaster", duration = 8},
41 | new WaitEvent { timeToWait = 9 },
42 | new StartCastBar { castName = "", duration = 100000 },
43 | new SpawnTargetedEvents { referenceMechanicName = "TetherAoe", targetingScheme = new TargetTetheredPlayers(), spawnOnTarget = true },
44 | new WaitEvent { timeToWait = 9 },
45 | new SpawnTargetedEvents { referenceMechanicName = "TetherAoe", targetingScheme = new TargetTetheredPlayers(), spawnOnTarget = true },
46 | new WaitEvent { timeToWait = 9 },
47 | new SpawnTargetedEvents { referenceMechanicName = "TetherAoe", targetingScheme = new TargetTetheredPlayers(), spawnOnTarget = true },
48 | new WaitEvent { timeToWait = 9 },
49 | new SpawnTargetedEvents { referenceMechanicName = "TetherAoe", targetingScheme = new TargetTetheredPlayers(), spawnOnTarget = true },
50 | new WaitEvent {timeToWait = float.PositiveInfinity }
51 | }
52 | }
53 | }
54 | },
55 | {
56 | "TetherAoe" ,
57 | new MechanicProperties
58 | {
59 | collisionShape = CollisionShape.Round,
60 | collisionShapeParams = new Vector4(5, 360),
61 | colorHtml = "#614879",
62 | mechanic = new ExecuteMultipleEvents
63 | {
64 | events = new List
65 | {
66 | new WaitEvent { timeToWait = 0.2f },
67 | new ApplyEffectToPlayers {
68 | condition = new CheckPlayerIsMechanicTarget(),
69 | effects = new List
70 | {
71 | new DamageEffect { damageAmount = 60000, damageType = "Damage", name = "Blaster" },
72 | new ApplyStatusEffect { referenceStatusName = "HpDown" },
73 | new ApplyStatusEffect { referenceStatusName = "DoomStack" },
74 | },
75 | failedConditionEffects = new List
76 | {
77 | new DamageEffect { damageAmount = 999999, damageType = "TrueDamage", name = "Blaster" },
78 | new ApplyStatusEffect { referenceStatusName = "HpDown" },
79 | new ApplyStatusEffect { referenceStatusName = "DoomStack" },
80 | }
81 | }
82 | }
83 | }
84 | }
85 | },
86 | {
87 | "ArenaBoundary",
88 | new MechanicProperties
89 | {
90 | collisionShape = CollisionShape.Round,
91 | collisionShapeParams = new Vector4(25, 360, 6.67f),
92 | colorHtml = "#8800FF",
93 | persistentTickInterval = 0.2f,
94 | persistentMechanic = new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 9999999, damageType = "TrueDamage" } },
95 | }
96 | },
97 | {
98 | "Tower Fail",
99 | new MechanicProperties
100 | {
101 | collisionShape = CollisionShape.Round,
102 | collisionShapeParams = new Vector4(50, 360),
103 | colorHtml = "#FF0000",
104 | mechanic = new ExecuteMultipleEvents
105 | {
106 | events = new List
107 | {
108 | new WaitEvent { timeToWait = 0.2f },
109 | new ApplyEffectToPlayers {
110 | effect = new DamageEffect { damageAmount = 9999999, damageType = "Damage", name = "Tower Failed" }
111 | }
112 | }
113 | }
114 | }
115 | },
116 | {
117 | "Tower",
118 | new MechanicProperties
119 | {
120 | collisionShape = CollisionShape.Round,
121 | collisionShapeParams = new Vector4(1, 360),
122 | colorHtml = "#FFFF00",
123 | mechanic = new ExecuteMultipleEvents
124 | {
125 | events = new List
126 | {
127 | new WaitEvent { timeToWait = 10 },
128 | new CheckNumberOfPlayers
129 | {
130 | expressionFormat = "{0} = 1",
131 | failEvent = new SpawnMechanicEvent { referenceMechanicName = "Tower Fail", isPositionRelative = true }
132 | },
133 | new ApplyEffectToPlayers {
134 | condition = new CheckPlayerStatus
135 | {
136 | statusName = "Circle Program",
137 | },
138 | effects = new List
139 | {
140 | new DamageEffect { damageAmount = 60000, damageType = "Damage", name = "Circle Program" },
141 | new RemoveStatusEffect { referenceStatusName = "Looper-1", doExpireEvent = false },
142 | new RemoveStatusEffect { referenceStatusName = "Looper-1", doExpireEvent = false },
143 | new RemoveStatusEffect { referenceStatusName = "Looper-2", doExpireEvent = false },
144 | new RemoveStatusEffect { referenceStatusName = "Looper-2", doExpireEvent = false },
145 | new RemoveStatusEffect { referenceStatusName = "Looper-3", doExpireEvent = false },
146 | new RemoveStatusEffect { referenceStatusName = "Looper-3", doExpireEvent = false },
147 | new RemoveStatusEffect { referenceStatusName = "Looper-4", doExpireEvent = false },
148 | new RemoveStatusEffect { referenceStatusName = "Looper-4", doExpireEvent = false },
149 | new RemoveStatusEffect { referenceStatusName = "Line-1" },
150 | new RemoveStatusEffect { referenceStatusName = "Line-1" },
151 | new RemoveStatusEffect { referenceStatusName = "Line-2" },
152 | new RemoveStatusEffect { referenceStatusName = "Line-2" },
153 | new RemoveStatusEffect { referenceStatusName = "Line-3" },
154 | new RemoveStatusEffect { referenceStatusName = "Line-3" },
155 | new RemoveStatusEffect { referenceStatusName = "Line-4" },
156 | new RemoveStatusEffect { referenceStatusName = "Line-4" },
157 | },
158 | failedConditionEffect = new DamageEffect { damageAmount = 120000, damageType = "Damage", name = "Circle Program" }
159 | }
160 | }
161 | }
162 | }
163 | },
164 | {
165 | "Tower-Offset",
166 | new MechanicProperties {
167 | visible = false,
168 | mechanic = new SpawnMechanicEvent {referenceMechanicName = "Tower", isPositionRelative = true, isRotationRelative = true, position = Vector3.right * 4.5f }
169 | }
170 | },
171 | {
172 | "TowerSet-A",
173 | new MechanicProperties
174 | {
175 | visible = false,
176 | mechanic = new ExecuteMultipleEvents
177 | {
178 | events = new List
179 | {
180 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true},
181 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 90},
182 | new WaitEvent { timeToWait = 9 },
183 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 180},
184 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 270},
185 | new WaitEvent { timeToWait = 9 },
186 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true},
187 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 90},
188 | new WaitEvent { timeToWait = 9 },
189 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 180},
190 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 270},
191 | }
192 | }
193 | }
194 | },
195 | {
196 | "TowerSet-B",
197 | new MechanicProperties
198 | {
199 | visible = false,
200 | mechanic = new ExecuteMultipleEvents
201 | {
202 | events = new List
203 | {
204 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true},
205 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 180},
206 | new WaitEvent { timeToWait = 9 },
207 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 90},
208 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 270},
209 | new WaitEvent { timeToWait = 9 },
210 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true},
211 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 180},
212 | new WaitEvent { timeToWait = 9 },
213 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 90},
214 | new SpawnMechanicEvent {referenceMechanicName = "Tower-Offset", isPositionRelative = true, isRotationRelative = true, rotation = 270},
215 | }
216 | }
217 | }
218 | },
219 | {
220 | "Looper",
221 | new MechanicProperties
222 | {
223 | visible = false,
224 | mechanic = new ApplyEffectToTargetOnly
225 | {
226 | effect = new DamageEffect { damageAmount = 99999999, damageType = "TrueDamage", name = "Circle Program" }
227 | }
228 | }
229 | },
230 | {
231 | "ApplyDoom",
232 | new MechanicProperties
233 | {
234 | visible = false,
235 | mechanic = new ApplyEffectToTargetOnly
236 | {
237 | effects = new List {
238 | new ApplyStatusEffect { referenceStatusName = "Doom" },
239 | new RemoveStatusEffect { referenceStatusName = "DoomStack" },
240 | }
241 | }
242 | }
243 | },
244 | {
245 | "Doom",
246 | new MechanicProperties
247 | {
248 | visible = false,
249 | mechanic = new ApplyEffectToTargetOnly
250 | {
251 | effect = new DamageEffect { damageAmount = 99999999, damageType = "TrueDamage", name = "Doom" }
252 | }
253 | }
254 | },
255 | {
256 | "AutoAttack",
257 | new MechanicProperties
258 | {
259 | visible = false,
260 | mechanic = new ApplyEffectToTargetOnly
261 | {
262 | effect = new DamageEffect { damageAmount = 100000, damageType = "Damage" }
263 | }
264 | }
265 | },
266 | {
267 | "StartButton",
268 | new MechanicProperties
269 | {
270 | collisionShape = CollisionShape.Round,
271 | collisionShapeParams = new Vector4(0.5f, 360),
272 | colorHtml = "#00ff00",
273 | persistentTickInterval = 0.1f,
274 | persistentActivationDelay = 1,
275 | mechanicTag = "StartButton",
276 | persistentMechanic = new CheckNumberOfPlayers
277 | {
278 | expressionFormat = "{0} = 0",
279 | failEvent = new ExecuteMultipleEvents{
280 | events = new List {
281 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses" },
282 | new ClearMechanicsWithTag { mechanicTag = "StartButton" },
283 | }
284 | }
285 | },
286 | }
287 | },
288 | {
289 | "SpawnBosses",
290 | new MechanicProperties
291 | {
292 | visible = false,
293 | mechanic = new ExecuteMultipleEvents
294 | {
295 | events = new List
296 | {
297 | new SpawnEnemy {
298 | enemyName = "Omega",
299 | textureFilePath = "Mechanics/Resources/Omega.png",
300 | colorHtml = "#0a4d8b",
301 | maxHp = 35000000,
302 | baseMoveSpeed = 2,
303 | hitboxSize = 10,
304 | visualPosition = new Vector3(0, 1.5f, 0),
305 | visualScale = Vector3.one * 4,
306 | referenceMechanicName = "OmegaMechanics",
307 | position = new Vector2(0, 0),
308 | isPositionRelative = true,
309 | isRotationRelative = true,
310 | },
311 | }
312 | }
313 | }
314 | },
315 | };
316 |
317 | mechanicData.referenceTetherProperties = new Dictionary
318 | {
319 | {
320 | "Blaster",
321 | new TetherProperties
322 | {
323 | colorHtml = "#ff8400",
324 | tetherDuration = 99,
325 | interceptMechanic = new SwitchTetheredPlayer(),
326 | oneTetherPerPlayer = true,
327 | tetherTag = "Blaster",
328 | retargetRandomPlayerOnDeath = true
329 | }
330 | },
331 | };
332 |
333 | mechanicData.referenceStatusProperties = new Dictionary
334 | {
335 | {
336 | "HpDown",
337 | new DamageModifier
338 | {
339 | statusIconPath = "Mechanics/Resources/HpDown.png",
340 | statusName = "HP Down",
341 | statusDescription = "This is actually just a vuln.",
342 | damageMultiplier = 100,
343 | duration = 10,
344 | }
345 | },
346 | {
347 | "DoomStack",
348 | new SpawnMechanicOnReachStacks
349 | {
350 | statusIconPath = "Mechanics/Resources/DoomStack.png",
351 | statusName = "Twice-come Ruin",
352 | statusDescription = "Too many stacks will result in Doom.",
353 | referenceMechanicName = "ApplyDoom",
354 | requiredStacks = 2,
355 | maxStacks = 2,
356 | duration = 40,
357 | }
358 | },
359 | {
360 | "Doom",
361 | new SpawnMechanicOnExpire
362 | {
363 | statusIconPath = "Mechanics/Resources/Doom.png",
364 | statusName = "Doom",
365 | statusDescription = "Certain death when counter reaches zero.",
366 | referenceMechanicName = "Doom",
367 | duration = 3,
368 | }
369 | },
370 | };
371 |
372 | mechanicData.mechanicEvents = new List
373 | {
374 | new SpawnMechanicEvent { referenceMechanicName = "ArenaBoundary" },
375 | new SpawnVisualObject
376 | {
377 | textureFilePath = "Mechanics/Resources/ArenaCircle.png",
378 | visualDuration = float.PositiveInfinity,
379 | relativePosition = new Vector3(0, -0.001f, 0),
380 | eulerAngles = new Vector3(90, 0, 0),
381 | scale = new Vector3(15.0931f, 15.0931f, 1),
382 | },
383 | new ExecuteMultipleEvents
384 | {
385 | events = new List
386 | {
387 | new SpawnMechanicEvent { referenceMechanicName = "StartButton", position = new Vector2(0, 3) },
388 | }
389 | }
390 | };
391 |
392 | var towerPool = new List();
393 | for (int i = 0; i < 12; i++)
394 | {
395 | towerPool.Add(new SpawnMechanicEvent { referenceMechanicName = "TowerSet-A", rotation = 45 + 30 * i });
396 | towerPool.Add(new SpawnMechanicEvent { referenceMechanicName = "TowerSet-B", rotation = 45 + 30 * i });
397 | }
398 |
399 | mechanicData.mechanicPools = new Dictionary>
400 | {
401 | {"Towers-Pool", towerPool},
402 | };
403 |
404 | var lineNames = new string[] { "Zero", "First", "Second", "Third", "Fourth" };
405 |
406 | for (int i = 1; i <= 4; i++)
407 | {
408 | mechanicData.referenceStatusProperties[$"Looper-{i}"] = new SpawnMechanicOnExpire
409 | {
410 | statusIconPath = "Mechanics/Resources/Looper.png",
411 | statusName = "Circle Program",
412 | statusDescription = "Certain death if not cleansed by a tower.",
413 | duration = i * 10 + 7,
414 | referenceMechanicName = "Looper",
415 | shouldKeepOnDeath = false,
416 | allowDuplicates = true,
417 | };
418 | mechanicData.referenceStatusProperties[$"Line-{i}"] = new StatusEffectData
419 | {
420 | statusIconPath = $"Mechanics/Resources/Line{i}.png",
421 | statusName = $"{lineNames[i]} in Line",
422 | statusDescription = $"Marked as target #{i}.",
423 | duration = i * 10 + 7,
424 | shouldKeepOnDeath = false,
425 | allowDuplicates = true,
426 | };
427 | mechanicData.referenceMechanicProperties[$"Looper-{i}"] = new MechanicProperties
428 | {
429 | visible = false,
430 | mechanic = new ExecuteMultipleEvents
431 | {
432 | events = new List
433 | {
434 | new ApplyEffectToTargetOnly { effect = new ApplyStatusEffect { referenceStatusName = $"Looper-{i}" } },
435 | new ApplyEffectToTargetOnly { effect = new ApplyStatusEffect { referenceStatusName = $"Line-{i}" } },
436 | }
437 | }
438 | };
439 | }
440 |
441 | var resultText = mechanicData.ToString();
442 |
443 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
444 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
445 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
446 |
447 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/MechanicSets/FellruinDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "FellruinDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-mechanics";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "BahamutMechanics",
17 | new MechanicProperties
18 | {
19 | visible = false,
20 | mechanic = new ExecuteMultipleEvents
21 | {
22 | events = new List
23 | {
24 | new WaitEvent { timeToWait = 6 },
25 | new SpawnTethersToPlayers { referenceTetherName = "TempestWing", tetherOffset = new Vector3(0, 1, 0), targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {0, 1} } },
26 | new WaitEvent { timeToWait = 8 },
27 | new SpawnTargetedEvents { referenceMechanicName = "TetherAoe", targetingScheme = new TargetTetheredPlayers(), spawnOnTarget = true },
28 | new SpawnMechanicEvent { referenceMechanicName = "Raidwide1" },
29 | new WaitEvent {timeToWait = float.PositiveInfinity }
30 | }
31 | }
32 | }
33 | },
34 | {
35 | "TwintaniaMechanics",
36 | new MechanicProperties
37 | {
38 | visible = false,
39 | mechanic = new ExecuteMultipleEvents
40 | {
41 | events = new List
42 | {
43 | new WaitEvent {timeToWait = float.PositiveInfinity }
44 | }
45 | }
46 | }
47 | },
48 | {
49 | "NaelMechanics",
50 | new MechanicProperties
51 | {
52 | visible = false,
53 | mechanic = new ExecuteMultipleEvents
54 | {
55 | events = new List
56 | {
57 | new WaitEvent {timeToWait = 1},
58 | new ExecuteRandomEventSequence { mechanicPoolName = "Quote-Pool" },
59 | new WaitEvent {timeToWait = 7},
60 | new ReshufflePlayerIds(),
61 | new SpawnTargetedEvents { referenceMechanicName = "SpreadAoe", spawnOnTarget = true, targetingScheme = new TargetSpecificPlayerIds {targetIds = new List{0, 1, 2, 3} } },
62 | new WaitEvent {timeToWait = float.PositiveInfinity }
63 | }
64 | }
65 | }
66 | },
67 | {
68 | "Neurolink",
69 | new MechanicProperties
70 | {
71 | collisionShape = CollisionShape.Round,
72 | collisionShapeParams = new Vector4(0.4f, 360),
73 | colorHtml = "#9cff00",
74 |
75 | persistentTickInterval = 0.2f,
76 | persistentMechanic = new ApplyEffectToPlayers { effect = new ApplyStatusEffect { referenceStatusName = "Neurolink" } },
77 | }
78 | },
79 | {
80 | "Dynamo",
81 | new MechanicProperties
82 | {
83 | collisionShape = CollisionShape.Round,
84 | collisionShapeParams = new Vector4(8, 360, 2f),
85 | colorHtml = "#910044",
86 | mechanic = new ExecuteMultipleEvents
87 | {
88 | events = new List
89 | {
90 | new WaitEvent { timeToWait = 0.2f },
91 | new ApplyEffectToPlayers {
92 | effect = new DamageEffect { damageAmount = 300000, damageType = "Damage", name = "Lunar Dynamo" }
93 | }
94 | }
95 | }
96 | }
97 | },
98 | {
99 | "Dive",
100 | new MechanicProperties
101 | {
102 | collisionShape = CollisionShape.Round,
103 | collisionShapeParams = new Vector4(1.5f, 360),
104 | colorHtml = "#370091",
105 | mechanic = new ExecuteMultipleEvents
106 | {
107 | events = new List
108 | {
109 | new WaitEvent { timeToWait = 0.2f },
110 | new ApplyEffectToPlayers {
111 | condition = new CheckPlayerIsMechanicTarget(),
112 | effects = new List
113 | {
114 | new DamageEffect { damageAmount = 40000, damageType = "Damage", name = "Raven's Dive" },
115 | },
116 | failedConditionEffects = new List
117 | {
118 | new DamageEffect { damageAmount = 40000, damageType = "Damage", name = "Raven's Dive" },
119 | new KnockbackEffect { knockbackDistance = 10},
120 | }
121 | }
122 | }
123 | }
124 | }
125 | },
126 | {
127 | "SpreadAoe" ,
128 | new MechanicProperties
129 | {
130 | collisionShape = CollisionShape.Round,
131 | collisionShapeParams = new Vector4(1.5f, 360),
132 | colorHtml = "#dcdcdc",
133 | mechanic = new ExecuteMultipleEvents
134 | {
135 | events = new List
136 | {
137 | new WaitEvent { timeToWait = 0.2f },
138 | new ApplyEffectToPlayers {
139 | effect = new DamageEffect { damageAmount = 80000, damageType = "Damage", name = "Meteor Stream" }
140 | }
141 | }
142 | }
143 | }
144 | },
145 | {
146 | "TetherAoe" ,
147 | new MechanicProperties
148 | {
149 | collisionShape = CollisionShape.Round,
150 | collisionShapeParams = new Vector4(1.5f, 360),
151 | colorHtml = "#59ce85",
152 | mechanic = new ExecuteMultipleEvents
153 | {
154 | events = new List
155 | {
156 | new WaitEvent { timeToWait = 0.2f },
157 | new ApplyEffectToPlayers {
158 | condition = new CheckPlayerIsMechanicTarget(),
159 | effects = new List
160 | {
161 | new DamageEffect { damageAmount = 120000, damageType = "Damage", name = "Tempest Wing" },
162 | },
163 | failedConditionEffects = new List
164 | {
165 | new DamageEffect { damageAmount = 120000, damageType = "Damage", name = "Tempest Wing" },
166 | new KnockbackEffect { knockbackDistance = 10},
167 | }
168 | }
169 | }
170 | }
171 | }
172 | },
173 | {
174 | "Raidwide1",
175 | new MechanicProperties
176 | {
177 | collisionShape = CollisionShape.Round,
178 | collisionShapeParams = new Vector4(100, 360),
179 | visible = false,
180 | mechanic = new ExecuteMultipleEvents
181 | {
182 | events = new List
183 | {
184 | new ApplyEffectToPlayers {
185 | condition = new CheckPlayerStatus { statusName = "Neurolink" },
186 | effect = new DamageEffect { damageAmount = 80000, damageType = "Magic", name = "Aetheric Profusion" },
187 | failedConditionEffect = new DamageEffect { damageAmount = 800000, damageType = "Magic", name = "Aetheric Profusion" },
188 | }
189 | }
190 | }
191 | }
192 | },
193 | {
194 | "SpawnBosses-A",
195 | new MechanicProperties
196 | {
197 | visible = false,
198 | mechanic = new ExecuteMultipleEvents
199 | {
200 | events = new List
201 | {
202 | new SpawnEnemy {
203 | enemyName = "Bahamut",
204 | textureFilePath = "Mechanics/Resources/Bahamut.png",
205 | colorHtml = "#0a4d8b",
206 | maxHp = 35000000,
207 | baseMoveSpeed = 2,
208 | hitboxSize = 2,
209 | visualPosition = new Vector3(0, 1, 0),
210 | visualScale = Vector3.one,
211 | referenceMechanicName = "BahamutMechanics",
212 | position = new Vector2(0, -3.7f),
213 | isPositionRelative = true,
214 | isRotationRelative = true,
215 | isTargetable = false,
216 | },
217 | new SpawnEnemy {
218 | enemyName = "Nael Deus Darnus",
219 | textureFilePath = "Mechanics/Resources/Nael.png",
220 | colorHtml = "#a917bf",
221 | maxHp = 35000000,
222 | baseMoveSpeed = 2,
223 | hitboxSize = 2,
224 | visualPosition = new Vector3(0, 1, 0),
225 | visualScale = Vector3.one,
226 | referenceMechanicName = "NaelMechanics",
227 | position = new Vector2(3.7f * 0.866f, 1.85f),
228 | rotation = 240,
229 | isPositionRelative = true,
230 | isRotationRelative = true,
231 | isTargetable = false
232 | },
233 | new SpawnEnemy {
234 | enemyName = "Twintania",
235 | textureFilePath = "Mechanics/Resources/Twintania.png",
236 | colorHtml = "#067743",
237 | maxHp = 35000000,
238 | baseMoveSpeed = 2,
239 | hitboxSize = 2,
240 | visualPosition = new Vector3(0, 1, 0),
241 | visualScale = Vector3.one,
242 | referenceMechanicName = "TwintaniaMechanics",
243 | position = new Vector2(-3.7f * 0.866f, 1.85f),
244 | rotation = 120,
245 | isPositionRelative = true,
246 | isRotationRelative = true,
247 | isTargetable = false
248 | },
249 | }
250 | }
251 | }
252 | },
253 | {
254 | "SpawnBosses-B",
255 | new MechanicProperties
256 | {
257 | visible = false,
258 | mechanic = new ExecuteMultipleEvents
259 | {
260 | events = new List
261 | {
262 | new SpawnEnemy {
263 | enemyName = "Bahamut",
264 | textureFilePath = "Mechanics/Resources/Bahamut.png",
265 | colorHtml = "#0a4d8b",
266 | maxHp = 35000000,
267 | baseMoveSpeed = 2,
268 | hitboxSize = 2,
269 | visualPosition = new Vector3(0, 1, 0),
270 | visualScale = Vector3.one,
271 | referenceMechanicName = "BahamutMechanics",
272 | position = new Vector2(0, -3.7f),
273 | isPositionRelative = true,
274 | isRotationRelative = true,
275 | isTargetable = false,
276 | },
277 | new SpawnEnemy {
278 | enemyName = "Nael Deus Darnus",
279 | textureFilePath = "Mechanics/Resources/Nael.png",
280 | colorHtml = "#a917bf",
281 | maxHp = 35000000,
282 | baseMoveSpeed = 2,
283 | hitboxSize = 2,
284 | visualPosition = new Vector3(0, 1, 0),
285 | visualScale = Vector3.one,
286 | referenceMechanicName = "NaelMechanics",
287 | position = new Vector2(-3.7f * 0.866f, 1.85f),
288 | rotation = 120,
289 | isPositionRelative = true,
290 | isRotationRelative = true,
291 | isTargetable = false
292 | },
293 | new SpawnEnemy {
294 | enemyName = "Twintania",
295 | textureFilePath = "Mechanics/Resources/Twintania.png",
296 | colorHtml = "#067743",
297 | maxHp = 35000000,
298 | baseMoveSpeed = 2,
299 | hitboxSize = 2,
300 | visualPosition = new Vector3(0, 1, 0),
301 | visualScale = Vector3.one,
302 | referenceMechanicName = "TwintaniaMechanics",
303 | position = new Vector2(3.7f * 0.866f, 1.85f),
304 | rotation = 240,
305 | isPositionRelative = true,
306 | isRotationRelative = true,
307 | isTargetable = false
308 | },
309 | }
310 | }
311 | }
312 | },
313 | {
314 | "ArenaBoundary",
315 | new MechanicProperties
316 | {
317 | collisionShape = CollisionShape.Round,
318 | collisionShapeParams = new Vector4(25, 360, 7),
319 | colorHtml = "#8800FF",
320 | persistentTickInterval = 0.2f,
321 | persistentMechanic = new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 9999999, damageType = "TrueDamage" } },
322 | }
323 | },
324 | {
325 | "Neurolinks-A",
326 | new MechanicProperties
327 | {
328 | visible = false,
329 | mechanic = new ExecuteMultipleEvents
330 | {
331 | events = new List {
332 | new SpawnMechanicEvent { referenceMechanicName = "Neurolink", position = new Vector2(0, 3.7f) },
333 | new SpawnMechanicEvent { referenceMechanicName = "Neurolink", position = new Vector2(3.7f * 0.866f, -1.85f) },
334 | new SpawnMechanicEvent { referenceMechanicName = "Neurolink", position = new Vector2(-3.7f * 0.866f, -1.85f) },
335 | }
336 | }
337 | }
338 | },
339 | {
340 | "Neurolinks-B",
341 | new MechanicProperties
342 | {
343 | visible = false,
344 | mechanic = new ExecuteMultipleEvents
345 | {
346 | events = new List {
347 | new SpawnMechanicEvent { referenceMechanicName = "Neurolink", position = new Vector2(0, -3.7f) },
348 | new SpawnMechanicEvent { referenceMechanicName = "Neurolink", position = new Vector2(3.7f * 0.866f, 1.85f) },
349 | new SpawnMechanicEvent { referenceMechanicName = "Neurolink", position = new Vector2(-3.7f * 0.866f, 1.85f) },
350 | }
351 | }
352 | }
353 | },
354 | {
355 | "StartButton-A",
356 | new MechanicProperties
357 | {
358 | collisionShape = CollisionShape.Round,
359 | collisionShapeParams = new Vector4(0.5f, 360),
360 | colorHtml = "#00ff00",
361 | persistentTickInterval = 0.1f,
362 | persistentActivationDelay = 1,
363 | mechanicTag = "StartButton",
364 | persistentMechanic = new CheckNumberOfPlayers
365 | {
366 | expressionFormat = "{0} = 0",
367 | failEvent = new ExecuteMultipleEvents{
368 | events = new List {
369 | new SpawnMechanicEvent { referenceMechanicName = "Neurolinks-A" },
370 | new SpawnMechanicEvent { referenceMechanicName = "StartMechanics" },
371 | new ClearMechanicsWithTag { mechanicTag = "StartButton" },
372 | }
373 | }
374 | },
375 | }
376 | },
377 | {
378 | "StartButton-B",
379 | new MechanicProperties
380 | {
381 | collisionShape = CollisionShape.Round,
382 | collisionShapeParams = new Vector4(0.5f, 360),
383 | colorHtml = "#00ff00",
384 | persistentTickInterval = 0.1f,
385 | persistentActivationDelay = 1,
386 | mechanicTag = "StartButton",
387 | persistentMechanic = new CheckNumberOfPlayers
388 | {
389 | expressionFormat = "{0} = 0",
390 | failEvent = new ExecuteMultipleEvents{
391 | events = new List {
392 | new SpawnMechanicEvent { referenceMechanicName = "Neurolinks-B" },
393 | new SpawnMechanicEvent { referenceMechanicName = "StartMechanics" },
394 | new ClearMechanicsWithTag { mechanicTag = "StartButton" },
395 | }
396 | }
397 | },
398 | }
399 | },
400 | {
401 | "StartMechanics",
402 | new MechanicProperties
403 | {
404 | visible = false,
405 | mechanic = new ExecuteMultipleEvents
406 | {
407 | events = new List
408 | {
409 | new WaitEvent { timeToWait = 2},
410 | new ExecuteRandomEvents { mechanicPoolName = "Spawn-Bosses-Pool" },
411 | }
412 | }
413 | }
414 | }
415 | };
416 |
417 | mechanicData.referenceTetherProperties = new Dictionary
418 | {
419 | {
420 | "TempestWing",
421 | new TetherProperties
422 | {
423 | colorHtml = "#00ff60",
424 | tetherDuration = 9,
425 | interceptMechanic = new SwitchTetheredPlayer(),
426 | oneTetherPerPlayer = true,
427 | tetherTag = "TempestWing",
428 | retargetRandomPlayerOnDeath = true
429 | }
430 | },
431 | };
432 |
433 | mechanicData.referenceStatusProperties = new Dictionary
434 | {
435 | {
436 | "Neurolink",
437 | new StatusEffectData
438 | {
439 | statusIconPath = "Mechanics/Resources/Neurolink.png",
440 | statusName = "Neurolink",
441 | statusDescription = "Neurolink",
442 | duration = 0.3f,
443 | }
444 | },
445 | };
446 |
447 | mechanicData.mechanicEvents = new List
448 | {
449 | new SpawnMechanicEvent { referenceMechanicName = "ArenaBoundary" },
450 | new SpawnVisualObject
451 | {
452 | textureFilePath = "Mechanics/Resources/ArenaCircle.png",
453 | visualDuration = float.PositiveInfinity,
454 | relativePosition = new Vector3(0, -0.001f, 0),
455 | eulerAngles = new Vector3(90, 0, 0),
456 | scale = new Vector3(15.8637f, 15.8637f, 1),
457 | },
458 | new ExecuteMultipleEvents
459 | {
460 | events = new List
461 | {
462 | new SpawnMechanicEvent { referenceMechanicName = "StartButton-A", position = new Vector2(0, 3) },
463 | new SpawnMechanicEvent { referenceMechanicName = "StartButton-B", position = new Vector2(0, -3) },
464 | }
465 | }
466 | };
467 | mechanicData.mechanicPools = new Dictionary>
468 | {
469 | {
470 | "Spawn-Bosses-Pool",
471 | new List
472 | {
473 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses-A" },
474 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses-A", rotation = 120 },
475 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses-A", rotation = 240 },
476 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses-B" },
477 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses-B", rotation = 120 },
478 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses-B", rotation = 240 },
479 | }
480 | },
481 | {
482 | "Quote-Pool",
483 | new List
484 | {
485 | new ExecuteMultipleEvents
486 | {
487 | events = new List
488 | {
489 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Fellruin-In-Spread.png", visualDuration = 6, isBillboard = true, relativePosition = Vector3.up * 2, scale = new Vector3(4.17f, 1, 1) },
490 | new WaitEvent { timeToWait = 6 },
491 | new SpawnMechanicEvent { referenceMechanicName = "Dynamo", isPositionRelative = true },
492 | new WaitEvent { timeToWait = 3 },
493 | new ReshufflePlayerIds(),
494 | new SetEnemyMovement {movementTime = 0.2f, moveToTarget = new TargetSpecificPlayerIds {targetIds = new List {0} } },
495 | new SpawnTargetedEvents { referenceMechanicName = "Dive", isPositionRelative = true, spawnOnTarget = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {0} } },
496 | }
497 | },
498 | new ExecuteMultipleEvents
499 | {
500 | events = new List
501 | {
502 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Fellruin-Spread-In.png", visualDuration = 6, isBillboard = true, relativePosition = Vector3.up * 2, scale = new Vector3(4.17f, 1, 1) },
503 | new WaitEvent { timeToWait = 6 },
504 | new ReshufflePlayerIds(),
505 | new SetEnemyMovement {movementTime = 0.2f, moveToTarget = new TargetSpecificPlayerIds {targetIds = new List {0} } },
506 | new SpawnTargetedEvents { referenceMechanicName = "Dive", isPositionRelative = true, spawnOnTarget = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {0} } },
507 | new WaitEvent { timeToWait = 3 },
508 | new SpawnMechanicEvent { referenceMechanicName = "Dynamo", isPositionRelative = true },
509 | }
510 | },
511 | }
512 | },
513 | };
514 |
515 | var resultText = mechanicData.ToString();
516 |
517 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
518 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
519 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
520 |
521 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/MechanicSets/Grand Octet.linq:
--------------------------------------------------------------------------------
1 |
2 | C:\Users\exces\Desktop\XIV SIM\xiv-sim_Data\Managed\Assembly-CSharp.dll
3 | C:\Users\exces\Desktop\XIV SIM\xiv-sim_Data\Managed\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var buildOutputPath = @"C:\Users\exces\Desktop\XIV SIM\Mechanic Builds";
8 |
9 | var mechanicName = "GrandOctetDemo";
10 | var mechanicData = new MechanicData();
11 |
12 | //Re-usable constants
13 | const int DIVE_WIDTH = 7;
14 | const float BOSS_DISTANCE = 7.5f;
15 |
16 | //Starting Parameters
17 | mechanicData.mechanicEvents = new List
18 | {
19 | new SpawnVisualObject
20 | {
21 | textureFilePath = "Mechanics/Resources/ArenaCircle.png",
22 | visualDuration = float.PositiveInfinity,
23 | relativePosition = new Vector3(0, -0.001f, 0),
24 | eulerAngles = new Vector3(90, 0, 0),
25 | scale = new Vector3(15.8637f, 15.8637f, 1),
26 | },
27 | new SpawnMechanicEvent { referenceMechanicName = "ArenaBoundary" },
28 | new WaitEvent { timeToWait = 1 },
29 |
30 | new SpawnEnemy {
31 | enemyName = "Bahamut",
32 | textureFilePath = "Mechanics/Resources/Bahamut.png",
33 | colorHtml = "#0a4d8b",
34 | maxHp = 10000000,
35 | baseMoveSpeed = 0,
36 | hitboxSize = 3,
37 | visualPosition = new Vector3(0, 1.2f, 0),
38 | visualScale = new Vector3(1, 1.5f, 1) * 1.5f,
39 | referenceMechanicName = "BahamutStart",
40 | rotation = 180
41 | }
42 | };
43 |
44 |
45 | mechanicData.referenceMechanicProperties = new Dictionary
46 | {
47 | //Modifiers
48 | {
49 | "Snapshot",
50 | new MechanicProperties
51 | {
52 | isTargeted = false,
53 | followSpeed = 0,
54 | }
55 | },
56 | {
57 | "SetVisible",
58 | new MechanicProperties
59 | {
60 | visible = true
61 | }
62 | },
63 | //Mechanics
64 | {
65 | "ArenaBoundary",
66 | new MechanicProperties
67 | {
68 | collisionShape = CollisionShape.Round,
69 | collisionShapeParams = new Vector4(25, 360, 7),
70 | colorHtml = "#8800FF",
71 | persistentTickInterval = 0.2f,
72 | persistentMechanic = new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 9999999, damageType = "TrueDamage" } },
73 | }
74 | },
75 | {
76 | "BahamutStart",
77 | new MechanicProperties
78 | {
79 | visible = false,
80 | mechanic = new ExecuteMultipleEvents {
81 | events = new List {
82 | new WaitForAggro(),
83 | new ExecuteRandomEvents { mechanicPoolName = "RotationPool" },
84 | new SpawnMechanicEvent { referenceMechanicName = "MechanicsPart2" },
85 |
86 | new SetEnemyMovement { movementTime = -100, moveToTarget = new TargetNthHighestAggro() },
87 | new StartCastBar { castName = "Grand Octet", duration = 4},
88 | new WaitEvent { timeToWait = 6.5f },
89 | new EndMechanic()
90 | }
91 | }
92 | }
93 | },
94 | {
95 | "SpawnBosses",
96 | new MechanicProperties
97 | {
98 | visible = false,
99 | mechanic = new ExecuteMultipleEvents
100 | {
101 | events = new List
102 | {
103 | new ExecuteRandomEvents { mechanicPoolName = "OrderPool" },
104 | new WaitEvent { timeToWait = 0.5f }
105 | }
106 | }
107 | }
108 | },
109 | {
110 | "MechanicsPart2",
111 | new MechanicProperties {
112 | visible = false,
113 | mechanic = new ExecuteMultipleEvents
114 | {
115 | events = new List
116 | {
117 | new WaitEvent { timeToWait = 35.9f },
118 | new ExecuteRandomEvents { mechanicPoolName = "TowerPool", numberToSpawn = 4},
119 | new WaitEvent { timeToWait = 1 },
120 | new SpawnTargetedEvents { referenceMechanicName = "MegaflareTarget", targetingScheme = new TargetRandomPlayers { totalTargetsNeeded = 4 } },
121 | new WaitEvent { timeToWait = 4.6f },
122 | new SpawnTargetedEvents
123 | {
124 | referenceMechanicName = "MegaflareStack",
125 | targetingScheme = new TargetRandomPlayers
126 | {
127 | numTargets = 0, // Get all players in a random order
128 | targetCondition = new CheckPlayerStatus { statusName = "MegaflareMark" }, // Filter to only players marked by megaflare
129 | totalTargetsNeeded = 1, // Select one of the players to place the stack on
130 | },
131 | spawnOnTarget = true
132 | },
133 | new WaitEvent { timeToWait = 2f },
134 | new SpawnTargetedEvents { referenceMechanicName = "Twister", spawnOnTarget = true, targetingScheme = new TargetRandomPlayers { totalTargetsNeeded = 4 } },
135 | }
136 | }
137 | }
138 | },
139 | {
140 | "Tower",
141 | new MechanicProperties
142 | {
143 | collisionShape = CollisionShape.Round,
144 | collisionShapeParams = new Vector4(1, 360),
145 | colorHtml = "#FFFF00",
146 | mechanic = new ExecuteMultipleEvents
147 | {
148 | events = new List
149 | {
150 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Tower.png", colorHtml = "#FFFF00", visualDuration = 7.8f,
151 | relativePosition = Vector3.up, scale = new Vector3(1, 1.9f, 1) * 0.6f, eulerAngles = new Vector3(0, 0, 0) },
152 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Tower.png", colorHtml = "#FFFF00", visualDuration = 7.8f,
153 | relativePosition = Vector3.up, scale = new Vector3(1, 1.9f, 1) * 0.6f, eulerAngles = new Vector3(0, 90, 0) },
154 | new WaitEvent { timeToWait = 7.8f },
155 | new CheckNumberOfPlayers
156 | {
157 | expressionFormat = "{0} >= 1",
158 | failEvent = new SpawnMechanicEvent { referenceMechanicName = "Tower Fail", isPositionRelative = true }
159 | },
160 | new ApplyEffectToPlayers {
161 | effect = new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Megaflare" }
162 | }
163 | }
164 | }
165 | }
166 | },
167 | {
168 | "Tower Fail",
169 | new MechanicProperties
170 | {
171 | collisionShape = CollisionShape.Round,
172 | collisionShapeParams = new Vector4(50, 360),
173 | colorHtml = "#FF0000",
174 | mechanic = new ExecuteMultipleEvents
175 | {
176 | events = new List
177 | {
178 | new WaitEvent { timeToWait = 0.2f },
179 | new ApplyEffectToPlayers {
180 | effect = new DamageEffect { damageAmount = 200000, damageType = "Damage", name = "Tower Failed" }
181 | }
182 | }
183 | }
184 | }
185 | },
186 | {
187 | "MegaflareTarget",
188 | new MechanicProperties
189 | {
190 | visible = false,
191 | mechanic = new ExecuteMultipleEvents
192 | {
193 | events = new List
194 | {
195 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Mark1.png", colorHtml = "#ff4200", visualDuration = 4,
196 | spawnOnPlayer = true, relativePosition = Vector3.up * 0.8f, scale = new Vector3(0.5f, 0.5f, 1), isBillboard = true },
197 | new ApplyEffectToTargetOnly { effect = new ApplyStatusEffect { referenceStatusName = "MegaflareMark" } }
198 | }
199 | },
200 | }
201 | },
202 | {
203 | "MegaflareStack",
204 | new MechanicProperties
205 | {
206 | collisionShape = CollisionShape.Round,
207 | collisionShapeParams = new Vector4(1.68f, 360),
208 | colorHtml = "#ff4200",
209 | isTargeted = true,
210 | followSpeed = 10000,
211 | visible = true,
212 | mechanic = new ExecuteMultipleEvents
213 | {
214 | events = new List
215 | {
216 | new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 350000, damageType = "Damage", name = "Megaflare", maxStackAmount = 4 } }
217 | }
218 | }
219 | }
220 | },
221 | {
222 | "Twister",
223 | new MechanicProperties
224 | {
225 | collisionShape = CollisionShape.Round,
226 | collisionShapeParams = new Vector4(0.25f, 360),
227 | colorHtml = "#008542",
228 | visible = false,
229 | isTargeted = true,
230 | followSpeed = 100,
231 | mechanic = new ExecuteMultipleEvents
232 | {
233 | events = new List
234 | {
235 | new ModifyMechanicEvent { referenceMechanicName = "Snapshot" },
236 | new WaitEvent { timeToWait = 0.8f },
237 | new ModifyMechanicEvent { referenceMechanicName = "SetVisible" },
238 | new WaitEvent { timeToWait = 5 },
239 | }
240 | },
241 | persistentTickInterval = 0.1f,
242 | persistentActivationDelay = 1.6f,
243 | persistentMechanic = new ExecuteMultipleEvents
244 | {
245 | events = new List
246 | {
247 | new CheckNumberOfPlayers
248 | {
249 | expressionFormat = "{0} = 0",
250 | failEvent = new ExecuteMultipleEvents{
251 | events = new List {
252 | new SpawnMechanicEvent { referenceMechanicName = "Twister Explode", isPositionRelative = true },
253 | new EndMechanic()
254 | }
255 | }
256 | },
257 | }
258 | },
259 | }
260 | },
261 | {
262 | "Twister Explode",
263 | new MechanicProperties
264 | {
265 | collisionShape = CollisionShape.Round,
266 | collisionShapeParams = new Vector4(3, 360),
267 | colorHtml = "#008542",
268 | mechanic = new ExecuteMultipleEvents
269 | {
270 | events = new List
271 | {
272 | new WaitEvent { timeToWait = 0.2f },
273 | new ApplyEffectToPlayers {
274 | effects = new List {
275 | new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Twister" },
276 | new KnockbackEffect { knockbackDistance = 10 },
277 | }
278 | }
279 | }
280 | }
281 | }
282 | },
283 | };
284 |
285 | int targetID = 0;
286 | void addDiveMechanic(string boss, string bossColor, string markerColor, string diveColor,
287 | float spawnTime, float markerTime, float snapshotTime, float markerDuration,
288 | string damageText, bool extraDragons = false)
289 | {
290 | for (int i = 0; i <= (extraDragons ? 4 : 0); i++)
291 | {
292 | mechanicData.referenceMechanicProperties[boss + (extraDragons ? i : "")] = new MechanicProperties
293 | {
294 | visible = false,
295 | mechanic = new ExecuteMultipleEvents
296 | {
297 | events = new List
298 | {
299 | new WaitEvent { timeToWait = spawnTime },
300 | new SpawnVisualObject()
301 | {
302 | textureFilePath = $"Mechanics/Resources/{boss}.png",
303 | colorHtml = bossColor,
304 | //The imprecise floats in JSON were bothering me, so I had to round some of these, sorry
305 | visualDuration = MathF.Round(snapshotTime - spawnTime + 2*i, 2),
306 | relativePosition = new Vector3(0, 1, -BOSS_DISTANCE),
307 | scale = new Vector3(1, 1, 1),
308 | eulerAngles = new Vector3(0, 180, 0),
309 | isRotationRelative = true
310 | },
311 | new WaitEvent { timeToWait = MathF.Round(markerTime - spawnTime + 2*i, 2) },
312 | new SpawnTargetedEvents
313 | {
314 | referenceMechanicName = $"{boss}Dive",
315 | position = new Vector2(0, -BOSS_DISTANCE),
316 | targetingScheme = new TargetSpecificPlayerIds { targetIds = new List { targetID++ } },
317 | isPositionRelative = true,
318 | isRotationRelative = true
319 | }
320 | }
321 | }
322 | };
323 | }
324 |
325 | mechanicData.referenceMechanicProperties[$"{boss}Dive"] = new MechanicProperties
326 | {
327 | collisionShape = CollisionShape.Rectangle,
328 | collisionShapeParams = new Vector4(16, DIVE_WIDTH),
329 | colorHtml = diveColor,
330 | visible = false,
331 | isTargeted = true,
332 | mechanic = new ExecuteMultipleEvents
333 | {
334 | events = new List
335 | {
336 | new SpawnVisualObject()
337 | {
338 | textureFilePath = "Mechanics/Resources/Mark1.png",
339 | colorHtml = markerColor,
340 | visualDuration = markerDuration,
341 | relativePosition = Vector3.up,
342 | spawnOnPlayer = true,
343 | scale = Vector3.one * 0.8f,
344 | isBillboard = true
345 | },
346 | new WaitEvent { timeToWait = MathF.Round(snapshotTime - markerTime, 2) },
347 | new SpawnVisualObject()
348 | {
349 | textureFilePath = $"Mechanics/Resources/{boss}.png",
350 | colorHtml = bossColor,
351 | visualDuration = 4,
352 | relativePosition = new Vector3(0, 1, 0),
353 | scale = new Vector3(1, 1, 1),
354 | eulerAngles = new Vector3(0, 180, 0),
355 | isRotationRelative = true
356 | },
357 | new ModifyMechanicEvent { referenceMechanicName = "Snapshot" },
358 | new WaitEvent { timeToWait = 4 },
359 | new ModifyMechanicEvent { referenceMechanicName = "SetVisible" },
360 | new ApplyEffectToPlayers {
361 | effects = new List {
362 | new DamageEffect { damageAmount = 90000, damageType = "Damage", name = damageText },
363 | new KnockbackEffect { knockbackDistance = 10 },
364 | }
365 | },
366 | new WaitEvent { timeToWait = 0.5f }
367 | }
368 | }
369 | };
370 | }
371 |
372 | addDiveMechanic(boss: "Nael", bossColor: "#a917bf", markerColor: "#c4c278", diveColor: "#c4c278",
373 | spawnTime: 8, markerTime: 12.4f, snapshotTime: 12.5f, markerDuration: 3,
374 | damageText: "Lunar Dive");
375 |
376 | addDiveMechanic(boss: "Bahamut", bossColor: "#0a4d8b", markerColor: "#f07b22", diveColor: "#b81515",
377 | spawnTime: 8, markerTime: 29.6f, snapshotTime: 29.7f, markerDuration: 2.8f,
378 | damageText: "Megaflare Dive");
379 |
380 | addDiveMechanic(boss: "Twintania", bossColor: "#067743", markerColor: "#32730a", diveColor: "#0a4d8b",
381 | spawnTime: 8, markerTime: 38.6f, snapshotTime: 38.7f, markerDuration: 3,
382 | damageText: "Twisting Dive");
383 |
384 | addDiveMechanic(boss: "Dragon", bossColor: null, markerColor: "#32730a", diveColor: "#7d1876",
385 | spawnTime: 2.9f, markerTime: 12.5f, snapshotTime: 19.5f, markerDuration: 6.4f,
386 | damageText: "Cauterize", extraDragons: true);
387 |
388 |
389 | //Mechanic Pools
390 | mechanicData.mechanicPools = new Dictionary>
391 | {
392 | {
393 | "RotationPool",
394 | new List()
395 | {
396 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = 0},
397 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = 90},
398 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = 180},
399 | new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = 270}
400 | }
401 | },
402 | { "OrderPool", new List() },
403 | { "TowerPool", new List() }
404 | };
405 | foreach (int orientation in new [] { 1, -1 })
406 | {
407 | //For the sake of a smaller file size, and better practice, I have opted to remove some easier patterns.
408 | //Otherwise these loops should be from 0 through 5, and from 0 through 6.
409 | for (int twin = 1; twin <= 5; twin++)
410 | {
411 | for (int nael = 2; nael <= 4; nael++)
412 | {
413 | var mech = new List { "Dragon0", "Dragon1", "Dragon2", "Dragon3", "Dragon4" };
414 | mech.Insert(twin, "Twintania");
415 | mech.Insert(nael, "Nael");
416 | mech.Insert(0, "Bahamut");
417 | var spawnEvents = new List();
418 | for (int i = 0; i < 8; i++)
419 | {
420 | float a = ((orientation == 1 ? 1 : 0) + i * orientation) * Mathf.PI / 4;
421 | // Postion is now calculated within the boss mechanic to reduce OrderPool size in JSON
422 | // Removes 5 lines * 8 bosses * 2*5*3 order variations = -1200 lines from the JSON file
423 | //float x = MathF.Round(BOSS_DISTANCE * Mathf.Cos(3 * Mathf.PI / 2 - a), 3);
424 | //float y = MathF.Round(BOSS_DISTANCE * Mathf.Sin(3 * Mathf.PI / 2 - a), 3);
425 | spawnEvents.Add(
426 | new SpawnMechanicEvent
427 | {
428 | referenceMechanicName = mech[i],
429 | rotation = MathF.Round(a * Mathf.Rad2Deg),
430 | //position = new Vector2(x, y),
431 | //isPositionRelative = true,
432 | isRotationRelative = true
433 | }
434 | );
435 | }
436 | mechanicData.mechanicPools["OrderPool"].Add(new ExecuteMultipleEvents { events = spawnEvents });
437 | }
438 | }
439 | }
440 | for (int i = 0; i < 8; i++)
441 | {
442 | float a = i * Mathf.PI / 4;
443 | float x = MathF.Round(3.5f * Mathf.Cos(a), 3);
444 | float y = MathF.Round(3.5f * Mathf.Sin(a), 3);
445 | mechanicData.mechanicPools["TowerPool"].Add(new SpawnMechanicEvent { referenceMechanicName = "Tower", position = new Vector2(x, y) });
446 | }
447 |
448 |
449 | //Status Effects
450 | mechanicData.referenceStatusProperties = new Dictionary
451 | {
452 | {
453 | "MegaflareMark",
454 | new StatusEffectData
455 | {
456 | statusName = "Marked for Megaflare",
457 | statusDescription = "Chosen to share the Megaflare stack.",
458 | duration = 7,
459 | }
460 | }
461 | };
462 |
463 |
464 | var resultText = mechanicData.ToString();
465 | File.WriteAllText($@"{buildOutputPath}\{mechanicName}.json", resultText);
466 |
467 | $"Finished writing json to {mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/MechanicSets/HeavensfallDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "HeavensfallDemo";
8 | var baseOutputPath = $@"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-mechanics";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "Megaflare",
17 | new MechanicProperties
18 | {
19 | collisionShape = CollisionShape.Round,
20 | collisionShapeParams = new Vector4(2, 360),
21 | colorHtml = "#FF4400",
22 | mechanic = new ExecuteMultipleEvents
23 | {
24 | events = new List
25 | {
26 | new WaitEvent { timeToWait = 3 },
27 | new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Megaflare" } }
28 | }
29 | }
30 | }
31 | },
32 | {
33 | "HeavensfallDeathZone",
34 | new MechanicProperties
35 | {
36 | collisionShape = CollisionShape.Rectangle,
37 | collisionShapeParams = new Vector4(2, 2.5f),
38 | colorHtml = "#0096ff",
39 |
40 | persistentTickInterval = 0.2f,
41 | persistentMechanic = new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 9999999, damageType = "OutOfBounds" } },
42 | mechanic = new WaitEvent {timeToWait = 10}
43 | }
44 | },
45 | {
46 | "HeavensfallConeCW",
47 | new MechanicProperties
48 | {
49 | collisionShape = CollisionShape.Round,
50 | collisionShapeParams = new Vector4(7, 360 / 16f),
51 | colorHtml = "#FFFF00",
52 | mechanic = new ExecuteMultipleEvents
53 | {
54 | events = new List
55 | {
56 | new WaitEvent { timeToWait = 0.5f },
57 | new CheckMechanicDepth
58 | {
59 | expressionFormat = "{0} < 9",
60 | successEvent = new SpawnMechanicEvent { referenceMechanicName = "HeavensfallConeCW", rotation = 360 / 16f, isRotationRelative = true }
61 | },
62 | new WaitEvent { timeToWait = 2 },
63 | new ApplyEffectToPlayers {
64 | effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Heavensfall Cone" }
65 | }
66 | }
67 | }
68 | }
69 | },
70 | {
71 | "HeavensfallConeInitialCW",
72 | new MechanicProperties
73 | {
74 | collisionShape = CollisionShape.Round,
75 | collisionShapeParams = new Vector4(7, 360 / 16f),
76 | colorHtml = "#FFFF00",
77 | mechanic = new ExecuteMultipleEvents
78 | {
79 | events = new List
80 | {
81 | new WaitEvent { timeToWait = 2 },
82 | new SpawnMechanicEvent { referenceMechanicName = "HeavensfallConeCW", rotation = 360 / 16f, isRotationRelative = true },
83 | new WaitEvent { timeToWait = 0.5f },
84 | new ApplyEffectToPlayers {
85 | effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Heavensfall Cone" }
86 | }
87 | }
88 | }
89 | }
90 | },
91 | {
92 | "HeavensfallConeCCW",
93 | new MechanicProperties
94 | {
95 | collisionShape = CollisionShape.Round,
96 | collisionShapeParams = new Vector4(7, 360 / 16f),
97 | colorHtml = "#FFFF00",
98 | mechanic = new ExecuteMultipleEvents
99 | {
100 | events = new List
101 | {
102 | new WaitEvent { timeToWait = 0.5f },
103 | new CheckMechanicDepth
104 | {
105 | expressionFormat = "{0} < 9",
106 | successEvent = new SpawnMechanicEvent { referenceMechanicName = "HeavensfallConeCCW", rotation = -360 / 16f, isRotationRelative = true }
107 | },
108 | new WaitEvent { timeToWait = 2 },
109 | new ApplyEffectToPlayers {
110 | effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Heavensfall Cone" }
111 | }
112 | }
113 | }
114 | }
115 | },
116 | {
117 | "HeavensfallConeInitialCCW",
118 | new MechanicProperties
119 | {
120 | collisionShape = CollisionShape.Round,
121 | collisionShapeParams = new Vector4(7, 360 / 16f),
122 | colorHtml = "#FFFF00",
123 | mechanic = new ExecuteMultipleEvents
124 | {
125 | events = new List
126 | {
127 | new WaitEvent { timeToWait = 2 },
128 | new SpawnMechanicEvent { referenceMechanicName = "HeavensfallConeCCW", rotation = -360 / 16f, isRotationRelative = true },
129 | new WaitEvent { timeToWait = 0.5f },
130 | new ApplyEffectToPlayers {
131 | effect = new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Heavensfall Cone" }
132 | }
133 | }
134 | }
135 | }
136 | },
137 | {
138 | "SpawnHeavensfallConesCW",
139 | new MechanicProperties
140 | {
141 | visible = false,
142 | mechanic = new ExecuteMultipleEvents
143 | {
144 | events = new List
145 | {
146 | new SpawnMechanicEvent { referenceMechanicName = "HeavensfallConeInitialCW", isRotationRelative = true },
147 | new SpawnMechanicEvent { referenceMechanicName = "HeavensfallConeInitialCW", isRotationRelative = true, rotation = 180 },
148 | }
149 | }
150 | }
151 | },
152 | {
153 | "SpawnHeavensfallConesCCW",
154 | new MechanicProperties
155 | {
156 | visible = false,
157 | mechanic = new ExecuteMultipleEvents
158 | {
159 | events = new List
160 | {
161 | new SpawnMechanicEvent { referenceMechanicName = "HeavensfallConeInitialCCW", isRotationRelative = true },
162 | new SpawnMechanicEvent { referenceMechanicName = "HeavensfallConeInitialCCW", isRotationRelative = true, rotation = 180 },
163 | }
164 | }
165 | }
166 | },
167 | {
168 | "SpawnHeavensfallCones",
169 | new MechanicProperties
170 | {
171 | visible = false,
172 | mechanic = new ExecuteMultipleEvents
173 | {
174 | events = new List
175 | {
176 | new ExecuteRandomEvents { mechanicPoolName = "HeavensfallConeDirectionPool" }
177 | }
178 | }
179 | }
180 | },
181 | {
182 | "Mechanics-B",
183 | new MechanicProperties
184 | {
185 | collisionShape = CollisionShape.Rectangle,
186 | collisionShapeParams = new Vector4(14, 3),
187 | colorHtml = "#0a4d8b",
188 | mechanic = new ExecuteMultipleEvents
189 | {
190 | events = new List
191 | {
192 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Bahamut.png", colorHtml = "#0a4d8b", visualDuration = 5, relativePosition = Vector3.up, scale = new Vector3(1, 1, 1), eulerAngles = new Vector3(0, 180, 0), isRotationRelative = true },
193 | new WaitEvent { timeToWait = 5 },
194 | new ApplyEffectToPlayers {
195 | effects = new List {
196 | new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Divebomb" },
197 | new KnockbackEffect { knockbackDistance = 10 },
198 | }
199 | }
200 | }
201 | }
202 | }
203 | },
204 | {
205 | "Twister Explode",
206 | new MechanicProperties
207 | {
208 | collisionShape = CollisionShape.Round,
209 | collisionShapeParams = new Vector4(3, 360),
210 | colorHtml = "#008542",
211 | mechanic = new ExecuteMultipleEvents
212 | {
213 | events = new List
214 | {
215 | new WaitEvent { timeToWait = 0.2f },
216 | new ApplyEffectToPlayers {
217 | effects = new List {
218 | new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Twister" },
219 | new KnockbackEffect { knockbackDistance = 10 },
220 | }
221 | }
222 | }
223 | }
224 | }
225 | },
226 | {
227 | "TwisterSnapshot",
228 | new MechanicProperties
229 | {
230 | isTargeted = false,
231 | followSpeed = 0,
232 | }
233 | },
234 | {
235 | "TwisterVisible",
236 | new MechanicProperties
237 | {
238 | visible = true,
239 | }
240 | },
241 | {
242 | "Twister",
243 | new MechanicProperties
244 | {
245 | collisionShape = CollisionShape.Round,
246 | collisionShapeParams = new Vector4(0.25f, 360),
247 | colorHtml = "#008542",
248 | visible = false,
249 | isTargeted = true,
250 | followSpeed = 100,
251 | mechanic = new ExecuteMultipleEvents
252 | {
253 | events = new List
254 | {
255 | new WaitEvent { timeToWait = 1.5f },
256 | new ModifyMechanicEvent { referenceMechanicName = "TwisterSnapshot" },
257 | new WaitEvent { timeToWait = 0.5f },
258 | new ModifyMechanicEvent { referenceMechanicName = "TwisterVisible" },
259 | new WaitEvent { timeToWait = 5 },
260 | }
261 | },
262 | persistentTickInterval = 0.1f,
263 | persistentActivationDelay = 2.5f,
264 | persistentMechanic = new ExecuteMultipleEvents
265 | {
266 | events = new List
267 | {
268 | new CheckNumberOfPlayers
269 | {
270 | expressionFormat = "{0} = 0",
271 | failEvent = new ExecuteMultipleEvents{
272 | events = new List {
273 | new SpawnMechanicEvent { referenceMechanicName = "Twister Explode", isPositionRelative = true },
274 | new EndMechanic()
275 | }
276 | }
277 | },
278 | }
279 | },
280 | }
281 | },
282 | {
283 | "Mechanics-T",
284 | new MechanicProperties
285 | {
286 | collisionShape = CollisionShape.Rectangle,
287 | collisionShapeParams = new Vector4(14, 3),
288 | colorHtml = "#067743",
289 | mechanic = new ExecuteMultipleEvents
290 | {
291 | events = new List
292 | {
293 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Twintania.png", colorHtml = "#067743", visualDuration = 5, relativePosition = Vector3.up, scale = new Vector3(1, 1, 1), eulerAngles = new Vector3(0, 180, 0), isRotationRelative = true },
294 | new WaitEvent { timeToWait = 3 },
295 | new SpawnTargetedEvents
296 | {
297 | referenceMechanicName = "Twister",
298 | spawnOnTarget = true,
299 | targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {0, 1, 2, 3 }, dropExtraEvents = true}
300 | },
301 | new WaitEvent { timeToWait = 2 },
302 | new ApplyEffectToPlayers
303 | {
304 | effects = new List
305 | {
306 | new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Divebomb" },
307 | new KnockbackEffect { knockbackDistance = 10 },
308 | }
309 | }
310 | }
311 | }
312 | }
313 | },
314 | {
315 | "Hypernova",
316 | new MechanicProperties
317 | {
318 | collisionShape = CollisionShape.Round,
319 | collisionShapeParams = new Vector4(1.5f, 360),
320 | colorHtml = "#352a43",
321 | mechanic = new ExecuteMultipleEvents
322 | {
323 | events = new List
324 | {
325 | new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Hypernova" } },
326 | new WaitEvent { timeToWait = 10 },
327 | }
328 | },
329 |
330 | persistentTickInterval = 0.3f,
331 | persistentActivationDelay = 2,
332 | persistentMechanic = new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 999999, damageType = "Damage", name = "Bleed" } },
333 | }
334 | },
335 | {
336 | "Mechanics-N",
337 | new MechanicProperties
338 | {
339 | visible = false,
340 | mechanic = new ExecuteMultipleEvents
341 | {
342 | events = new List
343 | {
344 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Nael.png", colorHtml = "#a917bf", visualDuration = 15, relativePosition = Vector3.up, scale = new Vector3(1, 1, 1), eulerAngles = new Vector3(0, 180, 0), isRotationRelative = true },
345 | new WaitEvent { timeToWait = 15 },
346 | new SpawnTargetedEvents {referenceMechanicName = "Hypernova", spawnOnTarget = true, targetingScheme = new TargetRandomPlayers() },
347 | new WaitEvent { timeToWait = 1 },
348 | new SpawnTargetedEvents {referenceMechanicName = "Hypernova", spawnOnTarget = true, targetingScheme = new TargetRandomPlayers() },
349 | new WaitEvent { timeToWait = 1 },
350 | new SpawnTargetedEvents {referenceMechanicName = "Hypernova", spawnOnTarget = true, targetingScheme = new TargetRandomPlayers() },
351 | new WaitEvent { timeToWait = 1 },
352 | new SpawnTargetedEvents {referenceMechanicName = "Hypernova", spawnOnTarget = true, targetingScheme = new TargetRandomPlayers() },
353 | new SpawnTargetedEvents {referenceMechanicName = "Fireball", spawnOnTarget = true, targetingScheme = new TargetRandomPlayers() },
354 | }
355 | }
356 | }
357 | },
358 | {
359 | "FireballVisible",
360 | new MechanicProperties
361 | {
362 | visible = true,
363 | }
364 | },
365 | {
366 | "Fireball",
367 | new MechanicProperties
368 | {
369 | collisionShape = CollisionShape.Round,
370 | collisionShapeParams = new Vector4(1, 360),
371 | colorHtml = "#ff4200",
372 | isTargeted = true,
373 | followSpeed = 10000,
374 | visible = false,
375 | mechanic = new ExecuteMultipleEvents
376 | {
377 | events = new List
378 | {
379 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Mark1.png", colorHtml = "#ff4200", visualDuration = 5, spawnOnPlayer = true, relativePosition = Vector3.up * 0.8f, scale = new Vector3(0.5f, 0.5f, 1), eulerAngles = new Vector3(0, 0, 0) },
380 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Mark1.png", colorHtml = "#ff4200", visualDuration = 5, spawnOnPlayer = true, relativePosition = Vector3.up * 0.8f, scale = new Vector3(0.5f, 0.5f, 1), eulerAngles = new Vector3(0, 90, 0) },
381 | new WaitEvent { timeToWait = 4 },
382 | new ModifyMechanicEvent { referenceMechanicName = "FireballVisible" },
383 | new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 600000, damageType = "Damage", name = "Fireball", maxStackAmount = 8 } },
384 | }
385 | }
386 | }
387 | },
388 | {
389 | "SpawnBosses",
390 | new MechanicProperties
391 | {
392 | visible = false,
393 | mechanic = new ExecuteMultipleEvents
394 | {
395 | events = new List
396 | {
397 | new ExecuteRandomEvents { mechanicPoolName = "DivebombPool" },
398 | }
399 | }
400 | }
401 | },
402 | {
403 | "KnockbackFromCenter",
404 | new MechanicProperties
405 | {
406 | collisionShape = CollisionShape.Round,
407 | collisionShapeParams = new Vector4(15, 360),
408 | visible = false,
409 | mechanic = new ExecuteMultipleEvents
410 | {
411 | events = new List
412 | {
413 | new ApplyEffectToPlayers {
414 | effects = new List {
415 | new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Heavensfall" },
416 | new KnockbackEffect { knockbackDistance = 4 },
417 | }
418 | }
419 | }
420 | }
421 | }
422 | },
423 | {
424 | "Tower Fail",
425 | new MechanicProperties
426 | {
427 | collisionShape = CollisionShape.Round,
428 | collisionShapeParams = new Vector4(50, 360),
429 | colorHtml = "#FF0000",
430 | mechanic = new ExecuteMultipleEvents
431 | {
432 | events = new List
433 | {
434 | new WaitEvent { timeToWait = 0.2f },
435 | new ApplyEffectToPlayers {
436 | effect = new DamageEffect { damageAmount = 9999999, damageType = "Damage", name = "Tower Failed" }
437 | }
438 | }
439 | }
440 | }
441 | },
442 | {
443 | "Tower",
444 | new MechanicProperties
445 | {
446 | collisionShape = CollisionShape.Round,
447 | collisionShapeParams = new Vector4(0.75f, 360),
448 | colorHtml = "#FFFF00",
449 | mechanic = new ExecuteMultipleEvents
450 | {
451 | events = new List
452 | {
453 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Tower.png", colorHtml = "#FFFF00", visualDuration = 8, relativePosition = Vector3.up, scale = new Vector3(1, 1.8876f, 1) * 0.6f, eulerAngles = new Vector3(0, 0, 0) },
454 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Tower.png", colorHtml = "#FFFF00", visualDuration = 8, relativePosition = Vector3.up, scale = new Vector3(1, 1.8876f, 1) * 0.6f, eulerAngles = new Vector3(0, 90, 0) },
455 | new WaitEvent { timeToWait = 8 },
456 | new CheckNumberOfPlayers
457 | {
458 | expressionFormat = "{0} = 1",
459 | failEvent = new SpawnMechanicEvent { referenceMechanicName = "Tower Fail", isPositionRelative = true }
460 | },
461 | new ApplyEffectToPlayers {
462 | effect = new DamageEffect { damageAmount = 10000, damageType = "Damage", name = "Megaflare" }
463 | }
464 | }
465 | }
466 | }
467 | },
468 | {
469 | "ArenaBoundary",
470 | new MechanicProperties
471 | {
472 | collisionShape = CollisionShape.Round,
473 | collisionShapeParams = new Vector4(15, 360, 7),
474 | colorHtml = "#8800FF",
475 |
476 | persistentTickInterval = 0.2f,
477 | persistentMechanic = new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 9999999, damageType = "OutOfBounds" } },
478 | }
479 | }
480 | };
481 |
482 | mechanicData.mechanicPools = new Dictionary>();
483 |
484 | var divebombPool = new List();
485 | mechanicData.mechanicPools["DivebombPool"] = divebombPool;
486 |
487 | foreach (var spawnCombo in new List { "TNB", "TBN", "BNT", "BTN", "NTB", "NBT" })
488 | {
489 | var divebombsToSpawn = new ExecuteMultipleEvents();
490 | divebombsToSpawn.events = new List();
491 |
492 | var angleOffset = 0f;
493 |
494 | if (spawnCombo[0] == 'N') {
495 | angleOffset = 7.5f;
496 | }
497 | else if (spawnCombo[2] == 'N') {
498 | angleOffset = -7.5f;
499 | }
500 |
501 | for (int i = -1; i <= 1; i++)
502 | {
503 | float a = (30 * i + angleOffset) * Mathf.Deg2Rad;
504 | float x = 7 * Mathf.Cos(a);
505 | float y = 7 * Mathf.Sin(a);
506 |
507 | var spawnId = spawnCombo[i + 1];
508 |
509 | divebombsToSpawn.events.Add(new SpawnMechanicEvent { referenceMechanicName = $"Mechanics-{spawnId}", position = new Vector2(x, y), rotation = -90 - a * Mathf.Rad2Deg, isPositionRelative = true, isRotationRelative = true });
510 | }
511 |
512 | mechanicData.referenceMechanicProperties[$"Mechanics-{spawnCombo}"] = new MechanicProperties
513 | {
514 | visible = false,
515 | mechanic = divebombsToSpawn
516 | };
517 |
518 | divebombPool.Add(new SpawnMechanicEvent { referenceMechanicName = $"Mechanics-{spawnCombo}", isPositionRelative = true, isRotationRelative = true });
519 | }
520 |
521 | var bossRotationPool = new List();
522 | mechanicData.mechanicPools["SpawnBossesRotationPool"] = bossRotationPool;
523 |
524 | var heavensfallTowerPool = new List();
525 | mechanicData.mechanicPools["HeavensfallTowerPool"] = heavensfallTowerPool;
526 |
527 | var heavensfallConePool = new List();
528 | mechanicData.mechanicPools["HeavensfallConePool"] = heavensfallConePool;
529 |
530 | for (int i = 0; i < 16; i++)
531 | {
532 | float a = 2 * Mathf.PI / 16 * i;
533 | float x = 7 * Mathf.Cos(a);
534 | float y = 7 * Mathf.Sin(a);
535 | bossRotationPool.Add(new SpawnMechanicEvent { referenceMechanicName = "SpawnBosses", rotation = a * Mathf.Rad2Deg });
536 | heavensfallConePool.Add(new SpawnMechanicEvent { referenceMechanicName = "SpawnHeavensfallCones", rotation = a * Mathf.Rad2Deg });
537 | heavensfallTowerPool.Add(new SpawnMechanicEvent { referenceMechanicName = "Tower", position = new Vector2(x, y) });
538 | }
539 |
540 | var heavensfallConeDirectionPool = new List();
541 | mechanicData.mechanicPools["HeavensfallConeDirectionPool"] = new List
542 | {
543 | new SpawnMechanicEvent { referenceMechanicName = "SpawnHeavensfallConesCW" },
544 | new SpawnMechanicEvent { referenceMechanicName = "SpawnHeavensfallConesCCW" }
545 | };
546 |
547 | var mechanicSequence = new List{
548 | new WaitEvent {timeToWait = 3},
549 | new ExecuteRandomEvents { mechanicPoolName = "SpawnBossesRotationPool"},
550 | new WaitEvent {timeToWait = 5},
551 | new ExecuteRandomEvents { mechanicPoolName = "HeavensfallTowerPool", numberToSpawn = 8},
552 | new WaitEvent {timeToWait = 1},
553 | new ReshufflePlayerIds(),
554 | new SpawnTargetedEvents { referenceMechanicName = "Megaflare", spawnOnTarget = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List { 0, 1, 2, 3 } } },
555 | new WaitEvent {timeToWait = 4},
556 | new SpawnMechanicEvent { referenceMechanicName = "KnockbackFromCenter"},
557 | new SpawnMechanicEvent { referenceMechanicName = "HeavensfallDeathZone", position = new Vector2(0, -1)},
558 | new WaitEvent {timeToWait = 3},
559 | new ExecuteRandomEvents { mechanicPoolName = "HeavensfallConePool"},
560 | };
561 |
562 | mechanicData.mechanicEvents = new List
563 | {
564 | new SpawnVisualObject
565 | {
566 | textureFilePath = "Mechanics/Resources/ArenaCircle.png",
567 | visualDuration = float.PositiveInfinity,
568 | relativePosition = new Vector3(0, -0.001f, 0),
569 | eulerAngles = new Vector3(90, 0, 0),
570 | scale = new Vector3(15.8637f, 15.8637f, 1),
571 | },
572 | new SpawnMechanicEvent { referenceMechanicName = "ArenaBoundary" },
573 | new ExecuteMultipleEvents { events = mechanicSequence }
574 | };
575 |
576 | var resultText = mechanicData.ToString();
577 |
578 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
579 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
580 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
581 |
582 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/MechanicSets/LimitCutDemo.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "LimitCutDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-mechanics";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | var hawkBlasterGap = 2.2f;
14 |
15 | var limitcutGap = 1.8f;
16 | var alphaSwordDelay = 1.0f;
17 | var blasstyChargeDelay = 1.7f;
18 |
19 | mechanicData.referenceMechanicProperties = new Dictionary
20 | {
21 | {
22 | "HawkBlasterSequence",
23 | new MechanicProperties
24 | {
25 | visible = false,
26 | mechanic = new ExecuteMultipleEvents
27 | {
28 | events = new List
29 | {
30 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true },
31 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 180 },
32 | new WaitEvent { timeToWait = hawkBlasterGap },
33 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 45 },
34 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 225 },
35 | new WaitEvent { timeToWait = hawkBlasterGap },
36 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 90 },
37 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 270 },
38 | new WaitEvent { timeToWait = hawkBlasterGap },
39 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 135 },
40 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 315 },
41 | new WaitEvent { timeToWait = hawkBlasterGap },
42 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlaster" },
43 | new WaitEvent { timeToWait = hawkBlasterGap },
44 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true },
45 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 180 },
46 | new WaitEvent { timeToWait = hawkBlasterGap },
47 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 45 },
48 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 225 },
49 | new WaitEvent { timeToWait = hawkBlasterGap },
50 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 90 },
51 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 270 },
52 | new WaitEvent { timeToWait = hawkBlasterGap },
53 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 135 },
54 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterOffset", isRotationRelative = true, rotation = 315 },
55 | new WaitEvent { timeToWait = hawkBlasterGap },
56 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlaster" },
57 | }
58 | }
59 | }
60 | },
61 | {
62 | "HawkBlasterOffset",
63 | new MechanicProperties
64 | {
65 | visible = false,
66 | mechanic = new SpawnMechanicEvent { referenceMechanicName = "HawkBlaster", position = new Vector2(4.75f, 0), isPositionRelative = true, isRotationRelative = true }
67 | }
68 | },
69 | {
70 | "HawkBlaster",
71 | new MechanicProperties
72 | {
73 | collisionShapeParams = new Vector4(3.3333f, 360),
74 | visible = false,
75 | mechanic = new ExecuteMultipleEvents
76 | {
77 | events = new List
78 | {
79 | new ApplyEffectToPlayers
80 | {
81 | effects = new List
82 | {
83 | new DamageEffect {damageAmount = 400000, damageType = "Magic", name = "Hawk Blaster" },
84 | new ApplyStatusEffect { referenceStatusName = "MagicVuln" }
85 | }
86 | },
87 | new WaitEvent { timeToWait = 1 },
88 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterVisual", isPositionRelative = true }
89 | }
90 | }
91 | }
92 | },
93 | {
94 | "HawkBlasterVisual",
95 | new MechanicProperties
96 | {
97 | collisionShapeParams = new Vector4(3.3333f, 360),
98 | colorHtml = "#ff5a00",
99 | visible = true,
100 | mechanic = new WaitEvent { timeToWait = 0.2f },
101 | }
102 | },
103 | {
104 | "Spawn-CruiseChaser-LC",
105 | new MechanicProperties
106 | {
107 | visible = false,
108 | mechanic = new SpawnEnemy
109 | {
110 | enemyName = "Cruise Chaser",
111 | textureFilePath = "Mechanics/Resources/CruiseChaser.png",
112 | colorHtml = "#8b4800",
113 | maxHp = int.MaxValue,
114 | baseMoveSpeed = 2,
115 | hitboxSize = 2,
116 | visualPosition = new Vector3(0, 1, 0),
117 | visualScale = Vector3.one * 2,
118 | referenceMechanicName = "LimitCutSequence",
119 | isTargetable = false,
120 | showInEnemyList = false,
121 | isVisible = false,
122 | },
123 | }
124 | },
125 | {
126 | "LimitCutSequence",
127 | new MechanicProperties
128 | {
129 | visible = false,
130 | mechanic = new ExecuteMultipleEvents
131 | {
132 | events = new List
133 | {
134 | new SpawnTargetedEvents { referenceMechanicName = "LimitCutMarker-1", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List{0}, dropExtraEvents = true } },
135 | new SpawnTargetedEvents { referenceMechanicName = "LimitCutMarker-2", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List{1}, dropExtraEvents = true } },
136 | new SpawnTargetedEvents { referenceMechanicName = "LimitCutMarker-3", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List{2}, dropExtraEvents = true } },
137 | new SpawnTargetedEvents { referenceMechanicName = "LimitCutMarker-4", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List{3}, dropExtraEvents = true } },
138 | new SpawnTargetedEvents { referenceMechanicName = "LimitCutMarker-5", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List{4}, dropExtraEvents = true } },
139 | new SpawnTargetedEvents { referenceMechanicName = "LimitCutMarker-6", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List{5}, dropExtraEvents = true } },
140 | new SpawnTargetedEvents { referenceMechanicName = "LimitCutMarker-7", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List{6}, dropExtraEvents = true } },
141 | new SpawnTargetedEvents { referenceMechanicName = "LimitCutMarker-8", targetingScheme = new TargetSpecificPlayerIds { targetIds = new List{7}, dropExtraEvents = true } },
142 | new WaitEvent { timeToWait = 2 },
143 | new ExecuteRandomEvents { mechanicPoolName = "Hawkblaster-Pool" },
144 | new WaitEvent { timeToWait = 6 },
145 | new SetEnemyMovement { movementTime = 0.01f, moveToTarget = new TargetSpecificPlayerIds { targetIds = new List{0} }, position = new Vector3(0, -1) },
146 | new WaitEvent { timeToWait = 0.01f },
147 | new SetEnemyMovement { movementTime = -1, moveToTarget =new TargetSpecificPlayerIds { targetIds = new List{0} } },
148 | new SetEnemyVisible { visible = true },
149 | new WaitEvent { timeToWait = alphaSwordDelay },
150 | new SpawnTargetedEvents { referenceMechanicName = "AlphaSword", isPositionRelative = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {0} } },
151 | new WaitEvent { timeToWait = blasstyChargeDelay },
152 | new SpawnTargetedEvents { referenceMechanicName = "BlasstyCharge", isPositionRelative = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {1} } },
153 | new SetEnemyVisible { visible = false },
154 |
155 | new WaitEvent { timeToWait = limitcutGap },
156 | new SetEnemyMovement { movementTime = 0.01f, moveToTarget = new TargetSpecificPlayerIds { targetIds = new List{2} }, position = new Vector3(0, -1) },
157 | new WaitEvent { timeToWait = 0.01f },
158 | new SetEnemyMovement { movementTime = -1, moveToTarget =new TargetSpecificPlayerIds { targetIds = new List{2} } },
159 | new SetEnemyVisible { visible = true },
160 | new WaitEvent { timeToWait = alphaSwordDelay },
161 | new SpawnTargetedEvents { referenceMechanicName = "AlphaSword", isPositionRelative = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {2} } },
162 | new WaitEvent { timeToWait = blasstyChargeDelay },
163 | new SpawnTargetedEvents { referenceMechanicName = "BlasstyCharge", isPositionRelative = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {3} } },
164 | new SetEnemyVisible { visible = false },
165 |
166 | new WaitEvent { timeToWait = limitcutGap },
167 | new SetEnemyMovement { movementTime = 0.01f, moveToTarget = new TargetSpecificPlayerIds { targetIds = new List{4} }, position = new Vector3(0, -1) },
168 | new WaitEvent { timeToWait = 0.01f },
169 | new SetEnemyMovement { movementTime = -1, moveToTarget =new TargetSpecificPlayerIds { targetIds = new List{4} } },
170 | new SetEnemyVisible { visible = true },
171 | new WaitEvent { timeToWait = alphaSwordDelay },
172 | new SpawnTargetedEvents { referenceMechanicName = "AlphaSword", isPositionRelative = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {4} } },
173 | new WaitEvent { timeToWait = blasstyChargeDelay },
174 | new SpawnTargetedEvents { referenceMechanicName = "BlasstyCharge", isPositionRelative = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {5} } },
175 | new SetEnemyVisible { visible = false },
176 |
177 | new WaitEvent { timeToWait = limitcutGap },
178 | new SetEnemyMovement { movementTime = 0.01f, moveToTarget = new TargetSpecificPlayerIds { targetIds = new List{6} }, position = new Vector3(0, -1) },
179 | new WaitEvent { timeToWait = 0.01f },
180 | new SetEnemyMovement { movementTime = -1, moveToTarget =new TargetSpecificPlayerIds { targetIds = new List{6} } },
181 | new SetEnemyVisible { visible = true },
182 | new WaitEvent { timeToWait = alphaSwordDelay },
183 | new SpawnTargetedEvents { referenceMechanicName = "AlphaSword", isPositionRelative = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {6} } },
184 | new WaitEvent { timeToWait = blasstyChargeDelay },
185 | new SpawnTargetedEvents { referenceMechanicName = "BlasstyCharge", isPositionRelative = true, targetingScheme = new TargetSpecificPlayerIds { targetIds = new List {7} } },
186 | new SetEnemyVisible { visible = false },
187 | }
188 | }
189 | }
190 | },
191 | {
192 | "SetVisible",
193 | new MechanicProperties {
194 | visible = true,
195 | }
196 | },
197 | {
198 | "AlphaSword",
199 | new MechanicProperties
200 | {
201 | collisionShapeParams = new Vector4(10, 90),
202 | colorHtml = "#ffff00",
203 | visible = true,
204 | isTargeted = true,
205 | mechanic = new ExecuteMultipleEvents
206 | {
207 | events = new List
208 | {
209 | new WaitEvent { timeToWait = 0.2f },
210 | new ApplyEffectToPlayers
211 | {
212 | effects = new List
213 | {
214 | new DamageEffect {damageAmount = 50000, damageType = "Physical", name = "Alpha Sword" },
215 | new ApplyStatusEffect { referenceStatusName = "MagicVuln" },
216 | new ApplyStatusEffect { referenceStatusName = "PhysVuln" },
217 | new KnockbackEffect { knockbackDistance = 2, canArmsLength = true }
218 | }
219 | }
220 | }
221 | }
222 | }
223 | },
224 | {
225 | "BlasstyCharge",
226 | new MechanicProperties
227 | {
228 | collisionShape = CollisionShape.Rectangle,
229 | collisionShapeParams = new Vector4(40, 3.33f),
230 | colorHtml = "#ffff00",
231 | isTargeted = true,
232 | visible = true,
233 | mechanic = new ExecuteMultipleEvents
234 | {
235 | events = new List
236 | {
237 | new WaitEvent { timeToWait = 0.2f },
238 | new ApplyEffectToPlayers
239 | {
240 | condition = new CheckPlayerFacingAway(),
241 | effects = new List
242 | {
243 | new DamageEffect {damageAmount = 45000, damageType = "Physical", name = "Super Blassty Charge" },
244 | new ApplyStatusEffect { referenceStatusName = "MagicVuln" },
245 | new ApplyStatusEffect { referenceStatusName = "PhysVuln" },
246 | new KnockbackEffect { knockbackDistance = 10, canArmsLength = true }
247 | },
248 | failedConditionEffects = new List
249 | {
250 | new DamageEffect {damageAmount = 45000, damageType = "Physical", name = "Super Blassty Charge" },
251 | new ApplyStatusEffect { referenceStatusName = "MagicVuln" },
252 | new ApplyStatusEffect { referenceStatusName = "PhysVuln" },
253 | },
254 | }
255 | }
256 | }
257 | }
258 | },
259 | {
260 | "ArenaBoundary",
261 | new MechanicProperties
262 | {
263 | collisionShape = CollisionShape.Round,
264 | collisionShapeParams = new Vector4(25, 360, 6.6667f),
265 | colorHtml = "#8800FF",
266 | persistentTickInterval = 0.2f,
267 | persistentMechanic = new ApplyEffectToPlayers { effect = new DamageEffect { damageAmount = 9999999, damageType = "TrueDamage" } },
268 | }
269 | },
270 | };
271 |
272 | for (int i = 1; i <= 8; i++)
273 | {
274 | var scale = Vector3.one * 0.5f;
275 | if (i == 5) {
276 | scale = new Vector3(1.78f, 1, 1) * 0.5f;
277 | }
278 | else if (i > 5)
279 | {
280 | scale = new Vector3(2.16f, 1, 1) * 0.5f;
281 | }
282 | mechanicData.referenceMechanicProperties[$"LimitCutMarker-{i}"] = new MechanicProperties {
283 | visible = false,
284 | mechanic = new SpawnVisualObject {
285 | textureFilePath = $"Mechanics/Resources/LimitCut-{i}.png",
286 | colorHtml = i % 2 == 0 ? "#ff0000" : "#0000ff",
287 | visualDuration = 8,
288 | scale = scale,
289 | relativePosition = Vector3.up,
290 | isBillboard = true,
291 | spawnOnPlayer = true,
292 | }
293 | };
294 | }
295 |
296 | mechanicData.referenceStatusProperties = new Dictionary
297 | {
298 | {
299 | "MagicVuln",
300 | new DamageModifier
301 | {
302 | statusIconPath = "Mechanics/Resources/MagicVuln.png",
303 | statusName = "Magic Vulnerability Up",
304 | statusDescription = "Magic damage taken is increased.",
305 | damageType = "Magic",
306 | damageMultiplier = 8,
307 | duration = 10,
308 | }
309 | },
310 | {
311 | "PhysVuln",
312 | new DamageModifier
313 | {
314 | statusIconPath = "Mechanics/Resources/PhysVuln.png",
315 | statusName = "Physical Vulnerability Up",
316 | statusDescription = "Physical damage taken is increased.",
317 | damageType = "Physical",
318 | damageMultiplier = 8,
319 | duration = 17,
320 | }
321 | }
322 | };
323 |
324 | mechanicData.mechanicEvents = new List
325 | {
326 | new SpawnMechanicEvent { referenceMechanicName = "ArenaBoundary" },
327 | new SpawnVisualObject
328 | {
329 | textureFilePath = "Mechanics/Resources/ArenaCircle.png",
330 | visualDuration = float.PositiveInfinity,
331 | relativePosition = new Vector3(0, -0.001f, 0),
332 | eulerAngles = new Vector3(90, 0, 0),
333 | scale = new Vector3(15.1082f, 15.1082f, 1),
334 | },
335 | new ExecuteMultipleEvents
336 | {
337 | events = new List
338 | {
339 | new WaitEvent { timeToWait = 2},
340 | new SpawnMechanicEvent { referenceMechanicName = "Spawn-CruiseChaser-LC" },
341 | }
342 | }
343 | };
344 | mechanicData.mechanicPools = new Dictionary>
345 | {
346 | {
347 | "Hawkblaster-Pool",
348 | new List
349 | {
350 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterSequence"},
351 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterSequence", rotation = 45 },
352 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterSequence", rotation = 90 },
353 | new SpawnMechanicEvent { referenceMechanicName = "HawkBlasterSequence", rotation = 135 },
354 | }
355 | },
356 | };
357 |
358 | var resultText = mechanicData.ToString();
359 |
360 | File.WriteAllText($@"{baseOutputPath}\Mechanics\{mechanicName}.json", resultText);
361 | File.WriteAllText($@"{baseOutputPath}\Build\Mechanics\{mechanicName}.json", resultText);
362 | File.WriteAllText($@"{buildOutputPath}\Mechanics\{mechanicName}.json", resultText);
363 |
364 | $"Finished writing json to Mechanics/{mechanicName}.json".Dump();
--------------------------------------------------------------------------------
/Linqpad/MechanicSets/Quickmarch.linq:
--------------------------------------------------------------------------------
1 |
2 | D:\src\Unity\xiv-sim\Library\ScriptAssemblies\Assembly-CSharp.dll
3 | <ProgramFilesX64>\Unity\Hub\Editor\2020.3.6f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
4 | UnityEngine
5 |
6 |
7 | var mechanicName = "QuickmarchDemo";
8 | var baseOutputPath = @"D:\src\Unity\xiv-sim";
9 | var buildOutputPath = @"D:\src\Unity\xiv-sim-mechanics";
10 |
11 | var mechanicData = new MechanicData();
12 |
13 | mechanicData.referenceMechanicProperties = new Dictionary
14 | {
15 | {
16 | "BahaDive",
17 | new MechanicProperties
18 | {
19 | collisionShape = CollisionShape.Rectangle,
20 | collisionShapeParams = new Vector4(14, 4),
21 | colorHtml = "#0a4d8b",
22 | visible = false,
23 | mechanic = new ExecuteMultipleEvents
24 | {
25 | events = new List
26 | {
27 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Bahamut.png", colorHtml = "#0a4d8b", visualDuration = 5, relativePosition = Vector3.up, scale = new Vector3(1, 1, 1), eulerAngles = new Vector3(0, 180, 0), isRotationRelative = true },
28 | new WaitEvent { timeToWait = 4.3f },
29 | new ModifyMechanicEvent { referenceMechanicName = "SetVisible" },
30 | new WaitEvent { timeToWait = 0.2f },
31 | new ApplyEffectToPlayers {
32 | effects = new List {
33 | new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Megaflare Dive" },
34 | new KnockbackEffect { knockbackDistance = 10 },
35 | }
36 | }
37 | }
38 | }
39 | }
40 | },
41 | {
42 | "NaelDive",
43 | new MechanicProperties
44 | {
45 | collisionShape = CollisionShape.Rectangle,
46 | collisionShapeParams = new Vector4(14, 4),
47 | colorHtml = "#a917bf",
48 | visible = false,
49 | mechanic = new ExecuteMultipleEvents
50 | {
51 | events = new List
52 | {
53 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Nael.png", colorHtml = "#a917bf", visualDuration = 5, relativePosition = Vector3.up, scale = new Vector3(1, 1, 1), eulerAngles = new Vector3(0, 180, 0), isRotationRelative = true },
54 | new WaitEvent { timeToWait = 4.3f },
55 | new ModifyMechanicEvent { referenceMechanicName = "SetVisible" },
56 | new WaitEvent { timeToWait = 0.2f },
57 | new ApplyEffectToPlayers {
58 | effects = new List {
59 | new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Raven Dive" },
60 | new KnockbackEffect { knockbackDistance = 10 },
61 | }
62 | }
63 | }
64 | }
65 | }
66 | },
67 | {
68 | "TwinDive",
69 | new MechanicProperties
70 | {
71 | collisionShape = CollisionShape.Rectangle,
72 | collisionShapeParams = new Vector4(14, 4),
73 | colorHtml = "#067743",
74 | visible = false,
75 | mechanic = new ExecuteMultipleEvents
76 | {
77 | events = new List
78 | {
79 | new SpawnVisualObject { textureFilePath = "Mechanics/Resources/Twintania.png", colorHtml = "#067743", visualDuration = 5, relativePosition = Vector3.up, scale = new Vector3(1, 1, 1), eulerAngles = new Vector3(0, 180, 0), isRotationRelative = true },
80 | new WaitEvent { timeToWait = 4.3f },
81 | new ModifyMechanicEvent { referenceMechanicName = "SetVisible" },
82 | new WaitEvent { timeToWait = 0.2f },
83 | new ApplyEffectToPlayers {
84 | effects = new List {
85 | new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Twisting Dive" },
86 | new KnockbackEffect { knockbackDistance = 10 },
87 | }
88 | }
89 | }
90 | }
91 | }
92 | },
93 | {
94 | "Twister Explode",
95 | new MechanicProperties
96 | {
97 | collisionShape = CollisionShape.Round,
98 | collisionShapeParams = new Vector4(3, 360),
99 | colorHtml = "#008542",
100 | mechanic = new ExecuteMultipleEvents
101 | {
102 | events = new List
103 | {
104 | new WaitEvent { timeToWait = 0.2f },
105 | new ApplyEffectToPlayers {
106 | effects = new List {
107 | new DamageEffect { damageAmount = 90000, damageType = "Damage", name = "Twister" },
108 | new KnockbackEffect { knockbackDistance = 10 },
109 | }
110 | }
111 | }
112 | }
113 | }
114 | },
115 | {
116 | "TwisterSnapshot",
117 | new MechanicProperties
118 | {
119 | isTargeted = false,
120 | followSpeed = 0,
121 | }
122 | },
123 | {
124 | "Twister",
125 | new MechanicProperties
126 | {
127 | collisionShape = CollisionShape.Round,
128 | collisionShapeParams = new Vector4(0.25f, 360),
129 | colorHtml = "#008542",
130 | visible = false,
131 | isTargeted = true,
132 | followSpeed = 100,
133 | mechanic = new ExecuteMultipleEvents
134 | {
135 | events = new List
136 | {
137 | new WaitEvent { timeToWait = 1.5f },
138 | new ModifyMechanicEvent { referenceMechanicName = "TwisterSnapshot" },
139 | new WaitEvent { timeToWait = 0.5f },
140 | new ModifyMechanicEvent { referenceMechanicName = "SetVisible" },
141 | new WaitEvent { timeToWait = 5 },
142 | }
143 | },
144 | persistentTickInterval = 0.1f,
145 | persistentActivationDelay = 2.5f,
146 | persistentMechanic = new ExecuteMultipleEvents
147 | {
148 | events = new List
149 | {
150 | new CheckNumberOfPlayers
151 | {
152 | expressionFormat = "{0} = 0",
153 | failEvent = new ExecuteMultipleEvents{
154 | events = new List