@almadar/std 16.153.0 → 16.155.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.
Files changed (93) hide show
  1. package/behaviors/lolo/ui/game/molecules/std-crew-board-2d.lolo +4 -4
  2. package/behaviors/lolo/ui/game/molecules/std-dungeon-board-2d.lolo +6 -6
  3. package/behaviors/lolo/ui/game/molecules/std-tactics-board-2d.lolo +74 -28
  4. package/behaviors/lolo/ui/game/molecules/std-worldmap-board-2d.lolo +2 -2
  5. package/behaviors/lolo/ui/game/molecules/ui-canvas.lolo +5 -0
  6. package/behaviors/lolo/ui/game/organisms/ui-arena-board.lolo +2 -2
  7. package/behaviors/lolo/ui/game/organisms/ui-battle-board.lolo +159 -8
  8. package/behaviors/lolo/ui/game/organisms/ui-builder-board.lolo +5 -20
  9. package/behaviors/lolo/ui/game/organisms/ui-card-battler-board.lolo +2 -0
  10. package/behaviors/lolo/ui/game/organisms/ui-castle-board.lolo +3 -3
  11. package/behaviors/lolo/ui/game/organisms/ui-city-builder-board.lolo +9 -7
  12. package/behaviors/lolo/ui/game/organisms/ui-grid-tactics-demo-board.lolo +2 -2
  13. package/behaviors/lolo/ui/game/organisms/ui-hex-strategy-board.lolo +158 -10
  14. package/behaviors/lolo/ui/game/organisms/ui-holiday-runner-board.lolo +1 -1
  15. package/behaviors/lolo/ui/game/organisms/ui-minigolf-board.lolo +22 -22
  16. package/behaviors/lolo/ui/game/organisms/ui-pinball-board.lolo +7 -7
  17. package/behaviors/lolo/ui/game/organisms/ui-pirate-board.lolo +14 -14
  18. package/behaviors/lolo/ui/game/organisms/ui-platformer-board.lolo +4 -0
  19. package/behaviors/lolo/ui/game/organisms/ui-sports-board.lolo +10 -7
  20. package/behaviors/lolo/ui/game/organisms/ui-tactics-demo-2d.lolo +135 -9
  21. package/behaviors/lolo/ui/game/organisms/ui-tanks-board.lolo +152 -8
  22. package/behaviors/lolo/ui/game/organisms/ui-topdown-rts-board.lolo +293 -17
  23. package/behaviors/lolo/ui/game/organisms/ui-tower-defense-board.lolo +8 -8
  24. package/behaviors/lolo/ui/game/organisms/ui-uncontrolled-battle-board.lolo +5 -5
  25. package/behaviors/lolo/ui/game/organisms/ui-world-map-board.lolo +3 -3
  26. package/behaviors/registry/factory-signatures.json +1893 -2294
  27. package/behaviors/registry/ui/game/molecules/std-crew-board-2d.orb +10 -12
  28. package/behaviors/registry/ui/game/molecules/std-dungeon-board-2d.orb +15 -18
  29. package/behaviors/registry/ui/game/molecules/std-tactics-board-2d.orb +1726 -395
  30. package/behaviors/registry/ui/game/molecules/std-worldmap-board-2d.orb +7 -60
  31. package/behaviors/registry/ui/game/molecules/ui-canvas.orb +7 -0
  32. package/behaviors/registry/ui/game/organisms/ui-arena-board.orb +5 -6
  33. package/behaviors/registry/ui/game/organisms/ui-battle-board.orb +103 -100
  34. package/behaviors/registry/ui/game/organisms/ui-builder-board.orb +21 -226
  35. package/behaviors/registry/ui/game/organisms/ui-card-battler-board.orb +42 -0
  36. package/behaviors/registry/ui/game/organisms/ui-castle-board.orb +30 -9
  37. package/behaviors/registry/ui/game/organisms/ui-city-builder-board.orb +49 -0
  38. package/behaviors/registry/ui/game/organisms/ui-grid-tactics-demo-board.orb +5 -6
  39. package/behaviors/registry/ui/game/organisms/ui-hex-strategy-board.orb +95 -1187
  40. package/behaviors/registry/ui/game/organisms/ui-holiday-runner-board.orb +2 -3
  41. package/behaviors/registry/ui/game/organisms/ui-minigolf-board.orb +55 -11
  42. package/behaviors/registry/ui/game/organisms/ui-pinball-board.orb +8 -8
  43. package/behaviors/registry/ui/game/organisms/ui-pirate-board.orb +14 -0
  44. package/behaviors/registry/ui/game/organisms/ui-platformer-board.orb +72 -0
  45. package/behaviors/registry/ui/game/organisms/ui-sports-board.orb +60 -0
  46. package/behaviors/registry/ui/game/organisms/ui-tactics-demo-2d.orb +222 -332
  47. package/behaviors/registry/ui/game/organisms/ui-tanks-board.orb +127 -95
  48. package/behaviors/registry/ui/game/organisms/ui-topdown-rts-board.orb +1501 -264
  49. package/behaviors/registry/ui/game/organisms/ui-tower-defense-board.orb +8 -0
  50. package/behaviors/registry/ui/game/organisms/ui-uncontrolled-battle-board.orb +5 -0
  51. package/behaviors/registry/ui/game/organisms/ui-world-map-board.orb +8 -12
  52. package/dist/behaviors/behaviors-embeddings.json +244 -236
  53. package/dist/behaviors/behaviors-registry.json +193 -812
  54. package/dist/behaviors/exports-reader.js +1099 -2090
  55. package/dist/behaviors/functions/index.d.ts +33 -26
  56. package/dist/behaviors/functions/index.js +1099 -2091
  57. package/dist/behaviors/index.d.ts +1 -1
  58. package/dist/behaviors/index.js +1100 -2091
  59. package/dist/behaviors/knob-embeddings.json +1 -1
  60. package/dist/behaviors/query.js +1099 -2090
  61. package/dist/behaviors/registry/factory-signatures.json +1893 -2294
  62. package/dist/behaviors/registry/ui/game/molecules/std-crew-board-2d.orb +10 -12
  63. package/dist/behaviors/registry/ui/game/molecules/std-dungeon-board-2d.orb +15 -18
  64. package/dist/behaviors/registry/ui/game/molecules/std-tactics-board-2d.orb +1726 -395
  65. package/dist/behaviors/registry/ui/game/molecules/std-worldmap-board-2d.orb +7 -60
  66. package/dist/behaviors/registry/ui/game/molecules/ui-canvas.orb +7 -0
  67. package/dist/behaviors/registry/ui/game/organisms/ui-arena-board.orb +5 -6
  68. package/dist/behaviors/registry/ui/game/organisms/ui-battle-board.orb +103 -100
  69. package/dist/behaviors/registry/ui/game/organisms/ui-builder-board.orb +21 -226
  70. package/dist/behaviors/registry/ui/game/organisms/ui-card-battler-board.orb +42 -0
  71. package/dist/behaviors/registry/ui/game/organisms/ui-castle-board.orb +30 -9
  72. package/dist/behaviors/registry/ui/game/organisms/ui-city-builder-board.orb +49 -0
  73. package/dist/behaviors/registry/ui/game/organisms/ui-grid-tactics-demo-board.orb +5 -6
  74. package/dist/behaviors/registry/ui/game/organisms/ui-hex-strategy-board.orb +95 -1187
  75. package/dist/behaviors/registry/ui/game/organisms/ui-holiday-runner-board.orb +2 -3
  76. package/dist/behaviors/registry/ui/game/organisms/ui-minigolf-board.orb +55 -11
  77. package/dist/behaviors/registry/ui/game/organisms/ui-pinball-board.orb +8 -8
  78. package/dist/behaviors/registry/ui/game/organisms/ui-pirate-board.orb +14 -0
  79. package/dist/behaviors/registry/ui/game/organisms/ui-platformer-board.orb +72 -0
  80. package/dist/behaviors/registry/ui/game/organisms/ui-sports-board.orb +60 -0
  81. package/dist/behaviors/registry/ui/game/organisms/ui-tactics-demo-2d.orb +222 -332
  82. package/dist/behaviors/registry/ui/game/organisms/ui-tanks-board.orb +127 -95
  83. package/dist/behaviors/registry/ui/game/organisms/ui-topdown-rts-board.orb +1501 -264
  84. package/dist/behaviors/registry/ui/game/organisms/ui-tower-defense-board.orb +8 -0
  85. package/dist/behaviors/registry/ui/game/organisms/ui-uncontrolled-battle-board.orb +5 -0
  86. package/dist/behaviors/registry/ui/game/organisms/ui-world-map-board.orb +8 -12
  87. package/dist/behaviors-embeddings.json +244 -236
  88. package/dist/behaviors-registry.json +193 -812
  89. package/dist/index.d.ts +1 -1
  90. package/dist/index.js +1100 -2091
  91. package/dist/knob-embeddings.json +1 -1
  92. package/dist/registry/factory-signatures.json +1893 -2294
  93. package/package.json +2 -2
@@ -1,6 +1,151 @@
1
1
  app ui-battle-board "1.0.0"
2
- "RPG-tactics battle: thin organism composing the std-tactics-board-2d frame + std-score + std-xp (kills grant xp; level-ups heal the party via a HEAL intent). Isometric shape-character theme supplied via config."
2
+ "RPG-tactics battle: thin organism composing the std-tactics-board-2d frame + std-score + std-xp (kills grant xp; level-ups heal the party via a HEAL intent). Isometric hand-authored svg theme supplied via config."
3
3
  ;; @capabilities "turn-based combat, RPG gameplay, strategy gameplay"
