@v12-engine/create 0.1.0 → 0.4.0
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.
- package/README.md +4 -1
- package/base/_gitignore +5 -0
- package/base/package.json +3 -3
- package/base/src/main.ts +36 -10
- package/base/src/navigation.worker.ts +7 -0
- package/base/vite.config.ts +24 -2
- package/cli.mjs +21 -6
- package/index.mjs +27 -7
- package/layers/desktop/electron/app.mjs +237 -0
- package/layers/desktop/electron/config.mjs +16 -0
- package/layers/desktop/electron/dev.mjs +63 -0
- package/layers/desktop/electron/files.mjs +86 -0
- package/layers/desktop/electron/icons/icon.icns +0 -0
- package/layers/desktop/electron/icons/icon.png +0 -0
- package/layers/desktop/electron/main.mjs +12 -0
- package/layers/desktop/electron/package.mjs +75 -0
- package/layers/desktop/electron/preload.cjs +41 -0
- package/layers/desktop/electron/presentation.m +87 -0
- package/layers/desktop/electron/serve.mjs +76 -0
- package/layers/desktop/electron/tools.mjs +63 -0
- package/layers/desktop/electron/updates.mjs +71 -0
- package/layers/desktop/package.json +13 -0
- package/layers/desktop/src/desktop.ts +175 -0
- package/layers/desktop/src/shell.ts +279 -0
- package/layers/desktop/tests/main.test.ts +189 -0
- package/layers/desktop/tests/shell.test.ts +152 -0
- package/layers/rooms/server.ts +13 -10
- package/layers/server/server.ts +4 -5
- package/layers/source/vite.config.ts +21 -1
- package/package.json +2 -1
- package/starters/campaign/README.md +9 -2
- package/starters/campaign/layers/rooms/server.ts +3 -3
- package/starters/campaign/layers/server/server.ts +3 -5
- package/starters/campaign/layers/tests/tests/rules.test.ts +40 -21
- package/starters/campaign/src/campaign/game.ts +26 -5
- package/starters/campaign/src/campaign/index.ts +104 -68
- package/starters/campaign/src/campaign/kills.ts +1 -1
- package/starters/campaign/src/campaign/missions/homecoming.ts +7 -7
- package/starters/campaign/src/campaign/missions/siege.ts +6 -6
- package/starters/campaign/src/campaign/missions/warlord.ts +13 -14
- package/starters/campaign/src/campaign/scenes.ts +8 -7
- package/starters/campaign/src/campaign/units.ts +59 -20
- package/starters/campaign/src/campaign/view/attacks.ts +19 -0
- package/starters/campaign/src/campaign/view/fire.ts +2 -2
- package/starters/campaign/src/campaign/view/index.ts +54 -43
- package/starters/campaign/src/campaign/waves.ts +18 -17
- package/starters/campaign/src/game.ts +8 -1
- package/starters/campaign/src/main.ts +38 -19
- package/starters/campaign/src/maps/fort.names.ts +2 -2
- package/starters/campaign/src/maps/fort.vgmap.json +102 -2
- package/starters/campaign/src/maps/homestead.names.ts +2 -2
- package/starters/campaign/src/maps/homestead.vgmap.json +85 -1
- package/starters/campaign/src/maps/pass.names.ts +2 -2
- package/starters/campaign/src/maps/pass.vgmap.json +69 -1
- package/starters/campaign/src/waves-panel.ts +2 -1
- package/starters/empty/README.md +18 -10
- package/starters/empty/layers/tests/tests/rules.test.ts +16 -17
- package/starters/empty/src/game.ts +11 -75
- package/starters/empty/src/generate.worker.ts +5 -5
- package/starters/empty/src/rules.ts +83 -25
- package/starters/empty/src/view.ts +82 -0
- package/starters/examples/README.md +83 -0
- package/starters/examples/layers/tests/tests/examples.test.ts +30 -0
- package/starters/examples/package.json +5 -0
- package/starters/examples/src/examples/abilities/areas.ts +165 -0
- package/starters/examples/src/examples/abilities/areasLooks.ts +30 -0
- package/starters/examples/src/examples/abilities/buffs.ts +287 -0
- package/starters/examples/src/examples/abilities/buffsLooks.ts +46 -0
- package/starters/examples/src/examples/abilities/changing.ts +228 -0
- package/starters/examples/src/examples/abilities/changingLooks.ts +61 -0
- package/starters/examples/src/examples/abilities/control.ts +158 -0
- package/starters/examples/src/examples/abilities/controlLooks.ts +78 -0
- package/starters/examples/src/examples/abilities/damage.ts +156 -0
- package/starters/examples/src/examples/abilities/damageLooks.ts +37 -0
- package/starters/examples/src/examples/abilities/family.ts +29 -0
- package/starters/examples/src/examples/abilities/index.ts +32 -0
- package/starters/examples/src/examples/abilities/kit.ts +179 -0
- package/starters/examples/src/examples/abilities/lookKit.ts +71 -0
- package/starters/examples/src/examples/abilities/looks.ts +47 -0
- package/starters/examples/src/examples/abilities/missiles.ts +203 -0
- package/starters/examples/src/examples/abilities/missilesLooks.ts +38 -0
- package/starters/examples/src/examples/abilities/moves.ts +206 -0
- package/starters/examples/src/examples/abilities/movesLooks.ts +52 -0
- package/starters/examples/src/examples/abilities/recasts.ts +181 -0
- package/starters/examples/src/examples/abilities/recastsLooks.ts +41 -0
- package/starters/examples/src/examples/abilities/resources.ts +166 -0
- package/starters/examples/src/examples/abilities/resourcesLooks.ts +42 -0
- package/starters/examples/src/examples/abilities/summons.ts +296 -0
- package/starters/examples/src/examples/abilities/summonsLooks.ts +115 -0
- package/starters/examples/src/examples/abilities/triggers.ts +204 -0
- package/starters/examples/src/examples/abilities/triggersLooks.ts +53 -0
- package/starters/examples/src/examples/abilities/vision.ts +137 -0
- package/starters/examples/src/examples/abilities/visionLooks.ts +50 -0
- package/starters/examples/src/examples/animation/index.ts +235 -0
- package/starters/examples/src/examples/animation/looks.ts +444 -0
- package/starters/examples/src/examples/catalog.ts +52 -0
- package/starters/examples/src/examples/cinematics/index.ts +217 -0
- package/starters/examples/src/examples/cinematics/looks.ts +476 -0
- package/starters/examples/src/examples/cinematics/tour.json +43 -0
- package/starters/examples/src/examples/cinematics/village.ts +88 -0
- package/starters/examples/src/examples/common/looks.ts +65 -0
- package/starters/examples/src/examples/common/units.ts +70 -0
- package/starters/examples/src/examples/construction/index.ts +329 -0
- package/starters/examples/src/examples/construction/looks.ts +275 -0
- package/starters/examples/src/examples/custom-animation/bones.ts +92 -0
- package/starters/examples/src/examples/custom-animation/index.ts +190 -0
- package/starters/examples/src/examples/custom-animation/looks.ts +523 -0
- package/starters/examples/src/examples/custom-animation/runes.ts +82 -0
- package/starters/examples/src/examples/custom-fx/glaive.look.ts +110 -0
- package/starters/examples/src/examples/custom-fx/glaive.ts +40 -0
- package/starters/examples/src/examples/custom-fx/gpu.look.ts +145 -0
- package/starters/examples/src/examples/custom-fx/gpu.ts +22 -0
- package/starters/examples/src/examples/custom-fx/index.ts +25 -0
- package/starters/examples/src/examples/custom-fx/lights.look.ts +144 -0
- package/starters/examples/src/examples/custom-fx/lights.ts +25 -0
- package/starters/examples/src/examples/custom-fx/looks.ts +36 -0
- package/starters/examples/src/examples/custom-fx/meteor.look.ts +133 -0
- package/starters/examples/src/examples/custom-fx/meteor.ts +26 -0
- package/starters/examples/src/examples/custom-fx/parts.look.ts +193 -0
- package/starters/examples/src/examples/custom-fx/parts.ts +21 -0
- package/starters/examples/src/examples/custom-fx/portal.look.ts +193 -0
- package/starters/examples/src/examples/custom-fx/portal.ts +48 -0
- package/starters/examples/src/examples/custom-fx/renderer.look.ts +139 -0
- package/starters/examples/src/examples/custom-fx/renderer.ts +18 -0
- package/starters/examples/src/examples/custom-fx/ribbons.look.ts +151 -0
- package/starters/examples/src/examples/custom-fx/ribbons.ts +22 -0
- package/starters/examples/src/examples/custom-fx/shader.ts +42 -0
- package/starters/examples/src/examples/custom-fx/shield.look.ts +226 -0
- package/starters/examples/src/examples/custom-fx/shield.ts +43 -0
- package/starters/examples/src/examples/define.ts +86 -0
- package/starters/examples/src/examples/destruction/index.ts +570 -0
- package/starters/examples/src/examples/destruction/looks.ts +447 -0
- package/starters/examples/src/examples/dialogs/index.ts +383 -0
- package/starters/examples/src/examples/dialogs/looks.ts +546 -0
- package/starters/examples/src/examples/dynamic-map/index.ts +603 -0
- package/starters/examples/src/examples/dynamic-map/looks.ts +301 -0
- package/starters/examples/src/examples/fx/blood.look.ts +62 -0
- package/starters/examples/src/examples/fx/blood.ts +59 -0
- package/starters/examples/src/examples/fx/feel.look.ts +86 -0
- package/starters/examples/src/examples/fx/feel.ts +57 -0
- package/starters/examples/src/examples/fx/fight.ts +28 -0
- package/starters/examples/src/examples/fx/floats.look.ts +108 -0
- package/starters/examples/src/examples/fx/floats.ts +24 -0
- package/starters/examples/src/examples/fx/gallery.look.ts +168 -0
- package/starters/examples/src/examples/fx/gallery.ts +23 -0
- package/starters/examples/src/examples/fx/index.ts +30 -0
- package/starters/examples/src/examples/fx/links.look.ts +83 -0
- package/starters/examples/src/examples/fx/links.ts +49 -0
- package/starters/examples/src/examples/fx/looks.ts +55 -0
- package/starters/examples/src/examples/fx/map.look.ts +93 -0
- package/starters/examples/src/examples/fx/map.ts +33 -0
- package/starters/examples/src/examples/fx/marks.look.ts +100 -0
- package/starters/examples/src/examples/fx/marks.ts +36 -0
- package/starters/examples/src/examples/fx/shots.look.ts +92 -0
- package/starters/examples/src/examples/fx/shots.ts +71 -0
- package/starters/examples/src/examples/fx/spells.look.ts +87 -0
- package/starters/examples/src/examples/fx/spells.ts +122 -0
- package/starters/examples/src/examples/fx/stage.ts +31 -0
- package/starters/examples/src/examples/gui/babylonScreen.ts +167 -0
- package/starters/examples/src/examples/gui/babylonWorld.ts +191 -0
- package/starters/examples/src/examples/gui/htmlPart.ts +95 -0
- package/starters/examples/src/examples/gui/index.ts +143 -0
- package/starters/examples/src/examples/gui/keys.ts +91 -0
- package/starters/examples/src/examples/gui/layout.ts +42 -0
- package/starters/examples/src/examples/gui/looks.ts +270 -0
- package/starters/examples/src/examples/gui/minimap.ts +127 -0
- package/starters/examples/src/examples/gui/ownInterface.ts +129 -0
- package/starters/examples/src/examples/gui/plates.ts +87 -0
- package/starters/examples/src/examples/gui/radial.ts +104 -0
- package/starters/examples/src/examples/gui/solidPart.ts +107 -0
- package/starters/examples/src/examples/looks.ts +45 -0
- package/starters/examples/src/examples/mechanics/battle.ts +51 -0
- package/starters/examples/src/examples/mechanics/damage.ts +80 -0
- package/starters/examples/src/examples/mechanics/flying.ts +93 -0
- package/starters/examples/src/examples/mechanics/formations.ts +58 -0
- package/starters/examples/src/examples/mechanics/highGround.ts +82 -0
- package/starters/examples/src/examples/mechanics/index.ts +44 -0
- package/starters/examples/src/examples/mechanics/looks.ts +289 -0
- package/starters/examples/src/examples/mechanics/maze.ts +119 -0
- package/starters/examples/src/examples/mechanics/orders.ts +68 -0
- package/starters/examples/src/examples/mechanics/selection.ts +30 -0
- package/starters/examples/src/examples/moba/index.ts +377 -0
- package/starters/examples/src/examples/moba/looks.ts +349 -0
- package/starters/examples/src/examples/moba/maps.ts +69 -0
- package/starters/examples/src/examples/moba/spells.ts +34 -0
- package/starters/examples/src/examples/moba/units.ts +196 -0
- package/starters/examples/src/examples/nature/camera.ts +15 -0
- package/starters/examples/src/examples/nature/grass.ts +64 -0
- package/starters/examples/src/examples/nature/index.ts +327 -0
- package/starters/examples/src/examples/nature/land.ts +173 -0
- package/starters/examples/src/examples/nature/looks.ts +577 -0
- package/starters/examples/src/examples/nature/maps.ts +370 -0
- package/starters/examples/src/examples/nature/skies.ts +324 -0
- package/starters/examples/src/examples/nature/weather.ts +80 -0
- package/starters/examples/src/examples/performance/index.ts +263 -0
- package/starters/examples/src/examples/performance/looks.ts +372 -0
- package/starters/examples/src/examples/performance/meter.ts +158 -0
- package/starters/examples/src/examples/post/grades.ts +86 -0
- package/starters/examples/src/examples/post/index.ts +202 -0
- package/starters/examples/src/examples/post/looks.ts +884 -0
- package/starters/examples/src/examples/post/passes.ts +213 -0
- package/starters/examples/src/examples/rts/ai.ts +49 -0
- package/starters/examples/src/examples/rts/airlift.ts +43 -0
- package/starters/examples/src/examples/rts/base.ts +129 -0
- package/starters/examples/src/examples/rts/build.ts +65 -0
- package/starters/examples/src/examples/rts/camps.ts +36 -0
- package/starters/examples/src/examples/rts/carry.ts +103 -0
- package/starters/examples/src/examples/rts/creeps.ts +61 -0
- package/starters/examples/src/examples/rts/data.ts +406 -0
- package/starters/examples/src/examples/rts/ferry.ts +41 -0
- package/starters/examples/src/examples/rts/garrison.ts +50 -0
- package/starters/examples/src/examples/rts/harvest.ts +29 -0
- package/starters/examples/src/examples/rts/hero.ts +67 -0
- package/starters/examples/src/examples/rts/index.ts +77 -0
- package/starters/examples/src/examples/rts/looks.ts +721 -0
- package/starters/examples/src/examples/rts/shop.ts +46 -0
- package/starters/examples/src/examples/rts/tech.ts +39 -0
- package/starters/examples/src/examples/rts/train.ts +48 -0
- package/starters/examples/src/examples/rts/waterside.ts +185 -0
- package/starters/examples/src/examples/showcase/index.ts +714 -0
- package/starters/examples/src/examples/showcase/looks.ts +238 -0
- package/starters/examples/src/game.ts +17 -0
- package/starters/examples/src/main.ts +82 -0
- package/starters/examples/src/rules.ts +31 -0
- package/starters/examples/src/shell/look.ts +79 -0
- package/starters/examples/src/shell/registry.ts +7 -0
- package/starters/examples/src/shell/scenes.ts +178 -0
- package/starters/examples/src/shell/shell.ts +290 -0
- package/starters/examples/src/shell/style.ts +202 -0
- package/starters/examples/src/view.ts +50 -0
- package/starters/melee/README.md +12 -3
- package/starters/melee/layers/tests/tests/heroes.test.ts +402 -0
- package/starters/melee/layers/tests/tests/rules.test.ts +10 -8
- package/starters/melee/src/game.ts +32 -2
- package/starters/melee/src/maps/bay.names.ts +2 -2
- package/starters/melee/src/maps/bay.vgmap.json +198 -1
- package/starters/melee/src/maps.ts +11 -9
- package/starters/melee/src/melee/abilities.ts +1 -194
- package/starters/melee/src/melee/blight.ts +7 -7
- package/starters/melee/src/melee/cellLayers.json +3 -3
- package/starters/melee/src/melee/data.json +1 -18
- package/starters/melee/src/melee/game.ts +6 -4
- package/starters/melee/src/melee/heroes.ts +1025 -0
- package/starters/melee/src/melee/index.ts +64 -61
- package/starters/melee/src/melee/items.ts +15 -362
- package/starters/melee/src/melee/languages/he.json +14 -2
- package/starters/melee/src/melee/pings.ts +5 -6
- package/starters/melee/src/melee/saves.ts +1 -1
- package/starters/melee/src/melee/undead.ts +15 -230
- package/starters/melee/src/melee/units.ts +37 -171
- package/starters/melee/src/melee/view/attacks.ts +19 -0
- package/starters/melee/src/melee/view/heroSpellLooks.ts +39 -8
- package/starters/melee/src/melee/view/index.ts +56 -52
- package/starters/melee/src/melee/view/looks.ts +86 -63
- package/starters/melee/src/melee/view/undeadLooks.ts +70 -31
- package/starters/melee/src/melee/view/walls.ts +1 -1
- package/starters.mjs +6 -0
- package/v12.mjs +14 -15
- package/starters/campaign/src/rules.ts +0 -20
- package/starters/empty/src/maps.ts +0 -44
- package/starters/empty/src/tiles.ts +0 -12
- package/starters/melee/src/melee/heroSpells.ts +0 -38
- package/starters/melee/src/rules.ts +0 -24
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Buffs and auras: something lasting on a unit, put on by the `buff` effect or kept on everyone near by an `aura`.
|
|
3
|
+
* Stats, a shield, stacks that go off at five, an immolation turned on and off, a bomb that goes off when its time is
|
|
4
|
+
* up, untouchable and unkillable, walking through units, cleaving blows, healing past full kept as a shield, and a
|
|
5
|
+
* doom that leaves a demon where its carrier dies
|
|
6
|
+
*/
|
|
7
|
+
import type { AbilityDef, BuffDef } from '@v12-engine/engine'
|
|
8
|
+
import { exampleField } from '../define'
|
|
9
|
+
import { ENEMY, PLAYER } from '../common/units'
|
|
10
|
+
import type { Family } from './family'
|
|
11
|
+
import { caster, put, sparring } from './kit'
|
|
12
|
+
|
|
13
|
+
const buffs: BuffDef[] = [
|
|
14
|
+
// flat and percent stats
|
|
15
|
+
{
|
|
16
|
+
id: 'abilitiesInnerFire',
|
|
17
|
+
name: 'Inner Fire',
|
|
18
|
+
description: '+10 armor, +40% attack damage',
|
|
19
|
+
duration: 20,
|
|
20
|
+
stats: { armor: 10 },
|
|
21
|
+
percent: { attackDamage: 0.4 }
|
|
22
|
+
},
|
|
23
|
+
// a shield takes damage first; its amount set by the cast
|
|
24
|
+
{ id: 'abilitiesBarrier', name: 'Barrier', description: 'A shield', duration: 8, shield: 150 },
|
|
25
|
+
// an aura's buff has no duration: it stays while its carrier is near the one with the aura
|
|
26
|
+
{ id: 'abilitiesDevotion', name: 'Devotion Aura', description: '+8 armor while near the paladin', stats: { armor: 8 } },
|
|
27
|
+
// stacks: at five, a stun, and the stacks spent
|
|
28
|
+
{
|
|
29
|
+
id: 'abilitiesRend',
|
|
30
|
+
name: 'Rend',
|
|
31
|
+
description: 'Bleeds; at five stacks, a stun',
|
|
32
|
+
harmful: true,
|
|
33
|
+
duration: 6,
|
|
34
|
+
maxStacks: 5,
|
|
35
|
+
stacking: 'refresh',
|
|
36
|
+
onTick: { every: 1, effects: [{ type: 'damage', amount: 10 }] },
|
|
37
|
+
onMaxStacks: [
|
|
38
|
+
{ type: 'buff', buff: 'abilitiesRendStun' },
|
|
39
|
+
{ type: 'removeBuff', buff: 'abilitiesRend' }
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{ id: 'abilitiesRendStun', name: 'Ruptured', harmful: true, duration: 1.5, stun: true },
|
|
43
|
+
// kept on until cast again, taking mana every second
|
|
44
|
+
{
|
|
45
|
+
id: 'abilitiesImmolating',
|
|
46
|
+
name: 'Immolation',
|
|
47
|
+
description: 'Burns everyone near, 8 mana a second',
|
|
48
|
+
drain: { mana: 8 },
|
|
49
|
+
onTick: { every: 1, effects: [{ type: 'damage', amount: 20, radius: 3 }] }
|
|
50
|
+
},
|
|
51
|
+
// goes off when its time is up
|
|
52
|
+
{ id: 'abilitiesTimeBomb', name: 'Time Bomb', harmful: true, duration: 3, onEnd: [{ type: 'damage', amount: 200, radius: 3 }] },
|
|
53
|
+
// no damage, no enemy casts or attacks
|
|
54
|
+
{ id: 'abilitiesDivineShield', name: 'Divine Shield', description: 'Takes no damage', duration: 5, invulnerable: true },
|
|
55
|
+
// out of everyone's reach, still seen, and held
|
|
56
|
+
{ id: 'abilitiesStasis', name: 'Stasis', description: 'Untouchable and held', duration: 2.5, invulnerable: true, untargetable: true, stun: true },
|
|
57
|
+
// damage never takes it under 100
|
|
58
|
+
{ id: 'abilitiesUndying', name: 'Undying Rage', description: 'Can not fall below 100 health', duration: 6, minHealth: 100 },
|
|
59
|
+
// walks through units, and they through it
|
|
60
|
+
{ id: 'abilitiesGhost', name: 'Ghost', description: 'Walks through units, 40% faster', duration: 6, phasing: true, percent: { moveSpeed: 0.4 } },
|
|
61
|
+
// its blows strike the enemies around their target too, 60% of their damage
|
|
62
|
+
{
|
|
63
|
+
id: 'abilitiesCleaving',
|
|
64
|
+
name: 'Cleaving Blows',
|
|
65
|
+
description: 'Blows strike those around the target too',
|
|
66
|
+
duration: 10,
|
|
67
|
+
cleave: { part: 0.6, radius: 2.5 }
|
|
68
|
+
},
|
|
69
|
+
// healing it gives past full health becomes a shield on the one healed
|
|
70
|
+
{
|
|
71
|
+
id: 'abilitiesMercy',
|
|
72
|
+
name: 'Mercy’s Echo',
|
|
73
|
+
description: 'Healing past full health becomes a shield',
|
|
74
|
+
duration: 20,
|
|
75
|
+
overheal: { buff: 'abilitiesEcho', part: 1, most: 0.5 }
|
|
76
|
+
},
|
|
77
|
+
{ id: 'abilitiesEcho', name: 'Echo', description: 'A shield of healing past full', duration: 6 },
|
|
78
|
+
// where its carrier dies carrying it, a demon of whoever put it on
|
|
79
|
+
{
|
|
80
|
+
id: 'abilitiesDoom',
|
|
81
|
+
name: 'Doom',
|
|
82
|
+
harmful: true,
|
|
83
|
+
duration: 30,
|
|
84
|
+
silence: true,
|
|
85
|
+
onTick: { every: 0.5, effects: [{ type: 'damage', amount: 60 }] },
|
|
86
|
+
onCarrierDeath: [{ type: 'spawn', unit: 'abilitiesDemon' }]
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
const abilities: AbilityDef[] = [
|
|
91
|
+
{
|
|
92
|
+
id: 'abilitiesCastInnerFire',
|
|
93
|
+
name: 'Inner Fire',
|
|
94
|
+
description: 'An ally: +10 armor and +40% attack damage for 20 seconds',
|
|
95
|
+
hotkey: 'Q',
|
|
96
|
+
target: 'unit',
|
|
97
|
+
targets: { allies: true, self: true },
|
|
98
|
+
range: 8,
|
|
99
|
+
cooldown: 0.5,
|
|
100
|
+
effects: [{ type: 'buff', buff: 'abilitiesInnerFire' }]
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
// the buff's shield, sized by the cast
|
|
104
|
+
id: 'abilitiesCastBarrier',
|
|
105
|
+
name: 'Shield',
|
|
106
|
+
description: 'An ally: a shield of 300 for 8 seconds, taken before its health',
|
|
107
|
+
hotkey: 'W',
|
|
108
|
+
target: 'unit',
|
|
109
|
+
targets: { allies: true, self: true },
|
|
110
|
+
range: 8,
|
|
111
|
+
cooldown: 0.5,
|
|
112
|
+
effects: [{ type: 'buff', buff: 'abilitiesBarrier', amount: 300 }]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: 'abilitiesCastRend',
|
|
116
|
+
name: 'Rend',
|
|
117
|
+
description: 'A stack of bleeding; at five, a stun, the stacks spent',
|
|
118
|
+
hotkey: 'E',
|
|
119
|
+
target: 'unit',
|
|
120
|
+
targets: { enemies: true },
|
|
121
|
+
range: 8,
|
|
122
|
+
cooldown: 0.2,
|
|
123
|
+
effects: [{ type: 'buff', buff: 'abilitiesRend', stack: true }]
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
// `toggle`: on, then off when cast again
|
|
127
|
+
id: 'abilitiesImmolation',
|
|
128
|
+
name: 'Immolation',
|
|
129
|
+
description: 'Turned on and off: burns everyone within 3, for mana every second',
|
|
130
|
+
hotkey: 'R',
|
|
131
|
+
target: 'none',
|
|
132
|
+
effects: [{ type: 'toggle', buff: 'abilitiesImmolating' }]
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: 'abilitiesCastTimeBomb',
|
|
136
|
+
name: 'Time Bomb',
|
|
137
|
+
description: 'A bomb on an enemy, going off around it in 3 seconds',
|
|
138
|
+
hotkey: 'T',
|
|
139
|
+
target: 'unit',
|
|
140
|
+
targets: { enemies: true },
|
|
141
|
+
range: 8,
|
|
142
|
+
cooldown: 0.5,
|
|
143
|
+
effects: [{ type: 'buff', buff: 'abilitiesTimeBomb' }]
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
id: 'abilitiesCastDivineShield',
|
|
147
|
+
name: 'Divine Shield',
|
|
148
|
+
description: 'The caster takes no damage for 5 seconds',
|
|
149
|
+
hotkey: 'D',
|
|
150
|
+
target: 'none',
|
|
151
|
+
cooldown: 0.5,
|
|
152
|
+
effects: [{ type: 'buff', buff: 'abilitiesDivineShield', on: 'caster' }]
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: 'abilitiesCastStasis',
|
|
156
|
+
name: 'Stasis',
|
|
157
|
+
description: 'The caster is untouchable, by anyone, and held for 2.5 seconds',
|
|
158
|
+
hotkey: 'F',
|
|
159
|
+
target: 'none',
|
|
160
|
+
cooldown: 0.5,
|
|
161
|
+
effects: [{ type: 'buff', buff: 'abilitiesStasis', on: 'caster' }]
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: 'abilitiesCastUndying',
|
|
165
|
+
name: 'Undying Rage',
|
|
166
|
+
description: 'An ally can not fall below 100 health for 6 seconds',
|
|
167
|
+
hotkey: 'G',
|
|
168
|
+
target: 'unit',
|
|
169
|
+
targets: { allies: true, self: true },
|
|
170
|
+
range: 8,
|
|
171
|
+
cooldown: 0.5,
|
|
172
|
+
effects: [{ type: 'buff', buff: 'abilitiesUndying' }]
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
id: 'abilitiesCastGhost',
|
|
176
|
+
name: 'Ghost',
|
|
177
|
+
description: 'The caster walks through units, faster, for 6 seconds',
|
|
178
|
+
hotkey: 'Z',
|
|
179
|
+
target: 'none',
|
|
180
|
+
cooldown: 0.5,
|
|
181
|
+
effects: [{ type: 'buff', buff: 'abilitiesGhost', on: 'caster' }]
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
id: 'abilitiesCastCleave',
|
|
185
|
+
name: 'Cleaving Blows',
|
|
186
|
+
description: 'An ally’s blows strike the enemies round its target too',
|
|
187
|
+
hotkey: 'X',
|
|
188
|
+
target: 'unit',
|
|
189
|
+
targets: { allies: true },
|
|
190
|
+
range: 8,
|
|
191
|
+
cooldown: 0.5,
|
|
192
|
+
effects: [{ type: 'buff', buff: 'abilitiesCleaving' }]
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
// with Mercy's Echo on the caster, a heal past full health leaves a shield on the healed
|
|
196
|
+
id: 'abilitiesCastMercy',
|
|
197
|
+
name: 'Overheal',
|
|
198
|
+
description: 'The caster’s healing past full becomes a shield; then it heals an ally for 400',
|
|
199
|
+
hotkey: 'C',
|
|
200
|
+
target: 'unit',
|
|
201
|
+
targets: { allies: true, self: true },
|
|
202
|
+
range: 8,
|
|
203
|
+
cooldown: 0.5,
|
|
204
|
+
effects: [
|
|
205
|
+
{ type: 'buff', buff: 'abilitiesMercy', on: 'caster' },
|
|
206
|
+
{ type: 'heal', amount: 400 }
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
id: 'abilitiesCastDoom',
|
|
211
|
+
name: 'Doom',
|
|
212
|
+
description: 'An enemy is silenced and burns; where it dies a demon of yours stands',
|
|
213
|
+
hotkey: 'V',
|
|
214
|
+
target: 'unit',
|
|
215
|
+
targets: { enemies: true },
|
|
216
|
+
range: 8,
|
|
217
|
+
cooldown: 0.5,
|
|
218
|
+
effects: [{ type: 'buff', buff: 'abilitiesDoom' }]
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
// takes stacks or a whole buff off: here every bomb and bleed off everyone near
|
|
222
|
+
id: 'abilitiesDefuse',
|
|
223
|
+
name: 'Remove buffs',
|
|
224
|
+
description: 'Takes every Time Bomb, Rend and Doom off the enemies within 12',
|
|
225
|
+
hotkey: 'B',
|
|
226
|
+
target: 'none',
|
|
227
|
+
cooldown: 0.5,
|
|
228
|
+
effects: [
|
|
229
|
+
{ type: 'removeBuff', buff: 'abilitiesTimeBomb', radius: 12, affects: 'enemies' },
|
|
230
|
+
{ type: 'removeBuff', buff: 'abilitiesRend', radius: 12, affects: 'enemies' },
|
|
231
|
+
{ type: 'removeBuff', buff: 'abilitiesDoom', radius: 12, affects: 'enemies' }
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
|
|
236
|
+
/** The paladin's aura: a passive that keeps its buff on every ally within 7 */
|
|
237
|
+
const devotionAura: AbilityDef = {
|
|
238
|
+
id: 'abilitiesDevotionAura',
|
|
239
|
+
name: 'Devotion Aura',
|
|
240
|
+
description: 'Allies within 7: +8 armor',
|
|
241
|
+
target: 'passive',
|
|
242
|
+
effects: [{ type: 'aura', buff: 'abilitiesDevotion', radius: 7, affects: 'allies' }]
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export const buffsFamily: Family = {
|
|
246
|
+
abilities,
|
|
247
|
+
more: [devotionAura],
|
|
248
|
+
buffs,
|
|
249
|
+
units: [
|
|
250
|
+
caster('abilitiesPaladin', 'Paladin', [...abilities.map((each) => each.id), devotionAura.id]),
|
|
251
|
+
// an ally that fights: what Inner Fire and Cleaving Blows make stronger
|
|
252
|
+
sparring('abilitiesSoldier', 'Footman', {
|
|
253
|
+
stats: { health: 900, healthRegen: 3, attackDamage: 20, attackSpeed: 1.1, attackRange: 0.5, armor: 5, moveSpeed: 4 },
|
|
254
|
+
attacks: [{ damagePoint: 0.45, acquisitionRange: 6 }]
|
|
255
|
+
}),
|
|
256
|
+
// what Doom leaves where its carrier dies
|
|
257
|
+
sparring('abilitiesDemon', 'Doom Guard', {
|
|
258
|
+
radius: 0.6,
|
|
259
|
+
stats: { health: 1400, attackDamage: 40, attackSpeed: 1, attackRange: 0.6, armor: 8, moveSpeed: 3.6 },
|
|
260
|
+
attacks: [{ damagePoint: 0.4, acquisitionRange: 8 }],
|
|
261
|
+
lifetime: 30
|
|
262
|
+
})
|
|
263
|
+
],
|
|
264
|
+
example: {
|
|
265
|
+
id: 'abilities-buffs',
|
|
266
|
+
category: 'abilities',
|
|
267
|
+
title: 'Buffs and auras',
|
|
268
|
+
summary:
|
|
269
|
+
'Stats, shields, stacks, an aura, a toggle that drains mana, a bomb on a timer, invulnerable and untargetable, a health floor, walking through units, cleaving blows, overheal and a doom. Your footman fights a pack of training footmen while you buff it.',
|
|
270
|
+
tags: ['buff', 'debuff', 'aura', 'shield', 'stacks', 'toggle', 'invulnerable', 'untargetable', 'cleave', 'overheal', 'phasing', 'doom'],
|
|
271
|
+
source: ['examples/abilities/buffs.ts', 'examples/abilities/kit.ts'],
|
|
272
|
+
map: () => exampleField({ name: 'Buffs', players: 2 }),
|
|
273
|
+
start: (world) => {
|
|
274
|
+
put(world, 'abilitiesPaladin', PLAYER, { x: 24, z: 17 }, 'caster')
|
|
275
|
+
put(world, 'abilitiesSoldier', PLAYER, { x: 24, z: 21 }, 'ally')
|
|
276
|
+
// the pack the footman fights: close enough for its blows to cleave
|
|
277
|
+
for (const [i, [x, z]] of [
|
|
278
|
+
[23, 24],
|
|
279
|
+
[25, 24],
|
|
280
|
+
[24, 25.3],
|
|
281
|
+
[22.4, 25.6],
|
|
282
|
+
[25.6, 25.6]
|
|
283
|
+
].entries())
|
|
284
|
+
put(world, 'abilitiesTarget', ENEMY, { x, z }, `enemy${i + 1}`, Math.PI)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** How the buffs example looks, and its card: a button for each buff (`./buffs.ts`) */
|
|
2
|
+
import { sharedLooks } from '../common/looks'
|
|
3
|
+
import { buffsFamily } from './buffs'
|
|
4
|
+
import type { FamilyLooks } from './looks'
|
|
5
|
+
import { castButton, look, readyOn, resetButton } from './lookKit'
|
|
6
|
+
|
|
7
|
+
/** A buff's look on its carrier: sparks of `shape` in its colour (`glow`) */
|
|
8
|
+
const glow = (color: [number, number, number], shape: string, more: Record<string, unknown> = {}) =>
|
|
9
|
+
look(color, undefined, { aura: 'glow', options: { shape, ...more } })
|
|
10
|
+
|
|
11
|
+
export const buffsLooks: FamilyLooks = {
|
|
12
|
+
units: {
|
|
13
|
+
abilitiesPaladin: { ...sharedLooks.knight, model: { ...sharedLooks.knight.model!, scale: 0.8 } },
|
|
14
|
+
abilitiesSoldier: sharedLooks.footman,
|
|
15
|
+
abilitiesDemon: { ...sharedLooks.knight, model: { ...sharedLooks.knight.model!, scale: 1.25 } }
|
|
16
|
+
},
|
|
17
|
+
abilities: {
|
|
18
|
+
abilitiesCastInnerFire: look([1, 0.55, 0.2], 'burst'),
|
|
19
|
+
abilitiesCastBarrier: look([0.5, 0.8, 1], 'burst'),
|
|
20
|
+
abilitiesImmolation: look([1, 0.45, 0.1], 'burst'),
|
|
21
|
+
abilitiesCastDoom: look([0.6, 0.05, 0.1], 'burst'),
|
|
22
|
+
abilitiesDefuse: look([1, 1, 1], 'sonar'),
|
|
23
|
+
abilitiesInnerFire: glow([1, 0.55, 0.2], 'rise'),
|
|
24
|
+
abilitiesBarrier: glow([0.5, 0.8, 1], 'shell'),
|
|
25
|
+
abilitiesDevotion: glow([1, 0.85, 0.4], 'ring'),
|
|
26
|
+
// a pip a stack over the carrier
|
|
27
|
+
abilitiesRend: look([0.9, 0.1, 0.1], undefined, { counter: { max: 5 }, aura: 'glow', options: { shape: 'fall', solid: true } }),
|
|
28
|
+
abilitiesRendStun: glow([1, 0.3, 0.3], 'ring', { at: 'head' }),
|
|
29
|
+
abilitiesImmolating: glow([1, 0.45, 0.1], 'column', { streaks: true }),
|
|
30
|
+
abilitiesTimeBomb: glow([1, 0.2, 0.1], 'ring', { at: 'head' }),
|
|
31
|
+
abilitiesDivineShield: glow([1, 0.95, 0.6], 'shell'),
|
|
32
|
+
abilitiesStasis: glow([0.95, 0.85, 0.3], 'shell'),
|
|
33
|
+
abilitiesUndying: glow([0.9, 0.2, 0.15], 'rise'),
|
|
34
|
+
abilitiesGhost: glow([0.7, 0.8, 1], 'dust'),
|
|
35
|
+
abilitiesCleaving: glow([0.9, 0.9, 0.9], 'about', { streaks: true }),
|
|
36
|
+
abilitiesMercy: glow([0.6, 1, 0.7], 'rise'),
|
|
37
|
+
abilitiesEcho: glow([0.6, 1, 0.7], 'shell'),
|
|
38
|
+
abilitiesDoom: glow([0.7, 0.05, 0.1], 'rise')
|
|
39
|
+
},
|
|
40
|
+
examples: {
|
|
41
|
+
'abilities-buffs': {
|
|
42
|
+
ready: (client) => readyOn(client, 'abilitiesPaladin', { minX: 18, minZ: 14, maxX: 30, maxZ: 28 }),
|
|
43
|
+
controls: [...buffsFamily.abilities.map((ability) => castButton(ability)), resetButton('abilities-buffs')]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Changing abilities while the game runs (the ability changes pack, `abilityChangesPack`): one granted for a while,
|
|
3
|
+
* one swapped for a stronger one for a cast, an enemy's ultimate stolen, an enemy taken over, one upgraded for good;
|
|
4
|
+
* and forms (`morph`): a demon form for a while, a cougar form turned on and off, each with abilities of its own
|
|
5
|
+
*/
|
|
6
|
+
import { type AbilityDef, type BuffDef, defineCommand, upgradeAbility } from '@v12-engine/engine'
|
|
7
|
+
import { exampleField } from '../define'
|
|
8
|
+
import { ENEMY, PLAYER } from '../common/units'
|
|
9
|
+
import type { Family } from './family'
|
|
10
|
+
import { caster, put, sparring } from './kit'
|
|
11
|
+
|
|
12
|
+
const buffs: BuffDef[] = [{ id: 'abilitiesSiphoned', name: 'Siphoned', harmful: true, duration: 3, percent: { moveSpeed: -0.5 } }]
|
|
13
|
+
|
|
14
|
+
const abilities: AbilityDef[] = [
|
|
15
|
+
{
|
|
16
|
+
// added after the caster's others, for 20 seconds
|
|
17
|
+
id: 'abilitiesGift',
|
|
18
|
+
name: 'Gift',
|
|
19
|
+
description: 'Holy Nova, added to the card for 20 seconds',
|
|
20
|
+
hotkey: 'Q',
|
|
21
|
+
target: 'none',
|
|
22
|
+
cooldown: 1,
|
|
23
|
+
effects: [{ type: 'grantAbility', ability: 'abilitiesHolyNova', atLevel: 1, duration: 20, on: 'caster' }]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
// Wildfire gives way to its awakened form for one cast, then comes back
|
|
27
|
+
id: 'abilitiesAwaken',
|
|
28
|
+
name: 'Awaken',
|
|
29
|
+
description: 'Wildfire becomes Wildfire Awakened for one cast',
|
|
30
|
+
hotkey: 'W',
|
|
31
|
+
target: 'none',
|
|
32
|
+
cooldown: 1,
|
|
33
|
+
effects: [{ type: 'swapAbility', from: 'abilitiesWildfire', ability: 'abilitiesWildfireAwakened', uses: 1, on: 'caster' }]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'abilitiesWildfire',
|
|
37
|
+
name: 'Wildfire',
|
|
38
|
+
description: 'Burns round the nearest enemy for 60',
|
|
39
|
+
hotkey: 'E',
|
|
40
|
+
target: 'point',
|
|
41
|
+
range: 9,
|
|
42
|
+
cooldown: 0.5,
|
|
43
|
+
effects: [{ type: 'damage', amount: 60, radius: 1.5 }]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
// the target's ultimate in the place of Hijack, for one cast
|
|
47
|
+
id: 'abilitiesHijack',
|
|
48
|
+
name: 'Hijack',
|
|
49
|
+
description: 'Takes the warlock’s ultimate, Cataclysm, for one cast in its place',
|
|
50
|
+
hotkey: 'R',
|
|
51
|
+
target: 'unit',
|
|
52
|
+
targets: { enemies: true },
|
|
53
|
+
range: 12,
|
|
54
|
+
cooldown: 1,
|
|
55
|
+
effects: [{ type: 'stealAbility', pick: 'ultimate' }]
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'abilitiesTakeOver',
|
|
59
|
+
name: 'Take over',
|
|
60
|
+
description: 'An enemy footman is yours for 15 seconds',
|
|
61
|
+
hotkey: 'T',
|
|
62
|
+
target: 'unit',
|
|
63
|
+
targets: { enemies: true },
|
|
64
|
+
range: 12,
|
|
65
|
+
cooldown: 1,
|
|
66
|
+
effects: [{ type: 'convert', duration: 15 }]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
// what it may be made into for good (`upgrades`): the Upgrade button picks it
|
|
70
|
+
id: 'abilitiesSiphon',
|
|
71
|
+
name: 'Siphon Power',
|
|
72
|
+
description: 'A blow of 60; upgraded, it slows and heals the caster too',
|
|
73
|
+
hotkey: 'D',
|
|
74
|
+
target: 'unit',
|
|
75
|
+
targets: { enemies: true },
|
|
76
|
+
range: 9,
|
|
77
|
+
cooldown: 0.5,
|
|
78
|
+
upgrades: ['abilitiesSiphonAugmented'],
|
|
79
|
+
effects: [{ type: 'damage', amount: 60 }]
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
// another unit type where it stands, for 15 seconds: its stats and its abilities
|
|
83
|
+
id: 'abilitiesMetamorphosis',
|
|
84
|
+
name: 'Metamorphosis',
|
|
85
|
+
description: 'A demon for 15 seconds, with a demon’s strength and spells',
|
|
86
|
+
hotkey: 'F',
|
|
87
|
+
target: 'none',
|
|
88
|
+
cooldown: 1,
|
|
89
|
+
effects: [{ type: 'morph', into: 'abilitiesDemonForm', duration: 15 }]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
// cast again (the cougar has it too) to turn back
|
|
93
|
+
id: 'abilitiesAspect',
|
|
94
|
+
name: 'Aspect of the Cougar',
|
|
95
|
+
description: 'A cougar until cast again, with a pounce of its own',
|
|
96
|
+
hotkey: 'G',
|
|
97
|
+
target: 'none',
|
|
98
|
+
cooldown: 1,
|
|
99
|
+
effects: [{ type: 'morph', into: 'abilitiesCougar', toggle: true }]
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
const more: AbilityDef[] = [
|
|
104
|
+
{
|
|
105
|
+
id: 'abilitiesHolyNova',
|
|
106
|
+
name: 'Holy Nova',
|
|
107
|
+
description: 'Heals allies and burns enemies within 4',
|
|
108
|
+
hotkey: 'Z',
|
|
109
|
+
target: 'none',
|
|
110
|
+
cooldown: 0.5,
|
|
111
|
+
effects: [
|
|
112
|
+
{ type: 'heal', amount: 100, radius: 4 },
|
|
113
|
+
{ type: 'damage', amount: 60, radius: 4 }
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: 'abilitiesWildfireAwakened',
|
|
118
|
+
name: 'Wildfire Awakened',
|
|
119
|
+
description: 'Burns round the nearest enemy for 250',
|
|
120
|
+
hotkey: 'E',
|
|
121
|
+
target: 'point',
|
|
122
|
+
range: 9,
|
|
123
|
+
cooldown: 0.5,
|
|
124
|
+
effects: [{ type: 'damage', amount: 250, radius: 3 }]
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
id: 'abilitiesSiphonAugmented',
|
|
128
|
+
name: 'Siphon Power+',
|
|
129
|
+
description: 'A blow of 60 that slows, and heals the caster as much',
|
|
130
|
+
hotkey: 'D',
|
|
131
|
+
target: 'unit',
|
|
132
|
+
targets: { enemies: true },
|
|
133
|
+
range: 9,
|
|
134
|
+
cooldown: 0.5,
|
|
135
|
+
effects: [
|
|
136
|
+
{ type: 'damage', amount: 60 },
|
|
137
|
+
{ type: 'buff', buff: 'abilitiesSiphoned' },
|
|
138
|
+
{ type: 'heal', amount: 60, on: 'caster' }
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: 'abilitiesCataclysm',
|
|
143
|
+
name: 'Cataclysm',
|
|
144
|
+
description: 'The warlock’s ultimate: fire falls round the spot',
|
|
145
|
+
target: 'point',
|
|
146
|
+
range: 12,
|
|
147
|
+
ultimate: true,
|
|
148
|
+
cooldown: 30,
|
|
149
|
+
effects: [{ type: 'after', delay: 0.8, effects: [{ type: 'damage', amount: 200, radius: 3.5 }] }]
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
id: 'abilitiesChaosBolt',
|
|
153
|
+
name: 'Chaos Bolt',
|
|
154
|
+
description: 'A demon’s bolt for 160',
|
|
155
|
+
hotkey: 'Q',
|
|
156
|
+
target: 'unit',
|
|
157
|
+
targets: { enemies: true },
|
|
158
|
+
range: 9,
|
|
159
|
+
cooldown: 0.5,
|
|
160
|
+
effects: [{ type: 'missile', homing: true, speed: 16, effects: [{ type: 'damage', amount: 160 }] }]
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
id: 'abilitiesPounce',
|
|
164
|
+
name: 'Pounce',
|
|
165
|
+
description: 'Leaps at the spot, clawing round where it lands',
|
|
166
|
+
hotkey: 'W',
|
|
167
|
+
target: 'point',
|
|
168
|
+
range: 5,
|
|
169
|
+
cooldown: 0.5,
|
|
170
|
+
effects: [{ type: 'dash', distance: 5, speed: 16, leap: 1, effects: [{ type: 'damage', amount: 80, radius: 1.5 }] }]
|
|
171
|
+
}
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
/** Makes Siphon Power into Siphon Power+ for good: what a player's pick of an upgrade does (`upgradeAbility`) */
|
|
175
|
+
export const upgrade = defineCommand('abilities.upgrade', {}, (world, player) => {
|
|
176
|
+
const unit = world.named('caster')
|
|
177
|
+
if (unit && unit.owner === player) upgradeAbility(world, unit, 'abilitiesSiphon', 'abilitiesSiphonAugmented')
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
export const changing: Family = {
|
|
181
|
+
abilities,
|
|
182
|
+
more,
|
|
183
|
+
buffs,
|
|
184
|
+
commands: [upgrade],
|
|
185
|
+
units: [
|
|
186
|
+
caster(
|
|
187
|
+
'abilitiesShifter',
|
|
188
|
+
'Shifter',
|
|
189
|
+
abilities.map((each) => each.id)
|
|
190
|
+
),
|
|
191
|
+
// the forms: unit types of their own, with what they cast
|
|
192
|
+
caster('abilitiesDemonForm', 'Demon form', ['abilitiesChaosBolt'], {
|
|
193
|
+
radius: 0.6,
|
|
194
|
+
stats: {
|
|
195
|
+
health: 2000,
|
|
196
|
+
healthRegen: 10,
|
|
197
|
+
mana: 1000,
|
|
198
|
+
manaRegen: 60,
|
|
199
|
+
attackDamage: 60,
|
|
200
|
+
attackSpeed: 1,
|
|
201
|
+
attackRange: 0.7,
|
|
202
|
+
moveSpeed: 4.6,
|
|
203
|
+
armor: 15
|
|
204
|
+
}
|
|
205
|
+
}),
|
|
206
|
+
caster('abilitiesCougar', 'Cougar', ['abilitiesPounce', 'abilitiesAspect'], {
|
|
207
|
+
radius: 0.45,
|
|
208
|
+
stats: { health: 1200, healthRegen: 4, mana: 1000, manaRegen: 60, attackDamage: 45, attackSpeed: 1.4, attackRange: 0.5, moveSpeed: 5.5 }
|
|
209
|
+
}),
|
|
210
|
+
// an enemy with an ultimate to steal
|
|
211
|
+
sparring('abilitiesWarlock', 'Warlock', { abilities: ['abilitiesCataclysm'] })
|
|
212
|
+
],
|
|
213
|
+
example: {
|
|
214
|
+
id: 'abilities-changing',
|
|
215
|
+
category: 'abilities',
|
|
216
|
+
title: 'Changing abilities and forms',
|
|
217
|
+
summary:
|
|
218
|
+
'An ability granted for a while, one swapped for a stronger cast, the warlock’s ultimate stolen, a footman taken over, an upgrade for good, a demon form and a cougar form. Watch the card below change.',
|
|
219
|
+
tags: ['grant', 'swap', 'steal', 'convert', 'upgrade', 'morph', 'form', 'transform', 'shapeshift'],
|
|
220
|
+
source: ['examples/abilities/changing.ts', 'examples/abilities/kit.ts'],
|
|
221
|
+
map: () => exampleField({ name: 'Changing', players: 2 }),
|
|
222
|
+
start: (world) => {
|
|
223
|
+
put(world, 'abilitiesShifter', PLAYER, { x: 24, z: 18 }, 'caster')
|
|
224
|
+
put(world, 'abilitiesWarlock', ENEMY, { x: 28, z: 25 }, 'warlock', Math.PI)
|
|
225
|
+
for (const [i, x] of [20, 23].entries()) put(world, 'abilitiesTarget', ENEMY, { x, z: 25 }, `enemy${i + 1}`, Math.PI)
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/** How the changing abilities example looks, and its card: what changes the card, and what the changes give */
|
|
2
|
+
import { button } from '../../shell/look'
|
|
3
|
+
import { character, hold, person, sharedLooks, TWO_HANDED } from '../common/looks'
|
|
4
|
+
import { changing, upgrade } from './changing'
|
|
5
|
+
import type { FamilyLooks } from './looks'
|
|
6
|
+
import { castButton, look, readyOn, resetButton } from './lookKit'
|
|
7
|
+
|
|
8
|
+
/** What the changes put on the card, cast by name: each is refused while the caster does not have it */
|
|
9
|
+
const given = ['abilitiesHolyNova', 'abilitiesWildfireAwakened', 'abilitiesCataclysm', 'abilitiesChaosBolt', 'abilitiesPounce']
|
|
10
|
+
|
|
11
|
+
export const changingLooks: FamilyLooks = {
|
|
12
|
+
units: {
|
|
13
|
+
abilitiesShifter: sharedLooks.mage,
|
|
14
|
+
abilitiesDemonForm: {
|
|
15
|
+
height: 2.6,
|
|
16
|
+
model: character('barbarian', 1.1, { hold: [hold('axe_2handed')] }),
|
|
17
|
+
attacks: [TWO_HANDED],
|
|
18
|
+
shapes: person(2.6, [0.5, 0.05, 0.1])
|
|
19
|
+
},
|
|
20
|
+
// the shared art has no animals: a cougar of parts, a long body and a head
|
|
21
|
+
abilitiesCougar: {
|
|
22
|
+
height: 1,
|
|
23
|
+
shapes: [
|
|
24
|
+
{ shape: 'sphere', size: [0.7, 0.6, 1.4], offset: [0, 0.6, 0], color: [0.75, 0.55, 0.3] },
|
|
25
|
+
{ shape: 'sphere', size: [0.45, 0.45, 0.5], offset: [0, 0.85, 0.75], color: [0.7, 0.5, 0.28] }
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
abilitiesWarlock: { ...sharedLooks.mage, model: character('skeleton_mage', 0.72, { hold: [hold('staff')] }) }
|
|
29
|
+
},
|
|
30
|
+
abilities: {
|
|
31
|
+
abilitiesGift: look([1, 0.95, 0.6], 'burst'),
|
|
32
|
+
abilitiesAwaken: look([1, 0.5, 0.1], 'burst'),
|
|
33
|
+
abilitiesWildfire: look([1, 0.5, 0.1], 'smash'),
|
|
34
|
+
abilitiesWildfireAwakened: look([1, 0.3, 0.05], 'smash'),
|
|
35
|
+
abilitiesHijack: look([0.4, 0.8, 1], 'tether'),
|
|
36
|
+
abilitiesTakeOver: look([1, 0.4, 0.8], 'tether'),
|
|
37
|
+
abilitiesSiphon: look([0.5, 0.3, 1], 'burst'),
|
|
38
|
+
abilitiesSiphonAugmented: look([0.3, 1, 0.8], 'burst'),
|
|
39
|
+
abilitiesMetamorphosis: look([0.6, 0.05, 0.1], 'tornado'),
|
|
40
|
+
abilitiesAspect: look([0.9, 0.7, 0.3], 'burst'),
|
|
41
|
+
abilitiesHolyNova: look([1, 0.95, 0.6], 'slam'),
|
|
42
|
+
abilitiesCataclysm: look([1, 0.35, 0.1], 'mark', { options: { lasts: 0.8, falls: 16, burst: 40 } }),
|
|
43
|
+
abilitiesChaosBolt: look([0.5, 1, 0.3], 'missile', { options: { shape: 'ball' } }),
|
|
44
|
+
abilitiesPounce: look([0.9, 0.7, 0.3], 'slam'),
|
|
45
|
+
abilitiesSiphoned: look([0.3, 1, 0.8], undefined, { aura: 'glow', options: { shape: 'fall' } })
|
|
46
|
+
},
|
|
47
|
+
examples: {
|
|
48
|
+
'abilities-changing': {
|
|
49
|
+
ready: (client) => readyOn(client, 'abilitiesShifter'),
|
|
50
|
+
controls: [
|
|
51
|
+
...changing.abilities.map((ability) => castButton(ability, ability.id === 'abilitiesHijack' ? { at: 'warlock' } : {})),
|
|
52
|
+
button('Upgrade Siphon Power', (client) => client.session.send(upgrade.make({})), 'Makes Siphon Power into Siphon Power+ for good'),
|
|
53
|
+
...given.map((id) => {
|
|
54
|
+
const ability = changing.more!.find((each) => each.id === id)!
|
|
55
|
+
return castButton(ability, { label: `${ability.name} (given)` })
|
|
56
|
+
}),
|
|
57
|
+
resetButton('abilities-changing')
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|