@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.
- package/behaviors/lolo/ui/game/molecules/std-crew-board-2d.lolo +4 -4
- package/behaviors/lolo/ui/game/molecules/std-dungeon-board-2d.lolo +6 -6
- package/behaviors/lolo/ui/game/molecules/std-tactics-board-2d.lolo +74 -28
- package/behaviors/lolo/ui/game/molecules/std-worldmap-board-2d.lolo +2 -2
- package/behaviors/lolo/ui/game/molecules/ui-canvas.lolo +5 -0
- package/behaviors/lolo/ui/game/organisms/ui-arena-board.lolo +2 -2
- package/behaviors/lolo/ui/game/organisms/ui-battle-board.lolo +159 -8
- package/behaviors/lolo/ui/game/organisms/ui-builder-board.lolo +5 -20
- package/behaviors/lolo/ui/game/organisms/ui-card-battler-board.lolo +2 -0
- package/behaviors/lolo/ui/game/organisms/ui-castle-board.lolo +3 -3
- package/behaviors/lolo/ui/game/organisms/ui-city-builder-board.lolo +9 -7
- package/behaviors/lolo/ui/game/organisms/ui-grid-tactics-demo-board.lolo +2 -2
- package/behaviors/lolo/ui/game/organisms/ui-hex-strategy-board.lolo +158 -10
- package/behaviors/lolo/ui/game/organisms/ui-holiday-runner-board.lolo +1 -1
- package/behaviors/lolo/ui/game/organisms/ui-minigolf-board.lolo +22 -22
- package/behaviors/lolo/ui/game/organisms/ui-pinball-board.lolo +7 -7
- package/behaviors/lolo/ui/game/organisms/ui-pirate-board.lolo +14 -14
- package/behaviors/lolo/ui/game/organisms/ui-platformer-board.lolo +4 -0
- package/behaviors/lolo/ui/game/organisms/ui-sports-board.lolo +10 -7
- package/behaviors/lolo/ui/game/organisms/ui-tactics-demo-2d.lolo +135 -9
- package/behaviors/lolo/ui/game/organisms/ui-tanks-board.lolo +152 -8
- package/behaviors/lolo/ui/game/organisms/ui-topdown-rts-board.lolo +293 -17
- package/behaviors/lolo/ui/game/organisms/ui-tower-defense-board.lolo +8 -8
- package/behaviors/lolo/ui/game/organisms/ui-uncontrolled-battle-board.lolo +5 -5
- package/behaviors/lolo/ui/game/organisms/ui-world-map-board.lolo +3 -3
- package/behaviors/registry/factory-signatures.json +1893 -2294
- package/behaviors/registry/ui/game/molecules/std-crew-board-2d.orb +10 -12
- package/behaviors/registry/ui/game/molecules/std-dungeon-board-2d.orb +15 -18
- package/behaviors/registry/ui/game/molecules/std-tactics-board-2d.orb +1726 -395
- package/behaviors/registry/ui/game/molecules/std-worldmap-board-2d.orb +7 -60
- package/behaviors/registry/ui/game/molecules/ui-canvas.orb +7 -0
- package/behaviors/registry/ui/game/organisms/ui-arena-board.orb +5 -6
- package/behaviors/registry/ui/game/organisms/ui-battle-board.orb +103 -100
- package/behaviors/registry/ui/game/organisms/ui-builder-board.orb +21 -226
- package/behaviors/registry/ui/game/organisms/ui-card-battler-board.orb +42 -0
- package/behaviors/registry/ui/game/organisms/ui-castle-board.orb +30 -9
- package/behaviors/registry/ui/game/organisms/ui-city-builder-board.orb +49 -0
- package/behaviors/registry/ui/game/organisms/ui-grid-tactics-demo-board.orb +5 -6
- package/behaviors/registry/ui/game/organisms/ui-hex-strategy-board.orb +95 -1187
- package/behaviors/registry/ui/game/organisms/ui-holiday-runner-board.orb +2 -3
- package/behaviors/registry/ui/game/organisms/ui-minigolf-board.orb +55 -11
- package/behaviors/registry/ui/game/organisms/ui-pinball-board.orb +8 -8
- package/behaviors/registry/ui/game/organisms/ui-pirate-board.orb +14 -0
- package/behaviors/registry/ui/game/organisms/ui-platformer-board.orb +72 -0
- package/behaviors/registry/ui/game/organisms/ui-sports-board.orb +60 -0
- package/behaviors/registry/ui/game/organisms/ui-tactics-demo-2d.orb +222 -332
- package/behaviors/registry/ui/game/organisms/ui-tanks-board.orb +127 -95
- package/behaviors/registry/ui/game/organisms/ui-topdown-rts-board.orb +1501 -264
- package/behaviors/registry/ui/game/organisms/ui-tower-defense-board.orb +8 -0
- package/behaviors/registry/ui/game/organisms/ui-uncontrolled-battle-board.orb +5 -0
- package/behaviors/registry/ui/game/organisms/ui-world-map-board.orb +8 -12
- package/dist/behaviors/behaviors-embeddings.json +244 -236
- package/dist/behaviors/behaviors-registry.json +193 -812
- package/dist/behaviors/exports-reader.js +1099 -2090
- package/dist/behaviors/functions/index.d.ts +33 -26
- package/dist/behaviors/functions/index.js +1099 -2091
- package/dist/behaviors/index.d.ts +1 -1
- package/dist/behaviors/index.js +1100 -2091
- package/dist/behaviors/knob-embeddings.json +1 -1
- package/dist/behaviors/query.js +1099 -2090
- package/dist/behaviors/registry/factory-signatures.json +1893 -2294
- package/dist/behaviors/registry/ui/game/molecules/std-crew-board-2d.orb +10 -12
- package/dist/behaviors/registry/ui/game/molecules/std-dungeon-board-2d.orb +15 -18
- package/dist/behaviors/registry/ui/game/molecules/std-tactics-board-2d.orb +1726 -395
- package/dist/behaviors/registry/ui/game/molecules/std-worldmap-board-2d.orb +7 -60
- package/dist/behaviors/registry/ui/game/molecules/ui-canvas.orb +7 -0
- package/dist/behaviors/registry/ui/game/organisms/ui-arena-board.orb +5 -6
- package/dist/behaviors/registry/ui/game/organisms/ui-battle-board.orb +103 -100
- package/dist/behaviors/registry/ui/game/organisms/ui-builder-board.orb +21 -226
- package/dist/behaviors/registry/ui/game/organisms/ui-card-battler-board.orb +42 -0
- package/dist/behaviors/registry/ui/game/organisms/ui-castle-board.orb +30 -9
- package/dist/behaviors/registry/ui/game/organisms/ui-city-builder-board.orb +49 -0
- package/dist/behaviors/registry/ui/game/organisms/ui-grid-tactics-demo-board.orb +5 -6
- package/dist/behaviors/registry/ui/game/organisms/ui-hex-strategy-board.orb +95 -1187
- package/dist/behaviors/registry/ui/game/organisms/ui-holiday-runner-board.orb +2 -3
- package/dist/behaviors/registry/ui/game/organisms/ui-minigolf-board.orb +55 -11
- package/dist/behaviors/registry/ui/game/organisms/ui-pinball-board.orb +8 -8
- package/dist/behaviors/registry/ui/game/organisms/ui-pirate-board.orb +14 -0
- package/dist/behaviors/registry/ui/game/organisms/ui-platformer-board.orb +72 -0
- package/dist/behaviors/registry/ui/game/organisms/ui-sports-board.orb +60 -0
- package/dist/behaviors/registry/ui/game/organisms/ui-tactics-demo-2d.orb +222 -332
- package/dist/behaviors/registry/ui/game/organisms/ui-tanks-board.orb +127 -95
- package/dist/behaviors/registry/ui/game/organisms/ui-topdown-rts-board.orb +1501 -264
- package/dist/behaviors/registry/ui/game/organisms/ui-tower-defense-board.orb +8 -0
- package/dist/behaviors/registry/ui/game/organisms/ui-uncontrolled-battle-board.orb +5 -0
- package/dist/behaviors/registry/ui/game/organisms/ui-world-map-board.orb +8 -12
- package/dist/behaviors-embeddings.json +244 -236
- package/dist/behaviors-registry.json +193 -812
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1100 -2091
- package/dist/knob-embeddings.json +1 -1
- package/dist/registry/factory-signatures.json +1893 -2294
- package/package.json +2 -2
|
@@ -123,11 +123,11 @@ orbital CrewBoard2DOrbital {
|
|
|
123
123
|
hud: { type: stack, direction: horizontal, gap: md, justify: between, children: [ { type: game-hud, stats: [ { label: "Crew", value: @entity.crewCount, iconUrl: @config.crewIcon }, { label: "Oxygen", value: @entity.oxygen, iconUrl: @config.oxygenIcon } ] }, { type: stack, direction: horizontal, gap: xs, align: center, children: [ { type: typography, variant: caption, content: "Status" }, { type: badge, label: @entity.phase, variant: (if (== @entity.phase "movement") "info" "neutral") } ] }, { type: timer-display, value: @entity.oxygen, label: "O2" }, { type: button, action: CANCEL, label: "Cancel", iconAsset: @config.cancelIcon, variant: secondary } ] }
|
|
124
124
|
children: [ { type: canvas, camera: { zoom: (math/min 1 (/ 5 (+ 1 (math/max (array/max @entity.tiles "x") (array/max @entity.tiles "y"))))), pos: { x: (/ (+ (array/min @entity.tiles "x") (array/max @entity.tiles "x")) 2), y: (/ (+ (array/min @entity.tiles "y") (array/max @entity.tiles "y")) 2) } }, projection: @config.projection, showMinimap: @config.showMinimap, tileClickEvent: TILE_CLICK, unitClickEvent: UNIT_CLICK, children: [
|
|
125
125
|
{ type: draw-shape-layer, items: (array/map @entity.tiles (fn t { type: draw-shape, shape: "cell", position: { x: (object/get @t x), y: (object/get @t y) }, fill: "#5c94fc", stroke: "rgba(255,255,255,0.35)", strokeWidth: 1 })) }
|
|
126
|
-
{ type: draw-sprite-layer, items: (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width:
|
|
126
|
+
{ type: draw-sprite-layer, items: (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width: 1, height: 1 })) }
|
|
127
127
|
{ type: draw-sprite-layer, items: (array/map @config.features (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f y) }, asset: (object/get @f assetUrl) })) }
|
|
128
128
|
{ type: draw-shape-layer, items: (array/map @entity.validMoves (fn m { type: draw-shape, shape: "cell", position: { x: (object/get @m x), y: (object/get @m z) }, fill: "rgba(74,222,128,0.4)" })) }
|
|
129
129
|
{ type: draw-shape-layer, items: (array/map (array/filter @entity.units (fn u (== (object/get @u id) @entity.selectedUnitId))) (fn u { type: draw-shape, shape: "ellipse", position: (object/get @u position), radiusX: 0.5, radiusY: 0.2, stroke: "rgba(0,200,255,0.8)", strokeWidth: 3 })) }
|
|
130
|
-
{ type: draw-sprite-layer, items: (array/map @entity.units (fn u { type: draw-sprite, position: (object/get @u position), asset: (if (object/get (object/get @u modelUrl) url) (object/get @u modelUrl) (object/get (object/get @config.assetManifest units) (object/get @u unitType))), id: (object/get @u id), anchor: "ground", width:
|
|
130
|
+
{ type: draw-sprite-layer, items: (array/map @entity.units (fn u { type: draw-sprite, position: (object/get @u position), asset: (if (object/get (object/get @u modelUrl) url) (object/get @u modelUrl) (object/get (object/get @config.assetManifest units) (object/get @u unitType))), id: (object/get @u id), anchor: "ground", width: 1, height: 1 })) }
|
|
131
131
|
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: 0.5, height: 0.12, fill: "rgba(0,0,0,0.6)" })) }
|
|
132
132
|
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: (* 0.5 (/ (object/get @u health) (object/get @u maxHealth))), height: 0.12, fill: "#22c55e" })) }
|
|
133
133
|
{ type: draw-text-layer, items: (array/map @entity.units (fn u { type: draw-text, text: (object/get @u name), position: (object/get @u position), offsetY: -0.85, color: "#ffffff" })) }
|
|
@@ -166,11 +166,11 @@ orbital CrewBoard2DOrbital {
|
|
|
166
166
|
hud: { type: stack, direction: horizontal, gap: md, justify: between, children: [ { type: game-hud, stats: [ { label: "Crew", value: @entity.crewCount, iconUrl: @config.crewIcon }, { label: "Oxygen", value: @entity.oxygen, iconUrl: @config.oxygenIcon } ] }, { type: stack, direction: horizontal, gap: xs, align: center, children: [ { type: typography, variant: caption, content: "Status" }, { type: badge, label: @entity.phase, variant: (if (== @entity.phase "movement") "info" "neutral") } ] }, { type: timer-display, value: @entity.oxygen, label: "O2" }, { type: button, action: CANCEL, label: "Cancel", iconAsset: @config.cancelIcon, variant: secondary } ] }
|
|
167
167
|
children: [ { type: canvas, camera: { zoom: (math/min 1 (/ 5 (+ 1 (math/max (array/max @entity.tiles "x") (array/max @entity.tiles "y"))))), pos: { x: (/ (+ (array/min @entity.tiles "x") (array/max @entity.tiles "x")) 2), y: (/ (+ (array/min @entity.tiles "y") (array/max @entity.tiles "y")) 2) } }, projection: @config.projection, showMinimap: @config.showMinimap, tileClickEvent: TILE_CLICK, unitClickEvent: UNIT_CLICK, children: [
|
|
168
168
|
{ type: draw-shape-layer, items: (array/map @entity.tiles (fn t { type: draw-shape, shape: "cell", position: { x: (object/get @t x), y: (object/get @t y) }, fill: "#5c94fc", stroke: "rgba(255,255,255,0.35)", strokeWidth: 1 })) }
|
|
169
|
-
{ type: draw-sprite-layer, items: (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width:
|
|
169
|
+
{ type: draw-sprite-layer, items: (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width: 1, height: 1 })) }
|
|
170
170
|
{ type: draw-sprite-layer, items: (array/map @config.features (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f y) }, asset: (object/get @f assetUrl) })) }
|
|
171
171
|
{ type: draw-shape-layer, items: (array/map @entity.validMoves (fn m { type: draw-shape, shape: "cell", position: { x: (object/get @m x), y: (object/get @m z) }, fill: "rgba(74,222,128,0.4)" })) }
|
|
172
172
|
{ type: draw-shape-layer, items: (array/map (array/filter @entity.units (fn u (== (object/get @u id) @entity.selectedUnitId))) (fn u { type: draw-shape, shape: "ellipse", position: (object/get @u position), radiusX: 0.5, radiusY: 0.2, stroke: "rgba(0,200,255,0.8)", strokeWidth: 3 })) }
|
|
173
|
-
{ type: draw-sprite-layer, items: (array/map @entity.units (fn u { type: draw-sprite, position: (object/get @u position), asset: (if (object/get (object/get @u modelUrl) url) (object/get @u modelUrl) (object/get (object/get @config.assetManifest units) (object/get @u unitType))), id: (object/get @u id), anchor: "ground", width:
|
|
173
|
+
{ type: draw-sprite-layer, items: (array/map @entity.units (fn u { type: draw-sprite, position: (object/get @u position), asset: (if (object/get (object/get @u modelUrl) url) (object/get @u modelUrl) (object/get (object/get @config.assetManifest units) (object/get @u unitType))), id: (object/get @u id), anchor: "ground", width: 1, height: 1 })) }
|
|
174
174
|
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: 0.5, height: 0.12, fill: "rgba(0,0,0,0.6)" })) }
|
|
175
175
|
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: (* 0.5 (/ (object/get @u health) (object/get @u maxHealth))), height: 0.12, fill: "#22c55e" })) }
|
|
176
176
|
{ type: draw-text-layer, items: (array/map @entity.units (fn u { type: draw-text, text: (object/get @u name), position: (object/get @u position), offsetY: -0.85, color: "#ffffff" })) }
|
|
@@ -195,11 +195,11 @@ orbital DungeonBoard2DOrbital {
|
|
|
195
195
|
hud: { type: game-hud, stats: [ { label: "HP", value: @entity.hp, max: @entity.maxHp, format: "hearts" }, { label: "Score", value: (+ @entity.score @entity.combatScore) } ] }
|
|
196
196
|
controls: { type: control-grid, kind: "dpad", directionEvents: { up: "MOVE_UP", down: "MOVE_DOWN", left: "MOVE_LEFT", right: "MOVE_RIGHT" }, directionAssets: @config.directionAssets }
|
|
197
197
|
overlay: (if (!= @entity.result "none") { type: game-menu, title: "VICTORY", subtitle: "You found the chest!", options: [ { id: "again", label: "Play Again", event: "PLAY_AGAIN", variant: "primary" } ] } (if (!= @entity.combatResult "none") { type: game-menu, title: "DEFEAT", subtitle: "The dungeon claims another hero", options: [ { id: "again", label: "Play Again", event: "PLAY_AGAIN", variant: "primary" } ] } null))
|
|
198
|
-
children: [ { type: canvas, camera: { zoom: @config.scale }, projection: "flat", showMinimap: false, keyMap: { ArrowUp: "MOVE_UP", KeyW: "MOVE_UP", ArrowDown: "MOVE_DOWN", KeyS: "MOVE_DOWN", ArrowLeft: "MOVE_LEFT", KeyA: "MOVE_LEFT", ArrowRight: "MOVE_RIGHT", KeyD: "MOVE_RIGHT" }, children: [
|
|
198
|
+
children: [ { type: canvas, fit: true, camera: { zoom: @config.scale }, projection: "flat", showMinimap: false, keyMap: { ArrowUp: "MOVE_UP", KeyW: "MOVE_UP", ArrowDown: "MOVE_DOWN", KeyS: "MOVE_DOWN", ArrowLeft: "MOVE_LEFT", KeyA: "MOVE_LEFT", ArrowRight: "MOVE_RIGHT", KeyD: "MOVE_RIGHT" }, children: [
|
|
199
199
|
{ type: draw-shape-layer, items: (array/map @entity.tiles (fn t { type: draw-shape, shape: "cell", position: { x: (object/get @t x), y: (object/get @t y) }, fill: "#5c94fc" })) }
|
|
200
|
-
{ type: draw-sprite-layer, items: (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width:
|
|
200
|
+
{ type: draw-sprite-layer, items: (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width: 1, height: 1 })) }
|
|
201
201
|
{ type: draw-sprite-layer, items: (array/map @entity.features (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f y) }, asset: (object/get @f sprite) })) }
|
|
202
|
-
{ type: draw-sprite-layer, items: (array/map (array/concat @entity.units @entity.enemies) (fn u { type: draw-sprite, position: (object/get @u position), asset: (if (object/get (object/get @u sprite) url) (object/get @u sprite) (object/get (object/get @config.assetManifest units) (object/get @u unitType))), anchor: "ground", width:
|
|
202
|
+
{ type: draw-sprite-layer, items: (array/map (array/concat @entity.units @entity.enemies) (fn u { type: draw-sprite, position: (object/get @u position), asset: (if (object/get (object/get @u sprite) url) (object/get @u sprite) (object/get (object/get @config.assetManifest units) (object/get @u unitType))), anchor: "ground", width: 1, height: 1 })) }
|
|
203
203
|
{ type: draw-shape-layer, items: (array/map (array/concat @entity.units @entity.enemies) (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: 0.5, height: 0.12, fill: "rgba(0,0,0,0.6)" })) }
|
|
204
204
|
{ type: draw-shape-layer, items: (array/map (array/concat @entity.units @entity.enemies) (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: (* 0.5 (/ (object/get @u health) (object/get @u maxHealth))), height: 0.12, fill: "#22c55e" })) }
|
|
205
205
|
{ type: draw-text-layer, items: (array/map (array/concat @entity.units @entity.enemies) (fn u { type: draw-text, text: (object/get @u name), position: (object/get @u position), offsetY: -0.85, color: "#ffffff" })) }
|
|
@@ -261,11 +261,11 @@ orbital DungeonBoard2DOrbital {
|
|
|
261
261
|
hud: { type: game-hud, stats: [ { label: "HP", value: @entity.hp, max: @entity.maxHp, format: "hearts" }, { label: "Score", value: (+ @entity.score @entity.combatScore) } ] }
|
|
262
262
|
controls: { type: control-grid, kind: "dpad", directionEvents: { up: "MOVE_UP", down: "MOVE_DOWN", left: "MOVE_LEFT", right: "MOVE_RIGHT" }, directionAssets: @config.directionAssets }
|
|
263
263
|
overlay: (if (!= @entity.result "none") { type: game-menu, title: "VICTORY", subtitle: "You found the chest!", options: [ { id: "again", label: "Play Again", event: "PLAY_AGAIN", variant: "primary" } ] } (if (!= @entity.combatResult "none") { type: game-menu, title: "DEFEAT", subtitle: "The dungeon claims another hero", options: [ { id: "again", label: "Play Again", event: "PLAY_AGAIN", variant: "primary" } ] } null))
|
|
264
|
-
children: [ { type: canvas, camera: { zoom: @config.scale }, projection: "flat", showMinimap: false, keyMap: { ArrowUp: "MOVE_UP", KeyW: "MOVE_UP", ArrowDown: "MOVE_DOWN", KeyS: "MOVE_DOWN", ArrowLeft: "MOVE_LEFT", KeyA: "MOVE_LEFT", ArrowRight: "MOVE_RIGHT", KeyD: "MOVE_RIGHT" }, children: [
|
|
264
|
+
children: [ { type: canvas, fit: true, camera: { zoom: @config.scale }, projection: "flat", showMinimap: false, keyMap: { ArrowUp: "MOVE_UP", KeyW: "MOVE_UP", ArrowDown: "MOVE_DOWN", KeyS: "MOVE_DOWN", ArrowLeft: "MOVE_LEFT", KeyA: "MOVE_LEFT", ArrowRight: "MOVE_RIGHT", KeyD: "MOVE_RIGHT" }, children: [
|
|
265
265
|
{ type: draw-shape-layer, items: (array/map @entity.tiles (fn t { type: draw-shape, shape: "cell", position: { x: (object/get @t x), y: (object/get @t y) }, fill: "#5c94fc" })) }
|
|
266
|
-
{ type: draw-sprite-layer, items: (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width:
|
|
266
|
+
{ type: draw-sprite-layer, items: (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width: 1, height: 1 })) }
|
|
267
267
|
{ type: draw-sprite-layer, items: (array/map @entity.features (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f y) }, asset: (object/get @f sprite) })) }
|
|
268
|
-
{ type: draw-sprite-layer, items: (array/map (array/concat @entity.units @entity.enemies) (fn u { type: draw-sprite, position: (object/get @u position), asset: (if (object/get (object/get @u sprite) url) (object/get @u sprite) (object/get (object/get @config.assetManifest units) (object/get @u unitType))), anchor: "ground", width:
|
|
268
|
+
{ type: draw-sprite-layer, items: (array/map (array/concat @entity.units @entity.enemies) (fn u { type: draw-sprite, position: (object/get @u position), asset: (if (object/get (object/get @u sprite) url) (object/get @u sprite) (object/get (object/get @config.assetManifest units) (object/get @u unitType))), anchor: "ground", width: 1, height: 1 })) }
|
|
269
269
|
{ type: draw-shape-layer, items: (array/map (array/concat @entity.units @entity.enemies) (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: 0.5, height: 0.12, fill: "rgba(0,0,0,0.6)" })) }
|
|
270
270
|
{ type: draw-shape-layer, items: (array/map (array/concat @entity.units @entity.enemies) (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: (* 0.5 (/ (object/get @u health) (object/get @u maxHealth))), height: 0.12, fill: "#22c55e" })) }
|
|
271
271
|
{ type: draw-text-layer, items: (array/map (array/concat @entity.units @entity.enemies) (fn u { type: draw-text, text: (object/get @u name), position: (object/get @u position), offsetY: -0.85, color: "#ffffff" })) }
|
|
@@ -5,6 +5,7 @@ orbital TacticsBoard2DOrbital {
|
|
|
5
5
|
uses Particles from "std/behaviors/std-fx-particles"
|
|
6
6
|
uses Round from "std/behaviors/std-round-flow"
|
|
7
7
|
uses Score from "std/behaviors/std-score"
|
|
8
|
+
uses AnimTick from "std/behaviors/std-anim-tick"
|
|
8
9
|
|
|
9
10
|
type Asset = {
|
|
10
11
|
url : asset
|
|
@@ -70,6 +71,7 @@ orbital TacticsBoard2DOrbital {
|
|
|
70
71
|
type HudStat = {
|
|
71
72
|
label : string
|
|
72
73
|
value : number
|
|
74
|
+
format : string
|
|
73
75
|
}
|
|
74
76
|
type HudButton = {
|
|
75
77
|
type : string
|
|
@@ -96,10 +98,19 @@ orbital TacticsBoard2DOrbital {
|
|
|
96
98
|
selectedUnitId : string = ""
|
|
97
99
|
validMoves : [ValidMove] = []
|
|
98
100
|
attackTargets : [ValidMove] = []
|
|
101
|
+
movedIds : [string] = []
|
|
102
|
+
actedIds : [string] = []
|
|
99
103
|
uiPhase : string = "observation"
|
|
100
104
|
turn : number = 0
|
|
101
105
|
score : number = 0
|
|
102
106
|
scoreBaseline : number = 0
|
|
107
|
+
animCounter : number = 0
|
|
108
|
+
frameName : string = "0"
|
|
109
|
+
animUnitId : string = ""
|
|
110
|
+
animState : string = "idle"
|
|
111
|
+
animTicksLeft : number = 0
|
|
112
|
+
animAttackerId : string = ""
|
|
113
|
+
animAtkTicksLeft : number = 0
|
|
103
114
|
}
|
|
104
115
|
|
|
105
116
|
trait TacticsAuthority = Tactics.traits.GridTactics -> GameState {
|
|
@@ -133,6 +144,10 @@ orbital TacticsBoard2DOrbital {
|
|
|
133
144
|
config { running: true, pointsPerKill: 10, startScore: 0, initialEnemies: 0 }
|
|
134
145
|
}
|
|
135
146
|
|
|
147
|
+
trait AnimClock = AnimTick.traits.AnimTick -> GameState {
|
|
148
|
+
config { frames: [] }
|
|
149
|
+
}
|
|
150
|
+
|
|
136
151
|
trait PlayerIntent -> GameState [interaction, instance] {
|
|
137
152
|
initial: playing
|
|
138
153
|
|
|
@@ -147,47 +162,52 @@ orbital TacticsBoard2DOrbital {
|
|
|
147
162
|
type: game-shell
|
|
148
163
|
backgroundAsset: @config.backgroundAsset
|
|
149
164
|
hudBackgroundAsset: @config.hudBackgroundAsset
|
|
150
|
-
hud: { type: game-hud, stats: (array/concat [ { label: "Result", value: @entity.result }, { label: "Phase", value: @entity.uiPhase }, { label: "Turn", value: @entity.turn }, { label: "Score", value: @entity.score } ] @config.extraStats) }
|
|
165
|
+
hud: { type: game-hud, stats: (array/concat [ { label: "Result", value: @entity.result, format: "text" }, { label: "Phase", value: @entity.uiPhase, format: "text" }, { label: "Turn", value: @entity.turn }, { label: "Score", value: @entity.score } ] @config.extraStats) }
|
|
151
166
|
addons: { type: stack, direction: vertical, gap: sm, children: (array/concat [ { type: button, action: END_TURN, label: "End Turn", variant: primary }, { type: button, action: CANCEL, label: "Cancel", variant: secondary } ] @config.extraAddons) }
|
|
152
|
-
children: [ { type: canvas,
|
|
167
|
+
children: [ { type: canvas, fit: true, camera: { pos: { x: (/ (+ (array/min @entity.tiles "x") (array/max @entity.tiles "x")) 2), y: (/ (+ (array/min @entity.tiles "y") (array/max @entity.tiles "y")) 2) } }, projection: @config.projection, showMinimap: @config.showMinimap, tileClickEvent: TILE_CLICK, unitClickEvent: UNIT_CLICK, children: [
|
|
153
168
|
{ type: draw-shape-layer, items: (array/map @entity.tiles (fn t { type: draw-shape, shape: "cell", position: { x: (object/get @t x), y: (object/get @t y) }, fill: "#5c94fc", stroke: "rgba(255,255,255,0.35)", strokeWidth: 1 })) }
|
|
154
|
-
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width:
|
|
155
|
-
{ type: draw-sprite-layer, items: (array/filter (array/map @config.features (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f y) }, asset: (object/get @f assetUrl) })) (fn s (object/get (object/get @s asset) url))) }
|
|
169
|
+
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width: 1, height: 1 })) (fn s (object/get (object/get @s asset) url))) }
|
|
170
|
+
{ type: draw-sprite-layer, items: (array/filter (array/map @config.features (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f y) }, asset: (object/get @f assetUrl), anchor: "ground", width: 1, height: 1 })) (fn s (object/get (object/get @s asset) url))) }
|
|
156
171
|
{ type: draw-shape-layer, items: (array/map @entity.validMoves (fn m { type: draw-shape, shape: "cell", position: { x: (object/get @m x), y: (object/get @m z) }, fill: "rgba(74,222,128,0.4)" })) }
|
|
157
172
|
{ type: draw-shape-layer, items: (array/map @entity.attackTargets (fn a { type: draw-shape, shape: "cell", position: { x: (object/get @a x), y: (object/get @a z) }, fill: "rgba(239,68,68,0.4)" })) }
|
|
158
173
|
{ type: draw-shape-layer, items: (array/map (array/filter @entity.units (fn u (== (object/get @u id) @entity.selectedUnitId))) (fn u { type: draw-shape, shape: "ellipse", position: (object/get @u position), radiusX: 0.5, radiusY: 0.2, stroke: "rgba(0,200,255,0.8)", strokeWidth: 3 })) }
|
|
159
|
-
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.units (fn u
|
|
160
|
-
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: 0.5, height: 0.12, fill: "rgba(0,0,0,0.6)" })) }
|
|
161
|
-
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: (* 0.5 (/ (object/get @u health) (object/get @u maxHealth))), height: 0.12, fill: "#22c55e" })) }
|
|
162
|
-
{ type: draw-text-layer, items: (array/map @entity.units (fn u { type: draw-text, text: (object/get @u name), position: (object/get @u position), offsetY: -0.85, color: "#ffffff" })) }
|
|
163
|
-
{ type: draw-text-layer, items: (array/map @entity.fx (fn f { type: draw-text, text: (object/get @f message), position: { x: (object/get @f x), y: (object/get @f
|
|
174
|
+
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.units (fn u (let ((unitAsset (if (object/get (object/get @u modelUrl) url) (object/get @u modelUrl) (object/get (object/get @config.assetManifest units) (object/get @u unitType)))) (unitUrl (object/get @unitAsset url)) (unitAnim (if (<= (object/get @u health) 0) "death" (if (and (== (object/get @u id) @entity.animAttackerId) (> @entity.animAtkTicksLeft 0)) "attack" (if (== (object/get @u id) @entity.animUnitId) @entity.animState "idle"))))) { type: draw-sprite, position: (object/get @u position), asset: (if (and @unitUrl (str/includes @unitUrl ".svg")) (object/merge @unitAsset { url: (str/concat (array/nth (str/split @unitUrl ".svg") 0) (str/concat "." (str/concat @unitAnim (str/concat "-" (str/concat (if (== @unitAnim "walk") (% @entity.animCounter 2) (if (== @unitAnim "idle") (% (math/floor (/ @entity.animCounter 3)) 4) 0))) ".svg")))) }) @unitAsset), id: (object/get @u id), anchor: "ground", width: 0.5, height: 0.5, opacity: (if (> (array/len (array/filter @entity.actedIds (fn aid (== @aid (object/get @u id))))) 0) 0.45 1) }))) (fn s (object/get (object/get @s asset) url))) }
|
|
175
|
+
{ type: draw-shape-layer, items: (array/map (array/filter @entity.units (fn u (> (object/get @u health) 0))) (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: 0.5, height: 0.12, fill: "rgba(0,0,0,0.6)" })) }
|
|
176
|
+
{ type: draw-shape-layer, items: (array/map (array/filter @entity.units (fn u (> (object/get @u health) 0))) (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: (* 0.5 (/ (object/get @u health) (object/get @u maxHealth))), height: 0.12, fill: "#22c55e" })) }
|
|
177
|
+
{ type: draw-text-layer, items: (array/map (array/filter @entity.units (fn u (> (object/get @u health) 0))) (fn u { type: draw-text, text: (object/get @u name), position: (object/get @u position), offsetY: -0.85, color: "#ffffff" })) }
|
|
178
|
+
{ type: draw-text-layer, items: (array/map @entity.fx (fn f { type: draw-text, text: (object/get @f message), position: { x: (object/get @f x), y: (object/get @f z) }, color: "#ffe066" })) }
|
|
179
|
+
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.fx (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f z) }, asset: (object/get (object/get @config.assetManifest effects) (object/get @f type)), anchor: "center", width: 0.6, height: 0.6 })) (fn s (object/get (object/get @s asset) url))) }
|
|
180
|
+
{ type: draw-sprite-layer, items: (array/map (array/filter (array/flatten (array/map @entity.units (fn u (array/flatten (array/map [ ["idle", 4], ["walk", 2], ["attack", 1], ["hit", 1], ["death", 1] ] (fn st (array/map (array/range 0 (array/nth @st 1)) (fn i (if (and (object/get (object/get @u modelUrl) url) (str/includes (object/get (object/get @u modelUrl) url) ".svg")) (str/concat (array/nth (str/split (object/get (object/get @u modelUrl) url) ".svg") 0) (str/concat "." (str/concat (array/nth @st 0) (str/concat "-" (str/concat @i ".svg"))))) ""))))))))) (fn w (!= @w ""))) (fn warmUrl { type: draw-sprite, position: { x: 0, y: 0 }, asset: { url: @warmUrl }, opacity: 0, width: 0.5, height: 0.5 })) }
|
|
164
181
|
] } ]
|
|
165
182
|
})
|
|
166
183
|
|
|
167
|
-
UNIT_CLICK -> playing when (and (== @entity.
|
|
184
|
+
UNIT_CLICK -> playing when (and (== @entity.result "none") (and (!= @entity.selectedUnitId "") (and (== (array/len (array/filter @entity.actedIds (fn aid (== @aid @entity.selectedUnitId)))) 0) (and (== (object/get (array/find @entity.units (fn u (== @u.id ?unitId))) team) "enemy") (and (> (object/get (array/find @entity.units (fn u (== @u.id ?unitId))) health) 0) (<= (grid/manhattan-distance (object/get (array/find @entity.units (fn u (== @u.id @entity.selectedUnitId))) position) (object/get (array/find @entity.units (fn u (== @u.id ?unitId))) position)) @config.attackRange))))))
|
|
168
185
|
(emit ATTACK { targetId: ?unitId })
|
|
186
|
+
(set @entity.actedIds (array/append @entity.actedIds @entity.selectedUnitId))
|
|
187
|
+
(set @entity.animAttackerId @entity.selectedUnitId)
|
|
188
|
+
(set @entity.animAtkTicksLeft 4)
|
|
169
189
|
(set @entity.selectedUnitId "")
|
|
170
190
|
(set @entity.validMoves [])
|
|
171
191
|
(set @entity.attackTargets [])
|
|
172
192
|
(set @entity.uiPhase "observation")
|
|
173
193
|
|
|
174
|
-
UNIT_CLICK -> playing when (== @entity.selectedUnitId ?unitId)
|
|
194
|
+
UNIT_CLICK -> playing when (and (== @entity.result "none") (== @entity.selectedUnitId ?unitId))
|
|
175
195
|
(set @entity.uiPhase "action")
|
|
176
196
|
(set @entity.validMoves [])
|
|
177
|
-
(set @entity.attackTargets (array/map (array/filter @entity.units (fn u (and (== @u.team "enemy") (and (> @u.health 0) (<= (grid/manhattan-distance (object/get (array/find @entity.units (fn s (== @s.id @entity.selectedUnitId))) position) (object/get @u position))
|
|
197
|
+
(set @entity.attackTargets (array/map (array/filter @entity.units (fn u (and (== @u.team "enemy") (and (> @u.health 0) (<= (grid/manhattan-distance (object/get (array/find @entity.units (fn s (== @s.id @entity.selectedUnitId))) position) (object/get @u position)) @config.attackRange))))) (fn u { x: (object/get (object/get @u position) x), z: (object/get (object/get @u position) y) })))
|
|
178
198
|
|
|
179
|
-
UNIT_CLICK -> playing when (== (object/get (array/find @entity.units (fn u (== @u.id ?unitId))) team) "player")
|
|
199
|
+
UNIT_CLICK -> playing when (and (== @entity.result "none") (and (> (object/get (array/find @entity.units (fn u (== @u.id ?unitId))) health) 0) (and (== (object/get (array/find @entity.units (fn u (== @u.id ?unitId))) team) "player") (== (array/len (array/filter @entity.actedIds (fn aid (== @aid ?unitId)))) 0))))
|
|
180
200
|
(set @entity.selectedUnitId ?unitId)
|
|
181
201
|
(set @entity.uiPhase "selection")
|
|
182
202
|
(set @entity.attackTargets [])
|
|
183
|
-
(set @entity.validMoves (array/map (array/filter @entity.tiles (fn t (and (== (object/get @t passable) true) (and (<= (grid/manhattan-distance (object/get (array/find @entity.units (fn u (== @u.id ?unitId))) position) { x: (object/get @t x), y: (object/get @t y) }) @config.movementRange) (== (array/len (array/filter @entity.units (fn u (and (== (object/get (object/get @u position) x) (object/get @t x)) (== (object/get (object/get @u position) y) (object/get @t y)))))) 0))))) (fn t { x: (object/get @t x), z: (object/get @t y) })))
|
|
203
|
+
(set @entity.validMoves (if (> (array/len (array/filter @entity.movedIds (fn aid (== @aid ?unitId)))) 0) [] (array/map (array/filter @entity.tiles (fn t (and (== (object/get @t passable) true) (and (<= (grid/manhattan-distance (object/get (array/find @entity.units (fn u (== @u.id ?unitId))) position) { x: (object/get @t x), y: (object/get @t y) }) @config.movementRange) (== (array/len (array/filter @entity.units (fn u (and (> (object/get @u health) 0) (and (== (object/get (object/get @u position) x) (object/get @t x)) (== (object/get (object/get @u position) y) (object/get @t y))))))) 0))))) (fn t { x: (object/get @t x), z: (object/get @t y) }))))
|
|
184
204
|
|
|
185
|
-
TILE_CLICK -> playing when (and (!= @entity.selectedUnitId "") (and (grid/in-bounds { x: ?x, y: ?y } @config.gridWidth @config.gridHeight) (<= (grid/manhattan-distance (object/get (array/find @entity.units (fn u (== @u.id @entity.selectedUnitId))) position) { x: ?x, y: ?y }) @config.movementRange)))
|
|
205
|
+
TILE_CLICK -> playing when (and (== @entity.result "none") (and (!= @entity.selectedUnitId "") (and (== (array/len (array/filter @entity.movedIds (fn aid (== @aid @entity.selectedUnitId)))) 0) (and (> (object/get (array/find @entity.units (fn u (== @u.id @entity.selectedUnitId))) health) 0) (and (grid/in-bounds { x: ?x, y: ?y } @config.gridWidth @config.gridHeight) (and (<= (grid/manhattan-distance (object/get (array/find @entity.units (fn u (== @u.id @entity.selectedUnitId))) position) { x: ?x, y: ?y }) @config.movementRange) (and (== (array/len (array/filter @entity.units (fn u (and (> (object/get @u health) 0) (and (== (object/get (object/get @u position) x) ?x) (== (object/get (object/get @u position) y) ?y)))))) 0) (== (object/get (array/find @entity.tiles (fn t (and (== (object/get @t x) ?x) (== (object/get @t y) ?y)))) passable) true))))))))
|
|
186
206
|
(emit MOVE { unitId: @entity.selectedUnitId, x: ?x, y: ?y })
|
|
187
|
-
(set @entity.selectedUnitId
|
|
207
|
+
(set @entity.movedIds (array/append @entity.movedIds @entity.selectedUnitId))
|
|
208
|
+
(set @entity.uiPhase "action")
|
|
188
209
|
(set @entity.validMoves [])
|
|
189
|
-
(set @entity.attackTargets
|
|
190
|
-
(set @entity.uiPhase "observation")
|
|
210
|
+
(set @entity.attackTargets (array/map (array/filter @entity.units (fn u (and (== @u.team "enemy") (and (> @u.health 0) (<= (grid/manhattan-distance { x: ?x, y: ?y } (object/get @u position)) @config.attackRange))))) (fn u { x: (object/get (object/get @u position) x), z: (object/get (object/get @u position) y) })))
|
|
191
211
|
|
|
192
212
|
CANCEL -> playing when (!= @entity.selectedUnitId "")
|
|
193
213
|
(set @entity.selectedUnitId "")
|
|
@@ -197,29 +217,51 @@ orbital TacticsBoard2DOrbital {
|
|
|
197
217
|
|
|
198
218
|
END_TURN -> playing when (== @entity.result "none")
|
|
199
219
|
(set @entity.turn (+ @entity.turn 1))
|
|
220
|
+
(set @entity.movedIds [])
|
|
221
|
+
(set @entity.actedIds [])
|
|
222
|
+
(set @entity.selectedUnitId "")
|
|
223
|
+
(set @entity.validMoves [])
|
|
224
|
+
(set @entity.attackTargets [])
|
|
225
|
+
(set @entity.uiPhase "observation")
|
|
200
226
|
(emit AI_TURN { turn: @entity.turn })
|
|
227
|
+
|
|
228
|
+
MOVE -> playing
|
|
229
|
+
(set @entity.animUnitId ?unitId)
|
|
230
|
+
(set @entity.animState "walk")
|
|
231
|
+
(set @entity.animTicksLeft 6)
|
|
232
|
+
|
|
233
|
+
ATTACK -> playing
|
|
234
|
+
(set @entity.animUnitId ?targetId)
|
|
235
|
+
(set @entity.animState "hit")
|
|
236
|
+
(set @entity.animTicksLeft 4)
|
|
201
237
|
}
|
|
202
238
|
|
|
203
239
|
ticks {
|
|
204
240
|
renderTick every 100ms
|
|
241
|
+
(set @entity.animTicksLeft (if (> @entity.animTicksLeft 0) (- @entity.animTicksLeft 1) 0))
|
|
242
|
+
(set @entity.animAtkTicksLeft (if (> @entity.animAtkTicksLeft 0) (- @entity.animAtkTicksLeft 1) 0))
|
|
243
|
+
(set @entity.animState (if (== @entity.animTicksLeft 0) "idle" @entity.animState))
|
|
244
|
+
(set @entity.animUnitId (if (== @entity.animTicksLeft 0) "" @entity.animUnitId))
|
|
245
|
+
(set @entity.animAttackerId (if (== @entity.animAtkTicksLeft 0) "" @entity.animAttackerId))
|
|
205
246
|
(render-ui main {
|
|
206
247
|
type: game-shell
|
|
207
248
|
backgroundAsset: @config.backgroundAsset
|
|
208
249
|
hudBackgroundAsset: @config.hudBackgroundAsset
|
|
209
|
-
hud: { type: game-hud, stats: (array/concat [ { label: "Result", value: @entity.result }, { label: "Phase", value: @entity.uiPhase }, { label: "Turn", value: @entity.turn }, { label: "Score", value: @entity.score } ] @config.extraStats) }
|
|
250
|
+
hud: { type: game-hud, stats: (array/concat [ { label: "Result", value: @entity.result, format: "text" }, { label: "Phase", value: @entity.uiPhase, format: "text" }, { label: "Turn", value: @entity.turn }, { label: "Score", value: @entity.score } ] @config.extraStats) }
|
|
210
251
|
addons: { type: stack, direction: vertical, gap: sm, children: (array/concat [ { type: button, action: END_TURN, label: "End Turn", variant: primary }, { type: button, action: CANCEL, label: "Cancel", variant: secondary } ] @config.extraAddons) }
|
|
211
|
-
children: [ { type: canvas,
|
|
252
|
+
children: [ { type: canvas, fit: true, camera: { pos: { x: (/ (+ (array/min @entity.tiles "x") (array/max @entity.tiles "x")) 2), y: (/ (+ (array/min @entity.tiles "y") (array/max @entity.tiles "y")) 2) } }, projection: @config.projection, showMinimap: @config.showMinimap, tileClickEvent: TILE_CLICK, unitClickEvent: UNIT_CLICK, children: [
|
|
212
253
|
{ type: draw-shape-layer, items: (array/map @entity.tiles (fn t { type: draw-shape, shape: "cell", position: { x: (object/get @t x), y: (object/get @t y) }, fill: "#5c94fc", stroke: "rgba(255,255,255,0.35)", strokeWidth: 1 })) }
|
|
213
|
-
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width:
|
|
214
|
-
{ type: draw-sprite-layer, items: (array/filter (array/map @config.features (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f y) }, asset: (object/get @f assetUrl) })) (fn s (object/get (object/get @s asset) url))) }
|
|
254
|
+
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width: 1, height: 1 })) (fn s (object/get (object/get @s asset) url))) }
|
|
255
|
+
{ type: draw-sprite-layer, items: (array/filter (array/map @config.features (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f y) }, asset: (object/get @f assetUrl), anchor: "ground", width: 1, height: 1 })) (fn s (object/get (object/get @s asset) url))) }
|
|
215
256
|
{ type: draw-shape-layer, items: (array/map @entity.validMoves (fn m { type: draw-shape, shape: "cell", position: { x: (object/get @m x), y: (object/get @m z) }, fill: "rgba(74,222,128,0.4)" })) }
|
|
216
257
|
{ type: draw-shape-layer, items: (array/map @entity.attackTargets (fn a { type: draw-shape, shape: "cell", position: { x: (object/get @a x), y: (object/get @a z) }, fill: "rgba(239,68,68,0.4)" })) }
|
|
217
258
|
{ type: draw-shape-layer, items: (array/map (array/filter @entity.units (fn u (== (object/get @u id) @entity.selectedUnitId))) (fn u { type: draw-shape, shape: "ellipse", position: (object/get @u position), radiusX: 0.5, radiusY: 0.2, stroke: "rgba(0,200,255,0.8)", strokeWidth: 3 })) }
|
|
218
|
-
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.units (fn u
|
|
219
|
-
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: 0.5, height: 0.12, fill: "rgba(0,0,0,0.6)" })) }
|
|
220
|
-
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: (* 0.5 (/ (object/get @u health) (object/get @u maxHealth))), height: 0.12, fill: "#22c55e" })) }
|
|
221
|
-
{ type: draw-text-layer, items: (array/map @entity.units (fn u { type: draw-text, text: (object/get @u name), position: (object/get @u position), offsetY: -0.85, color: "#ffffff" })) }
|
|
222
|
-
{ type: draw-text-layer, items: (array/map @entity.fx (fn f { type: draw-text, text: (object/get @f message), position: { x: (object/get @f x), y: (object/get @f
|
|
259
|
+
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.units (fn u (let ((unitAsset (if (object/get (object/get @u modelUrl) url) (object/get @u modelUrl) (object/get (object/get @config.assetManifest units) (object/get @u unitType)))) (unitUrl (object/get @unitAsset url)) (unitAnim (if (<= (object/get @u health) 0) "death" (if (and (== (object/get @u id) @entity.animAttackerId) (> @entity.animAtkTicksLeft 0)) "attack" (if (== (object/get @u id) @entity.animUnitId) @entity.animState "idle"))))) { type: draw-sprite, position: (object/get @u position), asset: (if (and @unitUrl (str/includes @unitUrl ".svg")) (object/merge @unitAsset { url: (str/concat (array/nth (str/split @unitUrl ".svg") 0) (str/concat "." (str/concat @unitAnim (str/concat "-" (str/concat (if (== @unitAnim "walk") (% @entity.animCounter 2) (if (== @unitAnim "idle") (% (math/floor (/ @entity.animCounter 3)) 4) 0))) ".svg")))) }) @unitAsset), id: (object/get @u id), anchor: "ground", width: 0.5, height: 0.5, opacity: (if (> (array/len (array/filter @entity.actedIds (fn aid (== @aid (object/get @u id))))) 0) 0.45 1) }))) (fn s (object/get (object/get @s asset) url))) }
|
|
260
|
+
{ type: draw-shape-layer, items: (array/map (array/filter @entity.units (fn u (> (object/get @u health) 0))) (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: 0.5, height: 0.12, fill: "rgba(0,0,0,0.6)" })) }
|
|
261
|
+
{ type: draw-shape-layer, items: (array/map (array/filter @entity.units (fn u (> (object/get @u health) 0))) (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), anchor: "ground", offsetX: -0.25, offsetY: -0.6, width: (* 0.5 (/ (object/get @u health) (object/get @u maxHealth))), height: 0.12, fill: "#22c55e" })) }
|
|
262
|
+
{ type: draw-text-layer, items: (array/map (array/filter @entity.units (fn u (> (object/get @u health) 0))) (fn u { type: draw-text, text: (object/get @u name), position: (object/get @u position), offsetY: -0.85, color: "#ffffff" })) }
|
|
263
|
+
{ type: draw-text-layer, items: (array/map @entity.fx (fn f { type: draw-text, text: (object/get @f message), position: { x: (object/get @f x), y: (object/get @f z) }, color: "#ffe066" })) }
|
|
264
|
+
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.fx (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f z) }, asset: (object/get (object/get @config.assetManifest effects) (object/get @f type)), anchor: "center", width: 0.6, height: 0.6 })) (fn s (object/get (object/get @s asset) url))) }
|
|
223
265
|
] } ]
|
|
224
266
|
})
|
|
225
267
|
}
|
|
@@ -278,6 +320,10 @@ orbital TacticsBoard2DOrbital {
|
|
|
278
320
|
@label "Movement Range"
|
|
279
321
|
@description "Max manhattan distance a selected unit may move."
|
|
280
322
|
@tier "domain"
|
|
323
|
+
attackRange : number = 1
|
|
324
|
+
@label "Attack Range"
|
|
325
|
+
@description "Max manhattan distance a selected unit may strike an enemy."
|
|
326
|
+
@tier "domain"
|
|
281
327
|
features : [Feature] = []
|
|
282
328
|
@label "Features"
|
|
283
329
|
@description "Decorative environment features drawn on the board."
|
|
@@ -321,5 +367,5 @@ orbital TacticsBoard2DOrbital {
|
|
|
321
367
|
}
|
|
322
368
|
}
|
|
323
369
|
|
|
324
|
-
page "/tactics-board-2d" as TacticsBoard2DPage -> TacticsAuthority, FxDecay, RoundLogic, ScoreKeeper, PlayerIntent
|
|
370
|
+
page "/tactics-board-2d" as TacticsBoard2DPage -> TacticsAuthority, FxDecay, RoundLogic, ScoreKeeper, PlayerIntent, AnimClock
|
|
325
371
|
}
|
|
@@ -147,7 +147,7 @@ orbital WorldMapBoard2DOrbital {
|
|
|
147
147
|
hud: { type: stack, direction: horizontal, gap: md, justify: between, children: [ { type: game-hud, stats: (array/concat [ { label: "Region", value: @config.region, iconUrl: @config.regionIconAsset }, { label: "Turn", value: @entity.turn, iconUrl: @config.turnIconAsset }, { label: "Gold", value: @entity.gold, iconUrl: @config.goldIconAsset } ] @config.extraStats) }, { type: stack, direction: horizontal, gap: xs, align: center, children: [ { type: icon, name: map-pin }, { type: typography, variant: caption, content: "Waypoints" } ] } ] }
|
|
148
148
|
addons: { type: stack, direction: vertical, gap: sm, children: (array/concat [ { type: button, action: ADVANCE_TURN, label: "Pass Turn", iconAsset: @config.travelIconAsset, variant: primary } ] @config.extraAddons) }
|
|
149
149
|
overlay: (if (!= @entity.result "none") { type: game-menu, title: (if (== @entity.result "victory") "VICTORY" "DEFEAT"), subtitle: (if (== @entity.result "victory") "The realm is secured" "Your heroes have fallen"), options: [] } null)
|
|
150
|
-
children: [ { type: canvas,
|
|
150
|
+
children: [ { type: canvas, fit: true, camera: { pos: { x: (/ (+ (array/min @entity.tiles "x") (array/max @entity.tiles "x")) 2), y: (/ (+ (array/min @entity.tiles "y") (array/max @entity.tiles "y")) 2) } }, projection: "isometric", showMinimap: true, tileClickEvent: HERO_MOVE, unitClickEvent: HERO_SELECT, children: [
|
|
151
151
|
{ type: draw-shape-layer, items: (array/map @entity.tiles (fn t { type: draw-shape, shape: "cell", position: { x: (object/get @t x), y: (object/get @t y) }, fill: "#5c94fc", stroke: "rgba(255,255,255,0.35)", strokeWidth: 1 })) }
|
|
152
152
|
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width: 0.5, height: 0.5 })) (fn s (object/get (object/get @s asset) url))) }
|
|
153
153
|
{ type: draw-sprite-layer, items: (array/map @config.features (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f y) }, asset: (object/get @f sprite) })) }
|
|
@@ -195,7 +195,7 @@ orbital WorldMapBoard2DOrbital {
|
|
|
195
195
|
hud: { type: stack, direction: horizontal, gap: md, justify: between, children: [ { type: game-hud, stats: (array/concat [ { label: "Region", value: @config.region, iconUrl: @config.regionIconAsset }, { label: "Turn", value: @entity.turn, iconUrl: @config.turnIconAsset }, { label: "Gold", value: @entity.gold, iconUrl: @config.goldIconAsset } ] @config.extraStats) }, { type: stack, direction: horizontal, gap: xs, align: center, children: [ { type: icon, name: map-pin }, { type: typography, variant: caption, content: "Waypoints" } ] } ] }
|
|
196
196
|
addons: { type: stack, direction: vertical, gap: sm, children: (array/concat [ { type: button, action: ADVANCE_TURN, label: "Pass Turn", iconAsset: @config.travelIconAsset, variant: primary } ] @config.extraAddons) }
|
|
197
197
|
overlay: (if (!= @entity.result "none") { type: game-menu, title: (if (== @entity.result "victory") "VICTORY" "DEFEAT"), subtitle: (if (== @entity.result "victory") "The realm is secured" "Your heroes have fallen"), options: [] } null)
|
|
198
|
-
children: [ { type: canvas,
|
|
198
|
+
children: [ { type: canvas, fit: true, camera: { pos: { x: (/ (+ (array/min @entity.tiles "x") (array/max @entity.tiles "x")) 2), y: (/ (+ (array/min @entity.tiles "y") (array/max @entity.tiles "y")) 2) } }, projection: "isometric", showMinimap: true, tileClickEvent: HERO_MOVE, unitClickEvent: HERO_SELECT, children: [
|
|
199
199
|
{ type: draw-shape-layer, items: (array/map @entity.tiles (fn t { type: draw-shape, shape: "cell", position: { x: (object/get @t x), y: (object/get @t y) }, fill: "#5c94fc", stroke: "rgba(255,255,255,0.35)", strokeWidth: 1 })) }
|
|
200
200
|
{ type: draw-sprite-layer, items: (array/filter (array/map @entity.tiles (fn t { type: draw-sprite, position: { x: (object/get @t x), y: (object/get @t y) }, asset: (if (object/get (object/get @t terrainSprite) url) (object/get @t terrainSprite) (object/get (object/get @config.assetManifest terrains) (object/get @t terrain))), anchor: "center", width: 0.5, height: 0.5 })) (fn s (object/get (object/get @s asset) url))) }
|
|
201
201
|
{ type: draw-sprite-layer, items: (array/map @config.features (fn f { type: draw-sprite, position: { x: (object/get @f x), y: (object/get @f y) }, asset: (object/get @f sprite) })) }
|
|
@@ -13,6 +13,7 @@ orbital CanvasOrbital {
|
|
|
13
13
|
(render-ui main {
|
|
14
14
|
mode: @config.mode
|
|
15
15
|
drawables: @config.drawables
|
|
16
|
+
children: @config.children
|
|
16
17
|
camera: @config.camera
|
|
17
18
|
projection: @config.projection
|
|
18
19
|
className: @config.className
|
|
@@ -82,6 +83,10 @@ orbital CanvasOrbital {
|
|
|
82
83
|
@label "Drawables"
|
|
83
84
|
@description "Neutral drawable descriptors — the `draw-*` children. Routed to the host's painter."
|
|
84
85
|
@tier "presentation"
|
|
86
|
+
children : node
|
|
87
|
+
@label "Children (drawable composition)"
|
|
88
|
+
@description "Declarative JSX drawable children — semantic atom invocations (`<SvgPrimitive/>`, `<SvgShading/>`, …) composed in paint order. The canvas is a draw-host: these children are routed to the painter as drawable descriptors, not DOM-wrapped. Use this to author a high-fidelity asset as a readable, nested JSX tree an LLM can rasterize."
|
|
89
|
+
@tier "presentation"
|
|
85
90
|
camera : json = {}
|
|
86
91
|
@label "Camera"
|
|
87
92
|
@description "Neutral camera pose. Mapped to the underlying host's framing + zoom."
|
|
@@ -42,7 +42,7 @@ orbital ArenaBoardOrbital {
|
|
|
42
42
|
(render-ui main {
|
|
43
43
|
type: game-shell
|
|
44
44
|
hud: { type: game-hud, stats: [ { label: "Result", value: @entity.result } ] }
|
|
45
|
-
children: [ { type: canvas, projection: "flat", showMinimap: false, children: [
|
|
45
|
+
children: [ { type: canvas, fit: true, projection: "flat", showMinimap: false, children: [
|
|
46
46
|
{ type: draw-shape-layer, items: (array/map @config.tiles (fn t { type: draw-shape, shape: "cell", position: { x: (object/get @t x), y: (object/get @t y) }, fill: "#4ade80", stroke: "rgba(0,0,0,0.2)" })) }
|
|
47
47
|
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "ellipse", position: (object/get @u position), radiusX: 0.4, radiusY: 0.4, fill: (if (== (object/get @u team) "player") "#3b82f6" "#ef4444") })) }
|
|
48
48
|
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), offsetY: -0.6, width: 0.8, height: 0.12, fill: "rgba(0,0,0,0.6)" })) }
|
|
@@ -57,7 +57,7 @@ orbital ArenaBoardOrbital {
|
|
|
57
57
|
(render-ui main {
|
|
58
58
|
type: game-shell
|
|
59
59
|
hud: { type: game-hud, stats: [ { label: "Result", value: @entity.result } ] }
|
|
60
|
-
children: [ { type: canvas, projection: "flat", showMinimap: false, children: [
|
|
60
|
+
children: [ { type: canvas, fit: true, projection: "flat", showMinimap: false, children: [
|
|
61
61
|
{ type: draw-shape-layer, items: (array/map @config.tiles (fn t { type: draw-shape, shape: "cell", position: { x: (object/get @t x), y: (object/get @t y) }, fill: "#4ade80", stroke: "rgba(0,0,0,0.2)" })) }
|
|
62
62
|
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "ellipse", position: (object/get @u position), radiusX: 0.4, radiusY: 0.4, fill: (if (== (object/get @u team) "player") "#3b82f6" "#ef4444") })) }
|
|
63
63
|
{ type: draw-shape-layer, items: (array/map @entity.units (fn u { type: draw-shape, shape: "rect", position: (object/get @u position), offsetY: -0.6, width: 0.8, height: 0.12, fill: "rgba(0,0,0,0.6)" })) }
|