4
+
5
+ ;; ============================================================================
6
+ ;; PERSONA + USER STORIES
7
+ ;;
8
+ ;; Read these before changing anything here, and walk them end to end after.
9
+ ;; One persona: the PLAYER, commanding a four-unit party on a 16x16 isometric
10
+ ;; grid against four enemies. Status re-verified 2026-07-30 by a scripted
11
+ ;; full playthrough (32/32 checks) driving the real game on the
12
+ ;; runtime-verify catalog through window.__orbitalVerification — events in,
13
+ ;; canvas drawables + HUD DOM + bus event log out. No claim below is
14
+ ;; untested hearsay.
15
+ ;;
16
+ ;; THE GENRE (what an RPG-tactics player expects): you command a small party,
17
+ ;; not an army. Positioning is the game — you read the grid, move each unit
18
+ ;; inside its reach, and commit to strikes when an enemy steps adjacent.
19
+ ;; Blows trade back and forth: every End Turn hands the board to the enemy
20
+ ;; AI, which closes the distance and punishes exposed units. Kills are the
21
+ ;; economy: each one scores, banks xp, and xp thresholds level the party up
22
+ ;; and patch their wounds. You win by wiping the enemy; you lose by being
23
+ ;; wiped. A round looks like: select a unit -> green reach cells -> move ->
24
+ ;; the unit STAYS selected and auto-arms (red cells = enemies in reach) ->
25
+ ;; strike for 3 -> the unit is SPENT (dims, cannot act again this turn) ->
26
+ ;; activate the next unit -> End Turn -> every living enemy strikes an
27
+ ;; adjacent player for 1 or steps 1 cell toward the nearest player -> repeat.
28
+ ;; Each unit may move ONCE and attack ONCE per turn (movedIds/actedIds track
29
+ ;; the activation; End Turn resets both). Kills score 10 and grant 25 xp;
30
+ ;; every 100 xp (+50 per level) levels up and heals the whole party +2.
31
+ ;; ============================================================================
32
+ ;;
33
+ ;; PLAYER — "I command my party and wipe the enemy before they wipe me."
34
+ ;;
35
+ ;; 1. I open the board and see the whole battlefield framed on screen —
36
+ ;; terrain under every cell, my party at the south, the enemy at the
37
+ ;; north, and the HUD showing Result/Phase/Turn/Score/XP/Lvl.
38
+ ;; WORKS. Boot paints 256 full-cell isometric grass cubes (no gaps),
39
+ ;; 8 units (4v4), portal + gold-mine features, minimap on; HUD reads
40
+ ;; "none / observation / 0 / 0 / 0 / 1". Verified: 39/39 assets
41
+ ;; loaded, zero failed. (Result/Phase used to render "0" — StatBadge
42
+ ;; defaults format "number" and parseInt-ed the strings; the frame's
43
+ ;; HudStat now carries format: "text" for both.)
44
+ ;; 2. Every unit on the board is a visible character sprite with a name
45
+ ;; label and a health bar I can read at a glance.
46
+ ;; WORKS. Each unit paints its svg idle frame (4-frame bob, cycled by
47
+ ;; the AnimClock tick) anchored "ground", with the black backing +
48
+ ;; green health fraction above and the name label. All 8 bars read
49
+ ;; full at boot. Dead units drop the bar and label (they are corpses,
50
+ ;; not combatants) and switch to the death frame.
51
+ ;; 3. I click one of MY units and the cells it can reach light up.
52
+ ;; WORKS. Clicking p1 sets phase "selection" and lights exactly 9
53
+ ;; green cells — the range-2 manhattan diamond minus occupied cells.
54
+ ;; Dead units are NOT selectable (guard on health > 0): clicking a
55
+ ;; corpse does nothing. SPENT units (already attacked this turn, in
56
+ ;; actedIds) are not selectable either — their activation is over.
57
+ ;; A unit that already MOVED this turn still selects (it may attack)
58
+ ;; but lights zero green cells — one move per turn.
59
+ ;; 4. I click a lit cell and the unit moves there — and stays selected,
60
+ ;; auto-armed, so I can strike immediately.
61
+ ;; WORKS. p1 walked (3,12)->(3,10): the walk animation plays (2-frame
62
+ ;; cycle, ~6 ticks), the authority re-validates bounds/passable/
63
+ ;; occupied and writes the position, and the unit lands in phase
64
+ ;; "action" with any enemies now in reach lit red. Clicking an
65
+ ;; OCCUPIED or out-of-reach cell is ignored outright (guard) instead
66
+ ;; of silently eating the selection. The move is SPENT: the unit
67
+ ;; cannot move again until End Turn (movedIds guard) — there is no
68
+ ;; way to chain moves.
69
+ ;; 5. Adjacent enemies I can strike light up red — right after my move,
70
+ ;; or when I click my selected unit again.
71
+ ;; WORKS. Post-move auto-arm computes red cells from the NEW position;
72
+ ;; the manual re-click arm (phase "action") still works from a fresh
73
+ ;; selection. Living enemies at manhattan distance <= attackRange
74
+ ;; (config, default 1) light red.
75
+ ;; 6. I click a red-lit enemy — or any enemy in reach, even without arming
76
+ ;; first — and it takes a hit; my unit is then spent for the turn.
77
+ ;; WORKS. The attack arm fires whenever a living selected unit has a
78
+ ;; living enemy in reach, regardless of phase (selection or action) —
79
+ ;; no more dead clicks on an enemy you just walked up to. The
80
+ ;; attacker plays its attack frame, the target plays its hit frame, a
81
+ ;; "-3" damage number + hit-star fx sprite spawn at the target
82
+ ;; (BURST, ttl 3 decayed by FxDecay), the health bar shrinks
83
+ ;; (verified e3 1.00 -> 0.63 of max), and the attacker joins actedIds:
84
+ ;; it dims to 45% opacity and cannot be selected or attack again
85
+ ;; until End Turn.
86
+ ;; 7. I change my mind mid-selection and back out cleanly.
87
+ ;; WORKS. CANCEL clears selection, highlights, and phase — verified
88
+ ;; green cells 9 -> 0 and phase back to "observation".
89
+ ;; 8. I end my turn and the enemy takes theirs — they close in and fight
90
+ ;; back, and my party is fresh again.
91
+ ;; WORKS. END_TURN bumps Turn, clears selection + both activation
92
+ ;; lists (movedIds/actedIds — every unit can act again), and emits
93
+ ;; AI_TURN; the authority strikes every player adjacent to a living
94
+ ;; enemy for 1 and steps each unengaged enemy 1 cell toward the
95
+ ;; nearest living player. Verified: enemy positions changed and/or
96
+ ;; player hp dropped every turn.
97
+ ;; LIMITATION: enemies POP to their new cell — the authority applies
98
+ ;; the step silently and the single walk-anim slot is player-facing;
99
+ ;; per-enemy MOVE fan-out is atom surgery, deferred.
100
+ ;; 9. When I kill an enemy I am rewarded — score ticks up, xp ticks up,
101
+ ;; and the corpse stays on the field.
102
+ ;; WORKS x4. Each kill: Score +10, XP +25 (ScoreKeeper/XpKeeper on
103
+ ;; UNITS_CHANGED), the corpse renders its death frame, and the cell
104
+ ;; becomes walkable again — corpses never block movement or green
105
+ ;; highlights (authority and highlight filters agree on health > 0;
106
+ ;; verified with four corpses piled on two cells).
107
+ ;; 10. When my xp crosses the threshold the party levels up and heals.
108
+ ;; WORKS. The 4th kill crossed 100 xp: Lvl 1 -> 2 on the HUD and a
109
+ ;; HEAL { team: "player", amount: 2 } fired on the bus, which the
110
+ ;; authority applies capped at maxHealth.
111
+ ;; 11. When the last enemy falls, I win and the game tells me — then the
112
+ ;; board freezes.
113
+ ;; WORKS. Result flips to "victory" (RoundLogic on UNITS_CHANGED),
114
+ ;; GAME_END fires, and the board is FROZEN: every UNIT_CLICK /
115
+ ;; TILE_CLICK arm is guarded on result == "none", so post-game clicks
116
+ ;; select nothing and move nothing (verified by probe). Reload to
117
+ ;; play again — an in-game rematch button does not exist yet.
118
+ ;;
119
+ ;; MULTIPLAYER NOTE: GameState is [runtime, shared], so every connected
120
+ ;; client watches the same battle on the same frame; intents serialize
121
+ ;; through the server authority. There is no per-seat turn ownership yet —
122
+ ;; any client can drive any player unit.
123
+ ;;
124
+ ;; ASSET INVENTORY (hand-authored svg, almadar-kflow-assets.web.app
125
+ ;; /shared/ui-battle-board/svg/isometric/, generated by tools/asset-workflow
126
+ ;; svg-generator from the sibling .md descriptions)
127
+ ;;
128
+ ;; Terrain terrain/grass.svg, terrain/stone.svg — full-cell isometric
129
+ ;; cubes (top + left + right faces) that tessellate exactly with
130
+ ;; the projector's cellPath; drawn at width/height 1.
131
+ ;; Units units/{guardian,scrapper,worker,mender}.svg + animation frames
132
+ ;; .{idle-0..3, walk-0..1, attack-0, hit-0, death-0}.svg; the
133
+ ;; frame swaps url-rewrites name.svg -> name.<anim>-<i>.svg and a
134
+ ;; hidden warm-up layer preloads every frame so swaps never pop.
135
+ ;; party: p1 Guardian 10hp (3,12) p2 Scrapper 8hp (2,11)
136
+ ;; p3 Worker 6hp (4,13) p4 Mender 7hp (2,13)
137
+ ;; enemy: e1/e2 Guardian 10hp (12,3),(13,4)
138
+ ;; e3/e4 Scrapper 8hp (11,2),(13,2)
139
+ ;; Features features/gold_mine.svg at (13,1), features/portal.svg at
140
+ ;; (1,14) — the two home bases, drawn from config.features
141
+ ;; anchored "ground" at 1x1 so they sit ON their cell (the
142
+ ;; draw-sprite default anchor is "top-left", which floated them
143
+ ;; off the board corner before the anchor was explicit).
144
+ ;; Effects effects/hit.svg (BURST "hit" fx), effects/explosion.svg
145
+ ;; (manifest-only).
146
+ ;; UI chrome ui/panel-frame.svg = game-shell background + HUD panel.
147
+ ;; ============================================================================
148
+
4
149
  orbital BattleBoardOrbital {
5
150
  uses Frame from "std/behaviors/std-tactics-board-2d"
6
151
  uses Score from "std/behaviors/std-score"
@@ -70,13 +215,15 @@ orbital BattleBoardOrbital {
70
215
 
71
216
  entity GameState [runtime, shared] {
72
217
  id : string!
73
- units : [Unit] = [ { id: "p1", position: { x: 3, y: 12 }, x: 3, y: 12, z: 0, team: "player", health: 10, maxHealth: 10, unitType: "guardian", name: "Guardian", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "blue_body_square.png", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "p2", position: { x: 2, y: 11 }, x: 2, y: 11, z: 0, team: "player", health: 8, maxHealth: 8, unitType: "scrapper", name: "Scrapper", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "red_body_rhombus.png", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } }, { id: "p3", position: { x: 4, y: 13 }, x: 4, y: 13, z: 0, team: "player", health: 6, maxHealth: 6, unitType: "worker", name: "Worker", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "yellow_body_squircle.png", role: "npc", category: "worker", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "worker", thumbnailUrl: "" } }, { id: "p4", position: { x: 2, y: 13 }, x: 2, y: 13, z: 0, team: "player", health: 7, maxHealth: 7, unitType: "mender", name: "Mender", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "green_body_circle.png", role: "npc", category: "mender", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "mender", thumbnailUrl: "" } }, { id: "e1", position: { x: 12, y: 3 }, x: 12, y: 3, z: 0, team: "enemy", health: 10, maxHealth: 10, unitType: "guardian", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "blue_body_square.png", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "e2", position: { x: 13, y: 4 }, x: 13, y: 4, z: 0, team: "enemy", health: 10, maxHealth: 10, unitType: "guardian", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "blue_body_square.png", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "e3", position: { x: 11, y: 2 }, x: 11, y: 2, z: 0, team: "enemy", health: 8, maxHealth: 8, unitType: "scrapper", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "red_body_rhombus.png", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } }, { id: "e4", position: { x: 13, y: 2 }, x: 13, y: 2, z: 0, team: "enemy", health: 8, maxHealth: 8, unitType: "scrapper", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "red_body_rhombus.png", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } } ]
218
+ units : [Unit] = [ { id: "p1", position: { x: 3, y: 12 }, x: 3, y: 12, z: 0, team: "player", health: 10, maxHealth: 10, unitType: "guardian", name: "Guardian", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/guardian.svg", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "p2", position: { x: 2, y: 11 }, x: 2, y: 11, z: 0, team: "player", health: 8, maxHealth: 8, unitType: "scrapper", name: "Scrapper", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/scrapper.svg", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } }, { id: "p3", position: { x: 4, y: 13 }, x: 4, y: 13, z: 0, team: "player", health: 6, maxHealth: 6, unitType: "worker", name: "Worker", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/worker.svg", role: "npc", category: "worker", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "worker", thumbnailUrl: "" } }, { id: "p4", position: { x: 2, y: 13 }, x: 2, y: 13, z: 0, team: "player", health: 7, maxHealth: 7, unitType: "mender", name: "Mender", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/mender.svg", role: "npc", category: "mender", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "mender", thumbnailUrl: "" } }, { id: "e1", position: { x: 12, y: 3 }, x: 12, y: 3, z: 0, team: "enemy", health: 10, maxHealth: 10, unitType: "guardian", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/guardian.svg", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "e2", position: { x: 13, y: 4 }, x: 13, y: 4, z: 0, team: "enemy", health: 10, maxHealth: 10, unitType: "guardian", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/guardian.svg", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "e3", position: { x: 11, y: 2 }, x: 11, y: 2, z: 0, team: "enemy", health: 8, maxHealth: 8, unitType: "scrapper", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/scrapper.svg", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } }, { id: "e4", position: { x: 13, y: 2 }, x: 13, y: 2, z: 0, team: "enemy", health: 8, maxHealth: 8, unitType: "scrapper", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/scrapper.svg", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } } ]
74
219
  fx : [Fx] = []
