@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.
@@ -15350,13 +15350,29 @@ var init_boardEntity = __esm({
15350
15350
  "components/game/organisms/boardEntity.ts"() {
15351
15351
  }
15352
15352
  });
15353
+ function buildDefaultBattleTiles() {
15354
+ const tiles = [];
15355
+ for (let y = 0; y < BATTLE_GRID_H; y++) {
15356
+ for (let x = 0; x < BATTLE_GRID_W; x++) {
15357
+ const variant = (x * 3 + y * 7 + (x ^ y)) % BATTLE_TERRAIN_SPRITES.length;
15358
+ tiles.push({
15359
+ x,
15360
+ y,
15361
+ terrain: ["grass", "dirt", "planks", "stone", "stone"][variant],
15362
+ terrainSprite: BATTLE_TERRAIN_SPRITES[variant],
15363
+ passable: true
15364
+ });
15365
+ }
15366
+ }
15367
+ return tiles;
15368
+ }
15353
15369
  function BattleBoard({
15354
15370
  entity,
15355
15371
  tiles: propTiles,
15356
15372
  units: propUnits,
15357
15373
  features: propFeatures,
15358
15374
  assetManifest: propAssetManifest,
15359
- scale = 0.45,
15375
+ scale = 0.25,
15360
15376
  unitScale = 1,
15361
15377
  spriteHeightRatio = 1.5,
15362
15378
  spriteMaxWidthRatio = 0.6,
@@ -15383,10 +15399,11 @@ function BattleBoard({
15383
15399
  className
15384
15400
  }) {
15385
15401
  const board = boardEntity(entity) ?? {};
15386
- const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
15402
+ const rawTiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
15403
+ const tiles = rawTiles.length === 0 ? DEFAULT_BATTLE_TILES : rawTiles;
15387
15404
  const features = propFeatures ?? (Array.isArray(board.features) ? board.features : []);
15388
- const boardWidth = num(board.gridWidth ?? board.boardWidth, 8);
15389
- const boardHeight = num(board.gridHeight ?? board.boardHeight, 6);
15405
+ const boardWidth = num(board.gridWidth ?? board.boardWidth, BATTLE_GRID_W);
15406
+ const boardHeight = num(board.gridHeight ?? board.boardHeight, BATTLE_GRID_H);
15390
15407
  const assetManifest = propAssetManifest ?? board.assetManifest;
15391
15408
  const backgroundImage = board.backgroundImage;
15392
15409
  const units = rows(board.units);
@@ -15708,6 +15725,7 @@ function BattleBoard({
15708
15725
  ] }) }))
15709
15726
  ] });
15710
15727
  }
