@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.
@@ -11611,13 +11611,29 @@ var init_boardEntity = __esm({
11611
11611
  "components/game/organisms/boardEntity.ts"() {
11612
11612
  }
11613
11613
  });
11614
+ function buildDefaultBattleTiles() {
11615
+ const tiles = [];
11616
+ for (let y = 0; y < BATTLE_GRID_H; y++) {
11617
+ for (let x = 0; x < BATTLE_GRID_W; x++) {
11618
+ const variant = (x * 3 + y * 7 + (x ^ y)) % BATTLE_TERRAIN_SPRITES.length;
11619
+ tiles.push({
11620
+ x,
11621
+ y,
11622
+ terrain: ["grass", "dirt", "planks", "stone", "stone"][variant],
11623
+ terrainSprite: BATTLE_TERRAIN_SPRITES[variant],
11624
+ passable: true
11625
+ });
11626
+ }
11627
+ }
11628
+ return tiles;
11629
+ }
11614
11630
  function BattleBoard({
11615
11631
  entity,
11616
11632
  tiles: propTiles,
11617
11633
  units: propUnits,
11618
11634
  features: propFeatures,
11619
11635
  assetManifest: propAssetManifest,
11620
- scale = 0.45,
11636
+ scale = 0.25,
11621
11637
  unitScale = 1,
11622
11638
  spriteHeightRatio = 1.5,
11623
11639
  spriteMaxWidthRatio = 0.6,
@@ -11644,10 +11660,11 @@ function BattleBoard({
11644
11660
  className
11645
11661
  }) {
11646
11662
  const board = boardEntity(entity) ?? {};
11647
- const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
11663
+ const rawTiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
11664
+ const tiles = rawTiles.length === 0 ? DEFAULT_BATTLE_TILES : rawTiles;
11648
11665
  const features = propFeatures ?? (Array.isArray(board.features) ? board.features : []);
11649
- const boardWidth = num(board.gridWidth ?? board.boardWidth, 8);
11650
- const boardHeight = num(board.gridHeight ?? board.boardHeight, 6);
11666
+ const boardWidth = num(board.gridWidth ?? board.boardWidth, BATTLE_GRID_W);
11667
+ const boardHeight = num(board.gridHeight ?? board.boardHeight, BATTLE_GRID_H);
11651
11668
  const assetManifest = propAssetManifest ?? board.assetManifest;
11652
11669
  const backgroundImage = board.backgroundImage;
11653
11670
  const units = rows(board.units);
@@ -11969,6 +11986,7 @@ function BattleBoard({
11969
11986
  ] }) }))
11970
11987
  ] });
11971
11988
  }