75
220
  tiles : [Tile] = [ { id: "t-0-0", x: 0, y: 0, terrain: "grass", passable: true }, { id: "t-1-0", x: 1, y: 0, terrain: "grass", passable: true }, { id: "t-2-0", x: 2, y: 0, terrain: "grass", passable: true }, { id: "t-3-0", x: 3, y: 0, terrain: "grass", passable: true }, { id: "t-4-0", x: 4, y: 0, terrain: "grass", passable: true }, { id: "t-5-0", x: 5, y: 0, terrain: "grass", passable: true }, { id: "t-6-0", x: 6, y: 0, terrain: "grass", passable: true }, { id: "t-7-0", x: 7, y: 0, terrain: "grass", passable: true }, { id: "t-8-0", x: 8, y: 0, terrain: "grass", passable: true }, { id: "t-9-0", x: 9, y: 0, terrain: "grass", passable: true }, { id: "t-10-0", x: 10, y: 0, terrain: "grass", passable: true }, { id: "t-11-0", x: 11, y: 0, terrain: "grass", passable: true }, { id: "t-12-0", x: 12, y: 0, terrain: "grass", passable: true }, { id: "t-13-0", x: 13, y: 0, terrain: "grass", passable: true }, { id: "t-14-0", x: 14, y: 0, terrain: "grass", passable: true }, { id: "t-15-0", x: 15, y: 0, terrain: "grass", passable: true }, { id: "t-0-1", x: 0, y: 1, terrain: "grass", passable: true }, { id: "t-1-1", x: 1, y: 1, terrain: "grass", passable: true }, { id: "t-2-1", x: 2, y: 1, terrain: "grass", passable: true }, { id: "t-3-1", x: 3, y: 1, terrain: "grass", passable: true }, { id: "t-4-1", x: 4, y: 1, terrain: "grass", passable: true }, { id: "t-5-1", x: 5, y: 1, terrain: "grass", passable: true }, { id: "t-6-1", x: 6, y: 1, terrain: "grass", passable: true }, { id: "t-7-1", x: 7, y: 1, terrain: "grass", passable: true }, { id: "t-8-1", x: 8, y: 1, terrain: "grass", passable: true }, { id: "t-9-1", x: 9, y: 1, terrain: "grass", passable: true }, { id: "t-10-1", x: 10, y: 1, terrain: "grass", passable: true }, { id: "t-11-1", x: 11, y: 1, terrain: "grass", passable: true }, { id: "t-12-1", x: 12, y: 1, terrain: "grass", passable: true }, { id: "t-13-1", x: 13, y: 1, terrain: "grass", passable: true }, { id: "t-14-1", x: 14, y: 1, terrain: "grass", passable: true }, { id: "t-15-1", x: 15, y: 1, terrain: "grass", passable: true }, { id: "t-0-2", x: 0, y: 2, terrain: "grass", passable: true }, { id: "t-1-2", x: 1, y: 2, terrain: "grass", passable: true }, { id: "t-2-2", x: 2, y: 2, terrain: "grass", passable: true }, { id: "t-3-2", x: 3, y: 2, terrain: "grass", passable: true }, { id: "t-4-2", x: 4, y: 2, terrain: "grass", passable: true }, { id: "t-5-2", x: 5, y: 2, terrain: "grass", passable: true }, { id: "t-6-2", x: 6, y: 2, terrain: "grass", passable: true }, { id: "t-7-2", x: 7, y: 2, terrain: "grass", passable: true }, { id: "t-8-2", x: 8, y: 2, terrain: "grass", passable: true }, { id: "t-9-2", x: 9, y: 2, terrain: "grass", passable: true }, { id: "t-10-2", x: 10, y: 2, terrain: "grass", passable: true }, { id: "t-11-2", x: 11, y: 2, terrain: "grass", passable: true }, { id: "t-12-2", x: 12, y: 2, terrain: "grass", passable: true }, { id: "t-13-2", x: 13, y: 2, terrain: "grass", passable: true }, { id: "t-14-2", x: 14, y: 2, terrain: "grass", passable: true }, { id: "t-15-2", x: 15, y: 2, terrain: "grass", passable: true }, { id: "t-0-3", x: 0, y: 3, terrain: "grass", passable: true }, { id: "t-1-3", x: 1, y: 3, terrain: "grass", passable: true }, { id: "t-2-3", x: 2, y: 3, terrain: "grass", passable: true }, { id: "t-3-3", x: 3, y: 3, terrain: "grass", passable: true }, { id: "t-4-3", x: 4, y: 3, terrain: "grass", passable: true }, { id: "t-5-3", x: 5, y: 3, terrain: "grass", passable: true }, { id: "t-6-3", x: 6, y: 3, terrain: "grass", passable: true }, { id: "t-7-3", x: 7, y: 3, terrain: "grass", passable: true }, { id: "t-8-3", x: 8, y: 3, terrain: "grass", passable: true }, { id: "t-9-3", x: 9, y: 3, terrain: "grass", passable: true }, { id: "t-10-3", x: 10, y: 3, terrain: "grass", passable: true }, { id: "t-11-3", x: 11, y: 3, terrain: "grass", passable: true }, { id: "t-12-3", x: 12, y: 3, terrain: "grass", passable: true }, { id: "t-13-3", x: 13, y: 3, terrain: "grass", passable: true }, { id: "t-14-3", x: 14, y: 3, terrain: "grass", passable: true }, { id: "t-15-3", x: 15, y: 3, terrain: "grass", passable: true }, { id: "t-0-4", x: 0, y: 4, terrain: "grass", passable: true }, { id: "t-1-4", x: 1, y: 4, terrain: "grass", passable: true }, { id: "t-2-4", x: 2, y: 4, terrain: "grass", passable: true }, { id: "t-3-4", x: 3, y: 4, terrain: "grass", passable: true }, { id: "t-4-4", x: 4, y: 4, terrain: "grass", passable: true }, { id: "t-5-4", x: 5, y: 4, terrain: "grass", passable: true }, { id: "t-6-4", x: 6, y: 4, terrain: "grass", passable: true }, { id: "t-7-4", x: 7, y: 4, terrain: "grass", passable: true }, { id: "t-8-4", x: 8, y: 4, terrain: "grass", passable: true }, { id: "t-9-4", x: 9, y: 4, terrain: "grass", passable: true }, { id: "t-10-4", x: 10, y: 4, terrain: "grass", passable: true }, { id: "t-11-4", x: 11, y: 4, terrain: "grass", passable: true }, { id: "t-12-4", x: 12, y: 4, terrain: "grass", passable: true }, { id: "t-13-4", x: 13, y: 4, terrain: "grass", passable: true }, { id: "t-14-4", x: 14, y: 4, terrain: "grass", passable: true }, { id: "t-15-4", x: 15, y: 4, terrain: "grass", passable: true }, { id: "t-0-5", x: 0, y: 5, terrain: "grass", passable: true }, { id: "t-1-5", x: 1, y: 5, terrain: "grass", passable: true }, { id: "t-2-5", x: 2, y: 5, terrain: "grass", passable: true }, { id: "t-3-5", x: 3, y: 5, terrain: "grass", passable: true }, { id: "t-4-5", x: 4, y: 5, terrain: "grass", passable: true }, { id: "t-5-5", x: 5, y: 5, terrain: "grass", passable: true }, { id: "t-6-5", x: 6, y: 5, terrain: "grass", passable: true }, { id: "t-7-5", x: 7, y: 5, terrain: "grass", passable: true }, { id: "t-8-5", x: 8, y: 5, terrain: "grass", passable: true }, { id: "t-9-5", x: 9, y: 5, terrain: "grass", passable: true }, { id: "t-10-5", x: 10, y: 5, terrain: "grass", passable: true }, { id: "t-11-5", x: 11, y: 5, terrain: "grass", passable: true }, { id: "t-12-5", x: 12, y: 5, terrain: "grass", passable: true }, { id: "t-13-5", x: 13, y: 5, terrain: "grass", passable: true }, { id: "t-14-5", x: 14, y: 5, terrain: "grass", passable: true }, { id: "t-15-5", x: 15, y: 5, terrain: "grass", passable: true }, { id: "t-0-6", x: 0, y: 6, terrain: "grass", passable: true }, { id: "t-1-6", x: 1, y: 6, terrain: "grass", passable: true }, { id: "t-2-6", x: 2, y: 6, terrain: "grass", passable: true }, { id: "t-3-6", x: 3, y: 6, terrain: "grass", passable: true }, { id: "t-4-6", x: 4, y: 6, terrain: "grass", passable: true }, { id: "t-5-6", x: 5, y: 6, terrain: "grass", passable: true }, { id: "t-6-6", x: 6, y: 6, terrain: "grass", passable: true }, { id: "t-7-6", x: 7, y: 6, terrain: "grass", passable: true }, { id: "t-8-6", x: 8, y: 6, terrain: "grass", passable: true }, { id: "t-9-6", x: 9, y: 6, terrain: "grass", passable: true }, { id: "t-10-6", x: 10, y: 6, terrain: "grass", passable: true }, { id: "t-11-6", x: 11, y: 6, terrain: "grass", passable: true }, { id: "t-12-6", x: 12, y: 6, terrain: "grass", passable: true }, { id: "t-13-6", x: 13, y: 6, terrain: "grass", passable: true }, { id: "t-14-6", x: 14, y: 6, terrain: "grass", passable: true }, { id: "t-15-6", x: 15, y: 6, terrain: "grass", passable: true }, { id: "t-0-7", x: 0, y: 7, terrain: "grass", passable: true }, { id: "t-1-7", x: 1, y: 7, terrain: "grass", passable: true }, { id: "t-2-7", x: 2, y: 7, terrain: "grass", passable: true }, { id: "t-3-7", x: 3, y: 7, terrain: "grass", passable: true }, { id: "t-4-7", x: 4, y: 7, terrain: "grass", passable: true }, { id: "t-5-7", x: 5, y: 7, terrain: "grass", passable: true }, { id: "t-6-7", x: 6, y: 7, terrain: "grass", passable: true }, { id: "t-7-7", x: 7, y: 7, terrain: "grass", passable: true }, { id: "t-8-7", x: 8, y: 7, terrain: "grass", passable: true }, { id: "t-9-7", x: 9, y: 7, terrain: "grass", passable: true }, { id: "t-10-7", x: 10, y: 7, terrain: "grass", passable: true }, { id: "t-11-7", x: 11, y: 7, terrain: "grass", passable: true }, { id: "t-12-7", x: 12, y: 7, terrain: "grass", passable: true }, { id: "t-13-7", x: 13, y: 7, terrain: "grass", passable: true }, { id: "t-14-7", x: 14, y: 7, terrain: "grass", passable: true }, { id: "t-15-7", x: 15, y: 7, terrain: "grass", passable: true }, { id: "t-0-8", x: 0, y: 8, terrain: "grass", passable: true }, { id: "t-1-8", x: 1, y: 8, terrain: "grass", passable: true }, { id: "t-2-8", x: 2, y: 8, terrain: "grass", passable: true }, { id: "t-3-8", x: 3, y: 8, terrain: "grass", passable: true }, { id: "t-4-8", x: 4, y: 8, terrain: "grass", passable: true }, { id: "t-5-8", x: 5, y: 8, terrain: "grass", passable: true }, { id: "t-6-8", x: 6, y: 8, terrain: "grass", passable: true }, { id: "t-7-8", x: 7, y: 8, terrain: "grass", passable: true }, { id: "t-8-8", x: 8, y: 8, terrain: "grass", passable: true }, { id: "t-9-8", x: 9, y: 8, terrain: "grass", passable: true }, { id: "t-10-8", x: 10, y: 8, terrain: "grass", passable: true }, { id: "t-11-8", x: 11, y: 8, terrain: "grass", passable: true }, { id: "t-12-8", x: 12, y: 8, terrain: "grass", passable: true }, { id: "t-13-8", x: 13, y: 8, terrain: "grass", passable: true }, { id: "t-14-8", x: 14, y: 8, terrain: "grass", passable: true }, { id: "t-15-8", x: 15, y: 8, terrain: "grass", passable: true }, { id: "t-0-9", x: 0, y: 9, terrain: "grass", passable: true }, { id: "t-1-9", x: 1, y: 9, terrain: "grass", passable: true }, { id: "t-2-9", x: 2, y: 9, terrain: "grass", passable: true }, { id: "t-3-9", x: 3, y: 9, terrain: "grass", passable: true }, { id: "t-4-9", x: 4, y: 9, terrain: "grass", passable: true }, { id: "t-5-9", x: 5, y: 9, terrain: "grass", passable: true }, { id: "t-6-9", x: 6, y: 9, terrain: "grass", passable: true }, { id: "t-7-9", x: 7, y: 9, terrain: "grass", passable: true }, { id: "t-8-9", x: 8, y: 9, terrain: "grass", passable: true }, { id: "t-9-9", x: 9, y: 9, terrain: "grass", passable: true }, { id: "t-10-9", x: 10, y: 9, terrain: "grass", passable: true }, { id: "t-11-9", x: 11, y: 9, terrain: "grass", passable: true }, { id: "t-12-9", x: 12, y: 9, terrain: "grass", passable: true }, { id: "t-13-9", x: 13, y: 9, terrain: "grass", passable: true }, { id: "t-14-9", x: 14, y: 9, terrain: "grass", passable: true }, { id: "t-15-9", x: 15, y: 9, terrain: "grass", passable: true }, { id: "t-0-10", x: 0, y: 10, terrain: "grass", passable: true }, { id: "t-1-10", x: 1, y: 10, terrain: "grass", passable: true }, { id: "t-2-10", x: 2, y: 10, terrain: "grass", passable: true }, { id: "t-3-10", x: 3, y: 10, terrain: "grass", passable: true }, { id: "t-4-10", x: 4, y: 10, terrain: "grass", passable: true }, { id: "t-5-10", x: 5, y: 10, terrain: "grass", passable: true }, { id: "t-6-10", x: 6, y: 10, terrain: "grass", passable: true }, { id: "t-7-10", x: 7, y: 10, terrain: "grass", passable: true }, { id: "t-8-10", x: 8, y: 10, terrain: "grass", passable: true }, { id: "t-9-10", x: 9, y: 10, terrain: "grass", passable: true }, { id: "t-10-10", x: 10, y: 10, terrain: "grass", passable: true }, { id: "t-11-10", x: 11, y: 10, terrain: "grass", passable: true }, { id: "t-12-10", x: 12, y: 10, terrain: "grass", passable: true }, { id: "t-13-10", x: 13, y: 10, terrain: "grass", passable: true }, { id: "t-14-10", x: 14, y: 10, terrain: "grass", passable: true }, { id: "t-15-10", x: 15, y: 10, terrain: "grass", passable: true }, { id: "t-0-11", x: 0, y: 11, terrain: "grass", passable: true }, { id: "t-1-11", x: 1, y: 11, terrain: "grass", passable: true }, { id: "t-2-11", x: 2, y: 11, terrain: "grass", passable: true }, { id: "t-3-11", x: 3, y: 11, terrain: "grass", passable: true }, { id: "t-4-11", x: 4, y: 11, terrain: "grass", passable: true }, { id: "t-5-11", x: 5, y: 11, terrain: "grass", passable: true }, { id: "t-6-11", x: 6, y: 11, terrain: "grass", passable: true }, { id: "t-7-11", x: 7, y: 11, terrain: "grass", passable: true }, { id: "t-8-11", x: 8, y: 11, terrain: "grass", passable: true }, { id: "t-9-11", x: 9, y: 11, terrain: "grass", passable: true }, { id: "t-10-11", x: 10, y: 11, terrain: "grass", passable: true }, { id: "t-11-11", x: 11, y: 11, terrain: "grass", passable: true }, { id: "t-12-11", x: 12, y: 11, terrain: "grass", passable: true }, { id: "t-13-11", x: 13, y: 11, terrain: "grass", passable: true }, { id: "t-14-11", x: 14, y: 11, terrain: "grass", passable: true }, { id: "t-15-11", x: 15, y: 11, terrain: "grass", passable: true }, { id: "t-0-12", x: 0, y: 12, terrain: "grass", passable: true }, { id: "t-1-12", x: 1, y: 12, terrain: "grass", passable: true }, { id: "t-2-12", x: 2, y: 12, terrain: "grass", passable: true }, { id: "t-3-12", x: 3, y: 12, terrain: "grass", passable: true }, { id: "t-4-12", x: 4, y: 12, terrain: "grass", passable: true }, { id: "t-5-12", x: 5, y: 12, terrain: "grass", passable: true }, { id: "t-6-12", x: 6, y: 12, terrain: "grass", passable: true }, { id: "t-7-12", x: 7, y: 12, terrain: "grass", passable: true }, { id: "t-8-12", x: 8, y: 12, terrain: "grass", passable: true }, { id: "t-9-12", x: 9, y: 12, terrain: "grass", passable: true }, { id: "t-10-12", x: 10, y: 12, terrain: "grass", passable: true }, { id: "t-11-12", x: 11, y: 12, terrain: "grass", passable: true }, { id: "t-12-12", x: 12, y: 12, terrain: "grass", passable: true }, { id: "t-13-12", x: 13, y: 12, terrain: "grass", passable: true }, { id: "t-14-12", x: 14, y: 12, terrain: "grass", passable: true }, { id: "t-15-12", x: 15, y: 12, terrain: "grass", passable: true }, { id: "t-0-13", x: 0, y: 13, terrain: "grass", passable: true }, { id: "t-1-13", x: 1, y: 13, terrain: "grass", passable: true }, { id: "t-2-13", x: 2, y: 13, terrain: "grass", passable: true }, { id: "t-3-13", x: 3, y: 13, terrain: "grass", passable: true }, { id: "t-4-13", x: 4, y: 13, terrain: "grass", passable: true }, { id: "t-5-13", x: 5, y: 13, terrain: "grass", passable: true }, { id: "t-6-13", x: 6, y: 13, terrain: "grass", passable: true }, { id: "t-7-13", x: 7, y: 13, terrain: "grass", passable: true }, { id: "t-8-13", x: 8, y: 13, terrain: "grass", passable: true }, { id: "t-9-13", x: 9, y: 13, terrain: "grass", passable: true }, { id: "t-10-13", x: 10, y: 13, terrain: "grass", passable: true }, { id: "t-11-13", x: 11, y: 13, terrain: "grass", passable: true }, { id: "t-12-13", x: 12, y: 13, terrain: "grass", passable: true }, { id: "t-13-13", x: 13, y: 13, terrain: "grass", passable: true }, { id: "t-14-13", x: 14, y: 13, terrain: "grass", passable: true }, { id: "t-15-13", x: 15, y: 13, terrain: "grass", passable: true }, { id: "t-0-14", x: 0, y: 14, terrain: "grass", passable: true }, { id: "t-1-14", x: 1, y: 14, terrain: "grass", passable: true }, { id: "t-2-14", x: 2, y: 14, terrain: "grass", passable: true }, { id: "t-3-14", x: 3, y: 14, terrain: "grass", passable: true }, { id: "t-4-14", x: 4, y: 14, terrain: "grass", passable: true }, { id: "t-5-14", x: 5, y: 14, terrain: "grass", passable: true }, { id: "t-6-14", x: 6, y: 14, terrain: "grass", passable: true }, { id: "t-7-14", x: 7, y: 14, terrain: "grass", passable: true }, { id: "t-8-14", x: 8, y: 14, terrain: "grass", passable: true }, { id: "t-9-14", x: 9, y: 14, terrain: "grass", passable: true }, { id: "t-10-14", x: 10, y: 14, terrain: "grass", passable: true }, { id: "t-11-14", x: 11, y: 14, terrain: "grass", passable: true }, { id: "t-12-14", x: 12, y: 14, terrain: "grass", passable: true }, { id: "t-13-14", x: 13, y: 14, terrain: "grass", passable: true }, { id: "t-14-14", x: 14, y: 14, terrain: "grass", passable: true }, { id: "t-15-14", x: 15, y: 14, terrain: "grass", passable: true }, { id: "t-0-15", x: 0, y: 15, terrain: "grass", passable: true }, { id: "t-1-15", x: 1, y: 15, terrain: "grass", passable: true }, { id: "t-2-15", x: 2, y: 15, terrain: "grass", passable: true }, { id: "t-3-15", x: 3, y: 15, terrain: "grass", passable: true }, { id: "t-4-15", x: 4, y: 15, terrain: "grass", passable: true }, { id: "t-5-15", x: 5, y: 15, terrain: "grass", passable: true }, { id: "t-6-15", x: 6, y: 15, terrain: "grass", passable: true }, { id: "t-7-15", x: 7, y: 15, terrain: "grass", passable: true }, { id: "t-8-15", x: 8, y: 15, terrain: "grass", passable: true }, { id: "t-9-15", x: 9, y: 15, terrain: "grass", passable: true }, { id: "t-10-15", x: 10, y: 15, terrain: "grass", passable: true }, { id: "t-11-15", x: 11, y: 15, terrain: "grass", passable: true }, { id: "t-12-15", x: 12, y: 15, terrain: "grass", passable: true }, { id: "t-13-15", x: 13, y: 15, terrain: "grass", passable: true }, { id: "t-14-15", x: 14, y: 15, terrain: "grass", passable: true }, { id: "t-15-15", x: 15, y: 15, terrain: "grass", passable: true } ]
