@almadar/ui 5.56.0 → 5.58.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.
@@ -11913,13 +11913,29 @@ var init_boardEntity = __esm({
11913
11913
  "components/game/organisms/boardEntity.ts"() {
11914
11914
  }
11915
11915
  });
11916
+ function buildDefaultBattleTiles() {
11917
+ const tiles = [];
11918
+ for (let y = 0; y < BATTLE_GRID_H; y++) {
11919
+ for (let x = 0; x < BATTLE_GRID_W; x++) {
11920
+ const variant = (x * 3 + y * 7 + (x ^ y)) % BATTLE_TERRAIN_SPRITES.length;
11921
+ tiles.push({
11922
+ x,
11923
+ y,
11924
+ terrain: ["grass", "dirt", "planks", "stone", "stone"][variant],
11925
+ terrainSprite: BATTLE_TERRAIN_SPRITES[variant],
11926
+ passable: true
11927
+ });
11928
+ }
11929
+ }
11930
+ return tiles;
11931
+ }
11916
11932
  function BattleBoard({
11917
11933
  entity,
11918
11934
  tiles: propTiles,
11919
11935
  units: propUnits,
11920
11936
  features: propFeatures,
11921
11937
  assetManifest: propAssetManifest,
11922
- scale = 0.45,
11938
+ scale = 0.25,
11923
11939
  unitScale = 1,
11924
11940
  spriteHeightRatio = 1.5,
11925
11941
  spriteMaxWidthRatio = 0.6,
@@ -11946,10 +11962,11 @@ function BattleBoard({
11946
11962
  className
11947
11963
  }) {
11948
11964
  const board = boardEntity(entity) ?? {};
11949
- const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
11965
+ const rawTiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
11966
+ const tiles = rawTiles.length === 0 ? DEFAULT_BATTLE_TILES : rawTiles;
11950
11967
  const features = propFeatures ?? (Array.isArray(board.features) ? board.features : []);
11951
- const boardWidth = num(board.gridWidth ?? board.boardWidth, 8);
11952
- const boardHeight = num(board.gridHeight ?? board.boardHeight, 6);
11968
+ const boardWidth = num(board.gridWidth ?? board.boardWidth, BATTLE_GRID_W);
11969
+ const boardHeight = num(board.gridHeight ?? board.boardHeight, BATTLE_GRID_H);
11953
11970
  const assetManifest = propAssetManifest ?? board.assetManifest;
11954
11971
  const backgroundImage = board.backgroundImage;
11955
11972
  const units = rows(board.units);
@@ -12271,6 +12288,7 @@ function BattleBoard({
12271
12288
  ] }) }))
12272
12289
  ] });
12273
12290
  }
