@v12-engine/create 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +26 -2
  3. package/base/_gitignore +10 -0
  4. package/base/index.html +20 -0
  5. package/base/package.json +23 -0
  6. package/base/src/ground.worker.ts +8 -0
  7. package/base/src/main.ts +61 -0
  8. package/base/tsconfig.json +14 -0
  9. package/base/vite.config.ts +25 -0
  10. package/bin.mjs +10 -0
  11. package/cli.mjs +381 -0
  12. package/index.mjs +286 -0
  13. package/layers/assets/package.json +5 -0
  14. package/layers/editor/package.json +8 -0
  15. package/layers/editor/src/editor.ts +13 -0
  16. package/layers/rooms/server.ts +69 -0
  17. package/layers/server/package.json +8 -0
  18. package/layers/server/server.ts +34 -0
  19. package/layers/source/package.json +12 -0
  20. package/layers/source/tsconfig.json +5 -0
  21. package/layers/source/vite.config.ts +45 -0
  22. package/layers/tests/package.json +8 -0
  23. package/package.json +46 -5
  24. package/starters/campaign/README.md +61 -0
  25. package/starters/campaign/files.txt +42 -0
  26. package/starters/campaign/layers/editor/src/editor.ts +18 -0
  27. package/starters/campaign/layers/rooms/server.ts +39 -0
  28. package/starters/campaign/layers/server/server.ts +33 -0
  29. package/starters/campaign/layers/tests/tests/rules.test.ts +320 -0
  30. package/starters/campaign/public/games/campaign/assets.json +1 -0
  31. package/starters/campaign/src/campaign/campaign.json +52 -0
  32. package/starters/campaign/src/campaign/carry.ts +47 -0
  33. package/starters/campaign/src/campaign/cinematics/intro.json +148 -0
  34. package/starters/campaign/src/campaign/cinematics/outro.json +92 -0
  35. package/starters/campaign/src/campaign/data.json +1 -0
  36. package/starters/campaign/src/campaign/fx.json +1 -0
  37. package/starters/campaign/src/campaign/game.ts +6 -0
  38. package/starters/campaign/src/campaign/ids.ts +77 -0
  39. package/starters/campaign/src/campaign/index.ts +121 -0
  40. package/starters/campaign/src/campaign/kills.ts +16 -0
  41. package/starters/campaign/src/campaign/looks.json +1 -0
  42. package/starters/campaign/src/campaign/maps.ts +34 -0
  43. package/starters/campaign/src/campaign/missions/homecoming.ts +160 -0
  44. package/starters/campaign/src/campaign/missions/siege.ts +91 -0
  45. package/starters/campaign/src/campaign/missions/warlord.ts +177 -0
  46. package/starters/campaign/src/campaign/prefabs/watchpost.prefab.json +18 -0
  47. package/starters/campaign/src/campaign/scenes.ts +46 -0
  48. package/starters/campaign/src/campaign/tiles.ts +8 -0
  49. package/starters/campaign/src/campaign/units.ts +390 -0
  50. package/starters/campaign/src/campaign/view/cinematics.ts +59 -0
  51. package/starters/campaign/src/campaign/view/fire.ts +115 -0
  52. package/starters/campaign/src/campaign/view/index.ts +334 -0
  53. package/starters/campaign/src/campaign/view/labels.ts +105 -0
  54. package/starters/campaign/src/campaign/view/rubble.ts +40 -0
  55. package/starters/campaign/src/campaign/view/waveLane.ts +88 -0
  56. package/starters/campaign/src/campaign/waves.json +36 -0
  57. package/starters/campaign/src/campaign/waves.ts +186 -0
  58. package/starters/campaign/src/campaign-editor.ts +43 -0
  59. package/starters/campaign/src/game.ts +2 -0
  60. package/starters/campaign/src/main.ts +70 -0
  61. package/starters/campaign/src/maps/fort.names.ts +31 -0
  62. package/starters/campaign/src/maps/fort.vgmap.json +1162 -0
  63. package/starters/campaign/src/maps/homestead.names.ts +36 -0
  64. package/starters/campaign/src/maps/homestead.vgmap.json +916 -0
  65. package/starters/campaign/src/maps/pass.names.ts +40 -0
  66. package/starters/campaign/src/maps/pass.vgmap.json +522 -0
  67. package/starters/campaign/src/maps.ts +2 -0
  68. package/starters/campaign/src/rules.ts +20 -0
  69. package/starters/campaign/src/waves-panel.ts +355 -0
  70. package/starters/empty/README.md +71 -0
  71. package/starters/empty/layers/tests/tests/rules.test.ts +31 -0
  72. package/starters/empty/src/game.ts +79 -0
  73. package/starters/empty/src/generate.worker.ts +9 -0
  74. package/starters/empty/src/maps.ts +44 -0
  75. package/starters/empty/src/rules.ts +67 -0
  76. package/starters/empty/src/tiles.ts +12 -0
  77. package/starters/melee/README.md +61 -0
  78. package/starters/melee/files.txt +60 -0
  79. package/starters/melee/layers/editor/src/editor.ts +13 -0
  80. package/starters/melee/layers/tests/tests/rules.test.ts +58 -0
  81. package/starters/melee/src/game.ts +2 -0
  82. package/starters/melee/src/maps/bay.names.ts +28 -0
  83. package/starters/melee/src/maps/bay.vgmap.json +3123 -0
  84. package/starters/melee/src/maps.ts +20 -0
  85. package/starters/melee/src/melee/abilities.ts +376 -0
  86. package/starters/melee/src/melee/bay.ts +319 -0
  87. package/starters/melee/src/melee/blight.ts +102 -0
  88. package/starters/melee/src/melee/cellLayers.json +11 -0
  89. package/starters/melee/src/melee/data.json +18 -0
  90. package/starters/melee/src/melee/floats.json +199 -0
  91. package/starters/melee/src/melee/formations.ts +46 -0
  92. package/starters/melee/src/melee/fx.json +1 -0
  93. package/starters/melee/src/melee/game.ts +6 -0
  94. package/starters/melee/src/melee/generator.ts +116 -0
  95. package/starters/melee/src/melee/heroSpells.ts +38 -0
  96. package/starters/melee/src/melee/hud.json +269 -0
  97. package/starters/melee/src/melee/index.ts +182 -0
  98. package/starters/melee/src/melee/items.ts +362 -0
  99. package/starters/melee/src/melee/languages/he.json +96 -0
  100. package/starters/melee/src/melee/looks.json +1 -0
  101. package/starters/melee/src/melee/maps.ts +53 -0
  102. package/starters/melee/src/melee/pings.json +16 -0
  103. package/starters/melee/src/melee/pings.ts +34 -0
  104. package/starters/melee/src/melee/quality.json +1 -0
  105. package/starters/melee/src/melee/saves.ts +12 -0
  106. package/starters/melee/src/melee/sounds.json +1 -0
  107. package/starters/melee/src/melee/undead.ts +683 -0
  108. package/starters/melee/src/melee/units.ts +785 -0
  109. package/starters/melee/src/melee/view/buildings.ts +33 -0
  110. package/starters/melee/src/melee/view/cheerLane.ts +42 -0
  111. package/starters/melee/src/melee/view/heroSpellLooks.ts +21 -0
  112. package/starters/melee/src/melee/view/index.ts +268 -0
  113. package/starters/melee/src/melee/view/languages.ts +10 -0
  114. package/starters/melee/src/melee/view/looks.ts +659 -0
  115. package/starters/melee/src/melee/view/undeadLooks.ts +220 -0
  116. package/starters/melee/src/melee/view/walls.ts +59 -0
  117. package/starters/melee/src/rules.ts +24 -0
  118. package/starters.mjs +35 -0
  119. package/v12.mjs +111 -0
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The maps of the game: those in `src/maps`, made in its editor (`/?editor`, whose Save writes them there). A new map is
3
+ * a new file there, imported here as this one is. (Not with Vite's `import.meta.glob`: a server run by Node has no such
4
+ * thing.) Random maps come from the rules' generator (`src/melee/generator.ts`): Play a random map on the start screen
5
+ */
6
+ import { type GameMap, mapsFrom } from '@v12-engine/engine'
7
+ import bay from './maps/bay.vgmap.json'
8
+
9
+ /** The maps by the name of their file, without `.vgmap.json`: `bay` */
10
+ export const maps: Readonly<Record<string, GameMap>> = mapsFrom({ './maps/bay.vgmap.json': bay })
11
+
12
+ /** The map a game is on when nothing says which, and the one the editor opens first */
13
+ export const DEFAULT_MAP = 'bay'
14
+
15
+ /** A map by name, as a copy: a game changes nothing of what the next one starts from */
16
+ export function mapNamed(name = DEFAULT_MAP): GameMap {
17
+ const map = maps[name]
18
+ if (!map) throw new Error(`There is no map "${name}": the maps are ${Object.keys(maps).join(', ')}`)
19
+ return structuredClone(map)
20
+ }
@@ -0,0 +1,376 @@
1
+ import { type AbilityDef, type BuffDef, invalidateStats } from '@v12-engine/engine'
2
+
3
+ export const buffs: BuffDef[] = [
4
+ { id: 'devotion', name: 'Devotion Aura', description: 'More armor from a Paladin nearby', stats: { armor: [9, 18, 27] } },
5
+ { id: 'clarity', name: 'Clarity Aura', description: 'Mana comes back faster near an Archmage', stats: { manaRegen: [0.75, 1.5, 2.25] } },
6
+ {
7
+ id: 'blessedSprint',
8
+ name: 'Blessed Sprint',
9
+ description: '+50% move speed that fades away over its time',
10
+ // worked out in code: the speed is the share of the time that is left, so the stats are added up again every tick (the engine's checks refuse stale ones)
11
+ change: (_world, _carrier, instance) => {
12
+ const total = instance.elapsed + instance.remaining
13
+ return { percent: { moveSpeed: total > 0 ? 0.5 * Math.max(instance.remaining / total, 0) : 0 } }
14
+ },
15
+ onTick: { every: 0.01, run: (world, carrier) => invalidateStats(world, carrier) }
16
+ },
17
+ { id: 'stunned', name: 'Stunned', description: 'Cannot do anything', harmful: true, stun: true },
18
+ {
19
+ id: 'avatar',
20
+ name: 'Avatar',
21
+ description: '+60 armor, +40 magic resist, +25 attack damage, stuns and slows last half as long, and immune to spells',
22
+ duration: 30,
23
+ stats: { armor: 60, magicResist: 40, attackDamage: 25, tenacity: 0.5 },
24
+ spellImmune: true,
25
+ // a dispel does not end it early
26
+ dispellable: false
27
+ },
28
+ {
29
+ id: 'burrowed',
30
+ name: 'Burrowed',
31
+ description: 'In the ground: unseen without detection, cannot move or attack, and heals 6 a second',
32
+ invisible: true,
33
+ root: true,
34
+ disarm: true,
35
+ stats: { healthRegen: 6 },
36
+ dispellable: false
37
+ },
38
+ {
39
+ id: 'defend',
40
+ name: 'Defend',
41
+ description: 'Shield raised: +24 armor, 30% slower',
42
+ duration: 10,
43
+ stats: { armor: 24 },
44
+ percent: { moveSpeed: -0.3 }
45
+ },
46
+ { id: 'innerFire', name: 'Inner Fire', description: '+5 attack damage and +18 armor', duration: 30, stats: { attackDamage: 5, armor: 18 } },
47
+ {
48
+ id: 'slow',
49
+ name: 'Slow',
50
+ description: 'Moves 50% and attacks 25% slower',
51
+ duration: 15,
52
+ harmful: true,
53
+ percent: { moveSpeed: -0.5, attackSpeed: -0.25 }
54
+ },
55
+ { id: 'knockedUp', name: 'Knocked Up', description: 'Thrown into the air, cannot do anything', harmful: true, airborne: true, duration: 1 },
56
+ {
57
+ id: 'lassoed',
58
+ name: 'Lassoed',
59
+ description: 'Pulled down and held: cannot do anything, and can be hit from the ground',
60
+ harmful: true,
61
+ stun: true,
62
+ grounds: true
63
+ },
64
+ {
65
+ id: 'manaShield',
66
+ name: 'Mana Shield',
67
+ description: 'A shield takes the damage',
68
+ duration: 8,
69
+ shield: [90, 150, 210],
70
+ shieldScaling: { abilityPower: 0.5 }
71
+ }
72
+ ]
73
+
74
+ export const abilities: AbilityDef[] = [
75
+ // ---- Paladin
76
+ {
77
+ id: 'holyLight',
78
+ name: 'Holy Light',
79
+ description: 'Heals a friendly unit for 200, 350 or 500 (+80% ability power)',
80
+ hotkey: 'T',
81
+ target: 'unit',
82
+ targets: { allies: true, self: false },
83
+ manaCost: 65,
84
+ cooldown: 5,
85
+ range: 8,
86
+ castTime: 0.4,
87
+ effects: [{ type: 'heal', amount: [200, 350, 500], scaling: { abilityPower: 0.8 } }]
88
+ },
89
+ {
90
+ id: 'stomp',
91
+ tags: ['ground'],
92
+ name: 'War Stomp',
93
+ description: 'Hits enemies on the ground around the hero for 40, 70 or 100 and stuns them for 2 seconds (+60% attack damage)',
94
+ hotkey: 'W',
95
+ target: 'none',
96
+ manaCost: 90,
97
+ cooldown: 7,
98
+ castTime: 0.3,
99
+ effects: [
100
+ { type: 'damage', amount: [40, 70, 100], scaling: { attackDamage: 0.6 }, damageType: 'physical', layers: ['ground'], radius: 3.5 },
101
+ { type: 'buff', buff: 'stunned', duration: 2, layers: ['ground'], radius: 3.5 }
102
+ ]
103
+ },
104
+ {
105
+ id: 'devotionAura',
106
+ name: 'Devotion Aura',
107
+ description: 'Friendly units nearby get 9, 18 or 27 armor',
108
+ target: 'passive',
109
+ effects: [{ type: 'aura', buff: 'devotion', radius: 9 }]
110
+ },
111
+ {
112
+ id: 'blessedSprint',
113
+ name: 'Blessed Sprint',
114
+ description: 'The Paladin runs 50% faster, fading away to normal over 2, 4 or 6 seconds',
115
+ hotkey: 'G',
116
+ target: 'none',
117
+ manaCost: 50,
118
+ cooldown: 15,
119
+ effects: [{ type: 'buff', buff: 'blessedSprint', on: 'caster', duration: [2, 4, 6] }]
120
+ },
121
+ {
122
+ id: 'avatar',
123
+ name: 'Avatar',
124
+ description: 'For 30 seconds: +60 armor, +40 magic resist, +25 attack damage, stuns and slows last half as long, and immune to spells',
125
+ hotkey: 'V',
126
+ target: 'none',
127
+ manaCost: 150,
128
+ cooldown: 120,
129
+ maxLevel: 1,
130
+ requiresLevel: 6,
131
+ effects: [{ type: 'buff', buff: 'avatar', on: 'caster' }]
132
+ },
133
+
134
+ // ---- Archmage
135
+ {
136
+ id: 'flameStrike',
137
+ name: 'Flame Strike',
138
+ description: 'Burns enemies on the ground in an area for 90, 150 or 210 (+70% ability power)',
139
+ hotkey: 'F',
140
+ target: 'point',
141
+ manaCost: 120,
142
+ cooldown: 9,
143
+ range: 9,
144
+ castTime: 0.8,
145
+ effects: [{ type: 'damage', amount: [90, 150, 210], scaling: { abilityPower: 0.7 }, layers: ['ground'], radius: 3 }]
146
+ },
147
+ {
148
+ id: 'frostBolt',
149
+ name: 'Frost Bolt',
150
+ description: 'Hits an enemy for 80, 140 or 200 and stuns it for 2 seconds (+60% ability power)',
151
+ hotkey: 'T',
152
+ target: 'unit',
153
+ targets: { enemies: true },
154
+ manaCost: 75,
155
+ cooldown: 8,
156
+ range: 8,
157
+ castTime: 0.3,
158
+ effects: [
159
+ { type: 'damage', amount: [80, 140, 200], scaling: { abilityPower: 0.6 } },
160
+ { type: 'buff', buff: 'stunned', duration: 2 }
161
+ ]
162
+ },
163
+ {
164
+ id: 'clarityAura',
165
+ name: 'Clarity Aura',
166
+ description: 'Friendly units nearby regain 0.75, 1.5 or 2.25 more mana per second',
167
+ target: 'passive',
168
+ effects: [{ type: 'aura', buff: 'clarity', radius: 9 }]
169
+ },
170
+ {
171
+ id: 'cataclysm',
172
+ name: 'Cataclysm',
173
+ description: 'Deals 350 damage to enemies in a large area (+100% ability power)',
174
+ hotkey: 'C',
175
+ target: 'point',
176
+ manaCost: 200,
177
+ cooldown: 120,
178
+ range: 9,
179
+ castTime: 1.2,
180
+ maxLevel: 1,
181
+ requiresLevel: 6,
182
+ effects: [{ type: 'damage', amount: 350, scaling: { abilityPower: 1 }, radius: 5 }]
183
+ },
184
+
185
+ // ---- Testiro
186
+ {
187
+ id: 'tornado',
188
+ name: 'Tornado',
189
+ description:
190
+ 'Whips up a tornado that takes shape where the hero stands and sets off in a line. Enemies it passes, on the ground and in the air, take 60, 85 or 110 (+35% ability power) and are thrown up for 1 second',
191
+ hotkey: 'T',
192
+ target: 'direction',
193
+ manaCost: [60, 70, 80],
194
+ cooldown: [12, 11, 10],
195
+ effects: [
196
+ {
197
+ type: 'missile',
198
+ delay: 0.75,
199
+ speed: 11,
200
+ distance: [11, 12.5, 14],
201
+ radius: 1.4,
202
+ effects: [
203
+ { type: 'damage', amount: [60, 85, 110], scaling: { abilityPower: 0.35 } },
204
+ { type: 'buff', buff: 'knockedUp', duration: 1 }
205
+ ]
206
+ }
207
+ ]
208
+ },
209
+ {
210
+ id: 'groundSmash',
211
+ tags: ['ground'],
212
+ name: 'Ground Smash',
213
+ description:
214
+ 'After a moment of standing still, breaks the ground in a circle: enemies standing on it are stunned for 1 second. What flies does not care',
215
+ hotkey: 'G',
216
+ target: 'point',
217
+ manaCost: [70, 75, 80],
218
+ cooldown: [14, 12, 10],
219
+ range: 8,
220
+ castTime: 0.35,
221
+ effects: [{ type: 'buff', buff: 'stunned', duration: 1, radius: [2.6, 3, 3.4], layers: ['ground'] }]
222
+ },
223
+ {
224
+ id: 'lasso',
225
+ name: 'Lasso',
226
+ description: 'Catches an enemy in the air and pulls it down for 3, 4 or 5 seconds: it cannot do anything, and can be hit from the ground',
227
+ hotkey: 'W',
228
+ target: 'unit',
229
+ targets: { enemies: true, layers: ['air'] },
230
+ manaCost: 50,
231
+ cooldown: [12, 10, 8],
232
+ range: 8,
233
+ castTime: 0.25,
234
+ effects: [{ type: 'buff', buff: 'lassoed', duration: [3, 4, 5] }]
235
+ },
236
+
237
+ // ---- creeps
238
+ {
239
+ id: 'clap',
240
+ tags: ['ground'],
241
+ name: 'Thunder Clap',
242
+ description: 'Hits enemies on the ground around for 60 and slows them',
243
+ target: 'none',
244
+ manaCost: 90,
245
+ cooldown: 12,
246
+ castTime: 0.5,
247
+ effects: [
248
+ { type: 'damage', amount: 60, layers: ['ground'], radius: 3 },
249
+ { type: 'buff', buff: 'slow', duration: 5, layers: ['ground'], radius: 3 }
250
+ ]
251
+ },
252
+
253
+ // ---- units
254
+ {
255
+ id: 'manaShield',
256
+ name: 'Mana Shield',
257
+ description: 'Shields a friendly unit against 90 damage (+50% ability power) for 8 seconds',
258
+ hotkey: 'D',
259
+ target: 'unit',
260
+ targets: { allies: true, self: true },
261
+ manaCost: 50,
262
+ cooldown: 6,
263
+ range: 7,
264
+ castTime: 0.3,
265
+ effects: [{ type: 'buff', buff: 'manaShield' }]
266
+ },
267
+ {
268
+ id: 'defend',
269
+ name: 'Defend',
270
+ description: 'Raises the shield for 10 seconds: +24 armor, but 30% slower',
271
+ hotkey: 'D',
272
+ target: 'none',
273
+ cooldown: 16,
274
+ effects: [{ type: 'buff', buff: 'defend', on: 'caster' }]
275
+ },
276
+ {
277
+ id: 'burrow',
278
+ name: 'Burrow',
279
+ description: 'Goes into the ground: unseen without detection, cannot move or attack, and heals. Again to come out',
280
+ hotkey: 'Z',
281
+ target: 'none',
282
+ cooldown: 1,
283
+ castTime: 0.5,
284
+ effects: [{ type: 'toggle', buff: 'burrowed' }]
285
+ },
286
+ {
287
+ id: 'dispelMagic',
288
+ name: 'Dispel Magic',
289
+ description: 'Takes what is good off enemies and what is bad off friends in an area, and deals 200 to what spells brought',
290
+ hotkey: 'C',
291
+ target: 'point',
292
+ range: 8,
293
+ manaCost: 75,
294
+ cooldown: 6,
295
+ castTime: 0.3,
296
+ aim: { shape: 'circle', radius: 3 },
297
+ effects: [{ type: 'dispel', radius: 3, amount: 200 }]
298
+ },
299
+ {
300
+ id: 'raiseDead',
301
+ name: 'Raise Dead',
302
+ description: 'Two corpses near the priest rise as Skeleton Warriors, for 40 seconds',
303
+ hotkey: 'V',
304
+ target: 'none',
305
+ manaCost: 60,
306
+ cooldown: 8,
307
+ castTime: 0.5,
308
+ effects: [{ type: 'raiseDead', unit: 'skeleton', count: 2, radius: 7, duration: 40 }]
309
+ },
310
+ {
311
+ id: 'mirrorImage',
312
+ name: 'Mirror Image',
313
+ description:
314
+ 'Two images of the sorceress appear next to her for 25 seconds. They deal a third of her damage and take twice as much. Enemies cannot tell them from her',
315
+ hotkey: 'X',
316
+ target: 'none',
317
+ manaCost: 80,
318
+ cooldown: 15,
319
+ castTime: 0.3,
320
+ effects: [{ type: 'illusion', count: 2, duration: 25, dealt: 1 / 3, taken: 2 }]
321
+ },
322
+ {
323
+ id: 'heal',
324
+ name: 'Heal',
325
+ description: 'Heals a friendly unit for 25 (+30% ability power)',
326
+ // E belongs to the camera
327
+ hotkey: 'R',
328
+ target: 'unit',
329
+ targets: { allies: true, self: false },
330
+ manaCost: 5,
331
+ cooldown: 1,
332
+ range: 6,
333
+ castTime: 0.3,
334
+ autocast: true,
335
+ effects: [{ type: 'heal', amount: 25, scaling: { abilityPower: 0.3 } }]
336
+ },
337
+ {
338
+ id: 'innerFire',
339
+ name: 'Inner Fire',
340
+ description: 'Gives a friendly unit +5 attack damage and +18 armor for 30 seconds',
341
+ hotkey: 'F',
342
+ target: 'unit',
343
+ targets: { allies: true, self: true },
344
+ manaCost: 35,
345
+ cooldown: 1,
346
+ range: 7,
347
+ castTime: 0.4,
348
+ effects: [{ type: 'buff', buff: 'innerFire' }]
349
+ },
350
+ {
351
+ id: 'slow',
352
+ name: 'Slow',
353
+ description: 'Slows an enemy for 15 seconds: moves 50% and attacks 25% slower',
354
+ hotkey: 'W',
355
+ target: 'unit',
356
+ targets: { enemies: true },
357
+ manaCost: 40,
358
+ cooldown: 1,
359
+ range: 7,
360
+ castTime: 0.3,
361
+ autocast: true,
362
+ effects: [{ type: 'buff', buff: 'slow' }]
363
+ },
364
+ {
365
+ id: 'arcaneBlast',
366
+ name: 'Arcane Blast',
367
+ description: 'Deals 45 damage to enemies in a small area (+50% ability power)',
368
+ hotkey: 'B',
369
+ target: 'point',
370
+ manaCost: 75,
371
+ cooldown: 8,
372
+ range: 8,
373
+ castTime: 0.6,
374
+ effects: [{ type: 'damage', amount: 45, scaling: { abilityPower: 0.5 }, radius: 2.5 }]
375
+ }
376
+ ]