76
221
  result : string = "none"
77
222
  selectedUnitId : string = ""
78
223
  validMoves : [ValidMove] = []
79
224
  attackTargets : [ValidMove] = []
225
+ movedIds : [string] = []
226
+ actedIds : [string] = []
80
227
  uiPhase : string = "observation"
81
228
  turn : number = 0
82
229
  score : number = 0
@@ -93,7 +240,7 @@ orbital BattleBoardOrbital {
93
240
  gridWidth: 16
94
241
  gridHeight: 16
95
242
  attackDamage: 3
96
- units: [ { id: "p1", position: { x: 3, y: 12 }, x: 3, y: 12, z: 0, team: "player", health: 10, maxHealth: 10, unitType: "guardian", name: "Guardian", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "blue_body_square.png", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "p2", position: { x: 2, y: 11 }, x: 2, y: 11, z: 0, team: "player", health: 8, maxHealth: 8, unitType: "scrapper", name: "Scrapper", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "red_body_rhombus.png", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } }, { id: "p3", position: { x: 4, y: 13 }, x: 4, y: 13, z: 0, team: "player", health: 6, maxHealth: 6, unitType: "worker", name: "Worker", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "yellow_body_squircle.png", role: "npc", category: "worker", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "worker", thumbnailUrl: "" } }, { id: "p4", position: { x: 2, y: 13 }, x: 2, y: 13, z: 0, team: "player", health: 7, maxHealth: 7, unitType: "mender", name: "Mender", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "green_body_circle.png", role: "npc", category: "mender", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "mender", thumbnailUrl: "" } }, { id: "e1", position: { x: 12, y: 3 }, x: 12, y: 3, z: 0, team: "enemy", health: 10, maxHealth: 10, unitType: "guardian", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "blue_body_square.png", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "e2", position: { x: 13, y: 4 }, x: 13, y: 4, z: 0, team: "enemy", health: 10, maxHealth: 10, unitType: "guardian", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "blue_body_square.png", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "e3", position: { x: 11, y: 2 }, x: 11, y: 2, z: 0, team: "enemy", health: 8, maxHealth: 8, unitType: "scrapper", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "red_body_rhombus.png", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } }, { id: "e4", position: { x: 13, y: 2 }, x: 13, y: 2, z: 0, team: "enemy", health: 8, maxHealth: 8, unitType: "scrapper", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "red_body_rhombus.png", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } } ]
243
+ units: [ { id: "p1", position: { x: 3, y: 12 }, x: 3, y: 12, z: 0, team: "player", health: 10, maxHealth: 10, unitType: "guardian", name: "Guardian", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/guardian.svg", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "p2", position: { x: 2, y: 11 }, x: 2, y: 11, z: 0, team: "player", health: 8, maxHealth: 8, unitType: "scrapper", name: "Scrapper", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/scrapper.svg", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } }, { id: "p3", position: { x: 4, y: 13 }, x: 4, y: 13, z: 0, team: "player", health: 6, maxHealth: 6, unitType: "worker", name: "Worker", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/worker.svg", role: "npc", category: "worker", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "worker", thumbnailUrl: "" } }, { id: "p4", position: { x: 2, y: 13 }, x: 2, y: 13, z: 0, team: "player", health: 7, maxHealth: 7, unitType: "mender", name: "Mender", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/mender.svg", role: "npc", category: "mender", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "mender", thumbnailUrl: "" } }, { id: "e1", position: { x: 12, y: 3 }, x: 12, y: 3, z: 0, team: "enemy", health: 10, maxHealth: 10, unitType: "guardian", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/guardian.svg", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "e2", position: { x: 13, y: 4 }, x: 13, y: 4, z: 0, team: "enemy", health: 10, maxHealth: 10, unitType: "guardian", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/guardian.svg", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" } }, { id: "e3", position: { x: 11, y: 2 }, x: 11, y: 2, z: 0, team: "enemy", health: 8, maxHealth: 8, unitType: "scrapper", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/scrapper.svg", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } }, { id: "e4", position: { x: 13, y: 2 }, x: 13, y: 2, z: 0, team: "enemy", health: 8, maxHealth: 8, unitType: "scrapper", name: "Foe", modelUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/scrapper.svg", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" } } ]
97
244
  tiles: [ { id: "t-0-0", x: 0, y: 0, terrain: "grass", passable: true }, { id: "t-1-0", x: 1, y: 0, terrain: "grass", passable: true }, { id: "t-2-0", x: 2, y: 0, terrain: "grass", passable: true }, { id: "t-3-0", x: 3, y: 0, terrain: "grass", passable: true }, { id: "t-4-0", x: 4, y: 0, terrain: "grass", passable: true }, { id: "t-5-0", x: 5, y: 0, terrain: "grass", passable: true }, { id: "t-6-0", x: 6, y: 0, terrain: "grass", passable: true }, { id: "t-7-0", x: 7, y: 0, terrain: "grass", passable: true }, { id: "t-8-0", x: 8, y: 0, terrain: "grass", passable: true }, { id: "t-9-0", x: 9, y: 0, terrain: "grass", passable: true }, { id: "t-10-0", x: 10, y: 0, terrain: "grass", passable: true }, { id: "t-11-0", x: 11, y: 0, terrain: "grass", passable: true }, { id: "t-12-0", x: 12, y: 0, terrain: "grass", passable: true }, { id: "t-13-0", x: 13, y: 0, terrain: "grass", passable: true }, { id: "t-14-0", x: 14, y: 0, terrain: "grass", passable: true }, { id: "t-15-0", x: 15, y: 0, terrain: "grass", passable: true }, { id: "t-0-1", x: 0, y: 1, terrain: "grass", passable: true }, { id: "t-1-1", x: 1, y: 1, terrain: "grass", passable: true }, { id: "t-2-1", x: 2, y: 1, terrain: "grass", passable: true }, { id: "t-3-1", x: 3, y: 1, terrain: "grass", passable: true }, { id: "t-4-1", x: 4, y: 1, terrain: "grass", passable: true }, { id: "t-5-1", x: 5, y: 1, terrain: "grass", passable: true }, { id: "t-6-1", x: 6, y: 1, terrain: "grass", passable: true }, { id: "t-7-1", x: 7, y: 1, terrain: "grass", passable: true }, { id: "t-8-1", x: 8, y: 1, terrain: "grass", passable: true }, { id: "t-9-1", x: 9, y: 1, terrain: "grass", passable: true }, { id: "t-10-1", x: 10, y: 1, terrain: "grass", passable: true }, { id: "t-11-1", x: 11, y: 1, terrain: "grass", passable: true }, { id: "t-12-1", x: 12, y: 1, terrain: "grass", passable: true }, { id: "t-13-1", x: 13, y: 1, terrain: "grass", passable: true }, { id: "t-14-1", x: 14, y: 1, terrain: "grass", passable: true }, { id: "t-15-1", x: 15, y: 1, terrain: "grass", passable: true }, { id: "t-0-2", x: 0, y: 2, terrain: "grass", passable: true }, { id: "t-1-2", x: 1, y: 2, terrain: "grass", passable: true }, { id: "t-2-2", x: 2, y: 2, terrain: "grass", passable: true }, { id: "t-3-2", x: 3, y: 2, terrain: "grass", passable: true }, { id: "t-4-2", x: 4, y: 2, terrain: "grass", passable: true }, { id: "t-5-2", x: 5, y: 2, terrain: "grass", passable: true }, { id: "t-6-2", x: 6, y: 2, terrain: "grass", passable: true }, { id: "t-7-2", x: 7, y: 2, terrain: "grass", passable: true }, { id: "t-8-2", x: 8, y: 2, terrain: "grass", passable: true }, { id: "t-9-2", x: 9, y: 2, terrain: "grass", passable: true }, { id: "t-10-2", x: 10, y: 2, terrain: "grass", passable: true }, { id: "t-11-2", x: 11, y: 2, terrain: "grass", passable: true }, { id: "t-12-2", x: 12, y: 2, terrain: "grass", passable: true }, { id: "t-13-2", x: 13, y: 2, terrain: "grass", passable: true }, { id: "t-14-2", x: 14, y: 2, terrain: "grass", passable: true }, { id: "t-15-2", x: 15, y: 2, terrain: "grass", passable: true }, { id: "t-0-3", x: 0, y: 3, terrain: "grass", passable: true }, { id: "t-1-3", x: 1, y: 3, terrain: "grass", passable: true }, { id: "t-2-3", x: 2, y: 3, terrain: "grass", passable: true }, { id: "t-3-3", x: 3, y: 3, terrain: "grass", passable: true }, { id: "t-4-3", x: 4, y: 3, terrain: "grass", passable: true }, { id: "t-5-3", x: 5, y: 3, terrain: "grass", passable: true }, { id: "t-6-3", x: 6, y: 3, terrain: "grass", passable: true }, { id: "t-7-3", x: 7, y: 3, terrain: "grass", passable: true }, { id: "t-8-3", x: 8, y: 3, terrain: "grass", passable: true }, { id: "t-9-3", x: 9, y: 3, terrain: "grass", passable: true }, { id: "t-10-3", x: 10, y: 3, terrain: "grass", passable: true }, { id: "t-11-3", x: 11, y: 3, terrain: "grass", passable: true }, { id: "t-12-3", x: 12, y: 3, terrain: "grass", passable: true }, { id: "t-13-3", x: 13, y: 3, terrain: "grass", passable: true }, { id: "t-14-3", x: 14, y: 3, terrain: "grass", passable: true }, { id: "t-15-3", x: 15, y: 3, terrain: "grass", passable: true }, { id: "t-0-4", x: 0, y: 4, terrain: "grass", passable: true }, { id: "t-1-4", x: 1, y: 4, terrain: "grass", passable: true }, { id: "t-2-4", x: 2, y: 4, terrain: "grass", passable: true }, { id: "t-3-4", x: 3, y: 4, terrain: "grass", passable: true }, { id: "t-4-4", x: 4, y: 4, terrain: "grass", passable: true }, { id: "t-5-4", x: 5, y: 4, terrain: "grass", passable: true }, { id: "t-6-4", x: 6, y: 4, terrain: "grass", passable: true }, { id: "t-7-4", x: 7, y: 4, terrain: "grass", passable: true }, { id: "t-8-4", x: 8, y: 4, terrain: "grass", passable: true }, { id: "t-9-4", x: 9, y: 4, terrain: "grass", passable: true }, { id: "t-10-4", x: 10, y: 4, terrain: "grass", passable: true }, { id: "t-11-4", x: 11, y: 4, terrain: "grass", passable: true }, { id: "t-12-4", x: 12, y: 4, terrain: "grass", passable: true }, { id: "t-13-4", x: 13, y: 4, terrain: "grass", passable: true }, { id: "t-14-4", x: 14, y: 4, terrain: "grass", passable: true }, { id: "t-15-4", x: 15, y: 4, terrain: "grass", passable: true }, { id: "t-0-5", x: 0, y: 5, terrain: "grass", passable: true }, { id: "t-1-5", x: 1, y: 5, terrain: "grass", passable: true }, { id: "t-2-5", x: 2, y: 5, terrain: "grass", passable: true }, { id: "t-3-5", x: 3, y: 5, terrain: "grass", passable: true }, { id: "t-4-5", x: 4, y: 5, terrain: "grass", passable: true }, { id: "t-5-5", x: 5, y: 5, terrain: "grass", passable: true }, { id: "t-6-5", x: 6, y: 5, terrain: "grass", passable: true }, { id: "t-7-5", x: 7, y: 5, terrain: "grass", passable: true }, { id: "t-8-5", x: 8, y: 5, terrain: "grass", passable: true }, { id: "t-9-5", x: 9, y: 5, terrain: "grass", passable: true }, { id: "t-10-5", x: 10, y: 5, terrain: "grass", passable: true }, { id: "t-11-5", x: 11, y: 5, terrain: "grass", passable: true }, { id: "t-12-5", x: 12, y: 5, terrain: "grass", passable: true }, { id: "t-13-5", x: 13, y: 5, terrain: "grass", passable: true }, { id: "t-14-5", x: 14, y: 5, terrain: "grass", passable: true }, { id: "t-15-5", x: 15, y: 5, terrain: "grass", passable: true }, { id: "t-0-6", x: 0, y: 6, terrain: "grass", passable: true }, { id: "t-1-6", x: 1, y: 6, terrain: "grass", passable: true }, { id: "t-2-6", x: 2, y: 6, terrain: "grass", passable: true }, { id: "t-3-6", x: 3, y: 6, terrain: "grass", passable: true }, { id: "t-4-6", x: 4, y: 6, terrain: "grass", passable: true }, { id: "t-5-6", x: 5, y: 6, terrain: "grass", passable: true }, { id: "t-6-6", x: 6, y: 6, terrain: "grass", passable: true }, { id: "t-7-6", x: 7, y: 6, terrain: "grass", passable: true }, { id: "t-8-6", x: 8, y: 6, terrain: "grass", passable: true }, { id: "t-9-6", x: 9, y: 6, terrain: "grass", passable: true }, { id: "t-10-6", x: 10, y: 6, terrain: "grass", passable: true }, { id: "t-11-6", x: 11, y: 6, terrain: "grass", passable: true }, { id: "t-12-6", x: 12, y: 6, terrain: "grass", passable: true }, { id: "t-13-6", x: 13, y: 6, terrain: "grass", passable: true }, { id: "t-14-6", x: 14, y: 6, terrain: "grass", passable: true }, { id: "t-15-6", x: 15, y: 6, terrain: "grass", passable: true }, { id: "t-0-7", x: 0, y: 7, terrain: "grass", passable: true }, { id: "t-1-7", x: 1, y: 7, terrain: "grass", passable: true }, { id: "t-2-7", x: 2, y: 7, terrain: "grass", passable: true }, { id: "t-3-7", x: 3, y: 7, terrain: "grass", passable: true }, { id: "t-4-7", x: 4, y: 7, terrain: "grass", passable: true }, { id: "t-5-7", x: 5, y: 7, terrain: "grass", passable: true }, { id: "t-6-7", x: 6, y: 7, terrain: "grass", passable: true }, { id: "t-7-7", x: 7, y: 7, terrain: "grass", passable: true }, { id: "t-8-7", x: 8, y: 7, terrain: "grass", passable: true }, { id: "t-9-7", x: 9, y: 7, terrain: "grass", passable: true }, { id: "t-10-7", x: 10, y: 7, terrain: "grass", passable: true }, { id: "t-11-7", x: 11, y: 7, terrain: "grass", passable: true }, { id: "t-12-7", x: 12, y: 7, terrain: "grass", passable: true }, { id: "t-13-7", x: 13, y: 7, terrain: "grass", passable: true }, { id: "t-14-7", x: 14, y: 7, terrain: "grass", passable: true }, { id: "t-15-7", x: 15, y: 7, terrain: "grass", passable: true }, { id: "t-0-8", x: 0, y: 8, terrain: "grass", passable: true }, { id: "t-1-8", x: 1, y: 8, terrain: "grass", passable: true }, { id: "t-2-8", x: 2, y: 8, terrain: "grass", passable: true }, { id: "t-3-8", x: 3, y: 8, terrain: "grass", passable: true }, { id: "t-4-8", x: 4, y: 8, terrain: "grass", passable: true }, { id: "t-5-8", x: 5, y: 8, terrain: "grass", passable: true }, { id: "t-6-8", x: 6, y: 8, terrain: "grass", passable: true }, { id: "t-7-8", x: 7, y: 8, terrain: "grass", passable: true }, { id: "t-8-8", x: 8, y: 8, terrain: "grass", passable: true }, { id: "t-9-8", x: 9, y: 8, terrain: "grass", passable: true }, { id: "t-10-8", x: 10, y: 8, terrain: "grass", passable: true }, { id: "t-11-8", x: 11, y: 8, terrain: "grass", passable: true }, { id: "t-12-8", x: 12, y: 8, terrain: "grass", passable: true }, { id: "t-13-8", x: 13, y: 8, terrain: "grass", passable: true }, { id: "t-14-8", x: 14, y: 8, terrain: "grass", passable: true }, { id: "t-15-8", x: 15, y: 8, terrain: "grass", passable: true }, { id: "t-0-9", x: 0, y: 9, terrain: "grass", passable: true }, { id: "t-1-9", x: 1, y: 9, terrain: "grass", passable: true }, { id: "t-2-9", x: 2, y: 9, terrain: "grass", passable: true }, { id: "t-3-9", x: 3, y: 9, terrain: "grass", passable: true }, { id: "t-4-9", x: 4, y: 9, terrain: "grass", passable: true }, { id: "t-5-9", x: 5, y: 9, terrain: "grass", passable: true }, { id: "t-6-9", x: 6, y: 9, terrain: "grass", passable: true }, { id: "t-7-9", x: 7, y: 9, terrain: "grass", passable: true }, { id: "t-8-9", x: 8, y: 9, terrain: "grass", passable: true }, { id: "t-9-9", x: 9, y: 9, terrain: "grass", passable: true }, { id: "t-10-9", x: 10, y: 9, terrain: "grass", passable: true }, { id: "t-11-9", x: 11, y: 9, terrain: "grass", passable: true }, { id: "t-12-9", x: 12, y: 9, terrain: "grass", passable: true }, { id: "t-13-9", x: 13, y: 9, terrain: "grass", passable: true }, { id: "t-14-9", x: 14, y: 9, terrain: "grass", passable: true }, { id: "t-15-9", x: 15, y: 9, terrain: "grass", passable: true }, { id: "t-0-10", x: 0, y: 10, terrain: "grass", passable: true }, { id: "t-1-10", x: 1, y: 10, terrain: "grass", passable: true }, { id: "t-2-10", x: 2, y: 10, terrain: "grass", passable: true }, { id: "t-3-10", x: 3, y: 10, terrain: "grass", passable: true }, { id: "t-4-10", x: 4, y: 10, terrain: "grass", passable: true }, { id: "t-5-10", x: 5, y: 10, terrain: "grass", passable: true }, { id: "t-6-10", x: 6, y: 10, terrain: "grass", passable: true }, { id: "t-7-10", x: 7, y: 10, terrain: "grass", passable: true }, { id: "t-8-10", x: 8, y: 10, terrain: "grass", passable: true }, { id: "t-9-10", x: 9, y: 10, terrain: "grass", passable: true }, { id: "t-10-10", x: 10, y: 10, terrain: "grass", passable: true }, { id: "t-11-10", x: 11, y: 10, terrain: "grass", passable: true }, { id: "t-12-10", x: 12, y: 10, terrain: "grass", passable: true }, { id: "t-13-10", x: 13, y: 10, terrain: "grass", passable: true }, { id: "t-14-10", x: 14, y: 10, terrain: "grass", passable: true }, { id: "t-15-10", x: 15, y: 10, terrain: "grass", passable: true }, { id: "t-0-11", x: 0, y: 11, terrain: "grass", passable: true }, { id: "t-1-11", x: 1, y: 11, terrain: "grass", passable: true }, { id: "t-2-11", x: 2, y: 11, terrain: "grass", passable: true }, { id: "t-3-11", x: 3, y: 11, terrain: "grass", passable: true }, { id: "t-4-11", x: 4, y: 11, terrain: "grass", passable: true }, { id: "t-5-11", x: 5, y: 11, terrain: "grass", passable: true }, { id: "t-6-11", x: 6, y: 11, terrain: "grass", passable: true }, { id: "t-7-11", x: 7, y: 11, terrain: "grass", passable: true }, { id: "t-8-11", x: 8, y: 11, terrain: "grass", passable: true }, { id: "t-9-11", x: 9, y: 11, terrain: "grass", passable: true }, { id: "t-10-11", x: 10, y: 11, terrain: "grass", passable: true }, { id: "t-11-11", x: 11, y: 11, terrain: "grass", passable: true }, { id: "t-12-11", x: 12, y: 11, terrain: "grass", passable: true }, { id: "t-13-11", x: 13, y: 11, terrain: "grass", passable: true }, { id: "t-14-11", x: 14, y: 11, terrain: "grass", passable: true }, { id: "t-15-11", x: 15, y: 11, terrain: "grass", passable: true }, { id: "t-0-12", x: 0, y: 12, terrain: "grass", passable: true }, { id: "t-1-12", x: 1, y: 12, terrain: "grass", passable: true }, { id: "t-2-12", x: 2, y: 12, terrain: "grass", passable: true }, { id: "t-3-12", x: 3, y: 12, terrain: "grass", passable: true }, { id: "t-4-12", x: 4, y: 12, terrain: "grass", passable: true }, { id: "t-5-12", x: 5, y: 12, terrain: "grass", passable: true }, { id: "t-6-12", x: 6, y: 12, terrain: "grass", passable: true }, { id: "t-7-12", x: 7, y: 12, terrain: "grass", passable: true }, { id: "t-8-12", x: 8, y: 12, terrain: "grass", passable: true }, { id: "t-9-12", x: 9, y: 12, terrain: "grass", passable: true }, { id: "t-10-12", x: 10, y: 12, terrain: "grass", passable: true }, { id: "t-11-12", x: 11, y: 12, terrain: "grass", passable: true }, { id: "t-12-12", x: 12, y: 12, terrain: "grass", passable: true }, { id: "t-13-12", x: 13, y: 12, terrain: "grass", passable: true }, { id: "t-14-12", x: 14, y: 12, terrain: "grass", passable: true }, { id: "t-15-12", x: 15, y: 12, terrain: "grass", passable: true }, { id: "t-0-13", x: 0, y: 13, terrain: "grass", passable: true }, { id: "t-1-13", x: 1, y: 13, terrain: "grass", passable: true }, { id: "t-2-13", x: 2, y: 13, terrain: "grass", passable: true }, { id: "t-3-13", x: 3, y: 13, terrain: "grass", passable: true }, { id: "t-4-13", x: 4, y: 13, terrain: "grass", passable: true }, { id: "t-5-13", x: 5, y: 13, terrain: "grass", passable: true }, { id: "t-6-13", x: 6, y: 13, terrain: "grass", passable: true }, { id: "t-7-13", x: 7, y: 13, terrain: "grass", passable: true }, { id: "t-8-13", x: 8, y: 13, terrain: "grass", passable: true }, { id: "t-9-13", x: 9, y: 13, terrain: "grass", passable: true }, { id: "t-10-13", x: 10, y: 13, terrain: "grass", passable: true }, { id: "t-11-13", x: 11, y: 13, terrain: "grass", passable: true }, { id: "t-12-13", x: 12, y: 13, terrain: "grass", passable: true }, { id: "t-13-13", x: 13, y: 13, terrain: "grass", passable: true }, { id: "t-14-13", x: 14, y: 13, terrain: "grass", passable: true }, { id: "t-15-13", x: 15, y: 13, terrain: "grass", passable: true }, { id: "t-0-14", x: 0, y: 14, terrain: "grass", passable: true }, { id: "t-1-14", x: 1, y: 14, terrain: "grass", passable: true }, { id: "t-2-14", x: 2, y: 14, terrain: "grass", passable: true }, { id: "t-3-14", x: 3, y: 14, terrain: "grass", passable: true }, { id: "t-4-14", x: 4, y: 14, terrain: "grass", passable: true }, { id: "t-5-14", x: 5, y: 14, terrain: "grass", passable: true }, { id: "t-6-14", x: 6, y: 14, terrain: "grass", passable: true }, { id: "t-7-14", x: 7, y: 14, terrain: "grass", passable: true }, { id: "t-8-14", x: 8, y: 14, terrain: "grass", passable: true }, { id: "t-9-14", x: 9, y: 14, terrain: "grass", passable: true }, { id: "t-10-14", x: 10, y: 14, terrain: "grass", passable: true }, { id: "t-11-14", x: 11, y: 14, terrain: "grass", passable: true }, { id: "t-12-14", x: 12, y: 14, terrain: "grass", passable: true }, { id: "t-13-14", x: 13, y: 14, terrain: "grass", passable: true }, { id: "t-14-14", x: 14, y: 14, terrain: "grass", passable: true }, { id: "t-15-14", x: 15, y: 14, terrain: "grass", passable: true }, { id: "t-0-15", x: 0, y: 15, terrain: "grass", passable: true }, { id: "t-1-15", x: 1, y: 15, terrain: "grass", passable: true }, { id: "t-2-15", x: 2, y: 15, terrain: "grass", passable: true }, { id: "t-3-15", x: 3, y: 15, terrain: "grass", passable: true }, { id: "t-4-15", x: 4, y: 15, terrain: "grass", passable: true }, { id: "t-5-15", x: 5, y: 15, terrain: "grass", passable: true }, { id: "t-6-15", x: 6, y: 15, terrain: "grass", passable: true }, { id: "t-7-15", x: 7, y: 15, terrain: "grass", passable: true }, { id: "t-8-15", x: 8, y: 15, terrain: "grass", passable: true }, { id: "t-9-15", x: 9, y: 15, terrain: "grass", passable: true }, { id: "t-10-15", x: 10, y: 15, terrain: "grass", passable: true }, { id: "t-11-15", x: 11, y: 15, terrain: "grass", passable: true }, { id: "t-12-15", x: 12, y: 15, terrain: "grass", passable: true }, { id: "t-13-15", x: 13, y: 15, terrain: "grass", passable: true }, { id: "t-14-15", x: 14, y: 15, terrain: "grass", passable: true }, { id: "t-15-15", x: 15, y: 15, terrain: "grass", passable: true } ]