15728
+ var BATTLE_CDN, BATTLE_GRID_W, BATTLE_GRID_H, BATTLE_TERRAIN_SPRITES, DEFAULT_BATTLE_TILES;
15711
15729
  var init_BattleBoard = __esm({
15712
15730
  "components/game/organisms/BattleBoard.tsx"() {
15713
15731
  "use client";
@@ -15720,6 +15738,17 @@ var init_BattleBoard = __esm({
15720
15738
  init_IsometricCanvas();
15721
15739
  init_boardEntity();
15722
15740
  init_isometric();
15741
+ BATTLE_CDN = "https://almadar-kflow-assets.web.app/shared";
15742
+ BATTLE_GRID_W = 16;
15743
+ BATTLE_GRID_H = 16;
15744
+ BATTLE_TERRAIN_SPRITES = [
15745
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`,
15746
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`,
15747
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`,
15748
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`,
15749
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`
15750
+ ];
15751
+ DEFAULT_BATTLE_TILES = buildDefaultBattleTiles();
15723
15752
  BattleBoard.displayName = "BattleBoard";
15724
15753
  }
15725
15754
  });
@@ -15727,7 +15756,7 @@ function BattleTemplate({
15727
15756
  entity,
15728
15757
  scale = 0.45,
15729
15758
  unitScale = 1,
15730
- tiles = DEFAULT_BATTLE_TILES,
15759
+ tiles = DEFAULT_BATTLE_TILES2,
15731
15760
  units = DEFAULT_BATTLE_UNITS,
15732
15761
  features = DEFAULT_BATTLE_FEATURES,
15733
15762
  assetManifest = DEFAULT_BATTLE_MANIFEST,
@@ -15756,12 +15785,12 @@ function BattleTemplate({
15756
15785
  }
15757
15786
  );
15758
15787
  }
15759
- var CDN, DEFAULT_BATTLE_TILES, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
15788
+ var CDN, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
15760
15789
  var init_BattleTemplate = __esm({
15761
15790
  "components/game/templates/BattleTemplate.tsx"() {
15762
15791
  init_BattleBoard();
15763
15792
  CDN = "https://almadar-kflow-assets.web.app/shared";
15764
- DEFAULT_BATTLE_TILES = [
15793
+ DEFAULT_BATTLE_TILES2 = [
15765
15794
  { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
15766
15795
  { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
15767
15796
  { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
@@ -32101,13 +32130,13 @@ var init_MapView = __esm({
32101
32130
  shadowSize: [41, 41]
32102
32131
  });
32103
32132
  L.Marker.prototype.options.icon = defaultIcon;
32104
- const { useEffect: useEffect85, useRef: useRef77, useCallback: useCallback125, useState: useState121 } = React90__namespace.default;
32133
+ const { useEffect: useEffect86, useRef: useRef77, useCallback: useCallback125, useState: useState121 } = React90__namespace.default;
32105
32134
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
32106
32135
  const { useEventBus: useEventBus4 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
32107
32136
  function MapUpdater({ centerLat, centerLng, zoom }) {
32108
32137
  const map = useMap();
32109
32138
  const prevRef = useRef77({ centerLat, centerLng, zoom });
32110
- useEffect85(() => {
32139
+ useEffect86(() => {
32111
32140
  const prev = prevRef.current;
32112
32141
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
32113
32142
  map.setView([centerLat, centerLng], zoom);
@@ -32118,7 +32147,7 @@ var init_MapView = __esm({
32118
32147
  }
32119
32148
  function MapClickHandler({ onMapClick }) {
32120
32149
  const map = useMap();
32121
- useEffect85(() => {
32150
+ useEffect86(() => {
32122
32151
  if (!onMapClick) return;
32123
32152
  const handler = (e) => {
32124
32153
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -44386,7 +44415,6 @@ var init_GameCanvas3D2 = __esm({
44386
44415
  selectedTileIds = [],
44387
44416
  selectedUnitId = null,
44388
44417
  unitScale = 1,
44389
- scale = 0.45,
44390
44418
  children
44391
44419
  }, ref) => {
44392
44420
  const containerRef = React90.useRef(null);
@@ -44833,7 +44861,7 @@ var init_GameCanvas3D2 = __esm({
44833
44861
  fadeStrength: 1
44834
44862
  }
44835
44863
  ),
44836
- /* @__PURE__ */ jsxRuntime.jsxs("group", { scale, children: [
44864
+ /* @__PURE__ */ jsxRuntime.jsxs("group", { children: [
44837
44865
  tiles.map((tile, index) => {
44838
44866
  const position = gridToWorld(
44839
44867
  tile.x,
@@ -46976,6 +47004,35 @@ var init_PricingPageTemplate = __esm({
46976
47004
  PricingPageTemplate.displayName = "PricingPageTemplate";
46977
47005
  }
46978
47006
  });
47007
+ function dungeonTerrain(x, y, stairsX, stairsY) {
47008
+ const isBorder = x === 0 || y === 0 || x === DUNGEON_GRID_W - 1 || y === DUNGEON_GRID_H - 1;
47009
+ const isPillar = x % 4 === 0 && y % 4 === 0 && !isBorder;
47010
+ const isWall = isBorder || isPillar;
47011
+ if (x === stairsX && y === stairsY) {
47012
+ return { terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` };
47013
+ }
47014
+ if (isWall) {
47015
+ return { terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` };
47016
+ }
47017
+ const variant = (x * 3 + y * 7) % 5;
47018
+ const sprites = [
47019
+ `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`,
47020
+ `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png`,
47021
+ `${CDN4}/isometric-dungeon/Isometric/planks_E.png`,
47022
+ `${CDN4}/isometric-dungeon/Isometric/stoneTile_E.png`,
47023
+ `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`
47024
+ ];
47025
+ return { terrain: "floor", passable: true, terrainSprite: sprites[variant] };
47026
+ }
47027
+ function buildDefaultDungeonTiles(stairsX, stairsY) {
47028
+ const tiles = [];
47029
+ for (let y = 0; y < DUNGEON_GRID_H; y++) {
47030
+ for (let x = 0; x < DUNGEON_GRID_W; x++) {
47031
+ tiles.push({ x, y, ...dungeonTerrain(x, y, stairsX, stairsY) });
47032
+ }
47033
+ }
47034
+ return tiles;
47035
+ }
46979
47036
  function RoguelikeBoard({
46980
47037
  entity,
46981
47038
  tiles: propTiles,
@@ -46991,7 +47048,7 @@ function RoguelikeBoard({
46991
47048
  stairsX: propStairsX,
46992
47049
  stairsY: propStairsY,
46993
47050
  assetManifest: propAssetManifest,
46994
- scale = 0.45,
47051
+ scale = 0.25,
46995
47052
  unitScale = 1,
46996
47053
  spriteHeightRatio = 1.5,
46997
47054
  spriteMaxWidthRatio = 0.6,
@@ -47001,7 +47058,9 @@ function RoguelikeBoard({
47001
47058
  className
47002
47059
  }) {
47003
47060
  const board = boardEntity(entity) ?? {};
47004
- const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : DEFAULT_TILES2);
47061
+ const resolvedStairsX = propStairsX ?? num(board.stairsX, 14);
47062
+ const resolvedStairsY = propStairsY ?? num(board.stairsY, 14);
47063
+ const tiles = propTiles ?? (Array.isArray(board.tiles) && board.tiles.length >= DUNGEON_GRID_W * DUNGEON_GRID_H ? board.tiles : buildDefaultDungeonTiles(resolvedStairsX, resolvedStairsY));
47005
47064
  const enemies = propEnemies ?? (Array.isArray(board.enemies) ? board.enemies : DEFAULT_ENEMIES);
47006
47065
  const items = propItems ?? (Array.isArray(board.items) ? board.items : DEFAULT_ITEMS);
47007
47066
  const player = propPlayer ?? board.player ?? { x: 1, y: 1 };
@@ -47011,8 +47070,8 @@ function RoguelikeBoard({
47011
47070
  const depth = propDepth ?? num(board.depth, 1);
47012
47071
  const result = propResult ?? (str(board.result) || "none");
47013
47072
  const phase = propPhase ?? (str(board.phase) || "player_turn");
47014
- propStairsX ?? num(board.stairsX, 3);
47015
- propStairsY ?? num(board.stairsY, 3);
47073
+ propStairsX ?? num(board.stairsX, 14);
47074
+ propStairsY ?? num(board.stairsY, 14);
47016
47075
  const eventBus = useEventBus();
47017
47076
  const { t } = hooks.useTranslate();
47018
47077
  const [hoveredTile, setHoveredTile] = React90.useState(null);
@@ -47188,7 +47247,7 @@ function RoguelikeBoard({
47188
47247
  ] }) })
47189
47248
  ] });
47190
47249
  }
47191
- var CDN4, DEFAULT_TILES2, DEFAULT_ENEMIES, DEFAULT_ITEMS, FEATURE_SPRITE;
47250
+ var CDN4, DUNGEON_GRID_W, DUNGEON_GRID_H, DEFAULT_ENEMIES, DEFAULT_ITEMS, FEATURE_SPRITE;
47192
47251
  var init_RoguelikeBoard = __esm({
47193
47252
  "components/game/organisms/RoguelikeBoard.tsx"() {
47194
47253
  "use client";
@@ -47201,39 +47260,19 @@ var init_RoguelikeBoard = __esm({
47201
47260
  init_IsometricCanvas();
47202
47261
  init_boardEntity();
47203
47262
  CDN4 = "https://almadar-kflow-assets.web.app/shared";
47204
- DEFAULT_TILES2 = [
47205
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47206
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47207
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47208
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47209
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47210
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47211
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47212
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47213
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47214
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47215
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47216
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47217
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47218
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47219
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47220
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47221
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47222
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47223
- { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` },
47224
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47225
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47226
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47227
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47228
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47229
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` }
47230
- ];
47263
+ DUNGEON_GRID_W = 16;
47264
+ DUNGEON_GRID_H = 16;
47265
+ buildDefaultDungeonTiles(14, 14);
47231
47266
  DEFAULT_ENEMIES = [
47232
- { id: "e1", x: 3, y: 1, hp: 5, attack: 2 },
47233
- { id: "e2", x: 1, y: 3, hp: 4, attack: 1 }
47267
+ { id: "e1", x: 5, y: 2, hp: 5, attack: 2 },
47268
+ { id: "e2", x: 9, y: 6, hp: 4, attack: 1 },
47269
+ { id: "e3", x: 3, y: 10, hp: 6, attack: 2 },
47270
+ { id: "e4", x: 12, y: 8, hp: 5, attack: 3 }
47234
47271
  ];
47235
47272
  DEFAULT_ITEMS = [
47236
- { id: "i1", x: 2, y: 2, kind: "health_potion" }
47273
+ { id: "i1", x: 3, y: 3, kind: "health_potion" },
47274
+ { id: "i2", x: 7, y: 9, kind: "sword" },
47275
+ { id: "i3", x: 11, y: 5, kind: "shield" }
47237
47276
  ];
47238
47277
  FEATURE_SPRITE = {
47239
47278
  health_potion: `${CDN4}/isometric-dungeon/Isometric/chestClosed_E.png`,
@@ -51460,6 +51499,22 @@ var init_ToastSlot = __esm({
51460
51499
  ToastSlot.displayName = "ToastSlot";
51461
51500
  }
51462
51501
  });
51502
+ function buildDefaultTDTiles() {
51503
+ const pathSet = new Set(DEFAULT_TD_PATH.map((p2) => `${p2.x},${p2.y}`));
51504
+ const tiles = [];
51505
+ for (let y = 0; y < TD_GRID_H; y++) {
51506
+ for (let x = 0; x < TD_GRID_W; x++) {
51507
+ if (pathSet.has(`${x},${y}`)) {
51508
+ tiles.push({ x, y, terrain: "path", passable: false, terrainSprite: TERRAIN_SPRITES.path });
51509
+ } else {
51510
+ const variant = (x * 3 + y * 5 + (x ^ y)) % 3;
51511
+ const terrainKey = ["ground", "grass", "dirt"][variant];
51512
+ tiles.push({ x, y, terrain: terrainKey, passable: true, terrainSprite: TERRAIN_SPRITES[terrainKey] ?? TERRAIN_SPRITES.ground });
51513
+ }
51514
+ }
51515
+ }
51516
+ return tiles;
51517
+ }
51463
51518
  function tilesToIso(tiles) {
51464
51519
  return tiles.map((t) => ({
51465
51520
  x: t.x,
@@ -51502,12 +51557,25 @@ function pathToFeatures(path) {
51502
51557
  sprite: `${CDN6}world-map/road_straight.png`
51503
51558
  }));
51504
51559
  }
51560
+ function heroToUnit(hero) {
51561
+ return {
51562
+ id: hero.id,
51563
+ position: { x: hero.x, y: hero.y },
51564
+ name: "Hero",
51565
+ team: "player",
51566
+ sprite: HERO_SPRITE,
51567
+ unitType: "amir",
51568
+ health: 1,
51569
+ maxHealth: 1
51570
+ };
51571
+ }
51505
51572
  function TowerDefenseBoard({
51506
51573
  entity,
51507
51574
  tiles: propTiles,
51508
51575
  path: propPath,
51509
51576
  towers: propTowers,
51510
51577
  creeps: propCreeps,
51578
+ hero: propHero,
51511
51579
  gold: propGold,
51512
51580
  lives: propLives,
51513
51581
  wave: propWave,
@@ -51515,7 +51583,7 @@ function TowerDefenseBoard({
51515
51583
  result: propResult,
51516
51584
  waveActive: propWaveActive,
51517
51585
  towerCost = 25,
51518
- scale = 0.45,
51586
+ scale = 0.25,
51519
51587
  unitScale = 1,
51520
51588
  spriteHeightRatio = 1.5,
51521
51589
  spriteMaxWidthRatio = 0.6,
@@ -51523,15 +51591,19 @@ function TowerDefenseBoard({
51523
51591
  startWaveEvent,
51524
51592
  playAgainEvent,
51525
51593
  gameEndEvent,
51594
+ moveHeroEvent,
51526
51595
  className
51527
51596
  }) {
51528
51597
  const board = boardEntity(entity) ?? {};
51529
51598
  const eventBus = useEventBus();
51530
51599
  const { t } = hooks.useTranslate();
51531
- const tiles = propTiles ?? rows(board.tiles);
51532
- const path = propPath ?? rows(board.path);
51600
+ const rawTiles = propTiles ?? rows(board.tiles);
51601
+ const tiles = rawTiles.length >= TD_GRID_W * TD_GRID_H ? rawTiles : DEFAULT_TD_TILES;
51602
+ const rawPath = propPath ?? rows(board.path);
51603
+ const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
51533
51604
  const towers = propTowers ?? rows(board.towers);
51534
51605
  const creeps = propCreeps ?? rows(board.creeps);
51606
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
51535
51607
  const gold = propGold ?? num(board.gold, 100);
51536
51608
  const lives = propLives ?? num(board.lives, 20);
51537
51609
  const wave = propWave ?? num(board.wave, 1);
@@ -51549,6 +51621,31 @@ function TowerDefenseBoard({
51549
51621
  if (result === "none") {
51550
51622
  emittedGameEnd.current = false;
51551
51623
  }
51624
+ const moveHeroEventRef = React90.useRef(moveHeroEvent);
51625
+ moveHeroEventRef.current = moveHeroEvent;
51626
+ const resultRef = React90.useRef(result);
51627
+ resultRef.current = result;
51628
+ React90.useEffect(() => {
51629
+ function onKeyDown(e) {
51630
+ const evt = moveHeroEventRef.current;
51631
+ if (!evt || resultRef.current !== "none") return;
51632
+ let dx = 0;
51633
+ let dy = 0;
51634
+ if (e.key === "ArrowUp") {
51635
+ dy = -1;
51636
+ } else if (e.key === "ArrowDown") {
51637
+ dy = 1;
51638
+ } else if (e.key === "ArrowLeft") {
51639
+ dx = -1;
51640
+ } else if (e.key === "ArrowRight") {
51641
+ dx = 1;
51642
+ } else return;
51643
+ e.preventDefault();
51644
+ eventBus.emit(`UI:${evt}`, { dx, dy });
51645
+ }
51646
+ window.addEventListener("keydown", onKeyDown);
51647
+ return () => window.removeEventListener("keydown", onKeyDown);
51648
+ }, [eventBus]);
51552
51649
  const towerPositions = React90.useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
51553
51650
  const pathPositions = React90.useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
51554
51651
  const validMoves = React90.useMemo(() => {
@@ -51560,7 +51657,8 @@ function TowerDefenseBoard({
51560
51657
  const isoTiles = React90.useMemo(() => tilesToIso(tiles), [tiles]);
51561
51658
  const towerUnits = React90.useMemo(() => towersToUnits(towers), [towers]);
51562
51659
  const creepUnits = React90.useMemo(() => creepsToUnits(creeps), [creeps]);
51563
- const isoUnits = React90.useMemo(() => [...towerUnits, ...creepUnits], [towerUnits, creepUnits]);
51660
+ const heroUnit = React90.useMemo(() => heroToUnit(hero), [hero]);
51661
+ const isoUnits = React90.useMemo(() => [...towerUnits, ...creepUnits, heroUnit], [towerUnits, creepUnits, heroUnit]);
51564
51662
  const pathFeatures = React90.useMemo(() => pathToFeatures(path), [path]);
51565
51663
  const handleTileClick = React90.useCallback((x, y) => {
51566
51664
  if (result !== "none") return;
@@ -51659,7 +51757,7 @@ function TowerDefenseBoard({
51659
51757
  ] }) })
51660
51758
  ] });
51661
51759
  }
51662
- var CDN6, TERRAIN_SPRITES, TOWER_SPRITE, CREEP_SPRITE;
51760
+ var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE, HERO_SPRITE;
51663
51761
  var init_TowerDefenseBoard = __esm({
51664
51762
  "components/game/organisms/TowerDefenseBoard.tsx"() {
51665
51763
  "use client";
@@ -51672,13 +51770,70 @@ var init_TowerDefenseBoard = __esm({
51672
51770
  init_IsometricCanvas();
51673
51771
  init_boardEntity();
51674
51772
  CDN6 = "https://almadar-kflow-assets.web.app/shared/";
51773
+ TD_GRID_W = 16;
51774
+ TD_GRID_H = 16;
51675
51775
  TERRAIN_SPRITES = {
51676
51776
  ground: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`,
51677
51777
  path: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_09.png`,
51678
- wall: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`
51679
- };
51680
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
51681
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
51778
+ wall: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`,
51779
+ grass: `${CDN6}isometric-dungeon/Isometric/dirt_E.png`,
51780
+ dirt: `${CDN6}isometric-dungeon/Isometric/dirtTiles_E.png`
51781
+ };
51782
+ DEFAULT_TD_PATH = [
51783
+ { x: 2, y: 0 },
51784
+ { x: 2, y: 1 },
51785
+ { x: 2, y: 2 },
51786
+ { x: 2, y: 3 },
51787
+ { x: 3, y: 3 },
51788
+ { x: 4, y: 3 },
51789
+ { x: 5, y: 3 },
51790
+ { x: 6, y: 3 },
51791
+ { x: 7, y: 3 },
51792
+ { x: 8, y: 3 },
51793
+ { x: 9, y: 3 },
51794
+ { x: 10, y: 3 },
51795
+ { x: 11, y: 3 },
51796
+ { x: 12, y: 3 },
51797
+ { x: 13, y: 3 },
51798
+ { x: 13, y: 4 },
51799
+ { x: 13, y: 5 },
51800
+ { x: 13, y: 6 },
51801
+ { x: 13, y: 7 },
51802
+ { x: 12, y: 7 },
51803
+ { x: 11, y: 7 },
51804
+ { x: 10, y: 7 },
51805
+ { x: 9, y: 7 },
51806
+ { x: 8, y: 7 },
51807
+ { x: 7, y: 7 },
51808
+ { x: 6, y: 7 },
51809
+ { x: 5, y: 7 },
51810
+ { x: 4, y: 7 },
51811
+ { x: 3, y: 7 },
51812
+ { x: 2, y: 7 },
51813
+ { x: 2, y: 8 },
51814
+ { x: 2, y: 9 },
51815
+ { x: 2, y: 10 },
51816
+ { x: 2, y: 11 },
51817
+ { x: 3, y: 11 },
51818
+ { x: 4, y: 11 },
51819
+ { x: 5, y: 11 },
51820
+ { x: 6, y: 11 },
51821
+ { x: 7, y: 11 },
51822
+ { x: 8, y: 11 },
51823
+ { x: 9, y: 11 },
51824
+ { x: 10, y: 11 },
51825
+ { x: 11, y: 11 },
51826
+ { x: 12, y: 11 },
51827
+ { x: 13, y: 11 },
51828
+ { x: 13, y: 12 },
51829
+ { x: 13, y: 13 },
51830
+ { x: 13, y: 14 },
51831
+ { x: 13, y: 15 }
51832
+ ];
51833
+ DEFAULT_TD_TILES = buildDefaultTDTiles();
51834
+ TOWER_SPRITE = `${CDN6}sprite-sheets/guardian-sprite-sheet-se.png`;
51835
+ CREEP_SPRITE = `${CDN6}sprite-sheets/scrapper-sprite-sheet-se.png`;
51836
+ HERO_SPRITE = `${CDN6}sprite-sheets/amir-sprite-sheet-se.png`;
51682
51837
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
51683
51838
  }
51684
51839
  });
@@ -51953,6 +52108,17 @@ function heroPosition(h) {
51953
52108
  function heroMovement(h) {
51954
52109
  return num(h.movement);
51955
52110
  }
52111
+ function buildDefaultWorldTiles() {
52112
+ const tiles = [];
52113
+ for (let y = 0; y < WORLD_GRID_H; y++) {
52114
+ for (let x = 0; x < WORLD_GRID_W; x++) {
52115
+ const isBorder = x === 0 || y === 0 || x === WORLD_GRID_W - 1 || y === WORLD_GRID_H - 1;
52116
+ const def = isBorder ? WORLD_TERRAIN_DEFS[3] : WORLD_TERRAIN_DEFS[(x * 5 + y * 3 + (x ^ y)) % (WORLD_TERRAIN_DEFS.length - 1)];
52117
+ tiles.push({ x, y, terrain: def.terrain, terrainSprite: def.sprite, passable: def.passable });
52118
+ }
52119
+ }
52120
+ return tiles;
52121
+ }
51956
52122
  function defaultIsInRange(from, to, range) {
51957
52123
  return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
51958
52124
  }
@@ -51963,7 +52129,7 @@ function WorldMapBoard({
51963
52129
  features: propFeatures,
51964
52130
  assetManifest: propAssetManifest,
51965
52131
  isLoading,
51966
- scale = 0.4,
52132
+ scale = 0.25,
51967
52133
  unitScale = 2.5,
51968
52134
  spriteHeightRatio = 1.5,
51969
52135
  spriteMaxWidthRatio = 0.6,
@@ -52007,7 +52173,8 @@ function WorldMapBoard({
52007
52173
  })),
52008
52174
  [entityTiles]
52009
52175
  );
52010
- const tiles = propTiles ?? derivedTiles;
52176
+ const rawTiles = propTiles ?? (derivedTiles.length > 0 ? derivedTiles : null);
52177
+ const tiles = rawTiles != null && rawTiles.length >= WORLD_GRID_W * WORLD_GRID_H ? rawTiles : DEFAULT_WORLD_TILES;
52011
52178
  const baseUnits = React90.useMemo(
52012
52179
  () => propUnits ?? entityUnits.map((u) => ({
52013
52180
  id: str(u.id),
@@ -52217,6 +52384,7 @@ function WorldMapBoard({
52217
52384
  footer && footer(ctx)
52218
52385
  ] });
52219
52386
  }
52387
+ var WORLD_CDN, WORLD_GRID_W, WORLD_GRID_H, WORLD_TERRAIN_DEFS, DEFAULT_WORLD_TILES;
52220
52388
  var init_WorldMapBoard = __esm({
52221
52389
  "components/game/organisms/WorldMapBoard.tsx"() {
52222
52390
  "use client";
@@ -52227,6 +52395,17 @@ var init_WorldMapBoard = __esm({
52227
52395
  init_IsometricCanvas();
52228
52396
  init_boardEntity();
52229
52397
  init_isometric();
52398
+ WORLD_CDN = "https://almadar-kflow-assets.web.app/shared";
52399
+ WORLD_GRID_W = 16;
52400
+ WORLD_GRID_H = 16;
52401
+ WORLD_TERRAIN_DEFS = [
52402
+ { terrain: "grass", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/dirt_E.png`, passable: true },
52403
+ { terrain: "dirt", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`, passable: true },
52404
+ { terrain: "forest", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/planks_E.png`, passable: true },
52405
+ { terrain: "stone", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`, passable: false },
52406
+ { terrain: "castle", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`, passable: true }
52407
+ ];
52408
+ DEFAULT_WORLD_TILES = buildDefaultWorldTiles();
52230
52409
  WorldMapBoard.displayName = "WorldMapBoard";
52231
52410
  }
52232
52411
  });