11989
+ var BATTLE_CDN, BATTLE_GRID_W, BATTLE_GRID_H, BATTLE_TERRAIN_SPRITES, DEFAULT_BATTLE_TILES;
11972
11990
  var init_BattleBoard = __esm({
11973
11991
  "components/game/organisms/BattleBoard.tsx"() {
11974
11992
  "use client";
@@ -11981,6 +11999,17 @@ var init_BattleBoard = __esm({
11981
11999
  init_IsometricCanvas();
11982
12000
  init_boardEntity();
11983
12001
  init_isometric();
12002
+ BATTLE_CDN = "https://almadar-kflow-assets.web.app/shared";
12003
+ BATTLE_GRID_W = 16;
12004
+ BATTLE_GRID_H = 16;
12005
+ BATTLE_TERRAIN_SPRITES = [
12006
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`,
12007
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`,
12008
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`,
12009
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`,
12010
+ `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`
12011
+ ];
12012
+ DEFAULT_BATTLE_TILES = buildDefaultBattleTiles();
11984
12013
  BattleBoard.displayName = "BattleBoard";
11985
12014
  }
11986
12015
  });
@@ -11988,7 +12017,7 @@ function BattleTemplate({
11988
12017
  entity,
11989
12018
  scale = 0.45,
11990
12019
  unitScale = 1,
11991
- tiles = DEFAULT_BATTLE_TILES,
12020
+ tiles = DEFAULT_BATTLE_TILES2,
11992
12021
  units = DEFAULT_BATTLE_UNITS,
11993
12022
  features = DEFAULT_BATTLE_FEATURES,
11994
12023
  assetManifest = DEFAULT_BATTLE_MANIFEST,
@@ -12017,12 +12046,12 @@ function BattleTemplate({
12017
12046
  }
12018
12047
  );
12019
12048
  }
12020
- var CDN, DEFAULT_BATTLE_TILES, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12049
+ var CDN, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12021
12050
  var init_BattleTemplate = __esm({
12022
12051
  "components/game/templates/BattleTemplate.tsx"() {
12023
12052
  init_BattleBoard();
12024
12053
  CDN = "https://almadar-kflow-assets.web.app/shared";
12025
- DEFAULT_BATTLE_TILES = [
12054
+ DEFAULT_BATTLE_TILES2 = [
12026
12055
  { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12027
12056
  { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12028
12057
  { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
@@ -29191,13 +29220,13 @@ var init_MapView = __esm({
29191
29220
  shadowSize: [41, 41]
29192
29221
  });
29193
29222
  L.Marker.prototype.options.icon = defaultIcon;
29194
- const { useEffect: useEffect81, useRef: useRef75, useCallback: useCallback119, useState: useState113 } = React81__namespace.default;
29223
+ const { useEffect: useEffect82, useRef: useRef75, useCallback: useCallback119, useState: useState113 } = React81__namespace.default;
29195
29224
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29196
29225
  const { useEventBus: useEventBus4 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29197
29226
  function MapUpdater({ centerLat, centerLng, zoom }) {
29198
29227
  const map = useMap();
29199
29228
  const prevRef = useRef75({ centerLat, centerLng, zoom });
29200
- useEffect81(() => {
29229
+ useEffect82(() => {
29201
29230
  const prev = prevRef.current;
29202
29231
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
29203
29232
  map.setView([centerLat, centerLng], zoom);
@@ -29208,7 +29237,7 @@ var init_MapView = __esm({
29208
29237
  }
29209
29238
  function MapClickHandler({ onMapClick }) {
29210
29239
  const map = useMap();
29211
- useEffect81(() => {
29240
+ useEffect82(() => {
29212
29241
  if (!onMapClick) return;
29213
29242
  const handler = (e) => {
29214
29243
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -41885,7 +41914,6 @@ var init_GameCanvas3D2 = __esm({
41885
41914
  selectedTileIds = [],
41886
41915
  selectedUnitId = null,
41887
41916
  unitScale = 1,
41888
- scale = 0.45,
41889
41917
  children
41890
41918
  }, ref) => {
41891
41919
  const containerRef = React81.useRef(null);
@@ -42332,7 +42360,7 @@ var init_GameCanvas3D2 = __esm({
42332
42360
  fadeStrength: 1
42333
42361
  }
42334
42362
  ),
42335
- /* @__PURE__ */ jsxRuntime.jsxs("group", { scale, children: [
42363
+ /* @__PURE__ */ jsxRuntime.jsxs("group", { children: [
42336
42364
  tiles.map((tile, index) => {
42337
42365
  const position = gridToWorld(
42338
42366
  tile.x,
@@ -44475,6 +44503,35 @@ var init_PricingPageTemplate = __esm({
44475
44503
  PricingPageTemplate.displayName = "PricingPageTemplate";
44476
44504
  }
44477
44505
  });
44506
+ function dungeonTerrain(x, y, stairsX, stairsY) {
44507
+ const isBorder = x === 0 || y === 0 || x === DUNGEON_GRID_W - 1 || y === DUNGEON_GRID_H - 1;
44508
+ const isPillar = x % 4 === 0 && y % 4 === 0 && !isBorder;
44509
+ const isWall = isBorder || isPillar;
44510
+ if (x === stairsX && y === stairsY) {
44511
+ return { terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` };
44512
+ }
44513
+ if (isWall) {
44514
+ return { terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` };
44515
+ }
44516
+ const variant = (x * 3 + y * 7) % 5;
44517
+ const sprites = [
44518
+ `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`,
44519
+ `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png`,
44520
+ `${CDN4}/isometric-dungeon/Isometric/planks_E.png`,
44521
+ `${CDN4}/isometric-dungeon/Isometric/stoneTile_E.png`,
44522
+ `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`
44523
+ ];
44524
+ return { terrain: "floor", passable: true, terrainSprite: sprites[variant] };
44525
+ }
44526
+ function buildDefaultDungeonTiles(stairsX, stairsY) {
44527
+ const tiles = [];
44528
+ for (let y = 0; y < DUNGEON_GRID_H; y++) {
44529
+ for (let x = 0; x < DUNGEON_GRID_W; x++) {
44530
+ tiles.push({ x, y, ...dungeonTerrain(x, y, stairsX, stairsY) });
44531
+ }
44532
+ }
44533
+ return tiles;
44534
+ }
44478
44535
  function RoguelikeBoard({
44479
44536
  entity,
44480
44537
  tiles: propTiles,
@@ -44490,7 +44547,7 @@ function RoguelikeBoard({
44490
44547
  stairsX: propStairsX,
44491
44548
  stairsY: propStairsY,
44492
44549
  assetManifest: propAssetManifest,
44493
- scale = 0.45,
44550
+ scale = 0.25,
44494
44551
  unitScale = 1,
44495
44552
  spriteHeightRatio = 1.5,
44496
44553
  spriteMaxWidthRatio = 0.6,
@@ -44500,7 +44557,9 @@ function RoguelikeBoard({
44500
44557
  className
44501
44558
  }) {
44502
44559
  const board = boardEntity(entity) ?? {};
44503
- const tiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : DEFAULT_TILES2);
44560
+ const resolvedStairsX = propStairsX ?? num(board.stairsX, 14);
44561
+ const resolvedStairsY = propStairsY ?? num(board.stairsY, 14);
44562
+ const tiles = propTiles ?? (Array.isArray(board.tiles) && board.tiles.length >= DUNGEON_GRID_W * DUNGEON_GRID_H ? board.tiles : buildDefaultDungeonTiles(resolvedStairsX, resolvedStairsY));
44504
44563
  const enemies = propEnemies ?? (Array.isArray(board.enemies) ? board.enemies : DEFAULT_ENEMIES);
44505
44564
  const items = propItems ?? (Array.isArray(board.items) ? board.items : DEFAULT_ITEMS);
44506
44565
  const player = propPlayer ?? board.player ?? { x: 1, y: 1 };
@@ -44510,8 +44569,8 @@ function RoguelikeBoard({
44510
44569
  const depth = propDepth ?? num(board.depth, 1);
44511
44570
  const result = propResult ?? (str(board.result) || "none");
44512
44571
  const phase = propPhase ?? (str(board.phase) || "player_turn");
44513
- propStairsX ?? num(board.stairsX, 3);
44514
- propStairsY ?? num(board.stairsY, 3);
44572
+ propStairsX ?? num(board.stairsX, 14);
44573
+ propStairsY ?? num(board.stairsY, 14);
44515
44574
  const eventBus = useEventBus();
44516
44575
  const { t } = hooks.useTranslate();
44517
44576
  const [hoveredTile, setHoveredTile] = React81.useState(null);
@@ -44687,7 +44746,7 @@ function RoguelikeBoard({
44687
44746
  ] }) })
44688
44747
  ] });
44689
44748
  }
44690
- var CDN4, DEFAULT_TILES2, DEFAULT_ENEMIES, DEFAULT_ITEMS, FEATURE_SPRITE;
44749
+ var CDN4, DUNGEON_GRID_W, DUNGEON_GRID_H, DEFAULT_ENEMIES, DEFAULT_ITEMS, FEATURE_SPRITE;
44691
44750
  var init_RoguelikeBoard = __esm({
44692
44751
  "components/game/organisms/RoguelikeBoard.tsx"() {
44693
44752
  "use client";
@@ -44700,39 +44759,19 @@ var init_RoguelikeBoard = __esm({
44700
44759
  init_IsometricCanvas();
44701
44760
  init_boardEntity();
44702
44761
  CDN4 = "https://almadar-kflow-assets.web.app/shared";
44703
- DEFAULT_TILES2 = [
44704
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44705
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44706
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44707
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44708
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44709
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44710
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
44711
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
44712
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
44713
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44714
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44715
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
44716
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
44717
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
44718
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44719
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44720
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
44721
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
44722
- { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` },
44723
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44724
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44725
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44726
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44727
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
44728
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` }
44729
- ];
44762
+ DUNGEON_GRID_W = 16;
44763
+ DUNGEON_GRID_H = 16;
44764
+ buildDefaultDungeonTiles(14, 14);
44730
44765
  DEFAULT_ENEMIES = [
44731
- { id: "e1", x: 3, y: 1, hp: 5, attack: 2 },
44732
- { id: "e2", x: 1, y: 3, hp: 4, attack: 1 }
44766
+ { id: "e1", x: 5, y: 2, hp: 5, attack: 2 },
44767
+ { id: "e2", x: 9, y: 6, hp: 4, attack: 1 },
44768
+ { id: "e3", x: 3, y: 10, hp: 6, attack: 2 },
44769
+ { id: "e4", x: 12, y: 8, hp: 5, attack: 3 }
44733
44770
  ];
44734
44771
  DEFAULT_ITEMS = [
44735
- { id: "i1", x: 2, y: 2, kind: "health_potion" }
44772
+ { id: "i1", x: 3, y: 3, kind: "health_potion" },
44773
+ { id: "i2", x: 7, y: 9, kind: "sword" },
44774
+ { id: "i3", x: 11, y: 5, kind: "shield" }
44736
44775
  ];
44737
44776
  FEATURE_SPRITE = {
44738
44777
  health_potion: `${CDN4}/isometric-dungeon/Isometric/chestClosed_E.png`,
@@ -48959,6 +48998,22 @@ var init_ToastSlot = __esm({
48959
48998
  ToastSlot.displayName = "ToastSlot";
48960
48999
  }
48961
49000
  });
49001
+ function buildDefaultTDTiles() {
49002
+ const pathSet = new Set(DEFAULT_TD_PATH.map((p2) => `${p2.x},${p2.y}`));
49003
+ const tiles = [];
49004
+ for (let y = 0; y < TD_GRID_H; y++) {
49005
+ for (let x = 0; x < TD_GRID_W; x++) {
49006
+ if (pathSet.has(`${x},${y}`)) {
49007
+ tiles.push({ x, y, terrain: "path", passable: false, terrainSprite: TERRAIN_SPRITES.path });
49008
+ } else {
49009
+ const variant = (x * 3 + y * 5 + (x ^ y)) % 3;
49010
+ const terrainKey = ["ground", "grass", "dirt"][variant];
49011
+ tiles.push({ x, y, terrain: terrainKey, passable: true, terrainSprite: TERRAIN_SPRITES[terrainKey] ?? TERRAIN_SPRITES.ground });
49012
+ }
49013
+ }
49014
+ }
49015
+ return tiles;
49016
+ }
48962
49017
  function tilesToIso(tiles) {
48963
49018
  return tiles.map((t) => ({
48964
49019
  x: t.x,
@@ -49001,12 +49056,25 @@ function pathToFeatures(path) {
49001
49056
  sprite: `${CDN6}world-map/road_straight.png`
49002
49057
  }));
49003
49058
  }
49059
+ function heroToUnit(hero) {
49060
+ return {
49061
+ id: hero.id,
49062
+ position: { x: hero.x, y: hero.y },
49063
+ name: "Hero",
49064
+ team: "player",
49065
+ sprite: HERO_SPRITE,
49066
+ unitType: "amir",
49067
+ health: 1,
49068
+ maxHealth: 1
49069
+ };
49070
+ }
49004
49071
  function TowerDefenseBoard({
49005
49072
  entity,
49006
49073
  tiles: propTiles,
49007
49074
  path: propPath,
49008
49075
  towers: propTowers,
49009
49076
  creeps: propCreeps,
49077
+ hero: propHero,
49010
49078
  gold: propGold,
49011
49079
  lives: propLives,
49012
49080
  wave: propWave,
@@ -49014,7 +49082,7 @@ function TowerDefenseBoard({
49014
49082
  result: propResult,
49015
49083
  waveActive: propWaveActive,
49016
49084
  towerCost = 25,
49017
- scale = 0.45,
49085
+ scale = 0.25,
49018
49086
  unitScale = 1,
49019
49087
  spriteHeightRatio = 1.5,
49020
49088
  spriteMaxWidthRatio = 0.6,
@@ -49022,15 +49090,19 @@ function TowerDefenseBoard({
49022
49090
  startWaveEvent,
49023
49091
  playAgainEvent,
49024
49092
  gameEndEvent,
49093
+ moveHeroEvent,
49025
49094
  className
49026
49095
  }) {
49027
49096
  const board = boardEntity(entity) ?? {};
49028
49097
  const eventBus = useEventBus();
49029
49098
  const { t } = hooks.useTranslate();
49030
- const tiles = propTiles ?? rows(board.tiles);
49031
- const path = propPath ?? rows(board.path);
49099
+ const rawTiles = propTiles ?? rows(board.tiles);
49100
+ const tiles = rawTiles.length >= TD_GRID_W * TD_GRID_H ? rawTiles : DEFAULT_TD_TILES;
49101
+ const rawPath = propPath ?? rows(board.path);
49102
+ const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
49032
49103
  const towers = propTowers ?? rows(board.towers);
49033
49104
  const creeps = propCreeps ?? rows(board.creeps);
49105
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
49034
49106
  const gold = propGold ?? num(board.gold, 100);
49035
49107
  const lives = propLives ?? num(board.lives, 20);
49036
49108
  const wave = propWave ?? num(board.wave, 1);
@@ -49048,6 +49120,31 @@ function TowerDefenseBoard({
49048
49120
  if (result === "none") {
49049
49121
  emittedGameEnd.current = false;
49050
49122
  }
49123
+ const moveHeroEventRef = React81.useRef(moveHeroEvent);
49124
+ moveHeroEventRef.current = moveHeroEvent;
49125
+ const resultRef = React81.useRef(result);
49126
+ resultRef.current = result;
49127
+ React81.useEffect(() => {
49128
+ function onKeyDown(e) {
49129
+ const evt = moveHeroEventRef.current;
49130
+ if (!evt || resultRef.current !== "none") return;
49131
+ let dx = 0;
49132
+ let dy = 0;
49133
+ if (e.key === "ArrowUp") {
49134
+ dy = -1;
49135
+ } else if (e.key === "ArrowDown") {
49136
+ dy = 1;
49137
+ } else if (e.key === "ArrowLeft") {
49138
+ dx = -1;
49139
+ } else if (e.key === "ArrowRight") {
49140
+ dx = 1;
49141
+ } else return;
49142
+ e.preventDefault();
49143
+ eventBus.emit(`UI:${evt}`, { dx, dy });
49144
+ }
49145
+ window.addEventListener("keydown", onKeyDown);
49146
+ return () => window.removeEventListener("keydown", onKeyDown);
49147
+ }, [eventBus]);
49051
49148
  const towerPositions = React81.useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
49052
49149
  const pathPositions = React81.useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
49053
49150
  const validMoves = React81.useMemo(() => {
@@ -49059,7 +49156,8 @@ function TowerDefenseBoard({
49059
49156
  const isoTiles = React81.useMemo(() => tilesToIso(tiles), [tiles]);
49060
49157
  const towerUnits = React81.useMemo(() => towersToUnits(towers), [towers]);
49061
49158
  const creepUnits = React81.useMemo(() => creepsToUnits(creeps), [creeps]);
49062
- const isoUnits = React81.useMemo(() => [...towerUnits, ...creepUnits], [towerUnits, creepUnits]);
49159
+ const heroUnit = React81.useMemo(() => heroToUnit(hero), [hero]);
49160
+ const isoUnits = React81.useMemo(() => [...towerUnits, ...creepUnits, heroUnit], [towerUnits, creepUnits, heroUnit]);
49063
49161
  const pathFeatures = React81.useMemo(() => pathToFeatures(path), [path]);
49064
49162
  const handleTileClick = React81.useCallback((x, y) => {
49065
49163
  if (result !== "none") return;
@@ -49158,7 +49256,7 @@ function TowerDefenseBoard({
49158
49256
  ] }) })
49159
49257
  ] });
49160
49258
  }
49161
- var CDN6, TERRAIN_SPRITES, TOWER_SPRITE, CREEP_SPRITE;
49259
+ var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE, HERO_SPRITE;
49162
49260
  var init_TowerDefenseBoard = __esm({
49163
49261
  "components/game/organisms/TowerDefenseBoard.tsx"() {
49164
49262
  "use client";
@@ -49171,13 +49269,70 @@ var init_TowerDefenseBoard = __esm({
49171
49269
  init_IsometricCanvas();
49172
49270
  init_boardEntity();
49173
49271
  CDN6 = "https://almadar-kflow-assets.web.app/shared/";
49272
+ TD_GRID_W = 16;
49273
+ TD_GRID_H = 16;
49174
49274
  TERRAIN_SPRITES = {
49175
49275
  ground: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`,
49176
49276
  path: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_09.png`,
49177
- wall: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`
49178
- };
49179
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
49180
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
49277
+ wall: `${CDN6}isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`,
49278
+ grass: `${CDN6}isometric-dungeon/Isometric/dirt_E.png`,
49279
+ dirt: `${CDN6}isometric-dungeon/Isometric/dirtTiles_E.png`
49280
+ };
49281
+ DEFAULT_TD_PATH = [
49282
+ { x: 2, y: 0 },
49283
+ { x: 2, y: 1 },
49284
+ { x: 2, y: 2 },
49285
+ { x: 2, y: 3 },
49286
+ { x: 3, y: 3 },
49287
+ { x: 4, y: 3 },
49288
+ { x: 5, y: 3 },
49289
+ { x: 6, y: 3 },
49290
+ { x: 7, y: 3 },
49291
+ { x: 8, y: 3 },
49292
+ { x: 9, y: 3 },
49293
+ { x: 10, y: 3 },
49294
+ { x: 11, y: 3 },
49295
+ { x: 12, y: 3 },
49296
+ { x: 13, y: 3 },
49297
+ { x: 13, y: 4 },
49298
+ { x: 13, y: 5 },
49299
+ { x: 13, y: 6 },
49300
+ { x: 13, y: 7 },
49301
+ { x: 12, y: 7 },
49302
+ { x: 11, y: 7 },
49303
+ { x: 10, y: 7 },
49304
+ { x: 9, y: 7 },
49305
+ { x: 8, y: 7 },
49306
+ { x: 7, y: 7 },
49307
+ { x: 6, y: 7 },
49308
+ { x: 5, y: 7 },
49309
+ { x: 4, y: 7 },
49310
+ { x: 3, y: 7 },
49311
+ { x: 2, y: 7 },
49312
+ { x: 2, y: 8 },
49313
+ { x: 2, y: 9 },
49314
+ { x: 2, y: 10 },
49315
+ { x: 2, y: 11 },
49316
+ { x: 3, y: 11 },
49317
+ { x: 4, y: 11 },
49318
+ { x: 5, y: 11 },
49319
+ { x: 6, y: 11 },
49320
+ { x: 7, y: 11 },
49321
+ { x: 8, y: 11 },
49322
+ { x: 9, y: 11 },
49323
+ { x: 10, y: 11 },
49324
+ { x: 11, y: 11 },
49325
+ { x: 12, y: 11 },
49326
+ { x: 13, y: 11 },
49327
+ { x: 13, y: 12 },
49328
+ { x: 13, y: 13 },
49329
+ { x: 13, y: 14 },
49330
+ { x: 13, y: 15 }
49331
+ ];
49332
+ DEFAULT_TD_TILES = buildDefaultTDTiles();
49333
+ TOWER_SPRITE = `${CDN6}sprite-sheets/guardian-sprite-sheet-se.png`;
49334
+ CREEP_SPRITE = `${CDN6}sprite-sheets/scrapper-sprite-sheet-se.png`;
49335
+ HERO_SPRITE = `${CDN6}sprite-sheets/amir-sprite-sheet-se.png`;
49181
49336
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
49182
49337
  }
49183
49338
  });
@@ -49452,6 +49607,17 @@ function heroPosition(h) {
49452
49607
  function heroMovement(h) {
49453
49608
  return num(h.movement);
49454
49609
  }
49610
+ function buildDefaultWorldTiles() {
49611
+ const tiles = [];
49612
+ for (let y = 0; y < WORLD_GRID_H; y++) {
49613
+ for (let x = 0; x < WORLD_GRID_W; x++) {
49614
+ const isBorder = x === 0 || y === 0 || x === WORLD_GRID_W - 1 || y === WORLD_GRID_H - 1;
49615
+ const def = isBorder ? WORLD_TERRAIN_DEFS[3] : WORLD_TERRAIN_DEFS[(x * 5 + y * 3 + (x ^ y)) % (WORLD_TERRAIN_DEFS.length - 1)];
49616
+ tiles.push({ x, y, terrain: def.terrain, terrainSprite: def.sprite, passable: def.passable });
49617
+ }
49618
+ }
49619
+ return tiles;
49620
+ }
49455
49621
  function defaultIsInRange(from, to, range) {
49456
49622
  return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
49457
49623
  }
@@ -49462,7 +49628,7 @@ function WorldMapBoard({
49462
49628
  features: propFeatures,
49463
49629
  assetManifest: propAssetManifest,
49464
49630
  isLoading,
49465
- scale = 0.4,
49631
+ scale = 0.25,
49466
49632
  unitScale = 2.5,
49467
49633
  spriteHeightRatio = 1.5,
49468
49634
  spriteMaxWidthRatio = 0.6,
@@ -49506,7 +49672,8 @@ function WorldMapBoard({
49506
49672
  })),
49507
49673
  [entityTiles]
49508
49674
  );
49509
- const tiles = propTiles ?? derivedTiles;
49675
+ const rawTiles = propTiles ?? (derivedTiles.length > 0 ? derivedTiles : null);
49676
+ const tiles = rawTiles != null && rawTiles.length >= WORLD_GRID_W * WORLD_GRID_H ? rawTiles : DEFAULT_WORLD_TILES;
49510
49677
  const baseUnits = React81.useMemo(
49511
49678
  () => propUnits ?? entityUnits.map((u) => ({
49512
49679
  id: str(u.id),
@@ -49716,6 +49883,7 @@ function WorldMapBoard({
49716
49883
  footer && footer(ctx)
49717
49884
  ] });
49718
49885
  }
49886
+ var WORLD_CDN, WORLD_GRID_W, WORLD_GRID_H, WORLD_TERRAIN_DEFS, DEFAULT_WORLD_TILES;
49719
49887
  var init_WorldMapBoard = __esm({
49720
49888
  "components/game/organisms/WorldMapBoard.tsx"() {
49721
49889
  "use client";
@@ -49726,6 +49894,17 @@ var init_WorldMapBoard = __esm({
49726
49894
  init_IsometricCanvas();
49727
49895
  init_boardEntity();
49728
49896
  init_isometric();
49897
+ WORLD_CDN = "https://almadar-kflow-assets.web.app/shared";
49898
+ WORLD_GRID_W = 16;
49899
+ WORLD_GRID_H = 16;
49900
+ WORLD_TERRAIN_DEFS = [
49901
+ { terrain: "grass", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/dirt_E.png`, passable: true },
49902
+ { terrain: "dirt", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`, passable: true },
49903
+ { terrain: "forest", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/planks_E.png`, passable: true },
49904
+ { terrain: "stone", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`, passable: false },
49905
+ { terrain: "castle", sprite: `${WORLD_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`, passable: true }
49906
+ ];
49907
+ DEFAULT_WORLD_TILES = buildDefaultWorldTiles();
49729
49908
  WorldMapBoard.displayName = "WorldMapBoard";
49730
49909
  }
49731
49910
  });