@almadar/ui 5.55.0 → 5.57.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/dist/avl/index.js CHANGED
@@ -10,7 +10,7 @@ import * as LucideIcons2 from 'lucide-react';
10
10
  import { Loader2, X, Code, FileText, WrapText, Check, Copy, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ZoomOut, ZoomIn, Download, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, ArrowLeft, HelpCircle, PauseCircle, Search, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, Bug, Send, ChevronUp, ChevronDown, Wrench, Tag, User, DollarSign, Zap, Sword, Move, Heart, Shield } from 'lucide-react';
11
11
  import { createPortal } from 'react-dom';
12
12
  import { UISlotProvider, useUISlots, useTheme } from '@almadar/ui/context';
13
- import { evaluate, createMinimalContext } from '@almadar/evaluator';
13
+ import { evaluateGuard, evaluate, createMinimalContext } from '@almadar/evaluator';
14
14
  import { Link, Outlet, useLocation } from 'react-router-dom';
15
15
  import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
16
16
  import dark from 'react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus.js';
@@ -47,7 +47,7 @@ import { Canvas, useLoader, useFrame, useThree } from '@react-three/fiber';
47
47
  import { Billboard, Grid as Grid$1, OrbitControls } from '@react-three/drei';
48
48
  import { getPatternDefinition, getComponentForPattern as getComponentForPattern$1, isEntityAwarePattern } from '@almadar/patterns';
49
49
  import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
50
- import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, interpolateValue, createContextFromBindings } from '@almadar/runtime';
50
+ import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, createContextFromBindings } from '@almadar/runtime';
51
51
 
52
52
  var __defProp = Object.defineProperty;
53
53
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -14534,6 +14534,8 @@ function IsometricCanvas({
14534
14534
  showMinimap = true,
14535
14535
  enableCamera = true,
14536
14536
  unitScale = 1,
14537
+ spriteHeightRatio = 1.5,
14538
+ spriteMaxWidthRatio = 0.6,
14537
14539
  // Asset resolution
14538
14540
  getTerrainSprite,
14539
14541
  getFeatureSprite,
@@ -14924,8 +14926,8 @@ function IsometricCanvas({
14924
14926
  const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
14925
14927
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
14926
14928
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
14927
- const unitDrawH = scaledFloorHeight * 1.5 * unitScale;
14928
- const maxUnitW = scaledTileWidth * 0.6 * unitScale;
14929
+ const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
14930
+ const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
14929
14931
  const ar = img ? img.naturalWidth / img.naturalHeight : 0.5;
14930
14932
  let drawH = unitDrawH;
14931
14933
  let drawW = unitDrawH * ar;
@@ -15301,14 +15303,32 @@ var init_boardEntity = __esm({
15301
15303
  "components/game/organisms/boardEntity.ts"() {
15302
15304
  }
15303
15305
  });
15306
+ function buildDefaultBattleTiles() {
15307
+ const tiles = [];
15308
+ for (let y = 0; y < BATTLE_GRID_H; y++) {
15309
+ for (let x = 0; x < BATTLE_GRID_W; x++) {
15310
+ const variant = (x * 3 + y * 7 + (x ^ y)) % BATTLE_TERRAIN_SPRITES.length;
15311
+ tiles.push({
15312
+ x,
15313
+ y,
15314
+ terrain: ["grass", "dirt", "planks", "stone", "stone"][variant],
15315
+ terrainSprite: BATTLE_TERRAIN_SPRITES[variant],
15316
+ passable: true
15317
+ });
15318
+ }
15319
+ }
15320
+ return tiles;
15321
+ }
15304
15322
  function BattleBoard({
15305
15323
  entity,
15306
15324
  tiles: propTiles,
15307
15325
  units: propUnits,
15308
15326
  features: propFeatures,
15309
15327
  assetManifest: propAssetManifest,
15310
- scale = 0.45,
15328
+ scale = 0.25,
15311
15329
  unitScale = 1,
15330
+ spriteHeightRatio = 1.5,
15331
+ spriteMaxWidthRatio = 0.6,
15312
15332
  header,
15313
15333
  sidebar,
15314
15334
  actions,
@@ -15332,10 +15352,11 @@ function BattleBoard({
15332
15352
  className
15333
15353
  }) {
15334
15354
  const board = boardEntity(entity) ?? {};
15335
- const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
15355
+ const rawTiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
15356
+ const tiles = rawTiles.length === 0 ? DEFAULT_BATTLE_TILES : rawTiles;
15336
15357
  const features = propFeatures ?? (Array.isArray(board.features) ? board.features : []);
15337
- const boardWidth = num(board.gridWidth ?? board.boardWidth, 8);
15338
- const boardHeight = num(board.gridHeight ?? board.boardHeight, 6);
15358
+ const boardWidth = num(board.gridWidth ?? board.boardWidth, BATTLE_GRID_W);
15359
+ const boardHeight = num(board.gridHeight ?? board.boardHeight, BATTLE_GRID_H);
15339
15360
  const assetManifest = propAssetManifest ?? board.assetManifest;
15340
15361
  const backgroundImage = board.backgroundImage;
15341
15362
  const units = rows(board.units);
@@ -15599,7 +15620,9 @@ function BattleBoard({
15599
15620
  hasActiveEffects: hasActiveEffects2,
15600
15621
  effectSpriteUrls,
15601
15622
  resolveUnitFrame,
15602
- unitScale
15623
+ unitScale,
15624
+ spriteHeightRatio,
15625
+ spriteMaxWidthRatio
15603
15626
  }
15604
15627
  ),
15605
15628
  overlay && overlay(ctx)
@@ -15655,6 +15678,7 @@ function BattleBoard({
15655
15678
  ] }) }))
15656
15679
  ] });