98
245
  }
99
246
  }
@@ -114,6 +261,10 @@ orbital BattleBoardOrbital {
114
261
  config { running: true, xpPerKill: 25, startXp: 0, baseXpToNext: 100, xpToNextIncrement: 50, levelUpHeal: 2, healTeam: "player", initialEnemies: 4 }
115
262
  }
116
263
 
264
+ trait AnimClock = Frame.traits.AnimClock -> GameState {
265
+ config { frames: [] }
266
+ }
267
+
117
268
  trait Player = Frame.traits.PlayerIntent -> GameState {
118
269
  config {
119
270
  gridWidth: 16
@@ -122,13 +273,13 @@ orbital BattleBoardOrbital {
122
273
  projection: "isometric"
123
274
  showMinimap: true
124
275
  scale: 1
125
- backgroundAsset: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-ui-adventure-pack/ui/uipack_rpg_sheet.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-ui-adventure-pack/ui/uipack_rpg_sheet.json", sprite: "panel_beige.png", role: "ui", category: "ui", animations: [], style: "adventure", dimension: "2d", aspect: "1:1", name: "panel-frame", thumbnailUrl: "" }
126
- hudBackgroundAsset: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-ui-adventure-pack/ui/uipack_rpg_sheet.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-ui-adventure-pack/ui/uipack_rpg_sheet.json", sprite: "panel_beige.png", role: "ui", category: "ui", animations: [], style: "adventure", dimension: "2d", aspect: "1:1", name: "panel-frame", thumbnailUrl: "" }
276
+ backgroundAsset: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/ui/panel-frame.svg", role: "ui", category: "ui", animations: [], style: "adventure", dimension: "2d", aspect: "1:1", name: "panel-frame", thumbnailUrl: "" }
277
+ hudBackgroundAsset: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/ui/panel-frame.svg", role: "ui", category: "ui", animations: [], style: "adventure", dimension: "2d", aspect: "1:1", name: "panel-frame", thumbnailUrl: "" }
127
278
  extraStats: [ { label: "XP", value: @entity.xp }, { label: "Lvl", value: @entity.level } ]
128
- features: [ { id: "f1", x: 13, y: 1, type: "gold_mine", assetUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-cartography-pack/ui/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-cartography-pack/ui/spritesheet_default.json", sprite: "mine.png", role: "decoration", category: "gold_mine", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "gold_mine", thumbnailUrl: "" } }, { id: "f2", x: 1, y: 14, type: "portal", assetUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-cartography-pack/ui/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-cartography-pack/ui/spritesheet_default.json", sprite: "gate.png", role: "decoration", category: "portal", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "portal", thumbnailUrl: "" } } ]
129
- assetManifest: { terrains: { grass: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-isometric-tiles-base/terrain/landscapeTiles_sheet.png", atlas: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-isometric-tiles-base/terrain/landscapeTiles_sheet.json", sprite: "landscapeTiles_000.png", role: "tile", category: "grass", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "grass", thumbnailUrl: "" }, stone: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-isometric-tiles-base/terrain/landscapeTiles_sheet.png", atlas: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-isometric-tiles-base/terrain/landscapeTiles_sheet.json", sprite: "landscapeTiles_001.png", role: "tile", category: "stone", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "stone", thumbnailUrl: "" } }, units: { guardian: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "blue_body_square.png", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" }, scrapper: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "red_body_rhombus.png", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" }, worker: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "yellow_body_squircle.png", role: "npc", category: "worker", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "worker", thumbnailUrl: "" }, mender: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-shape-characters/units/spritesheet_default.json", sprite: "green_body_circle.png", role: "npc", category: "mender", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "mender", thumbnailUrl: "" } }, features: { gold_mine: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-cartography-pack/ui/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-cartography-pack/ui/spritesheet_default.json", sprite: "mine.png", role: "decoration", category: "gold_mine", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "gold_mine", thumbnailUrl: "" }, portal: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-cartography-pack/ui/spritesheet_default.png", atlas: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/kenney-cartography-pack/ui/spritesheet_default.json", sprite: "gate.png", role: "decoration", category: "portal", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "portal", thumbnailUrl: "" } }, effects: { explosion: { url: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-explosion-pack/effects/spritesheet_pixelExplosion.png", atlas: "https://almadar-kflow-assets.web.app/shared/_shared/kenney-explosion-pack/effects/spritesheet_pixelExplosion.json", sprite: "pixelExplosion07.png", role: "effect", category: "explosion", animations: ["static"], style: "", dimension: "2d", aspect: "8:1", name: "explosion", thumbnailUrl: "" } } }
279
+ features: [ { id: "f1", x: 13, y: 1, type: "gold_mine", assetUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/features/gold_mine.svg", role: "decoration", category: "gold_mine", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "gold_mine", thumbnailUrl: "" } }, { id: "f2", x: 1, y: 14, type: "portal", assetUrl: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/features/portal.svg", role: "decoration", category: "portal", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "portal", thumbnailUrl: "" } } ]
280
+ assetManifest: { terrains: { grass: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/terrain/grass.svg", role: "tile", category: "grass", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "grass", thumbnailUrl: "" }, stone: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/terrain/stone.svg", role: "tile", category: "stone", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "stone", thumbnailUrl: "" } }, units: { guardian: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/guardian.svg", role: "npc", category: "guardian", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "guardian", thumbnailUrl: "" }, scrapper: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/scrapper.svg", role: "npc", category: "scrapper", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "scrapper", thumbnailUrl: "" }, worker: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/worker.svg", role: "npc", category: "worker", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "worker", thumbnailUrl: "" }, mender: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/units/mender.svg", role: "npc", category: "mender", animations: ["idle","walk","attack","hit","death"], style: "", dimension: "2d", aspect: "1:1", name: "mender", thumbnailUrl: "" } }, features: { gold_mine: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/features/gold_mine.svg", role: "decoration", category: "gold_mine", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "gold_mine", thumbnailUrl: "" }, portal: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/features/portal.svg", role: "decoration", category: "portal", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "portal", thumbnailUrl: "" } }, effects: { explosion: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/effects/explosion.svg", role: "effect", category: "explosion", animations: ["static"], style: "", dimension: "2d", aspect: "8:1", name: "explosion", thumbnailUrl: "" }, hit: { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/effects/hit.svg", role: "effect", category: "hit", animations: ["static"], style: "", dimension: "2d", aspect: "1:1", name: "hit", thumbnailUrl: "" } }, ui: { "panel-frame": { url: "https://almadar-kflow-assets.web.app/shared/ui-battle-board/svg/isometric/ui/panel-frame.svg", role: "ui", category: "ui", animations: [], style: "adventure", dimension: "2d", aspect: "1:1", name: "panel-frame", thumbnailUrl: "" } } }
130
281
  }