12291
+ var BATTLE_CDN, BATTLE_GRID_W, BATTLE_GRID_H, BATTLE_TERRAIN_SPRITES, DEFAULT_BATTLE_TILES;
12274
12292
  var init_BattleBoard = __esm({
12275
12293
  "components/game/organisms/BattleBoard.tsx"() {
12276
12294
  "use client";
@@ -12283,6 +12301,17 @@ var init_BattleBoard = __esm({
12283
12301
  init_IsometricCanvas();
12284
12302
  init_boardEntity();
12285
12303
  init_isometric();
12304
+ BATTLE_CDN = "https://almadar-kflow-assets.web.app/shared";
12305
+ BATTLE_GRID_W = 16;
12306
+ BATTLE_GRID_H = 16;
12307
+ BATTLE_TERRAIN_SPRITES = [
12308
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`,
12309
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`,
12310
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`,
12311
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`,
12312
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`
12313
+ ];
12314
+ DEFAULT_BATTLE_TILES = buildDefaultBattleTiles();
12286
12315
  BattleBoard.displayName = "BattleBoard";
12287
12316
  }
12288
12317
  });
@@ -12290,7 +12319,7 @@ function BattleTemplate({
12290
12319
  entity,
12291
12320
  scale = 0.45,
12292
12321
  unitScale = 1,
12293
- tiles = DEFAULT_BATTLE_TILES,
12322
+ tiles = DEFAULT_BATTLE_TILES2,
12294
12323
  units = DEFAULT_BATTLE_UNITS,
12295
12324
  features = DEFAULT_BATTLE_FEATURES,
12296
12325
  assetManifest = DEFAULT_BATTLE_MANIFEST,
@@ -12319,12 +12348,12 @@ function BattleTemplate({
12319
12348
  }
12320
12349
  );
12321
12350
  }
12322
- var CDN, DEFAULT_BATTLE_TILES, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12351
+ var CDN, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12323
12352
  var init_BattleTemplate = __esm({
12324
12353
  "components/game/templates/BattleTemplate.tsx"() {
12325
12354
  init_BattleBoard();
12326
12355
  CDN = "https://almadar-kflow-assets.web.app/shared";
12327
- DEFAULT_BATTLE_TILES = [
12356
+ DEFAULT_BATTLE_TILES2 = [
12328
12357
  { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12329
12358
  { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12330
12359
  { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
@@ -29493,13 +29522,13 @@ var init_MapView = __esm({
29493
29522
  shadowSize: [41, 41]
29494
29523
  });
29495
29524
  L.Marker.prototype.options.icon = defaultIcon;
29496
- const { useEffect: useEffect79, useRef: useRef75, useCallback: useCallback118, useState: useState109 } = React82__namespace.default;
29525
+ const { useEffect: useEffect80, useRef: useRef75, useCallback: useCallback118, useState: useState109 } = React82__namespace.default;
29497
29526
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29498
29527
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29499
29528
  function MapUpdater({ centerLat, centerLng, zoom }) {
29500
29529
  const map = useMap();
29501
29530
  const prevRef = useRef75({ centerLat, centerLng, zoom });
29502
- useEffect79(() => {
29531
+ useEffect80(() => {
29503
29532
  const prev = prevRef.current;
29504
29533
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
29505
29534
  map.setView([centerLat, centerLng], zoom);
@@ -29510,7 +29539,7 @@ var init_MapView = __esm({
29510
29539
  }
29511
29540
  function MapClickHandler({ onMapClick }) {
29512
29541
  const map = useMap();
29513
- useEffect79(() => {
29542
+ useEffect80(() => {
29514
29543
  if (!onMapClick) return;
29515
29544
  const handler = (e) => {
29516
29545
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -42187,7 +42216,6 @@ var init_GameCanvas3D2 = __esm({
42187
42216
  selectedTileIds = [],
42188
42217
  selectedUnitId = null,
42189
42218
  unitScale = 1,
42190
- scale = 0.45,
42191
42219
  children
42192
42220
  }, ref) => {
42193
42221
  const containerRef = React82.useRef(null);
@@ -42634,7 +42662,7 @@ var init_GameCanvas3D2 = __esm({
42634
42662
  fadeStrength: 1
42635
42663
  }
42636
42664
  ),
42637
- /* @__PURE__ */ jsxRuntime.jsxs("group", { scale, children: [
42665
+ /* @__PURE__ */ jsxRuntime.jsxs("group", { children: [
42638
42666
  tiles.map((tile, index) => {
42639
42667
  const position = gridToWorld(
42640
42668
  tile.x,
@@ -44777,6 +44805,35 @@ var init_PricingPageTemplate = __esm({
44777
44805
  PricingPageTemplate.displayName = "PricingPageTemplate";
44778
44806
  }
44779
44807
  });
44808
+ function dungeonTerrain(x, y, stairsX, stairsY) {
44809
+ const isBorder = x === 0 || y === 0 || x === DUNGEON_GRID_W - 1 || y === DUNGEON_GRID_H - 1;
44810
+ const isPillar = x % 4 === 0 && y % 4 === 0 && !isBorder;
44811
+ const isWall = isBorder || isPillar;
44812
+ if (x === stairsX && y === stairsY) {
44813
+ return { terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` };
44814
+ }
44815
+ if (isWall) {
44816
+ return { terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` };
44817
+ }
44818
+ const variant = (x * 3 + y * 7) % 5;
44819
+ const sprites = [
44820
+ `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`,
44821
+ `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png`,
44822
+ `${CDN4}/isometric-dungeon/Isometric/planks_E.png`,
44823
+ `${CDN4}/isometric-dungeon/Isometric/stoneTile_E.png`,
44824
+ `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`
44825
+ ];
44826
+ return { terrain: "floor", passable: true, terrainSprite: sprites[variant] };
44827
+ }
44828
+ function buildDefaultDungeonTiles(stairsX, stairsY) {
44829
+ const tiles = [];
44830
+ for (let y = 0; y < DUNGEON_GRID_H; y++) {
44831
+ for (let x = 0; x < DUNGEON_GRID_W; x++) {
44832
+ tiles.push({ x, y, ...dungeonTerrain(x, y, stairsX, stairsY) });
44833
+ }
44834
+ }
44835
+ return tiles;
44836
+ }
44780
44837
  function RoguelikeBoard({
44781
44838
  entity,
44782
44839
  tiles: propTiles,
@@ -44792,7 +44849,7 @@ function RoguelikeBoard({
44792
44849
  stairsX: propStairsX,
44793
44850
  stairsY: propStairsY,
44794
44851
  assetManifest: propAssetManifest,
44795
- scale = 0.45,
44852
+ scale = 0.25,
44796
44853
  unitScale = 1,
44797
44854
  spriteHeightRatio = 1.5,
44798
44855
  spriteMaxWidthRatio = 0.6,
@@ -44802,7 +44859,9 @@ function RoguelikeBoard({
44802
44859
  className
44803
44860
  }) {
44804
44861
  const board = boardEntity(entity) ?? {};
44805
- const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : DEFAULT_TILES2);
44862
+ const resolvedStairsX = propStairsX ?? num(board.stairsX, 14);
44863
+ const resolvedStairsY = propStairsY ?? num(board.stairsY, 14);
44864
+ const tiles = propTiles ?? (Array.isArray(board.tiles) && board.tiles.length >= DUNGEON_GRID_W * DUNGEON_GRID_H ? board.tiles : buildDefaultDungeonTiles(resolvedStairsX, resolvedStairsY));
44806
44865
  const enemies = propEnemies ?? (Array.isArray(board.enemies) ? board.enemies : DEFAULT_ENEMIES);
44807
44866
  const items = propItems ?? (Array.isArray(board.items) ? board.items : DEFAULT_ITEMS);
44808
44867
  const player = propPlayer ?? board.player ?? { x: 1, y: 1 };
@@ -44812,8 +44871,8 @@ function RoguelikeBoard({
44812
44871
  const depth = propDepth ?? num(board.depth, 1);
44813
44872
  const result = propResult ?? (str(board.result) || "none");
44814
44873
  const phase = propPhase ?? (str(board.phase) || "player_turn");
44815
- propStairsX ?? num(board.stairsX, 3);
44816
- propStairsY ?? num(board.stairsY, 3);
44874
+ propStairsX ?? num(board.stairsX, 14);
44875
+ propStairsY ?? num(board.stairsY, 14);
44817
44876
  const eventBus = useEventBus();
44818
44877
  const { t } = hooks.useTranslate();
44819
44878
  const [hoveredTile, setHoveredTile] = React82.useState(null);
@@ -44989,7 +45048,7 @@ function RoguelikeBoard({
44989
45048
  ] }) })
44990
45049
  ] });
44991
45050
  }
44992
- var CDN4, DEFAULT_TILES2, DEFAULT_ENEMIES, DEFAULT_ITEMS, FEATURE_SPRITE;
45051
+ var CDN4, DUNGEON_GRID_W, DUNGEON_GRID_H, DEFAULT_ENEMIES, DEFAULT_ITEMS, FEATURE_SPRITE;
44993
45052
  var init_RoguelikeBoard = __esm({
44994
45053
  "components/game/organisms/RoguelikeBoard.tsx"() {
44995
45054
  "use client";
@@ -45002,39 +45061,19 @@ var init_RoguelikeBoard = __esm({
45002
45061
  init_IsometricCanvas();
45003
45062
  init_boardEntity();
45004
45063
  CDN4 = "https://almadar-kflow-assets.web.app/shared";
45005
- DEFAULT_TILES2 = [
45006
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45007
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45008
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45009
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45010
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45011
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45012
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
45013
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
45014
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
45015
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45016
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45017
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
45018
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
45019
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
45020
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45021
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45022
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
45023
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
45024
- { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` },
45025
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45026
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45027
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45028
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45029
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
45030
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` }
45031
- ];
45064
+ DUNGEON_GRID_W = 16;
45065
+ DUNGEON_GRID_H = 16;
45066
+ buildDefaultDungeonTiles(14, 14);
45032
45067
  DEFAULT_ENEMIES = [
45033
- { id: "e1", x: 3, y: 1, hp: 5, attack: 2 },
45034
- { id: "e2", x: 1, y: 3, hp: 4, attack: 1 }
45068
+ { id: "e1", x: 5, y: 2, hp: 5, attack: 2 },
45069
+ { id: "e2", x: 9, y: 6, hp: 4, attack: 1 },
45070
+ { id: "e3", x: 3, y: 10, hp: 6, attack: 2 },
45071
+ { id: "e4", x: 12, y: 8, hp: 5, attack: 3 }
45035
45072
  ];
45036
45073
  DEFAULT_ITEMS = [
45037
- { id: "i1", x: 2, y: 2, kind: "health_potion" }
45074
+ { id: "i1", x: 3, y: 3, kind: "health_potion" },
45075
+ { id: "i2", x: 7, y: 9, kind: "sword" },
45076
+ { id: "i3", x: 11, y: 5, kind: "shield" }
45038
45077
  ];
45039
45078
  FEATURE_SPRITE = {
45040
45079
  health_potion: `${CDN4}/isometric-dungeon/Isometric/chestClosed_E.png`,
@@ -49242,6 +49281,22 @@ var init_ToastSlot = __esm({
49242
49281
  ToastSlot.displayName = "ToastSlot";
49243
49282
  }
49244
49283
  });
49284
+ function buildDefaultTDTiles() {
49285
+ const pathSet = new Set(DEFAULT_TD_PATH.map((p2) => `${p2.x},${p2.y}`));
49286
+ const tiles = [];
49287
+ for (let y = 0; y < TD_GRID_H; y++) {
49288
+ for (let x = 0; x < TD_GRID_W; x++) {
49289
+ if (pathSet.has(`${x},${y}`)) {
49290
+ tiles.push({ x, y, terrain: "path", passable: false, terrainSprite: TERRAIN_SPRITES.path });
49291
+ } else {
49292
+ const variant = (x * 3 + y * 5 + (x ^ y)) % 3;
49293
+ const terrainKey = ["ground", "grass", "dirt"][variant];
49294
+ tiles.push({ x, y, terrain: terrainKey, passable: true, terrainSprite: TERRAIN_SPRITES[terrainKey] ?? TERRAIN_SPRITES.ground });
49295
+ }
49296
+ }
49297
+ }
49298
+ return tiles;
49299
+ }
49245
49300
  function tilesToIso(tiles) {
49246
49301
  return tiles.map((t) => ({
49247
49302
  x: t.x,
@@ -49284,12 +49339,25 @@ function pathToFeatures(path) {
49284
49339
  sprite: `${CDN6}world-map/road_straight.png`
49285
49340
  }));
49286
49341
  }
49342
+ function heroToUnit(hero) {
49343
+ return {
49344
+ id: hero.id,
49345
+ position: { x: hero.x, y: hero.y },
49346
+ name: "Hero",
49347
+ team: "player",
49348
+ sprite: HERO_SPRITE,
49349
+ unitType: "amir",
49350
+ health: 1,
49351
+ maxHealth: 1
49352
+ };
49353
+ }
49287
49354
  function TowerDefenseBoard({
49288
49355
  entity,
49289
49356
  tiles: propTiles,
49290
49357
  path: propPath,
49291
49358
  towers: propTowers,
49292
49359
  creeps: propCreeps,
49360
+ hero: propHero,
49293
49361
  gold: propGold,
49294
49362
  lives: propLives,
49295
49363
  wave: propWave,
@@ -49297,7 +49365,7 @@ function TowerDefenseBoard({
49297
49365
  result: propResult,
49298
49366
  waveActive: propWaveActive,
49299
49367
  towerCost = 25,
49300
- scale = 0.45,
49368
+ scale = 0.25,
49301
49369
  unitScale = 1,
49302
49370
  spriteHeightRatio = 1.5,
49303
49371
  spriteMaxWidthRatio = 0.6,
@@ -49305,15 +49373,19 @@ function TowerDefenseBoard({
49305
49373
  startWaveEvent,
49306
49374
  playAgainEvent,
49307
49375
  gameEndEvent,
49376
+ moveHeroEvent,
49308
49377
  className
49309
49378
  }) {
49310
49379
  const board = boardEntity(entity) ?? {};
49311
49380
  const eventBus = useEventBus();
49312
49381
  const { t } = hooks.useTranslate();
49313
- const tiles = propTiles ?? rows(board.tiles);
49314
- const path = propPath ?? rows(board.path);
49382
+ const rawTiles = propTiles ?? rows(board.tiles);
49383
+ const tiles = rawTiles.length >= TD_GRID_W * TD_GRID_H ? rawTiles : DEFAULT_TD_TILES;
49384
+ const rawPath = propPath ?? rows(board.path);
49385
+ const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
49315
49386
  const towers = propTowers ?? rows(board.towers);
49316
49387
  const creeps = propCreeps ?? rows(board.creeps);
49388
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
49317
49389
  const gold = propGold ?? num(board.gold, 100);
49318
49390
  const lives = propLives ?? num(board.lives, 20);
49319
49391
  const wave = propWave ?? num(board.wave, 1);
@@ -49331,6 +49403,31 @@ function TowerDefenseBoard({
49331
49403
  if (result === "none") {
49332
49404
  emittedGameEnd.current = false;
49333
49405
  }
49406
+ const moveHeroEventRef = React82.useRef(moveHeroEvent);
49407
+ moveHeroEventRef.current = moveHeroEvent;
49408
+ const resultRef = React82.useRef(result);
49409
+ resultRef.current = result;
49410
+ React82.useEffect(() => {
49411
+ function onKeyDown(e) {
49412
+ const evt = moveHeroEventRef.current;
49413
+ if (!evt || resultRef.current !== "none") return;
49414
+ let dx = 0;
49415
+ let dy = 0;
49416
+ if (e.key === "ArrowUp") {
49417
+ dy = -1;
49418
+ } else if (e.key === "ArrowDown") {
49419
+ dy = 1;
49420
+ } else if (e.key === "ArrowLeft") {
49421
+ dx = -1;
49422
+ } else if (e.key === "ArrowRight") {
49423
+ dx = 1;
49424
+ } else return;
49425
+ e.preventDefault();
49426
+ eventBus.emit(`UI:${evt}`, { dx, dy });
49427
+ }
49428
+ window.addEventListener("keydown", onKeyDown);
49429
+ return () => window.removeEventListener("keydown", onKeyDown);
49430
+ }, [eventBus]);
49334
49431
  const towerPositions = React82.useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
49335
49432
  const pathPositions = React82.useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
49336
49433
  const validMoves = React82.useMemo(() => {
@@ -49342,7 +49439,8 @@ function TowerDefenseBoard({
49342
49439
  const isoTiles = React82.useMemo(() => tilesToIso(tiles), [tiles]);
49343
49440
  const towerUnits = React82.useMemo(() => towersToUnits(towers), [towers]);
49344
49441
  const creepUnits = React82.useMemo(() => creepsToUnits(creeps), [creeps]);
49345
- const isoUnits = React82.useMemo(() => [...towerUnits, ...creepUnits], [towerUnits, creepUnits]);
49442
+ const heroUnit = React82.useMemo(() => heroToUnit(hero), [hero]);
49443
+ const isoUnits = React82.useMemo(() => [...towerUnits, ...creepUnits, heroUnit], [towerUnits, creepUnits, heroUnit]);
49346
49444
  const pathFeatures = React82.useMemo(() => pathToFeatures(path), [path]);
49347
49445
  const handleTileClick = React82.useCallback((x, y) => {
49348
49446
  if (result !== "none") return;
@@ -49441,7 +49539,7 @@ function TowerDefenseBoard({
49441
49539
  ] }) })
49442
49540
  ] });
49443
49541
  }
49444
- var CDN6, TERRAIN_SPRITES, TOWER_SPRITE, CREEP_SPRITE;
49542
+ var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE, HERO_SPRITE;
49445
49543
  var init_TowerDefenseBoard = __esm({
49446
49544
  "components/game/organisms/TowerDefenseBoard.tsx"() {
49447
49545
  "use client";
@@ -49454,13 +49552,70 @@ var init_TowerDefenseBoard = __esm({
49454
49552
  init_IsometricCanvas();
49455
49553
  init_boardEntity();
49456
49554
  CDN6 = "https://almadar-kflow-assets.web.app/shared/";
49555
+ TD_GRID_W = 16;
49556
+ TD_GRID_H = 16;
49457
49557
  TERRAIN_SPRITES = {
49458
49558
  ground: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`,
49459
49559
  path: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_09.png`,
49460
- wall: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`
49461
- };
49462
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
49463
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
49560
+ wall: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`,
49561
+ grass: `${CDN6}isometric-dungeon/Isometric/dirt_E.png`,
49562
+ dirt: `${CDN6}isometric-dungeon/Isometric/dirtTiles_E.png`
49563
+ };
49564
+ DEFAULT_TD_PATH = [
49565
+ { x: 2, y: 0 },
49566
+ { x: 2, y: 1 },
49567
+ { x: 2, y: 2 },
49568
+ { x: 2, y: 3 },
49569
+ { x: 3, y: 3 },
49570
+ { x: 4, y: 3 },
49571
+ { x: 5, y: 3 },
49572
+ { x: 6, y: 3 },
49573
+ { x: 7, y: 3 },
49574
+ { x: 8, y: 3 },
49575
+ { x: 9, y: 3 },
49576
+ { x: 10, y: 3 },
49577
+ { x: 11, y: 3 },
49578
+ { x: 12, y: 3 },
49579
+ { x: 13, y: 3 },
49580
+ { x: 13, y: 4 },
49581
+ { x: 13, y: 5 },
49582
+ { x: 13, y: 6 },
49583
+ { x: 13, y: 7 },
49584
+ { x: 12, y: 7 },
49585
+ { x: 11, y: 7 },
49586
+ { x: 10, y: 7 },
49587
+ { x: 9, y: 7 },
49588
+ { x: 8, y: 7 },
49589
+ { x: 7, y: 7 },
49590
+ { x: 6, y: 7 },
49591
+ { x: 5, y: 7 },
49592
+ { x: 4, y: 7 },
49593
+ { x: 3, y: 7 },
49594
+ { x: 2, y: 7 },
49595
+ { x: 2, y: 8 },
49596
+ { x: 2, y: 9 },
49597
+ { x: 2, y: 10 },
49598
+ { x: 2, y: 11 },
49599
+ { x: 3, y: 11 },
49600
+ { x: 4, y: 11 },
49601
+ { x: 5, y: 11 },
49602
+ { x: 6, y: 11 },
49603
+ { x: 7, y: 11 },
49604
+ { x: 8, y: 11 },
49605
+ { x: 9, y: 11 },
49606
+ { x: 10, y: 11 },
49607
+ { x: 11, y: 11 },
49608
+ { x: 12, y: 11 },
49609
+ { x: 13, y: 11 },
49610
+ { x: 13, y: 12 },
49611
+ { x: 13, y: 13 },
49612
+ { x: 13, y: 14 },
49613
+ { x: 13, y: 15 }
49614
+ ];
49615
+ DEFAULT_TD_TILES = buildDefaultTDTiles();
49616
+ TOWER_SPRITE = `${CDN6}sprite-sheets/guardian-sprite-sheet-se.png`;
49617
+ CREEP_SPRITE = `${CDN6}sprite-sheets/scrapper-sprite-sheet-se.png`;
49618
+ HERO_SPRITE = `${CDN6}sprite-sheets/amir-sprite-sheet-se.png`;
49464
49619
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
49465
49620
  }
49466
49621
  });
@@ -49735,6 +49890,17 @@ function heroPosition(h) {
49735
49890
  function heroMovement(h) {
49736
49891
  return num(h.movement);
49737
49892
  }
49893
+ function buildDefaultWorldTiles() {
49894
+ const tiles = [];
49895
+ for (let y = 0; y < WORLD_GRID_H; y++) {
49896
+ for (let x = 0; x < WORLD_GRID_W; x++) {
49897
+ const isBorder = x === 0 || y === 0 || x === WORLD_GRID_W - 1 || y === WORLD_GRID_H - 1;
49898
+ const def = isBorder ? WORLD_TERRAIN_DEFS[3] : WORLD_TERRAIN_DEFS[(x * 5 + y * 3 + (x ^ y)) % (WORLD_TERRAIN_DEFS.length - 1)];
49899
+ tiles.push({ x, y, terrain: def.terrain, terrainSprite: def.sprite, passable: def.passable });
49900
+ }
49901
+ }
49902
+ return tiles;
49903
+ }
49738
49904
  function defaultIsInRange(from, to, range) {
49739
49905
  return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
49740
49906
  }
@@ -49745,7 +49911,7 @@ function WorldMapBoard({
49745
49911
  features: propFeatures,
49746
49912
  assetManifest: propAssetManifest,
49747
49913
  isLoading,
49748
- scale = 0.4,
49914
+ scale = 0.25,
49749
49915
  unitScale = 2.5,
49750
49916
  spriteHeightRatio = 1.5,
49751
49917
  spriteMaxWidthRatio = 0.6,
@@ -49789,7 +49955,8 @@ function WorldMapBoard({
49789
49955
  })),
49790
49956
  [entityTiles]
49791
49957
  );
49792
- const tiles = propTiles ?? derivedTiles;
49958
+ const rawTiles = propTiles ?? (derivedTiles.length > 0 ? derivedTiles : null);
49959
+ const tiles = rawTiles != null && rawTiles.length >= WORLD_GRID_W * WORLD_GRID_H ? rawTiles : DEFAULT_WORLD_TILES;
49793
49960
  const baseUnits = React82.useMemo(
49794
49961
  () => propUnits ?? entityUnits.map((u) => ({
49795
49962
  id: str(u.id),
@@ -49999,6 +50166,7 @@ function WorldMapBoard({
49999
50166
  footer && footer(ctx)
50000
50167
  ] });
50001
50168
  }
50169
+ var WORLD_CDN, WORLD_GRID_W, WORLD_GRID_H, WORLD_TERRAIN_DEFS, DEFAULT_WORLD_TILES;
50002
50170
  var init_WorldMapBoard = __esm({
50003
50171
  "components/game/organisms/WorldMapBoard.tsx"() {
50004
50172
  "use client";
@@ -50009,6 +50177,17 @@ var init_WorldMapBoard = __esm({
50009
50177
  init_IsometricCanvas();
50010
50178
  init_boardEntity();
50011
50179
  init_isometric();
50180
+ WORLD_CDN = "https://almadar-kflow-assets.web.app/shared";
50181
+ WORLD_GRID_W = 16;
50182
+ WORLD_GRID_H = 16;
50183
+ WORLD_TERRAIN_DEFS = [
50184
+ { terrain: "grass", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/dirt_E.png`, passable: true },
50185
+ { terrain: "dirt", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`, passable: true },
50186
+ { terrain: "forest", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/planks_E.png`, passable: true },
50187
+ { terrain: "stone", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`, passable: false },
50188
+ { terrain: "castle", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`, passable: true }
50189
+ ];
50190
+ DEFAULT_WORLD_TILES = buildDefaultWorldTiles();
50012
50191
  WorldMapBoard.displayName = "WorldMapBoard";
50013
50192
  }
50014
50193
  });