15657
15680
  }
15681
+ var BATTLE_CDN, BATTLE_GRID_W, BATTLE_GRID_H, BATTLE_TERRAIN_SPRITES, DEFAULT_BATTLE_TILES;
15658
15682
  var init_BattleBoard = __esm({
15659
15683
  "components/game/organisms/BattleBoard.tsx"() {
15660
15684
  "use client";
@@ -15667,6 +15691,17 @@ var init_BattleBoard = __esm({
15667
15691
  init_IsometricCanvas();
15668
15692
  init_boardEntity();
15669
15693
  init_isometric();
15694
+ BATTLE_CDN = "https://almadar-kflow-assets.web.app/shared";
15695
+ BATTLE_GRID_W = 16;
15696
+ BATTLE_GRID_H = 16;
15697
+ BATTLE_TERRAIN_SPRITES = [
15698
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`,
15699
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`,
15700
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`,
15701
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`,
15702
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`
15703
+ ];
15704
+ DEFAULT_BATTLE_TILES = buildDefaultBattleTiles();
15670
15705
  BattleBoard.displayName = "BattleBoard";
15671
15706
  }
15672
15707
  });
@@ -15674,7 +15709,7 @@ function BattleTemplate({
15674
15709
  entity,
15675
15710
  scale = 0.45,
15676
15711
  unitScale = 1,
15677
- tiles = DEFAULT_BATTLE_TILES,
15712
+ tiles = DEFAULT_BATTLE_TILES2,
15678
15713
  units = DEFAULT_BATTLE_UNITS,
15679
15714
  features = DEFAULT_BATTLE_FEATURES,
15680
15715
  assetManifest = DEFAULT_BATTLE_MANIFEST,
@@ -15703,12 +15738,12 @@ function BattleTemplate({
15703
15738
  }
15704
15739
  );
15705
15740
  }
15706
- var CDN, DEFAULT_BATTLE_TILES, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
15741
+ var CDN, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
15707
15742
  var init_BattleTemplate = __esm({
15708
15743
  "components/game/templates/BattleTemplate.tsx"() {
15709
15744
  init_BattleBoard();
15710
15745
  CDN = "https://almadar-kflow-assets.web.app/shared";
15711
- DEFAULT_BATTLE_TILES = [
15746
+ DEFAULT_BATTLE_TILES2 = [
15712
15747
  { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
15713
15748
  { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
15714
15749
  { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
@@ -44332,6 +44367,7 @@ var init_GameCanvas3D2 = __esm({
44332
44367
  attackTargets = [],
44333
44368
  selectedTileIds = [],
44334
44369
  selectedUnitId = null,
44370
+ unitScale = 1,
44335
44371
  children
44336
44372
  }, ref) => {
44337
44373
  const containerRef = useRef(null);
@@ -44548,12 +44584,18 @@ var init_GameCanvas3D2 = __esm({
44548
44584
  },
44549
44585
  [selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
44550
44586
  );
44587
+ const UNIT_BASE_MODEL_SCALE = 0.5;
44588
+ const UNIT_BASE_BILLBOARD_HEIGHT = 1.2;
44589
+ const UNIT_BASE_PRIMITIVE_RADIUS = 0.3;
44551
44590
  const DefaultUnitRenderer = useCallback(
44552
44591
  ({ unit, position }) => {
44553
44592
  const isSelected = selectedUnitId === unit.id;
44554
44593
  const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
44555
44594
  const hasAtlas = unitAtlasUrl(unit) !== null;
44556
44595
  const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
44596
+ const modelScale = UNIT_BASE_MODEL_SCALE * unitScale;
44597
+ const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale;
44598
+ const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale;
44557
44599
  return /* @__PURE__ */ jsxs(
44558
44600
  "group",
44559
44601
  {
@@ -44571,7 +44613,8 @@ var init_GameCanvas3D2 = __esm({
44571
44613
  UnitSpriteBillboard,
44572
44614
  {
44573
44615
  sheetUrl: initialFrame.sheetUrl,
44574
- resolveFrame: () => resolveUnitFrame(unit.id)
44616
+ resolveFrame: () => resolveUnitFrame(unit.id),
44617
+ height: billboardHeight
44575
44618
  }
44576
44619
  ) })
44577
44620
  ) : unit.modelUrl ? (
@@ -44580,22 +44623,22 @@ var init_GameCanvas3D2 = __esm({
44580
44623
  ModelLoader,
44581
44624
  {
44582
44625
  url: unit.modelUrl,
44583
- scale: 0.5,
44626
+ scale: modelScale,
44584
44627
  fallbackGeometry: "box",
44585
44628
  castShadow: true
44586
44629
  }
44587
44630
  )
44588
44631
  ) : /* @__PURE__ */ jsxs(Fragment, { children: [
44589
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.3, 0], children: [
44590
- /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.3, 0.1, 8] }),
44632
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius, 0], children: [
44633
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [primitiveRadius, primitiveRadius, primitiveRadius * 0.33, 8] }),
44591
44634
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
44592
44635
  ] }),
44593
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.6, 0], children: [
44594
- /* @__PURE__ */ jsx("capsuleGeometry", { args: [0.2, 0.4, 4, 8] }),
44636
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius * 2, 0], children: [
44637
+ /* @__PURE__ */ jsx("capsuleGeometry", { args: [primitiveRadius * 0.67, primitiveRadius * 1.33, 4, 8] }),
44595
44638
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
44596
44639
  ] }),
44597
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.9, 0], children: [
44598
- /* @__PURE__ */ jsx("sphereGeometry", { args: [0.12, 8, 8] }),
44640
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius * 3, 0], children: [
44641
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [primitiveRadius * 0.4, 8, 8] }),
44599
44642
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
44600
44643
  ] })
44601
44644
  ] }),
@@ -44628,7 +44671,7 @@ var init_GameCanvas3D2 = __esm({
44628
44671
  }
44629
44672
  );
44630
44673
  },
44631
- [selectedUnitId, handleUnitClick, resolveUnitFrame]
44674
+ [selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale]
44632
44675
  );
44633
44676
  const DefaultFeatureRenderer = useCallback(
44634
44677
  ({
@@ -44771,33 +44814,35 @@ var init_GameCanvas3D2 = __esm({
44771
44814
  fadeStrength: 1
44772
44815
  }
44773
44816
  ),
44774
- tiles.map((tile, index) => {
44775
- const position = gridToWorld(
44776
- tile.x,
44777
- tile.z ?? tile.y ?? 0,
44778
- tile.elevation ?? 0
44779
- );
44780
- const Renderer = CustomTileRenderer || DefaultTileRenderer;
44781
- return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
44782
- }),
44783
- features.map((feature, index) => {
44784
- const position = gridToWorld(
44785
- feature.x,
44786
- feature.z ?? feature.y ?? 0,
44787
- (feature.elevation ?? 0) + 0.5
44788
- );
44789
- const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
44790
- return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
44791
- }),
44792
- units.map((unit) => {
44793
- const position = gridToWorld(
44794
- unit.x ?? 0,
44795
- unit.z ?? unit.y ?? 0,
44796
- (unit.elevation ?? 0) + 0.5
44797
- );
44798
- const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
44799
- return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
44800
- }),
44817
+ /* @__PURE__ */ jsxs("group", { children: [
44818
+ tiles.map((tile, index) => {
44819
+ const position = gridToWorld(
44820
+ tile.x,
44821
+ tile.z ?? tile.y ?? 0,
44822
+ tile.elevation ?? 0
44823
+ );
44824
+ const Renderer = CustomTileRenderer || DefaultTileRenderer;
44825
+ return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
44826
+ }),
44827
+ features.map((feature, index) => {
44828
+ const position = gridToWorld(
44829
+ feature.x,
44830
+ feature.z ?? feature.y ?? 0,
44831
+ (feature.elevation ?? 0) + 0.5
44832
+ );
44833
+ const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
44834
+ return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
44835
+ }),
44836
+ units.map((unit) => {
44837
+ const position = gridToWorld(
44838
+ unit.x ?? 0,
44839
+ unit.z ?? unit.y ?? 0,
44840
+ (unit.elevation ?? 0) + 0.5
44841
+ );
44842
+ const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
44843
+ return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
44844
+ })
44845
+ ] }),
44801
44846
  children,
44802
44847
  /* @__PURE__ */ jsx(
44803
44848
  OrbitControls,
@@ -44840,6 +44885,8 @@ function GameBoard3D({
44840
44885
  features = [],
44841
44886
  cameraMode = "perspective",
44842
44887
  backgroundColor = "#2a1a1a",
44888
+ unitScale = 1,
44889
+ scale = 0.45,
44843
44890
  tileClickEvent,
44844
44891
  unitClickEvent,
44845
44892
  attackEvent,
@@ -44940,6 +44987,8 @@ function GameBoard3D({
44940
44987
  selectedUnitId,
44941
44988
  validMoves,
44942
44989
  attackTargets,
44990
+ unitScale,
44991
+ scale,
44943
44992
  className: "game-board-3d__canvas w-full min-h-[85vh]"
44944
44993
  }
44945
44994
  ),
@@ -46908,6 +46957,35 @@ var init_PricingPageTemplate = __esm({
46908
46957
  PricingPageTemplate.displayName = "PricingPageTemplate";
46909
46958
  }
46910
46959
  });
46960
+ function dungeonTerrain(x, y, stairsX, stairsY) {
46961
+ const isBorder = x === 0 || y === 0 || x === DUNGEON_GRID_W - 1 || y === DUNGEON_GRID_H - 1;
46962
+ const isPillar = x % 4 === 0 && y % 4 === 0 && !isBorder;
46963
+ const isWall = isBorder || isPillar;
46964
+ if (x === stairsX && y === stairsY) {
46965
+ return { terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` };
46966
+ }
46967
+ if (isWall) {
46968
+ return { terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` };
46969
+ }
46970
+ const variant = (x * 3 + y * 7) % 5;
46971
+ const sprites = [
46972
+ `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`,
46973
+ `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png`,
46974
+ `${CDN4}/isometric-dungeon/Isometric/planks_E.png`,
46975
+ `${CDN4}/isometric-dungeon/Isometric/stoneTile_E.png`,
46976
+ `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`
46977
+ ];
46978
+ return { terrain: "floor", passable: true, terrainSprite: sprites[variant] };
46979
+ }
46980
+ function buildDefaultDungeonTiles(stairsX, stairsY) {
46981
+ const tiles = [];
46982
+ for (let y = 0; y < DUNGEON_GRID_H; y++) {
46983
+ for (let x = 0; x < DUNGEON_GRID_W; x++) {
46984
+ tiles.push({ x, y, ...dungeonTerrain(x, y, stairsX, stairsY) });
46985
+ }
46986
+ }
46987
+ return tiles;
46988
+ }
46911
46989
  function RoguelikeBoard({
46912
46990
  entity,
46913
46991
  tiles: propTiles,
@@ -46923,15 +47001,19 @@ function RoguelikeBoard({
46923
47001
  stairsX: propStairsX,
46924
47002
  stairsY: propStairsY,
46925
47003
  assetManifest: propAssetManifest,
46926
- scale = 0.45,
47004
+ scale = 0.25,
46927
47005
  unitScale = 1,
47006
+ spriteHeightRatio = 1.5,
47007
+ spriteMaxWidthRatio = 0.6,
46928
47008
  moveEvent,
46929
47009
  playAgainEvent,
46930
47010
  gameEndEvent,
46931
47011
  className
46932
47012
  }) {
46933
47013
  const board = boardEntity(entity) ?? {};
46934
- const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : DEFAULT_TILES2);
47014
+ const resolvedStairsX = propStairsX ?? num(board.stairsX, 14);
47015
+ const resolvedStairsY = propStairsY ?? num(board.stairsY, 14);
47016
+ const tiles = propTiles ?? (Array.isArray(board.tiles) && board.tiles.length >= DUNGEON_GRID_W * DUNGEON_GRID_H ? board.tiles : buildDefaultDungeonTiles(resolvedStairsX, resolvedStairsY));
46935
47017
  const enemies = propEnemies ?? (Array.isArray(board.enemies) ? board.enemies : DEFAULT_ENEMIES);
46936
47018
  const items = propItems ?? (Array.isArray(board.items) ? board.items : DEFAULT_ITEMS);
46937
47019
  const player = propPlayer ?? board.player ?? { x: 1, y: 1 };
@@ -46941,8 +47023,8 @@ function RoguelikeBoard({
46941
47023
  const depth = propDepth ?? num(board.depth, 1);
46942
47024
  const result = propResult ?? (str(board.result) || "none");
46943
47025
  const phase = propPhase ?? (str(board.phase) || "player_turn");
46944
- propStairsX ?? num(board.stairsX, 3);
46945
- propStairsY ?? num(board.stairsY, 3);
47026
+ propStairsX ?? num(board.stairsX, 14);
47027
+ propStairsY ?? num(board.stairsY, 14);
46946
47028
  const eventBus = useEventBus();
46947
47029
  const { t } = useTranslate();
46948
47030
  const [hoveredTile, setHoveredTile] = useState(null);
@@ -47072,7 +47154,9 @@ function RoguelikeBoard({
47072
47154
  scale,
47073
47155
  assetBaseUrl: propAssetManifest?.baseUrl ?? CDN4,
47074
47156
  assetManifest: propAssetManifest,
47075
- unitScale
47157
+ unitScale,
47158
+ spriteHeightRatio,
47159
+ spriteMaxWidthRatio
47076
47160
  }
47077
47161
  ) }),
47078
47162
  !isGameOver && /* @__PURE__ */ jsx(HStack, { className: "justify-center gap-2 p-3", gap: "none", children: [
@@ -47116,7 +47200,7 @@ function RoguelikeBoard({
47116
47200
  ] }) })
47117
47201
  ] });
47118
47202
  }
47119
- var CDN4, DEFAULT_TILES2, DEFAULT_ENEMIES, DEFAULT_ITEMS, FEATURE_SPRITE;
47203
+ var CDN4, DUNGEON_GRID_W, DUNGEON_GRID_H, DEFAULT_ENEMIES, DEFAULT_ITEMS, FEATURE_SPRITE;
47120
47204
  var init_RoguelikeBoard = __esm({
47121
47205
  "components/game/organisms/RoguelikeBoard.tsx"() {
47122
47206
  "use client";
@@ -47129,39 +47213,19 @@ var init_RoguelikeBoard = __esm({
47129
47213
  init_IsometricCanvas();
47130
47214
  init_boardEntity();
47131
47215
  CDN4 = "https://almadar-kflow-assets.web.app/shared";
47132
- DEFAULT_TILES2 = [
47133
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47134
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47135
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47136
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47137
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47138
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47139
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47140
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47141
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47142
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47143
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47144
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47145
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47146
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47147
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47148
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47149
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47150
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47151
- { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` },
47152
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47153
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47154
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47155
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47156
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47157
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` }
47158
- ];
47216
+ DUNGEON_GRID_W = 16;
47217
+ DUNGEON_GRID_H = 16;
47218
+ buildDefaultDungeonTiles(14, 14);
47159
47219
  DEFAULT_ENEMIES = [
47160
- { id: "e1", x: 3, y: 1, hp: 5, attack: 2 },
47161
- { id: "e2", x: 1, y: 3, hp: 4, attack: 1 }
47220
+ { id: "e1", x: 5, y: 2, hp: 5, attack: 2 },
47221
+ { id: "e2", x: 9, y: 6, hp: 4, attack: 1 },
47222
+ { id: "e3", x: 3, y: 10, hp: 6, attack: 2 },
47223
+ { id: "e4", x: 12, y: 8, hp: 5, attack: 3 }
47162
47224
  ];
47163
47225
  DEFAULT_ITEMS = [
47164
- { id: "i1", x: 2, y: 2, kind: "health_potion" }
47226
+ { id: "i1", x: 3, y: 3, kind: "health_potion" },
47227
+ { id: "i2", x: 7, y: 9, kind: "sword" },
47228
+ { id: "i3", x: 11, y: 5, kind: "shield" }
47165
47229
  ];
47166
47230
  FEATURE_SPRITE = {
47167
47231
  health_potion: `${CDN4}/isometric-dungeon/Isometric/chestClosed_E.png`,
@@ -51388,6 +51452,22 @@ var init_ToastSlot = __esm({
51388
51452
  ToastSlot.displayName = "ToastSlot";
51389
51453
  }
51390
51454
  });
51455
+ function buildDefaultTDTiles() {
51456
+ const pathSet = new Set(DEFAULT_TD_PATH.map((p2) => `${p2.x},${p2.y}`));
51457
+ const tiles = [];
51458
+ for (let y = 0; y < TD_GRID_H; y++) {
51459
+ for (let x = 0; x < TD_GRID_W; x++) {
51460
+ if (pathSet.has(`${x},${y}`)) {
51461
+ tiles.push({ x, y, terrain: "path", passable: false, terrainSprite: TERRAIN_SPRITES.path });
51462
+ } else {
51463
+ const variant = (x * 3 + y * 5 + (x ^ y)) % 3;
51464
+ const terrainKey = ["ground", "grass", "dirt"][variant];
51465
+ tiles.push({ x, y, terrain: terrainKey, passable: true, terrainSprite: TERRAIN_SPRITES[terrainKey] ?? TERRAIN_SPRITES.ground });
51466
+ }
51467
+ }
51468
+ }
51469
+ return tiles;
51470
+ }
51391
51471
  function tilesToIso(tiles) {
51392
51472
  return tiles.map((t) => ({
51393
51473
  x: t.x,
@@ -51443,7 +51523,10 @@ function TowerDefenseBoard({
51443
51523
  result: propResult,
51444
51524
  waveActive: propWaveActive,
51445
51525
  towerCost = 25,
51446
- scale = 0.45,
51526
+ scale = 0.25,
51527
+ unitScale = 1,
51528
+ spriteHeightRatio = 1.5,
51529
+ spriteMaxWidthRatio = 0.6,
51447
51530
  placeTowerEvent,
51448
51531
  startWaveEvent,
51449
51532
  playAgainEvent,
@@ -51453,8 +51536,10 @@ function TowerDefenseBoard({
51453
51536
  const board = boardEntity(entity) ?? {};
51454
51537
  const eventBus = useEventBus();
51455
51538
  const { t } = useTranslate();
51456
- const tiles = propTiles ?? rows(board.tiles);
51457
- const path = propPath ?? rows(board.path);
51539
+ const rawTiles = propTiles ?? rows(board.tiles);
51540
+ const tiles = rawTiles.length >= TD_GRID_W * TD_GRID_H ? rawTiles : DEFAULT_TD_TILES;
51541
+ const rawPath = propPath ?? rows(board.path);
51542
+ const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
51458
51543
  const towers = propTowers ?? rows(board.towers);
51459
51544
  const creeps = propCreeps ?? rows(board.creeps);
51460
51545
  const gold = propGold ?? num(board.gold, 100);
@@ -51551,7 +51636,10 @@ function TowerDefenseBoard({
51551
51636
  onTileClick: handleTileClick,
51552
51637
  onTileHover: (x, y) => setHoveredTile({ x, y }),
51553
51638
  onTileLeave: () => setHoveredTile(null),
51554
- scale
51639
+ scale,
51640
+ unitScale,
51641
+ spriteHeightRatio,
51642
+ spriteMaxWidthRatio
51555
51643
  }
51556
51644
  ),
51557
51645
  hoveredTile && canPlaceTower && validMoves.some((m) => m.x === hoveredTile.x && m.y === hoveredTile.y) && /* @__PURE__ */ jsx(Box, { className: "absolute bottom-4 left-1/2 -translate-x-1/2 z-10 bg-background/80 rounded px-3 py-1 backdrop-blur-sm pointer-events-none", children: /* @__PURE__ */ jsx(Typography, { variant: "small", children: t("td.placeTower") ?? `Place tower (${towerCost} gold)` }) })
@@ -51581,7 +51669,7 @@ function TowerDefenseBoard({
51581
51669
  ] }) })
51582
51670
  ] });
51583
51671
  }
51584
- var CDN6, TERRAIN_SPRITES, TOWER_SPRITE, CREEP_SPRITE;
51672
+ var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE;
51585
51673
  var init_TowerDefenseBoard = __esm({
51586
51674
  "components/game/organisms/TowerDefenseBoard.tsx"() {
51587
51675
  "use client";
@@ -51594,11 +51682,67 @@ var init_TowerDefenseBoard = __esm({
51594
51682
  init_IsometricCanvas();
51595
51683
  init_boardEntity();
51596
51684
  CDN6 = "https://almadar-kflow-assets.web.app/shared/";
51685
+ TD_GRID_W = 16;
51686
+ TD_GRID_H = 16;
51597
51687
  TERRAIN_SPRITES = {
51598
51688
  ground: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`,
51599
51689
  path: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_09.png`,
51600
- wall: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`
51601
- };
51690
+ wall: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`,
51691
+ grass: `${CDN6}isometric-dungeon/Isometric/dirt_E.png`,
51692
+ dirt: `${CDN6}isometric-dungeon/Isometric/dirtTiles_E.png`
51693
+ };
51694
+ DEFAULT_TD_PATH = [
51695
+ { x: 2, y: 0 },
51696
+ { x: 2, y: 1 },
51697
+ { x: 2, y: 2 },
51698
+ { x: 2, y: 3 },
51699
+ { x: 3, y: 3 },
51700
+ { x: 4, y: 3 },
51701
+ { x: 5, y: 3 },
51702
+ { x: 6, y: 3 },
51703
+ { x: 7, y: 3 },
51704
+ { x: 8, y: 3 },
51705
+ { x: 9, y: 3 },
51706
+ { x: 10, y: 3 },
51707
+ { x: 11, y: 3 },
51708
+ { x: 12, y: 3 },
51709
+ { x: 13, y: 3 },
51710
+ { x: 13, y: 4 },
51711
+ { x: 13, y: 5 },
51712
+ { x: 13, y: 6 },
51713
+ { x: 13, y: 7 },
51714
+ { x: 12, y: 7 },
51715
+ { x: 11, y: 7 },
51716
+ { x: 10, y: 7 },
51717
+ { x: 9, y: 7 },
51718
+ { x: 8, y: 7 },
51719
+ { x: 7, y: 7 },
51720
+ { x: 6, y: 7 },
51721
+ { x: 5, y: 7 },
51722
+ { x: 4, y: 7 },
51723
+ { x: 3, y: 7 },
51724
+ { x: 2, y: 7 },
51725
+ { x: 2, y: 8 },
51726
+ { x: 2, y: 9 },
51727
+ { x: 2, y: 10 },
51728
+ { x: 2, y: 11 },
51729
+ { x: 3, y: 11 },
51730
+ { x: 4, y: 11 },
51731
+ { x: 5, y: 11 },
51732
+ { x: 6, y: 11 },
51733
+ { x: 7, y: 11 },
51734
+ { x: 8, y: 11 },
51735
+ { x: 9, y: 11 },
51736
+ { x: 10, y: 11 },
51737
+ { x: 11, y: 11 },
51738
+ { x: 12, y: 11 },
51739
+ { x: 13, y: 11 },
51740
+ { x: 13, y: 12 },
51741
+ { x: 13, y: 13 },
51742
+ { x: 13, y: 14 },
51743
+ { x: 13, y: 15 }
51744
+ ];
51745
+ DEFAULT_TD_TILES = buildDefaultTDTiles();
51602
51746
  TOWER_SPRITE = `${CDN6}units/guardian.png`;
51603
51747
  CREEP_SPRITE = `${CDN6}units/scrapper.png`;
51604
51748
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
@@ -51875,6 +52019,17 @@ function heroPosition(h) {
51875
52019
  function heroMovement(h) {
51876
52020
  return num(h.movement);
51877
52021
  }
52022
+ function buildDefaultWorldTiles() {
52023
+ const tiles = [];
52024
+ for (let y = 0; y < WORLD_GRID_H; y++) {
52025
+ for (let x = 0; x < WORLD_GRID_W; x++) {
52026
+ const isBorder = x === 0 || y === 0 || x === WORLD_GRID_W - 1 || y === WORLD_GRID_H - 1;
52027
+ const def = isBorder ? WORLD_TERRAIN_DEFS[3] : WORLD_TERRAIN_DEFS[(x * 5 + y * 3 + (x ^ y)) % (WORLD_TERRAIN_DEFS.length - 1)];
52028
+ tiles.push({ x, y, terrain: def.terrain, terrainSprite: def.sprite, passable: def.passable });
52029
+ }
52030
+ }
52031
+ return tiles;
52032
+ }
51878
52033
  function defaultIsInRange(from, to, range) {
51879
52034
  return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
51880
52035
  }
@@ -51885,8 +52040,10 @@ function WorldMapBoard({
51885
52040
  features: propFeatures,
51886
52041
  assetManifest: propAssetManifest,
51887
52042
  isLoading,
51888
- scale = 0.4,
52043
+ scale = 0.25,
51889
52044
  unitScale = 2.5,
52045
+ spriteHeightRatio = 1.5,
52046
+ spriteMaxWidthRatio = 0.6,
51890
52047
  allowMoveAllHeroes = false,
51891
52048
  isInRange = defaultIsInRange,
51892
52049
  heroSelectEvent,
@@ -51927,7 +52084,8 @@ function WorldMapBoard({
51927
52084
  })),
51928
52085
  [entityTiles]
51929
52086
  );
51930
- const tiles = propTiles ?? derivedTiles;
52087
+ const rawTiles = propTiles ?? (derivedTiles.length > 0 ? derivedTiles : null);
52088
+ const tiles = rawTiles != null && rawTiles.length >= WORLD_GRID_W * WORLD_GRID_H ? rawTiles : DEFAULT_WORLD_TILES;
51931
52089
  const baseUnits = useMemo(
51932
52090
  () => propUnits ?? entityUnits.map((u) => ({
51933
52091
  id: str(u.id),
@@ -52124,6 +52282,8 @@ function WorldMapBoard({
52124
52282
  effectSpriteUrls,
52125
52283
  resolveUnitFrame,
52126
52284
  unitScale,
52285
+ spriteHeightRatio,
52286
+ spriteMaxWidthRatio,
52127
52287
  diamondTopY,
52128
52288
  enableCamera
52129
52289
  }
@@ -52135,6 +52295,7 @@ function WorldMapBoard({
52135
52295
  footer && footer(ctx)
52136
52296
  ] });
52137
52297
  }
52298
+ var WORLD_CDN, WORLD_GRID_W, WORLD_GRID_H, WORLD_TERRAIN_DEFS, DEFAULT_WORLD_TILES;
52138
52299
  var init_WorldMapBoard = __esm({
52139
52300
  "components/game/organisms/WorldMapBoard.tsx"() {
52140
52301
  "use client";
@@ -52145,6 +52306,17 @@ var init_WorldMapBoard = __esm({
52145
52306
  init_IsometricCanvas();
52146
52307
  init_boardEntity();
52147
52308
  init_isometric();
52309
+ WORLD_CDN = "https://almadar-kflow-assets.web.app/shared";
52310
+ WORLD_GRID_W = 16;
52311
+ WORLD_GRID_H = 16;
52312
+ WORLD_TERRAIN_DEFS = [
52313
+ { terrain: "grass", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/dirt_E.png`, passable: true },
52314
+ { terrain: "dirt", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`, passable: true },
52315
+ { terrain: "forest", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/planks_E.png`, passable: true },
52316
+ { terrain: "stone", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`, passable: false },
52317
+ { terrain: "castle", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`, passable: true }
52318
+ ];
52319
+ DEFAULT_WORLD_TILES = buildDefaultWorldTiles();
52148
52320
  WorldMapBoard.displayName = "WorldMapBoard";
52149
52321
  }
52150
52322
  });
@@ -57810,7 +57982,10 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57810
57982
  if (binding.config) {
57811
57983
  guardCtx.config = binding.config;
57812
57984
  }
57813
- const passed = interpolateValue(tick.guard, createContextFromBindings(guardCtx));
57985
+ const passed = evaluateGuard(
57986
+ tick.guard,
57987
+ createContextFromBindings(guardCtx)
57988
+ );
57814
57989
  if (!passed) {
57815
57990
  tickLog.debug("guard-blocked", { traitName, tick: tick.name, state: currentState });
57816
57991
  return;