131
282
  }
132
283
 
133
- page "/battle-board" as BattleBoardPage -> Authority, FxDecay, RoundLogic, ScoreKeeper, XpKeeper, Player
284
+ page "/battle-board" as BattleBoardPage -> Authority, FxDecay, RoundLogic, ScoreKeeper, XpKeeper, Player, AnimClock
134
285
  }
@@ -53,25 +53,6 @@ orbital BuilderBoardOrbital {
53
53
  trait BuilderBoardRender -> @rebindable BuilderBoardItem [interaction, instance] {
54
54
  initial: playing
55
55
 
56
- state menu {
57
- START -> playing
58
- (set @entity.components @config.components)
59
- (set @entity.slots (array/map @config.slots (fn s (object/merge @s { options: (array/map @config.components (fn c { slotId: (object/get @s id), componentId: (object/get @c id), label: (object/get @c label), iconUrl: (object/get @c iconUrl) })) }))))
60
- (set @entity.title @config.title)
61
- (set @entity.description @config.description)
62
- (set @entity.hint @config.hint)
63
- (set @entity.attempts 0)
64
- (set @entity.result "none")
65
- (render-ui main {
66
- type: game-shell
67
- hud: { type: stack, direction: horizontal, gap: md, justify: between, children: [ { type: game-hud, stats: [ { label: "Attempts", value: @entity.attempts }, { label: "Status", value: @entity.result } ] }, { type: stack, direction: horizontal, gap: sm, children: [ { type: button, action: CHECK, label: "Check", variant: primary }, { type: button, action: PLAY_AGAIN, label: "Reset", variant: secondary } ] } ] }
68
- children: [
69
- { type: card, children: [ { type: typography, variant: h4, content: @entity.title }, { type: typography, variant: body, content: @entity.description } ] },
70
- { type: card, children: [ { type: data-list, entity: @entity.slots, fields: [], gap: sm, renderItem: (fn s { type: card, children: [ { type: stack, direction: horizontal, gap: sm, justify: between, children: [ { type: typography, variant: label, content: @s.id }, { type: badge, label: @s.placedComponentId } ] }, { type: data-list, entity: @s.options, fields: [], gap: sm, renderItem: (fn opt { type: button, action: PLACE, actionPayload: { slotId: @opt.slotId, componentId: @opt.componentId }, label: @opt.label, iconAsset: @opt.iconUrl, variant: primary }) } ] }) } ] }
71
- ]
72
- })
73
- }
74
-
75
56
  state playing {
76
57
  INIT -> playing
77
58
  (set @entity.components @config.components)
@@ -125,8 +106,12 @@ orbital BuilderBoardOrbital {
125
106
  }
126
107
 
127
108
  state complete {
128
- PLAY_AGAIN -> menu
109
+ PLAY_AGAIN -> playing
110
+ (set @entity.components @config.components)
129
111
  (set @entity.slots (array/map @config.slots (fn s (object/merge @s { options: (array/map @config.components (fn c { slotId: (object/get @s id), componentId: (object/get @c id), label: (object/get @c label), iconUrl: (object/get @c iconUrl) })) }))))
112
+ (set @entity.title @config.title)
113
+ (set @entity.description @config.description)
114
+ (set @entity.hint @config.hint)
130
115
  (set @entity.attempts 0)
131
116
  (set @entity.result "none")
132
117
  (render-ui main {
@@ -85,6 +85,7 @@ orbital CardBattlerBoardOrbital {
85
85
  (set @entity.hand (array/concat @entity.hand (array/slice @entity.deck 0 @config.drawPerTurn)))
86
86
  (set @entity.deck (array/slice @entity.deck @config.drawPerTurn (array/len @entity.deck)))
87
87
  (set @entity.result (if (>= @entity.turn @config.turnsToWin) "won" @entity.result))
88
+ (if (!= @entity.result "none") (emit GAME_END { result: @entity.result }) null)
88
89
  (render-ui main {
89
90
  type: game-shell
90
91
  hud: { type: stack, direction: horizontal, gap: md, justify: between, children: [ { type: game-hud, stats: [ { label: "Mana", value: @entity.mana }, { label: "Turn", value: @entity.turn } ] }, { type: stack, direction: horizontal, gap: sm, children: [ { type: button, action: END_TURN, label: "End Turn", variant: primary }, { type: button, action: PLAY_AGAIN, label: "Play Again", variant: secondary } ] } ] }
@@ -97,6 +98,7 @@ orbital CardBattlerBoardOrbital {
97
98
  GAME_END -> gameover when (or (== @entity.result "won") (== @entity.result "lost"))
98
99
  (render-ui main {
99
100
  type: game-shell
101
+ overlay: { type: game-menu, title: (if (== @entity.result "won") "VICTORY!" "DEFEAT"), subtitle: (str/concat "Result: " @entity.result), options: [ { id: "again", label: "Play Again", event: "PLAY_AGAIN", variant: "primary" } ] }
100
102
  hud: { type: stack, direction: horizontal, gap: md, justify: between, children: [ { type: game-hud, stats: [ { label: "Mana", value: @entity.mana }, { label: "Turn", value: @entity.turn } ] }, { type: stack, direction: horizontal, gap: sm, children: [ { type: button, action: END_TURN, label: "End Turn", variant: primary }, { type: button, action: PLAY_AGAIN, label: "Play Again", variant: secondary } ] } ] }
101
103
  children: [
102
104
  { type: data-list, entity: @entity.board, fields: [], gap: sm, renderItem: (fn c { type: button, variant: ghost, children: [ { type: atlas-image, asset: { url: "https://almadar-kflow-assets.web.app/shared/ui-card-battler-board/kenney-boardgame-pack/ui/diceWhite_border.png", atlas: "https://almadar-kflow-assets.web.app/shared/ui-card-battler-board/kenney-boardgame-pack/ui/diceWhite_border.json", sprite: "dieWhite_border6.png", role: "ui", category: "ui", animations: [], style: "", variant: "", dimension: "2d", aspect: "5:7", name: "card-frame", thumbnailUrl: "" }, fill: true, fit: "fill" }, { type: stack, direction: vertical, gap: xs, align: center, children: [ { type: badge, label: @c.cost, variant: info }, { type: game-icon, assetUrl: @c.sprite, icon: "image", size: 52, alt: @c.title }, { type: typography, variant: caption, content: @c.title }, { type: stack, direction: horizontal, gap: xs, justify: between, children: [ { type: typography, variant: caption, content: (str/concat "⚔" @c.attack) }, { type: typography, variant: caption, content: (str/concat "🛡" @c.defense) } ] } ] } ] }) },
@@ -325,7 +325,7 @@ orbital CastleBoardOrbital {
325
325
  ] } ]
326
326
  })
327
327
 
328
- WAVE_DEFEATED -> victory when (>= @entity.wave 3)
328
+ WAVE_DEFEATED -> victory when (and (>= @entity.wave 3) (> @entity.health 0))
329
329
  (set @entity.result "victory")
330
330
  (render-ui main {
331
331
  type: game-shell
@@ -518,7 +518,7 @@ orbital CastleBoardOrbital {
518
518
  waveTick every 8s
519
519
  when (and (== @entity.result "none") (and (> @entity.health 0) (< @entity.wave 3)))
520
520
  (set @entity.wave (+ @entity.wave 1))
521
- (set @entity.lastWaveDamage (math/max 0 (- @entity.wave (array/len @entity.buildings))))
521
+ (set @entity.lastWaveDamage (math/max 0 (- (* @entity.wave 4) (array/len @entity.buildings))))
522
522
  (set @entity.health (math/max 0 (- @entity.health @entity.lastWaveDamage)))
523
523
  (set @entity.units (array/map @entity.units (fn u (if (== @u.team "enemy") (object/merge @u { animation: "attack" }) (if (== @u.team "player") (object/merge @u { animation: (if (<= @entity.health 0) "hit" "idle") }) @u)))))
524
524
  (set @entity.effects (array/append @entity.effects { key: "slash", x: (object/get (object/get (array/first (array/filter @entity.units (fn u (== @u.team "enemy")))) position) x), y: (object/get (object/get (array/first (array/filter @entity.units (fn u (== @u.team "enemy")))) position) y), ttl: 4 }))
@@ -543,7 +543,7 @@ orbital CastleBoardOrbital {
543
543
  ] } ]
544
544
  })
545
545
  (emit CASTLE_HIT { damage: @entity.lastWaveDamage })
546
- (emit WAVE_DEFEATED { wave: @entity.wave })
546
+ (if (> @entity.health 0) (emit WAVE_DEFEATED { wave: @entity.wave }) null)
547
547
  }
548
548
 
549
549
  emits {