@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.
@@ -11866,13 +11866,29 @@ var init_boardEntity = __esm({
11866
11866
  "components/game/organisms/boardEntity.ts"() {
11867
11867
  }
11868
11868
  });
11869
+ function buildDefaultBattleTiles() {
11870
+ const tiles = [];
11871
+ for (let y = 0; y < BATTLE_GRID_H; y++) {
11872
+ for (let x = 0; x < BATTLE_GRID_W; x++) {
11873
+ const variant = (x * 3 + y * 7 + (x ^ y)) % BATTLE_TERRAIN_SPRITES.length;
11874
+ tiles.push({
11875
+ x,
11876
+ y,
11877
+ terrain: ["grass", "dirt", "planks", "stone", "stone"][variant],
11878
+ terrainSprite: BATTLE_TERRAIN_SPRITES[variant],
11879
+ passable: true
11880
+ });
11881
+ }
11882
+ }
11883
+ return tiles;
11884
+ }
11869
11885
  function BattleBoard({
11870
11886
  entity,
11871
11887
  tiles: propTiles,
11872
11888
  units: propUnits,
11873
11889
  features: propFeatures,
11874
11890
  assetManifest: propAssetManifest,
11875
- scale = 0.45,
11891
+ scale = 0.25,
11876
11892
  unitScale = 1,
11877
11893
  spriteHeightRatio = 1.5,
11878
11894
  spriteMaxWidthRatio = 0.6,
@@ -11899,10 +11915,11 @@ function BattleBoard({
11899
11915
  className
11900
11916
  }) {
11901
11917
  const board = boardEntity(entity) ?? {};
11902
- const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
11918
+ const rawTiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
11919
+ const tiles = rawTiles.length === 0 ? DEFAULT_BATTLE_TILES : rawTiles;
11903
11920
  const features = propFeatures ?? (Array.isArray(board.features) ? board.features : []);
11904
- const boardWidth = num(board.gridWidth ?? board.boardWidth, 8);
11905
- const boardHeight = num(board.gridHeight ?? board.boardHeight, 6);
11921
+ const boardWidth = num(board.gridWidth ?? board.boardWidth, BATTLE_GRID_W);
11922
+ const boardHeight = num(board.gridHeight ?? board.boardHeight, BATTLE_GRID_H);
11906
11923
  const assetManifest = propAssetManifest ?? board.assetManifest;
11907
11924
  const backgroundImage = board.backgroundImage;
11908
11925
  const units = rows(board.units);
@@ -12224,6 +12241,7 @@ function BattleBoard({
12224
12241
  ] }) }))
12225
12242
  ] });
12226
12243
  }
12244
+ var BATTLE_CDN, BATTLE_GRID_W, BATTLE_GRID_H, BATTLE_TERRAIN_SPRITES, DEFAULT_BATTLE_TILES;
12227
12245
  var init_BattleBoard = __esm({
12228
12246
  "components/game/organisms/BattleBoard.tsx"() {
12229
12247
  "use client";
@@ -12236,6 +12254,17 @@ var init_BattleBoard = __esm({
12236
12254
  init_IsometricCanvas();
12237
12255
  init_boardEntity();
12238
12256
  init_isometric();
12257
+ BATTLE_CDN = "https://almadar-kflow-assets.web.app/shared";
12258
+ BATTLE_GRID_W = 16;
12259
+ BATTLE_GRID_H = 16;
12260
+ BATTLE_TERRAIN_SPRITES = [
12261
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`,
12262
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`,
12263
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`,
12264
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`,
12265
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`
12266
+ ];
12267
+ DEFAULT_BATTLE_TILES = buildDefaultBattleTiles();
12239
12268
  BattleBoard.displayName = "BattleBoard";
12240
12269
  }
12241
12270
  });
@@ -12243,7 +12272,7 @@ function BattleTemplate({
12243
12272
  entity,
12244
12273
  scale = 0.45,
12245
12274
  unitScale = 1,
12246
- tiles = DEFAULT_BATTLE_TILES,
12275
+ tiles = DEFAULT_BATTLE_TILES2,
12247
12276
  units = DEFAULT_BATTLE_UNITS,
12248
12277
  features = DEFAULT_BATTLE_FEATURES,
12249
12278
  assetManifest = DEFAULT_BATTLE_MANIFEST,
@@ -12272,12 +12301,12 @@ function BattleTemplate({
12272
12301
  }
12273
12302
  );
12274
12303
  }
12275
- var CDN, DEFAULT_BATTLE_TILES, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12304
+ var CDN, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12276
12305
  var init_BattleTemplate = __esm({
12277
12306
  "components/game/templates/BattleTemplate.tsx"() {
12278
12307
  init_BattleBoard();
12279
12308
  CDN = "https://almadar-kflow-assets.web.app/shared";
12280
- DEFAULT_BATTLE_TILES = [
12309
+ DEFAULT_BATTLE_TILES2 = [
12281
12310
  { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12282
12311
  { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12283
12312
  { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
@@ -29446,13 +29475,13 @@ var init_MapView = __esm({
29446
29475
  shadowSize: [41, 41]
29447
29476
  });
29448
29477
  L.Marker.prototype.options.icon = defaultIcon;
29449
- const { useEffect: useEffect79, useRef: useRef75, useCallback: useCallback118, useState: useState109 } = React82__default;
29478
+ const { useEffect: useEffect80, useRef: useRef75, useCallback: useCallback118, useState: useState109 } = React82__default;
29450
29479
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29451
29480
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29452
29481
  function MapUpdater({ centerLat, centerLng, zoom }) {
29453
29482
  const map = useMap();
29454
29483
  const prevRef = useRef75({ centerLat, centerLng, zoom });
29455
- useEffect79(() => {
29484
+ useEffect80(() => {
29456
29485
  const prev = prevRef.current;
29457
29486
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
29458
29487
  map.setView([centerLat, centerLng], zoom);
@@ -29463,7 +29492,7 @@ var init_MapView = __esm({
29463
29492
  }
29464
29493
  function MapClickHandler({ onMapClick }) {
29465
29494
  const map = useMap();
29466
- useEffect79(() => {
29495
+ useEffect80(() => {
29467
29496
  if (!onMapClick) return;
29468
29497
  const handler = (e) => {
29469
29498
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -42140,7 +42169,6 @@ var init_GameCanvas3D2 = __esm({
42140
42169
  selectedTileIds = [],
42141
42170
  selectedUnitId = null,
42142
42171
  unitScale = 1,
42143
- scale = 0.45,
42144
42172
  children
42145
42173
  }, ref) => {
42146
42174
  const containerRef = useRef(null);
@@ -42587,7 +42615,7 @@ var init_GameCanvas3D2 = __esm({
42587
42615
  fadeStrength: 1
42588
42616
  }
42589
42617
  ),
42590
- /* @__PURE__ */ jsxs("group", { scale, children: [
42618
+ /* @__PURE__ */ jsxs("group", { children: [
42591
42619
  tiles.map((tile, index) => {
42592
42620
  const position = gridToWorld(
42593
42621
  tile.x,
@@ -44730,6 +44758,35 @@ var init_PricingPageTemplate = __esm({
44730
44758
  PricingPageTemplate.displayName = "PricingPageTemplate";
44731
44759
  }
44732
44760
  });
44761
+ function dungeonTerrain(x, y, stairsX, stairsY) {
44762
+ const isBorder = x === 0 || y === 0 || x === DUNGEON_GRID_W - 1 || y === DUNGEON_GRID_H - 1;
44763
+ const isPillar = x % 4 === 0 && y % 4 === 0 && !isBorder;
44764
+ const isWall = isBorder || isPillar;
44765
+ if (x === stairsX && y === stairsY) {
44766
+ return { terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` };
44767
+ }
44768
+ if (isWall) {
44769
+ return { terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` };
44770
+ }
44771
+ const variant = (x * 3 + y * 7) % 5;
44772
+ const sprites = [
44773
+ `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`,
44774
+ `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png`,
44775
+ `${CDN4}/isometric-dungeon/Isometric/planks_E.png`,
44776
+ `${CDN4}/isometric-dungeon/Isometric/stoneTile_E.png`,
44777
+ `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`
44778
+ ];
44779
+ return { terrain: "floor", passable: true, terrainSprite: sprites[variant] };
44780
+ }
44781
+ function buildDefaultDungeonTiles(stairsX, stairsY) {
44782
+ const tiles = [];
44783
+ for (let y = 0; y < DUNGEON_GRID_H; y++) {
44784
+ for (let x = 0; x < DUNGEON_GRID_W; x++) {
44785
+ tiles.push({ x, y, ...dungeonTerrain(x, y, stairsX, stairsY) });
44786
+ }
44787
+ }
44788
+ return tiles;
44789
+ }
44733
44790
  function RoguelikeBoard({
44734
44791
  entity,
44735
44792
  tiles: propTiles,
@@ -44745,7 +44802,7 @@ function RoguelikeBoard({
44745
44802
  stairsX: propStairsX,
44746
44803
  stairsY: propStairsY,
44747
44804
  assetManifest: propAssetManifest,
44748
- scale = 0.45,
44805
+ scale = 0.25,
44749
44806
  unitScale = 1,
44750
44807
  spriteHeightRatio = 1.5,
44751
44808
  spriteMaxWidthRatio = 0.6,
@@ -44755,7 +44812,9 @@ function RoguelikeBoard({
44755
44812
  className
44756
44813
  }) {
44757
44814
  const board = boardEntity(entity) ?? {};
44758
- const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : DEFAULT_TILES2);
44815
+ const resolvedStairsX = propStairsX ?? num(board.stairsX, 14);
44816
+ const resolvedStairsY = propStairsY ?? num(board.stairsY, 14);
44817
+ const tiles = propTiles ?? (Array.isArray(board.tiles) && board.tiles.length >= DUNGEON_GRID_W * DUNGEON_GRID_H ? board.tiles : buildDefaultDungeonTiles(resolvedStairsX, resolvedStairsY));
44759
44818
  const enemies = propEnemies ?? (Array.isArray(board.enemies) ? board.enemies : DEFAULT_ENEMIES);
44760
44819
  const items = propItems ?? (Array.isArray(board.items) ? board.items : DEFAULT_ITEMS);
44761
44820
  const player = propPlayer ?? board.player ?? { x: 1, y: 1 };
@@ -44765,8 +44824,8 @@ function RoguelikeBoard({
44765
44824
  const depth = propDepth ?? num(board.depth, 1);
44766
44825
  const result = propResult ?? (str(board.result) || "none");
44767
44826
  const phase = propPhase ?? (str(board.phase) || "player_turn");
44768
- propStairsX ?? num(board.stairsX, 3);
44769
- propStairsY ?? num(board.stairsY, 3);
44827
+ propStairsX ?? num(board.stairsX, 14);
44828
+ propStairsY ?? num(board.stairsY, 14);
44770
44829
  const eventBus = useEventBus();
44771
44830
  const { t } = useTranslate();
44772
44831
  const [hoveredTile, setHoveredTile] = useState(null);
@@ -44942,7 +45001,7 @@ function RoguelikeBoard({
44942
45001
  ] }) })
44943
45002
  ] });
44944
45003
  }
44945
- var CDN4, DEFAULT_TILES2, DEFAULT_ENEMIES, DEFAULT_ITEMS, FEATURE_SPRITE;
45004
+ var CDN4, DUNGEON_GRID_W, DUNGEON_GRID_H, DEFAULT_ENEMIES, DEFAULT_ITEMS, FEATURE_SPRITE;
44946
45005
  var init_RoguelikeBoard = __esm({
44947
45006
  "components/game/organisms/RoguelikeBoard.tsx"() {
44948
45007
  "use client";
@@ -44955,39 +45014,19 @@ var init_RoguelikeBoard = __esm({
44955
45014
  init_IsometricCanvas();
44956
45015
  init_boardEntity();
44957
45016
  CDN4 = "https://almadar-kflow-assets.web.app/shared";
44958
- DEFAULT_TILES2 = [
44959
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44960
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44961
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44962
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44963
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44964
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44965
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
44966
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
44967
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
44968
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44969
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44970
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
44971
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
44972
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
44973
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44974
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44975
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
44976
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
44977
- { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` },
44978
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44979
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44980
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44981
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44982
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44983
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` }
44984
- ];
45017
+ DUNGEON_GRID_W = 16;
45018
+ DUNGEON_GRID_H = 16;
45019
+ buildDefaultDungeonTiles(14, 14);
44985
45020
  DEFAULT_ENEMIES = [
44986
- { id: "e1", x: 3, y: 1, hp: 5, attack: 2 },
44987
- { id: "e2", x: 1, y: 3, hp: 4, attack: 1 }
45021
+ { id: "e1", x: 5, y: 2, hp: 5, attack: 2 },
45022
+ { id: "e2", x: 9, y: 6, hp: 4, attack: 1 },
45023
+ { id: "e3", x: 3, y: 10, hp: 6, attack: 2 },
45024
+ { id: "e4", x: 12, y: 8, hp: 5, attack: 3 }
44988
45025
  ];
44989
45026
  DEFAULT_ITEMS = [
44990
- { id: "i1", x: 2, y: 2, kind: "health_potion" }
45027
+ { id: "i1", x: 3, y: 3, kind: "health_potion" },
45028
+ { id: "i2", x: 7, y: 9, kind: "sword" },
45029
+ { id: "i3", x: 11, y: 5, kind: "shield" }
44991
45030
  ];
44992
45031
  FEATURE_SPRITE = {
44993
45032
  health_potion: `${CDN4}/isometric-dungeon/Isometric/chestClosed_E.png`,
@@ -49195,6 +49234,22 @@ var init_ToastSlot = __esm({
49195
49234
  ToastSlot.displayName = "ToastSlot";
49196
49235
  }
49197
49236
  });
49237
+ function buildDefaultTDTiles() {
49238
+ const pathSet = new Set(DEFAULT_TD_PATH.map((p2) => `${p2.x},${p2.y}`));
49239
+ const tiles = [];
49240
+ for (let y = 0; y < TD_GRID_H; y++) {
49241
+ for (let x = 0; x < TD_GRID_W; x++) {
49242
+ if (pathSet.has(`${x},${y}`)) {
49243
+ tiles.push({ x, y, terrain: "path", passable: false, terrainSprite: TERRAIN_SPRITES.path });
49244
+ } else {
49245
+ const variant = (x * 3 + y * 5 + (x ^ y)) % 3;
49246
+ const terrainKey = ["ground", "grass", "dirt"][variant];
49247
+ tiles.push({ x, y, terrain: terrainKey, passable: true, terrainSprite: TERRAIN_SPRITES[terrainKey] ?? TERRAIN_SPRITES.ground });
49248
+ }
49249
+ }
49250
+ }
49251
+ return tiles;
49252
+ }
49198
49253
  function tilesToIso(tiles) {
49199
49254
  return tiles.map((t) => ({
49200
49255
  x: t.x,
@@ -49237,12 +49292,25 @@ function pathToFeatures(path) {
49237
49292
  sprite: `${CDN6}world-map/road_straight.png`
49238
49293
  }));
49239
49294
  }
49295
+ function heroToUnit(hero) {
49296
+ return {
49297
+ id: hero.id,
49298
+ position: { x: hero.x, y: hero.y },
49299
+ name: "Hero",
49300
+ team: "player",
49301
+ sprite: HERO_SPRITE,
49302
+ unitType: "amir",
49303
+ health: 1,
49304
+ maxHealth: 1
49305
+ };
49306
+ }
49240
49307
  function TowerDefenseBoard({
49241
49308
  entity,
49242
49309
  tiles: propTiles,
49243
49310
  path: propPath,
49244
49311
  towers: propTowers,
49245
49312
  creeps: propCreeps,
49313
+ hero: propHero,
49246
49314
  gold: propGold,
49247
49315
  lives: propLives,
49248
49316
  wave: propWave,
@@ -49250,7 +49318,7 @@ function TowerDefenseBoard({
49250
49318
  result: propResult,
49251
49319
  waveActive: propWaveActive,
49252
49320
  towerCost = 25,
49253
- scale = 0.45,
49321
+ scale = 0.25,
49254
49322
  unitScale = 1,
49255
49323
  spriteHeightRatio = 1.5,
49256
49324
  spriteMaxWidthRatio = 0.6,
@@ -49258,15 +49326,19 @@ function TowerDefenseBoard({
49258
49326
  startWaveEvent,
49259
49327
  playAgainEvent,
49260
49328
  gameEndEvent,
49329
+ moveHeroEvent,
49261
49330
  className
49262
49331
  }) {
49263
49332
  const board = boardEntity(entity) ?? {};
49264
49333
  const eventBus = useEventBus();
49265
49334
  const { t } = useTranslate();
49266
- const tiles = propTiles ?? rows(board.tiles);
49267
- const path = propPath ?? rows(board.path);
49335
+ const rawTiles = propTiles ?? rows(board.tiles);
49336
+ const tiles = rawTiles.length >= TD_GRID_W * TD_GRID_H ? rawTiles : DEFAULT_TD_TILES;
49337
+ const rawPath = propPath ?? rows(board.path);
49338
+ const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
49268
49339
  const towers = propTowers ?? rows(board.towers);
49269
49340
  const creeps = propCreeps ?? rows(board.creeps);
49341
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
49270
49342
  const gold = propGold ?? num(board.gold, 100);
49271
49343
  const lives = propLives ?? num(board.lives, 20);
49272
49344
  const wave = propWave ?? num(board.wave, 1);
@@ -49284,6 +49356,31 @@ function TowerDefenseBoard({
49284
49356
  if (result === "none") {
49285
49357
  emittedGameEnd.current = false;
49286
49358
  }
49359
+ const moveHeroEventRef = useRef(moveHeroEvent);
49360
+ moveHeroEventRef.current = moveHeroEvent;
49361
+ const resultRef = useRef(result);
49362
+ resultRef.current = result;
49363
+ useEffect(() => {
49364
+ function onKeyDown(e) {
49365
+ const evt = moveHeroEventRef.current;
49366
+ if (!evt || resultRef.current !== "none") return;
49367
+ let dx = 0;
49368
+ let dy = 0;
49369
+ if (e.key === "ArrowUp") {
49370
+ dy = -1;
49371
+ } else if (e.key === "ArrowDown") {
49372
+ dy = 1;
49373
+ } else if (e.key === "ArrowLeft") {
49374
+ dx = -1;
49375
+ } else if (e.key === "ArrowRight") {
49376
+ dx = 1;
49377
+ } else return;
49378
+ e.preventDefault();
49379
+ eventBus.emit(`UI:${evt}`, { dx, dy });
49380
+ }
49381
+ window.addEventListener("keydown", onKeyDown);
49382
+ return () => window.removeEventListener("keydown", onKeyDown);
49383
+ }, [eventBus]);
49287
49384
  const towerPositions = useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
49288
49385
  const pathPositions = useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
49289
49386
  const validMoves = useMemo(() => {
@@ -49295,7 +49392,8 @@ function TowerDefenseBoard({
49295
49392
  const isoTiles = useMemo(() => tilesToIso(tiles), [tiles]);
49296
49393
  const towerUnits = useMemo(() => towersToUnits(towers), [towers]);
49297
49394
  const creepUnits = useMemo(() => creepsToUnits(creeps), [creeps]);
49298
- const isoUnits = useMemo(() => [...towerUnits, ...creepUnits], [towerUnits, creepUnits]);
49395
+ const heroUnit = useMemo(() => heroToUnit(hero), [hero]);
49396
+ const isoUnits = useMemo(() => [...towerUnits, ...creepUnits, heroUnit], [towerUnits, creepUnits, heroUnit]);
49299
49397
  const pathFeatures = useMemo(() => pathToFeatures(path), [path]);
49300
49398
  const handleTileClick = useCallback((x, y) => {
49301
49399
  if (result !== "none") return;
@@ -49394,7 +49492,7 @@ function TowerDefenseBoard({
49394
49492
  ] }) })
49395
49493
  ] });
49396
49494
  }
49397
- var CDN6, TERRAIN_SPRITES, TOWER_SPRITE, CREEP_SPRITE;
49495
+ var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE, HERO_SPRITE;
49398
49496
  var init_TowerDefenseBoard = __esm({
49399
49497
  "components/game/organisms/TowerDefenseBoard.tsx"() {
49400
49498
  "use client";
@@ -49407,13 +49505,70 @@ var init_TowerDefenseBoard = __esm({
49407
49505
  init_IsometricCanvas();
49408
49506
  init_boardEntity();
49409
49507
  CDN6 = "https://almadar-kflow-assets.web.app/shared/";
49508
+ TD_GRID_W = 16;
49509
+ TD_GRID_H = 16;
49410
49510
  TERRAIN_SPRITES = {
49411
49511
  ground: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`,
49412
49512
  path: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_09.png`,
49413
- wall: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`
49414
- };
49415
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
49416
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
49513
+ wall: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`,
49514
+ grass: `${CDN6}isometric-dungeon/Isometric/dirt_E.png`,
49515
+ dirt: `${CDN6}isometric-dungeon/Isometric/dirtTiles_E.png`
49516
+ };
49517
+ DEFAULT_TD_PATH = [
49518
+ { x: 2, y: 0 },
49519
+ { x: 2, y: 1 },
49520
+ { x: 2, y: 2 },
49521
+ { x: 2, y: 3 },
49522
+ { x: 3, y: 3 },
49523
+ { x: 4, y: 3 },
49524
+ { x: 5, y: 3 },
49525
+ { x: 6, y: 3 },
49526
+ { x: 7, y: 3 },
49527
+ { x: 8, y: 3 },
49528
+ { x: 9, y: 3 },
49529
+ { x: 10, y: 3 },
49530
+ { x: 11, y: 3 },
49531
+ { x: 12, y: 3 },
49532
+ { x: 13, y: 3 },
49533
+ { x: 13, y: 4 },
49534
+ { x: 13, y: 5 },
49535
+ { x: 13, y: 6 },
49536
+ { x: 13, y: 7 },
49537
+ { x: 12, y: 7 },
49538
+ { x: 11, y: 7 },
49539
+ { x: 10, y: 7 },
49540
+ { x: 9, y: 7 },
49541
+ { x: 8, y: 7 },
49542
+ { x: 7, y: 7 },
49543
+ { x: 6, y: 7 },
49544
+ { x: 5, y: 7 },
49545
+ { x: 4, y: 7 },
49546
+ { x: 3, y: 7 },
49547
+ { x: 2, y: 7 },
49548
+ { x: 2, y: 8 },
49549
+ { x: 2, y: 9 },
49550
+ { x: 2, y: 10 },
49551
+ { x: 2, y: 11 },
49552
+ { x: 3, y: 11 },
49553
+ { x: 4, y: 11 },
49554
+ { x: 5, y: 11 },
49555
+ { x: 6, y: 11 },
49556
+ { x: 7, y: 11 },
49557
+ { x: 8, y: 11 },
49558
+ { x: 9, y: 11 },
49559
+ { x: 10, y: 11 },
49560
+ { x: 11, y: 11 },
49561
+ { x: 12, y: 11 },
49562
+ { x: 13, y: 11 },
49563
+ { x: 13, y: 12 },
49564
+ { x: 13, y: 13 },
49565
+ { x: 13, y: 14 },
49566
+ { x: 13, y: 15 }
49567
+ ];
49568
+ DEFAULT_TD_TILES = buildDefaultTDTiles();
49569
+ TOWER_SPRITE = `${CDN6}sprite-sheets/guardian-sprite-sheet-se.png`;
49570
+ CREEP_SPRITE = `${CDN6}sprite-sheets/scrapper-sprite-sheet-se.png`;
49571
+ HERO_SPRITE = `${CDN6}sprite-sheets/amir-sprite-sheet-se.png`;
49417
49572
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
49418
49573
  }
49419
49574
  });
@@ -49688,6 +49843,17 @@ function heroPosition(h) {
49688
49843
  function heroMovement(h) {
49689
49844
  return num(h.movement);
49690
49845
  }
49846
+ function buildDefaultWorldTiles() {
49847
+ const tiles = [];
49848
+ for (let y = 0; y < WORLD_GRID_H; y++) {
49849
+ for (let x = 0; x < WORLD_GRID_W; x++) {
49850
+ const isBorder = x === 0 || y === 0 || x === WORLD_GRID_W - 1 || y === WORLD_GRID_H - 1;
49851
+ const def = isBorder ? WORLD_TERRAIN_DEFS[3] : WORLD_TERRAIN_DEFS[(x * 5 + y * 3 + (x ^ y)) % (WORLD_TERRAIN_DEFS.length - 1)];
49852
+ tiles.push({ x, y, terrain: def.terrain, terrainSprite: def.sprite, passable: def.passable });
49853
+ }
49854
+ }
49855
+ return tiles;
49856
+ }
49691
49857
  function defaultIsInRange(from, to, range) {
49692
49858
  return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
49693
49859
  }
@@ -49698,7 +49864,7 @@ function WorldMapBoard({
49698
49864
  features: propFeatures,
49699
49865
  assetManifest: propAssetManifest,
49700
49866
  isLoading,
49701
- scale = 0.4,
49867
+ scale = 0.25,
49702
49868
  unitScale = 2.5,
49703
49869
  spriteHeightRatio = 1.5,
49704
49870
  spriteMaxWidthRatio = 0.6,
@@ -49742,7 +49908,8 @@ function WorldMapBoard({
49742
49908
  })),
49743
49909
  [entityTiles]
49744
49910
  );
49745
- const tiles = propTiles ?? derivedTiles;
49911
+ const rawTiles = propTiles ?? (derivedTiles.length > 0 ? derivedTiles : null);
49912
+ const tiles = rawTiles != null && rawTiles.length >= WORLD_GRID_W * WORLD_GRID_H ? rawTiles : DEFAULT_WORLD_TILES;
49746
49913
  const baseUnits = useMemo(
49747
49914
  () => propUnits ?? entityUnits.map((u) => ({
49748
49915
  id: str(u.id),
@@ -49952,6 +50119,7 @@ function WorldMapBoard({
49952
50119
  footer && footer(ctx)
49953
50120
  ] });
49954
50121
  }
50122
+ var WORLD_CDN, WORLD_GRID_W, WORLD_GRID_H, WORLD_TERRAIN_DEFS, DEFAULT_WORLD_TILES;
49955
50123
  var init_WorldMapBoard = __esm({
49956
50124
  "components/game/organisms/WorldMapBoard.tsx"() {
49957
50125
  "use client";
@@ -49962,6 +50130,17 @@ var init_WorldMapBoard = __esm({
49962
50130
  init_IsometricCanvas();
49963
50131
  init_boardEntity();
49964
50132
  init_isometric();
50133
+ WORLD_CDN = "https://almadar-kflow-assets.web.app/shared";
50134
+ WORLD_GRID_W = 16;
50135
+ WORLD_GRID_H = 16;
50136
+ WORLD_TERRAIN_DEFS = [
50137
+ { terrain: "grass", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/dirt_E.png`, passable: true },
50138
+ { terrain: "dirt", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`, passable: true },
50139
+ { terrain: "forest", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/planks_E.png`, passable: true },
50140
+ { terrain: "stone", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`, passable: false },
50141
+ { terrain: "castle", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`, passable: true }
50142
+ ];
50143
+ DEFAULT_WORLD_TILES = buildDefaultWorldTiles();
49965
50144
  WorldMapBoard.displayName = "WorldMapBoard";
49966
50145
  }
49967
50146
  });