@almadar/ui 5.57.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.
@@ -32130,13 +32130,13 @@ var init_MapView = __esm({
32130
32130
  shadowSize: [41, 41]
32131
32131
  });
32132
32132
  L.Marker.prototype.options.icon = defaultIcon;
32133
- 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;
32134
32134
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
32135
32135
  const { useEventBus: useEventBus4 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
32136
32136
  function MapUpdater({ centerLat, centerLng, zoom }) {
32137
32137
  const map = useMap();
32138
32138
  const prevRef = useRef77({ centerLat, centerLng, zoom });
32139
- useEffect85(() => {
32139
+ useEffect86(() => {
32140
32140
  const prev = prevRef.current;
32141
32141
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
32142
32142
  map.setView([centerLat, centerLng], zoom);
@@ -32147,7 +32147,7 @@ var init_MapView = __esm({
32147
32147
  }
32148
32148
  function MapClickHandler({ onMapClick }) {
32149
32149
  const map = useMap();
32150
- useEffect85(() => {
32150
+ useEffect86(() => {
32151
32151
  if (!onMapClick) return;
32152
32152
  const handler = (e) => {
32153
32153
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -51557,12 +51557,25 @@ function pathToFeatures(path) {
51557
51557
  sprite: `${CDN6}world-map/road_straight.png`
51558
51558
  }));
51559
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
+ }
51560
51572
  function TowerDefenseBoard({
51561
51573
  entity,
51562
51574
  tiles: propTiles,
51563
51575
  path: propPath,
51564
51576
  towers: propTowers,
51565
51577
  creeps: propCreeps,
51578
+ hero: propHero,
51566
51579
  gold: propGold,
51567
51580
  lives: propLives,
51568
51581
  wave: propWave,
@@ -51578,6 +51591,7 @@ function TowerDefenseBoard({
51578
51591
  startWaveEvent,
51579
51592
  playAgainEvent,
51580
51593
  gameEndEvent,
51594
+ moveHeroEvent,
51581
51595
  className
51582
51596
  }) {
51583
51597
  const board = boardEntity(entity) ?? {};
@@ -51589,6 +51603,7 @@ function TowerDefenseBoard({
51589
51603
  const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
51590
51604
  const towers = propTowers ?? rows(board.towers);
51591
51605
  const creeps = propCreeps ?? rows(board.creeps);
51606
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
51592
51607
  const gold = propGold ?? num(board.gold, 100);
51593
51608
  const lives = propLives ?? num(board.lives, 20);
51594
51609
  const wave = propWave ?? num(board.wave, 1);
@@ -51606,6 +51621,31 @@ function TowerDefenseBoard({
51606
51621
  if (result === "none") {
51607
51622
  emittedGameEnd.current = false;
51608
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]);
51609
51649
  const towerPositions = React90.useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
51610
51650
  const pathPositions = React90.useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
51611
51651
  const validMoves = React90.useMemo(() => {
@@ -51617,7 +51657,8 @@ function TowerDefenseBoard({
51617
51657
  const isoTiles = React90.useMemo(() => tilesToIso(tiles), [tiles]);
51618
51658
  const towerUnits = React90.useMemo(() => towersToUnits(towers), [towers]);
51619
51659
  const creepUnits = React90.useMemo(() => creepsToUnits(creeps), [creeps]);
51620
- 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]);
51621
51662
  const pathFeatures = React90.useMemo(() => pathToFeatures(path), [path]);
51622
51663
  const handleTileClick = React90.useCallback((x, y) => {
51623
51664
  if (result !== "none") return;
@@ -51716,7 +51757,7 @@ function TowerDefenseBoard({
51716
51757
  ] }) })
51717
51758
  ] });
51718
51759
  }
51719
- var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, 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;
51720
51761
  var init_TowerDefenseBoard = __esm({
51721
51762
  "components/game/organisms/TowerDefenseBoard.tsx"() {
51722
51763
  "use client";
@@ -51790,8 +51831,9 @@ var init_TowerDefenseBoard = __esm({
51790
51831
  { x: 13, y: 15 }
51791
51832
  ];
51792
51833
  DEFAULT_TD_TILES = buildDefaultTDTiles();
51793
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
51794
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
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`;
51795
51837
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
51796
51838
  }
51797
51839
  });
package/dist/avl/index.js CHANGED
@@ -32083,13 +32083,13 @@ var init_MapView = __esm({
32083
32083
  shadowSize: [41, 41]
32084
32084
  });
32085
32085
  L.Marker.prototype.options.icon = defaultIcon;
32086
- const { useEffect: useEffect85, useRef: useRef77, useCallback: useCallback125, useState: useState121 } = React90__default;
32086
+ const { useEffect: useEffect86, useRef: useRef77, useCallback: useCallback125, useState: useState121 } = React90__default;
32087
32087
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
32088
32088
  const { useEventBus: useEventBus4 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
32089
32089
  function MapUpdater({ centerLat, centerLng, zoom }) {
32090
32090
  const map = useMap();
32091
32091
  const prevRef = useRef77({ centerLat, centerLng, zoom });
32092
- useEffect85(() => {
32092
+ useEffect86(() => {
32093
32093
  const prev = prevRef.current;
32094
32094
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
32095
32095
  map.setView([centerLat, centerLng], zoom);
@@ -32100,7 +32100,7 @@ var init_MapView = __esm({
32100
32100
  }
32101
32101
  function MapClickHandler({ onMapClick }) {
32102
32102
  const map = useMap();
32103
- useEffect85(() => {
32103
+ useEffect86(() => {
32104
32104
  if (!onMapClick) return;
32105
32105
  const handler = (e) => {
32106
32106
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -51510,12 +51510,25 @@ function pathToFeatures(path) {
51510
51510
  sprite: `${CDN6}world-map/road_straight.png`
51511
51511
  }));
51512
51512
  }
51513
+ function heroToUnit(hero) {
51514
+ return {
51515
+ id: hero.id,
51516
+ position: { x: hero.x, y: hero.y },
51517
+ name: "Hero",
51518
+ team: "player",
51519
+ sprite: HERO_SPRITE,
51520
+ unitType: "amir",
51521
+ health: 1,
51522
+ maxHealth: 1
51523
+ };
51524
+ }
51513
51525
  function TowerDefenseBoard({
51514
51526
  entity,
51515
51527
  tiles: propTiles,
51516
51528
  path: propPath,
51517
51529
  towers: propTowers,
51518
51530
  creeps: propCreeps,
51531
+ hero: propHero,
51519
51532
  gold: propGold,
51520
51533
  lives: propLives,
51521
51534
  wave: propWave,
@@ -51531,6 +51544,7 @@ function TowerDefenseBoard({
51531
51544
  startWaveEvent,
51532
51545
  playAgainEvent,
51533
51546
  gameEndEvent,
51547
+ moveHeroEvent,
51534
51548
  className
51535
51549
  }) {
51536
51550
  const board = boardEntity(entity) ?? {};
@@ -51542,6 +51556,7 @@ function TowerDefenseBoard({
51542
51556
  const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
51543
51557
  const towers = propTowers ?? rows(board.towers);
51544
51558
  const creeps = propCreeps ?? rows(board.creeps);
51559
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
51545
51560
  const gold = propGold ?? num(board.gold, 100);
51546
51561
  const lives = propLives ?? num(board.lives, 20);
51547
51562
  const wave = propWave ?? num(board.wave, 1);
@@ -51559,6 +51574,31 @@ function TowerDefenseBoard({
51559
51574
  if (result === "none") {
51560
51575
  emittedGameEnd.current = false;
51561
51576
  }
51577
+ const moveHeroEventRef = useRef(moveHeroEvent);
51578
+ moveHeroEventRef.current = moveHeroEvent;
51579
+ const resultRef = useRef(result);
51580
+ resultRef.current = result;
51581
+ useEffect(() => {
51582
+ function onKeyDown(e) {
51583
+ const evt = moveHeroEventRef.current;
51584
+ if (!evt || resultRef.current !== "none") return;
51585
+ let dx = 0;
51586
+ let dy = 0;
51587
+ if (e.key === "ArrowUp") {
51588
+ dy = -1;
51589
+ } else if (e.key === "ArrowDown") {
51590
+ dy = 1;
51591
+ } else if (e.key === "ArrowLeft") {
51592
+ dx = -1;
51593
+ } else if (e.key === "ArrowRight") {
51594
+ dx = 1;
51595
+ } else return;
51596
+ e.preventDefault();
51597
+ eventBus.emit(`UI:${evt}`, { dx, dy });
51598
+ }
51599
+ window.addEventListener("keydown", onKeyDown);
51600
+ return () => window.removeEventListener("keydown", onKeyDown);
51601
+ }, [eventBus]);
51562
51602
  const towerPositions = useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
51563
51603
  const pathPositions = useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
51564
51604
  const validMoves = useMemo(() => {
@@ -51570,7 +51610,8 @@ function TowerDefenseBoard({
51570
51610
  const isoTiles = useMemo(() => tilesToIso(tiles), [tiles]);
51571
51611
  const towerUnits = useMemo(() => towersToUnits(towers), [towers]);
51572
51612
  const creepUnits = useMemo(() => creepsToUnits(creeps), [creeps]);
51573
- const isoUnits = useMemo(() => [...towerUnits, ...creepUnits], [towerUnits, creepUnits]);
51613
+ const heroUnit = useMemo(() => heroToUnit(hero), [hero]);
51614
+ const isoUnits = useMemo(() => [...towerUnits, ...creepUnits, heroUnit], [towerUnits, creepUnits, heroUnit]);
51574
51615
  const pathFeatures = useMemo(() => pathToFeatures(path), [path]);
51575
51616
  const handleTileClick = useCallback((x, y) => {
51576
51617
  if (result !== "none") return;
@@ -51669,7 +51710,7 @@ function TowerDefenseBoard({
51669
51710
  ] }) })
51670
51711
  ] });
51671
51712
  }
51672
- var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE;
51713
+ var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE, HERO_SPRITE;
51673
51714
  var init_TowerDefenseBoard = __esm({
51674
51715
  "components/game/organisms/TowerDefenseBoard.tsx"() {
51675
51716
  "use client";
@@ -51743,8 +51784,9 @@ var init_TowerDefenseBoard = __esm({
51743
51784
  { x: 13, y: 15 }
51744
51785
  ];
51745
51786
  DEFAULT_TD_TILES = buildDefaultTDTiles();
51746
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
51747
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
51787
+ TOWER_SPRITE = `${CDN6}sprite-sheets/guardian-sprite-sheet-se.png`;
51788
+ CREEP_SPRITE = `${CDN6}sprite-sheets/scrapper-sprite-sheet-se.png`;
51789
+ HERO_SPRITE = `${CDN6}sprite-sheets/amir-sprite-sheet-se.png`;
51748
51790
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
51749
51791
  }
51750
51792
  });
@@ -30,6 +30,11 @@ export interface TowerDefenseCreep {
30
30
  pathIndex: number;
31
31
  speed: number;
32
32
  }
33
+ export interface TowerDefenseHero {
34
+ id: string;
35
+ x: number;
36
+ y: number;
37
+ }
33
38
  export interface TowerDefenseBoardProps extends DisplayStateProps {
34
39
  entity?: EntityRow | readonly EntityRow[];
35
40
  tiles?: TowerDefenseTile[];
@@ -42,6 +47,7 @@ export interface TowerDefenseBoardProps extends DisplayStateProps {
42
47
  maxWaves?: number;
43
48
  result?: 'none' | 'won' | 'lost';
44
49
  waveActive?: boolean;
50
+ hero?: TowerDefenseHero;
45
51
  towerCost?: number;
46
52
  scale?: number;
47
53
  unitScale?: number;
@@ -58,9 +64,13 @@ export interface TowerDefenseBoardProps extends DisplayStateProps {
58
64
  gameEndEvent?: EventEmit<{
59
65
  result: 'won' | 'lost';
60
66
  }>;
67
+ moveHeroEvent?: EventEmit<{
68
+ dx: number;
69
+ dy: number;
70
+ }>;
61
71
  className?: string;
62
72
  }
63
- export declare function TowerDefenseBoard({ entity, tiles: propTiles, path: propPath, towers: propTowers, creeps: propCreeps, gold: propGold, lives: propLives, wave: propWave, maxWaves: propMaxWaves, result: propResult, waveActive: propWaveActive, towerCost, scale, unitScale, spriteHeightRatio, spriteMaxWidthRatio, placeTowerEvent, startWaveEvent, playAgainEvent, gameEndEvent, className, }: TowerDefenseBoardProps): React.JSX.Element;
73
+ export declare function TowerDefenseBoard({ entity, tiles: propTiles, path: propPath, towers: propTowers, creeps: propCreeps, hero: propHero, gold: propGold, lives: propLives, wave: propWave, maxWaves: propMaxWaves, result: propResult, waveActive: propWaveActive, towerCost, scale, unitScale, spriteHeightRatio, spriteMaxWidthRatio, placeTowerEvent, startWaveEvent, playAgainEvent, gameEndEvent, moveHeroEvent, className, }: TowerDefenseBoardProps): React.JSX.Element;
64
74
  export declare namespace TowerDefenseBoard {
65
75
  var displayName: string;
66
76
  }
@@ -29941,13 +29941,13 @@ var init_MapView = __esm({
29941
29941
  shadowSize: [41, 41]
29942
29942
  });
29943
29943
  L.Marker.prototype.options.icon = defaultIcon;
29944
- const { useEffect: useEffect80, useRef: useRef78, useCallback: useCallback120, useState: useState110 } = React76__namespace.default;
29944
+ const { useEffect: useEffect81, useRef: useRef78, useCallback: useCallback120, useState: useState110 } = React76__namespace.default;
29945
29945
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29946
29946
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29947
29947
  function MapUpdater({ centerLat, centerLng, zoom }) {
29948
29948
  const map = useMap();
29949
29949
  const prevRef = useRef78({ centerLat, centerLng, zoom });
29950
- useEffect80(() => {
29950
+ useEffect81(() => {
29951
29951
  const prev = prevRef.current;
29952
29952
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
29953
29953
  map.setView([centerLat, centerLng], zoom);
@@ -29958,7 +29958,7 @@ var init_MapView = __esm({
29958
29958
  }
29959
29959
  function MapClickHandler({ onMapClick }) {
29960
29960
  const map = useMap();
29961
- useEffect80(() => {
29961
+ useEffect81(() => {
29962
29962
  if (!onMapClick) return;
29963
29963
  const handler = (e) => {
29964
29964
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -50500,12 +50500,25 @@ function pathToFeatures(path) {
50500
50500
  sprite: `${CDN6}world-map/road_straight.png`
50501
50501
  }));
50502
50502
  }
50503
+ function heroToUnit(hero) {
50504
+ return {
50505
+ id: hero.id,
50506
+ position: { x: hero.x, y: hero.y },
50507
+ name: "Hero",
50508
+ team: "player",
50509
+ sprite: HERO_SPRITE,
50510
+ unitType: "amir",
50511
+ health: 1,
50512
+ maxHealth: 1
50513
+ };
50514
+ }
50503
50515
  function TowerDefenseBoard({
50504
50516
  entity,
50505
50517
  tiles: propTiles,
50506
50518
  path: propPath,
50507
50519
  towers: propTowers,
50508
50520
  creeps: propCreeps,
50521
+ hero: propHero,
50509
50522
  gold: propGold,
50510
50523
  lives: propLives,
50511
50524
  wave: propWave,
@@ -50521,6 +50534,7 @@ function TowerDefenseBoard({
50521
50534
  startWaveEvent,
50522
50535
  playAgainEvent,
50523
50536
  gameEndEvent,
50537
+ moveHeroEvent,
50524
50538
  className
50525
50539
  }) {
50526
50540
  const board = boardEntity(entity) ?? {};
@@ -50532,6 +50546,7 @@ function TowerDefenseBoard({
50532
50546
  const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
50533
50547
  const towers = propTowers ?? rows(board.towers);
50534
50548
  const creeps = propCreeps ?? rows(board.creeps);
50549
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
50535
50550
  const gold = propGold ?? num(board.gold, 100);
50536
50551
  const lives = propLives ?? num(board.lives, 20);
50537
50552
  const wave = propWave ?? num(board.wave, 1);
@@ -50549,6 +50564,31 @@ function TowerDefenseBoard({
50549
50564
  if (result === "none") {
50550
50565
  emittedGameEnd.current = false;
50551
50566
  }
50567
+ const moveHeroEventRef = React76.useRef(moveHeroEvent);
50568
+ moveHeroEventRef.current = moveHeroEvent;
50569
+ const resultRef = React76.useRef(result);
50570
+ resultRef.current = result;
50571
+ React76.useEffect(() => {
50572
+ function onKeyDown(e) {
50573
+ const evt = moveHeroEventRef.current;
50574
+ if (!evt || resultRef.current !== "none") return;
50575
+ let dx = 0;
50576
+ let dy = 0;
50577
+ if (e.key === "ArrowUp") {
50578
+ dy = -1;
50579
+ } else if (e.key === "ArrowDown") {
50580
+ dy = 1;
50581
+ } else if (e.key === "ArrowLeft") {
50582
+ dx = -1;
50583
+ } else if (e.key === "ArrowRight") {
50584
+ dx = 1;
50585
+ } else return;
50586
+ e.preventDefault();
50587
+ eventBus.emit(`UI:${evt}`, { dx, dy });
50588
+ }
50589
+ window.addEventListener("keydown", onKeyDown);
50590
+ return () => window.removeEventListener("keydown", onKeyDown);
50591
+ }, [eventBus]);
50552
50592
  const towerPositions = React76.useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
50553
50593
  const pathPositions = React76.useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
50554
50594
  const validMoves = React76.useMemo(() => {
@@ -50560,7 +50600,8 @@ function TowerDefenseBoard({
50560
50600
  const isoTiles = React76.useMemo(() => tilesToIso(tiles), [tiles]);
50561
50601
  const towerUnits = React76.useMemo(() => towersToUnits(towers), [towers]);
50562
50602
  const creepUnits = React76.useMemo(() => creepsToUnits(creeps), [creeps]);
50563
- const isoUnits = React76.useMemo(() => [...towerUnits, ...creepUnits], [towerUnits, creepUnits]);
50603
+ const heroUnit = React76.useMemo(() => heroToUnit(hero), [hero]);
50604
+ const isoUnits = React76.useMemo(() => [...towerUnits, ...creepUnits, heroUnit], [towerUnits, creepUnits, heroUnit]);
50564
50605
  const pathFeatures = React76.useMemo(() => pathToFeatures(path), [path]);
50565
50606
  const handleTileClick = React76.useCallback((x, y) => {
50566
50607
  if (result !== "none") return;
@@ -50659,7 +50700,7 @@ function TowerDefenseBoard({
50659
50700
  ] }) })
50660
50701
  ] });
50661
50702
  }
50662
- var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE;
50703
+ var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE, HERO_SPRITE;
50663
50704
  var init_TowerDefenseBoard = __esm({
50664
50705
  "components/game/organisms/TowerDefenseBoard.tsx"() {
50665
50706
  "use client";
@@ -50733,8 +50774,9 @@ var init_TowerDefenseBoard = __esm({
50733
50774
  { x: 13, y: 15 }
50734
50775
  ];
50735
50776
  DEFAULT_TD_TILES = buildDefaultTDTiles();
50736
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
50737
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
50777
+ TOWER_SPRITE = `${CDN6}sprite-sheets/guardian-sprite-sheet-se.png`;
50778
+ CREEP_SPRITE = `${CDN6}sprite-sheets/scrapper-sprite-sheet-se.png`;
50779
+ HERO_SPRITE = `${CDN6}sprite-sheets/amir-sprite-sheet-se.png`;
50738
50780
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
50739
50781
  }
50740
50782
  });
@@ -29895,13 +29895,13 @@ var init_MapView = __esm({
29895
29895
  shadowSize: [41, 41]
29896
29896
  });
29897
29897
  L.Marker.prototype.options.icon = defaultIcon;
29898
- const { useEffect: useEffect80, useRef: useRef78, useCallback: useCallback120, useState: useState110 } = React76__default;
29898
+ const { useEffect: useEffect81, useRef: useRef78, useCallback: useCallback120, useState: useState110 } = React76__default;
29899
29899
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29900
29900
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29901
29901
  function MapUpdater({ centerLat, centerLng, zoom }) {
29902
29902
  const map = useMap();
29903
29903
  const prevRef = useRef78({ centerLat, centerLng, zoom });
29904
- useEffect80(() => {
29904
+ useEffect81(() => {
29905
29905
  const prev = prevRef.current;
29906
29906
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
29907
29907
  map.setView([centerLat, centerLng], zoom);
@@ -29912,7 +29912,7 @@ var init_MapView = __esm({
29912
29912
  }
29913
29913
  function MapClickHandler({ onMapClick }) {
29914
29914
  const map = useMap();
29915
- useEffect80(() => {
29915
+ useEffect81(() => {
29916
29916
  if (!onMapClick) return;
29917
29917
  const handler = (e) => {
29918
29918
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -50454,12 +50454,25 @@ function pathToFeatures(path) {
50454
50454
  sprite: `${CDN6}world-map/road_straight.png`
50455
50455
  }));
50456
50456
  }
50457
+ function heroToUnit(hero) {
50458
+ return {
50459
+ id: hero.id,
50460
+ position: { x: hero.x, y: hero.y },
50461
+ name: "Hero",
50462
+ team: "player",
50463
+ sprite: HERO_SPRITE,
50464
+ unitType: "amir",
50465
+ health: 1,
50466
+ maxHealth: 1
50467
+ };
50468
+ }
50457
50469
  function TowerDefenseBoard({
50458
50470
  entity,
50459
50471
  tiles: propTiles,
50460
50472
  path: propPath,
50461
50473
  towers: propTowers,
50462
50474
  creeps: propCreeps,
50475
+ hero: propHero,
50463
50476
  gold: propGold,
50464
50477
  lives: propLives,
50465
50478
  wave: propWave,
@@ -50475,6 +50488,7 @@ function TowerDefenseBoard({
50475
50488
  startWaveEvent,
50476
50489
  playAgainEvent,
50477
50490
  gameEndEvent,
50491
+ moveHeroEvent,
50478
50492
  className
50479
50493
  }) {
50480
50494
  const board = boardEntity(entity) ?? {};
@@ -50486,6 +50500,7 @@ function TowerDefenseBoard({
50486
50500
  const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
50487
50501
  const towers = propTowers ?? rows(board.towers);
50488
50502
  const creeps = propCreeps ?? rows(board.creeps);
50503
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
50489
50504
  const gold = propGold ?? num(board.gold, 100);
50490
50505
  const lives = propLives ?? num(board.lives, 20);
50491
50506
  const wave = propWave ?? num(board.wave, 1);
@@ -50503,6 +50518,31 @@ function TowerDefenseBoard({
50503
50518
  if (result === "none") {
50504
50519
  emittedGameEnd.current = false;
50505
50520
  }
50521
+ const moveHeroEventRef = useRef(moveHeroEvent);
50522
+ moveHeroEventRef.current = moveHeroEvent;
50523
+ const resultRef = useRef(result);
50524
+ resultRef.current = result;
50525
+ useEffect(() => {
50526
+ function onKeyDown(e) {
50527
+ const evt = moveHeroEventRef.current;
50528
+ if (!evt || resultRef.current !== "none") return;
50529
+ let dx = 0;
50530
+ let dy = 0;
50531
+ if (e.key === "ArrowUp") {
50532
+ dy = -1;
50533
+ } else if (e.key === "ArrowDown") {
50534
+ dy = 1;
50535
+ } else if (e.key === "ArrowLeft") {
50536
+ dx = -1;
50537
+ } else if (e.key === "ArrowRight") {
50538
+ dx = 1;
50539
+ } else return;
50540
+ e.preventDefault();
50541
+ eventBus.emit(`UI:${evt}`, { dx, dy });
50542
+ }
50543
+ window.addEventListener("keydown", onKeyDown);
50544
+ return () => window.removeEventListener("keydown", onKeyDown);
50545
+ }, [eventBus]);
50506
50546
  const towerPositions = useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
50507
50547
  const pathPositions = useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
50508
50548
  const validMoves = useMemo(() => {
@@ -50514,7 +50554,8 @@ function TowerDefenseBoard({
50514
50554
  const isoTiles = useMemo(() => tilesToIso(tiles), [tiles]);
50515
50555
  const towerUnits = useMemo(() => towersToUnits(towers), [towers]);
50516
50556
  const creepUnits = useMemo(() => creepsToUnits(creeps), [creeps]);
50517
- const isoUnits = useMemo(() => [...towerUnits, ...creepUnits], [towerUnits, creepUnits]);
50557
+ const heroUnit = useMemo(() => heroToUnit(hero), [hero]);
50558
+ const isoUnits = useMemo(() => [...towerUnits, ...creepUnits, heroUnit], [towerUnits, creepUnits, heroUnit]);
50518
50559
  const pathFeatures = useMemo(() => pathToFeatures(path), [path]);
50519
50560
  const handleTileClick = useCallback((x, y) => {
50520
50561
  if (result !== "none") return;
@@ -50613,7 +50654,7 @@ function TowerDefenseBoard({
50613
50654
  ] }) })
50614
50655
  ] });
50615
50656
  }
50616
- var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE;
50657
+ var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE, HERO_SPRITE;
50617
50658
  var init_TowerDefenseBoard = __esm({
50618
50659
  "components/game/organisms/TowerDefenseBoard.tsx"() {
50619
50660
  "use client";
@@ -50687,8 +50728,9 @@ var init_TowerDefenseBoard = __esm({
50687
50728
  { x: 13, y: 15 }
50688
50729
  ];
50689
50730
  DEFAULT_TD_TILES = buildDefaultTDTiles();
50690
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
50691
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
50731
+ TOWER_SPRITE = `${CDN6}sprite-sheets/guardian-sprite-sheet-se.png`;
50732
+ CREEP_SPRITE = `${CDN6}sprite-sheets/scrapper-sprite-sheet-se.png`;
50733
+ HERO_SPRITE = `${CDN6}sprite-sheets/amir-sprite-sheet-se.png`;
50692
50734
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
50693
50735
  }
50694
50736
  });
@@ -29522,13 +29522,13 @@ var init_MapView = __esm({
29522
29522
  shadowSize: [41, 41]
29523
29523
  });
29524
29524
  L.Marker.prototype.options.icon = defaultIcon;
29525
- 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;
29526
29526
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29527
29527
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29528
29528
  function MapUpdater({ centerLat, centerLng, zoom }) {
29529
29529
  const map = useMap();
29530
29530
  const prevRef = useRef75({ centerLat, centerLng, zoom });
29531
- useEffect79(() => {
29531
+ useEffect80(() => {
29532
29532
  const prev = prevRef.current;
29533
29533
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
29534
29534
  map.setView([centerLat, centerLng], zoom);
@@ -29539,7 +29539,7 @@ var init_MapView = __esm({
29539
29539
  }
29540
29540
  function MapClickHandler({ onMapClick }) {
29541
29541
  const map = useMap();
29542
- useEffect79(() => {
29542
+ useEffect80(() => {
29543
29543
  if (!onMapClick) return;
29544
29544
  const handler = (e) => {
29545
29545
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -49339,12 +49339,25 @@ function pathToFeatures(path) {
49339
49339
  sprite: `${CDN6}world-map/road_straight.png`
49340
49340
  }));
49341
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
+ }
49342
49354
  function TowerDefenseBoard({
49343
49355
  entity,
49344
49356
  tiles: propTiles,
49345
49357
  path: propPath,
49346
49358
  towers: propTowers,
49347
49359
  creeps: propCreeps,
49360
+ hero: propHero,
49348
49361
  gold: propGold,
49349
49362
  lives: propLives,
49350
49363
  wave: propWave,
@@ -49360,6 +49373,7 @@ function TowerDefenseBoard({
49360
49373
  startWaveEvent,
49361
49374
  playAgainEvent,
49362
49375
  gameEndEvent,
49376
+ moveHeroEvent,
49363
49377
  className
49364
49378
  }) {
49365
49379
  const board = boardEntity(entity) ?? {};
@@ -49371,6 +49385,7 @@ function TowerDefenseBoard({
49371
49385
  const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
49372
49386
  const towers = propTowers ?? rows(board.towers);
49373
49387
  const creeps = propCreeps ?? rows(board.creeps);
49388
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
49374
49389
  const gold = propGold ?? num(board.gold, 100);
49375
49390
  const lives = propLives ?? num(board.lives, 20);
49376
49391
  const wave = propWave ?? num(board.wave, 1);
@@ -49388,6 +49403,31 @@ function TowerDefenseBoard({
49388
49403
  if (result === "none") {
49389
49404
  emittedGameEnd.current = false;
49390
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]);
49391
49431
  const towerPositions = React82.useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
49392
49432
  const pathPositions = React82.useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
49393
49433
  const validMoves = React82.useMemo(() => {
@@ -49399,7 +49439,8 @@ function TowerDefenseBoard({
49399
49439
  const isoTiles = React82.useMemo(() => tilesToIso(tiles), [tiles]);
49400
49440
  const towerUnits = React82.useMemo(() => towersToUnits(towers), [towers]);
49401
49441
  const creepUnits = React82.useMemo(() => creepsToUnits(creeps), [creeps]);
49402
- 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]);
49403
49444
  const pathFeatures = React82.useMemo(() => pathToFeatures(path), [path]);
49404
49445
  const handleTileClick = React82.useCallback((x, y) => {
49405
49446
  if (result !== "none") return;
@@ -49498,7 +49539,7 @@ function TowerDefenseBoard({
49498
49539
  ] }) })
49499
49540
  ] });
49500
49541
  }
49501
- var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, 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;
49502
49543
  var init_TowerDefenseBoard = __esm({
49503
49544
  "components/game/organisms/TowerDefenseBoard.tsx"() {
49504
49545
  "use client";
@@ -49572,8 +49613,9 @@ var init_TowerDefenseBoard = __esm({
49572
49613
  { x: 13, y: 15 }
49573
49614
  ];
49574
49615
  DEFAULT_TD_TILES = buildDefaultTDTiles();
49575
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
49576
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
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`;
49577
49619
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
49578
49620
  }
49579
49621
  });
@@ -29475,13 +29475,13 @@ var init_MapView = __esm({
29475
29475
  shadowSize: [41, 41]
29476
29476
  });
29477
29477
  L.Marker.prototype.options.icon = defaultIcon;
29478
- const { useEffect: useEffect79, useRef: useRef75, useCallback: useCallback118, useState: useState109 } = React82__default;
29478
+ const { useEffect: useEffect80, useRef: useRef75, useCallback: useCallback118, useState: useState109 } = React82__default;
29479
29479
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29480
29480
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29481
29481
  function MapUpdater({ centerLat, centerLng, zoom }) {
29482
29482
  const map = useMap();
29483
29483
  const prevRef = useRef75({ centerLat, centerLng, zoom });
29484
- useEffect79(() => {
29484
+ useEffect80(() => {
29485
29485
  const prev = prevRef.current;
29486
29486
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
29487
29487
  map.setView([centerLat, centerLng], zoom);
@@ -29492,7 +29492,7 @@ var init_MapView = __esm({
29492
29492
  }
29493
29493
  function MapClickHandler({ onMapClick }) {
29494
29494
  const map = useMap();
29495
- useEffect79(() => {
29495
+ useEffect80(() => {
29496
29496
  if (!onMapClick) return;
29497
29497
  const handler = (e) => {
29498
29498
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -49292,12 +49292,25 @@ function pathToFeatures(path) {
49292
49292
  sprite: `${CDN6}world-map/road_straight.png`
49293
49293
  }));
49294
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
+ }
49295
49307
  function TowerDefenseBoard({
49296
49308
  entity,
49297
49309
  tiles: propTiles,
49298
49310
  path: propPath,
49299
49311
  towers: propTowers,
49300
49312
  creeps: propCreeps,
49313
+ hero: propHero,
49301
49314
  gold: propGold,
49302
49315
  lives: propLives,
49303
49316
  wave: propWave,
@@ -49313,6 +49326,7 @@ function TowerDefenseBoard({
49313
49326
  startWaveEvent,
49314
49327
  playAgainEvent,
49315
49328
  gameEndEvent,
49329
+ moveHeroEvent,
49316
49330
  className
49317
49331
  }) {
49318
49332
  const board = boardEntity(entity) ?? {};
@@ -49324,6 +49338,7 @@ function TowerDefenseBoard({
49324
49338
  const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
49325
49339
  const towers = propTowers ?? rows(board.towers);
49326
49340
  const creeps = propCreeps ?? rows(board.creeps);
49341
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
49327
49342
  const gold = propGold ?? num(board.gold, 100);
49328
49343
  const lives = propLives ?? num(board.lives, 20);
49329
49344
  const wave = propWave ?? num(board.wave, 1);
@@ -49341,6 +49356,31 @@ function TowerDefenseBoard({
49341
49356
  if (result === "none") {
49342
49357
  emittedGameEnd.current = false;
49343
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]);
49344
49384
  const towerPositions = useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
49345
49385
  const pathPositions = useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
49346
49386
  const validMoves = useMemo(() => {
@@ -49352,7 +49392,8 @@ function TowerDefenseBoard({
49352
49392
  const isoTiles = useMemo(() => tilesToIso(tiles), [tiles]);
49353
49393
  const towerUnits = useMemo(() => towersToUnits(towers), [towers]);
49354
49394
  const creepUnits = useMemo(() => creepsToUnits(creeps), [creeps]);
49355
- const isoUnits = useMemo(() => [...towerUnits, ...creepUnits], [towerUnits, creepUnits]);
49395
+ const heroUnit = useMemo(() => heroToUnit(hero), [hero]);
49396
+ const isoUnits = useMemo(() => [...towerUnits, ...creepUnits, heroUnit], [towerUnits, creepUnits, heroUnit]);
49356
49397
  const pathFeatures = useMemo(() => pathToFeatures(path), [path]);
49357
49398
  const handleTileClick = useCallback((x, y) => {
49358
49399
  if (result !== "none") return;
@@ -49451,7 +49492,7 @@ function TowerDefenseBoard({
49451
49492
  ] }) })
49452
49493
  ] });
49453
49494
  }
49454
- var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, 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;
49455
49496
  var init_TowerDefenseBoard = __esm({
49456
49497
  "components/game/organisms/TowerDefenseBoard.tsx"() {
49457
49498
  "use client";
@@ -49525,8 +49566,9 @@ var init_TowerDefenseBoard = __esm({
49525
49566
  { x: 13, y: 15 }
49526
49567
  ];
49527
49568
  DEFAULT_TD_TILES = buildDefaultTDTiles();
49528
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
49529
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
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`;
49530
49572
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
49531
49573
  }
49532
49574
  });
@@ -29220,13 +29220,13 @@ var init_MapView = __esm({
29220
29220
  shadowSize: [41, 41]
29221
29221
  });
29222
29222
  L.Marker.prototype.options.icon = defaultIcon;
29223
- 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;
29224
29224
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29225
29225
  const { useEventBus: useEventBus4 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29226
29226
  function MapUpdater({ centerLat, centerLng, zoom }) {
29227
29227
  const map = useMap();
29228
29228
  const prevRef = useRef75({ centerLat, centerLng, zoom });
29229
- useEffect81(() => {
29229
+ useEffect82(() => {
29230
29230
  const prev = prevRef.current;
29231
29231
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
29232
29232
  map.setView([centerLat, centerLng], zoom);
@@ -29237,7 +29237,7 @@ var init_MapView = __esm({
29237
29237
  }
29238
29238
  function MapClickHandler({ onMapClick }) {
29239
29239
  const map = useMap();
29240
- useEffect81(() => {
29240
+ useEffect82(() => {
29241
29241
  if (!onMapClick) return;
29242
29242
  const handler = (e) => {
29243
29243
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -49056,12 +49056,25 @@ function pathToFeatures(path) {
49056
49056
  sprite: `${CDN6}world-map/road_straight.png`
49057
49057
  }));
49058
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
+ }
49059
49071
  function TowerDefenseBoard({
49060
49072
  entity,
49061
49073
  tiles: propTiles,
49062
49074
  path: propPath,
49063
49075
  towers: propTowers,
49064
49076
  creeps: propCreeps,
49077
+ hero: propHero,
49065
49078
  gold: propGold,
49066
49079
  lives: propLives,
49067
49080
  wave: propWave,
@@ -49077,6 +49090,7 @@ function TowerDefenseBoard({
49077
49090
  startWaveEvent,
49078
49091
  playAgainEvent,
49079
49092
  gameEndEvent,
49093
+ moveHeroEvent,
49080
49094
  className
49081
49095
  }) {
49082
49096
  const board = boardEntity(entity) ?? {};
@@ -49088,6 +49102,7 @@ function TowerDefenseBoard({
49088
49102
  const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
49089
49103
  const towers = propTowers ?? rows(board.towers);
49090
49104
  const creeps = propCreeps ?? rows(board.creeps);
49105
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
49091
49106
  const gold = propGold ?? num(board.gold, 100);
49092
49107
  const lives = propLives ?? num(board.lives, 20);
49093
49108
  const wave = propWave ?? num(board.wave, 1);
@@ -49105,6 +49120,31 @@ function TowerDefenseBoard({
49105
49120
  if (result === "none") {
49106
49121
  emittedGameEnd.current = false;
49107
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]);
49108
49148
  const towerPositions = React81.useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
49109
49149
  const pathPositions = React81.useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
49110
49150
  const validMoves = React81.useMemo(() => {
@@ -49116,7 +49156,8 @@ function TowerDefenseBoard({
49116
49156
  const isoTiles = React81.useMemo(() => tilesToIso(tiles), [tiles]);
49117
49157
  const towerUnits = React81.useMemo(() => towersToUnits(towers), [towers]);
49118
49158
  const creepUnits = React81.useMemo(() => creepsToUnits(creeps), [creeps]);
49119
- 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]);
49120
49161
  const pathFeatures = React81.useMemo(() => pathToFeatures(path), [path]);
49121
49162
  const handleTileClick = React81.useCallback((x, y) => {
49122
49163
  if (result !== "none") return;
@@ -49215,7 +49256,7 @@ function TowerDefenseBoard({
49215
49256
  ] }) })
49216
49257
  ] });
49217
49258
  }
49218
- var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, 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;
49219
49260
  var init_TowerDefenseBoard = __esm({
49220
49261
  "components/game/organisms/TowerDefenseBoard.tsx"() {
49221
49262
  "use client";
@@ -49289,8 +49330,9 @@ var init_TowerDefenseBoard = __esm({
49289
49330
  { x: 13, y: 15 }
49290
49331
  ];
49291
49332
  DEFAULT_TD_TILES = buildDefaultTDTiles();
49292
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
49293
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
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`;
49294
49336
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
49295
49337
  }
49296
49338
  });
@@ -29173,13 +29173,13 @@ var init_MapView = __esm({
29173
29173
  shadowSize: [41, 41]
29174
29174
  });
29175
29175
  L.Marker.prototype.options.icon = defaultIcon;
29176
- const { useEffect: useEffect81, useRef: useRef75, useCallback: useCallback119, useState: useState113 } = React81__default;
29176
+ const { useEffect: useEffect82, useRef: useRef75, useCallback: useCallback119, useState: useState113 } = React81__default;
29177
29177
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29178
29178
  const { useEventBus: useEventBus4 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29179
29179
  function MapUpdater({ centerLat, centerLng, zoom }) {
29180
29180
  const map = useMap();
29181
29181
  const prevRef = useRef75({ centerLat, centerLng, zoom });
29182
- useEffect81(() => {
29182
+ useEffect82(() => {
29183
29183
  const prev = prevRef.current;
29184
29184
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
29185
29185
  map.setView([centerLat, centerLng], zoom);
@@ -29190,7 +29190,7 @@ var init_MapView = __esm({
29190
29190
  }
29191
29191
  function MapClickHandler({ onMapClick }) {
29192
29192
  const map = useMap();
29193
- useEffect81(() => {
29193
+ useEffect82(() => {
29194
29194
  if (!onMapClick) return;
29195
29195
  const handler = (e) => {
29196
29196
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -49009,12 +49009,25 @@ function pathToFeatures(path) {
49009
49009
  sprite: `${CDN6}world-map/road_straight.png`
49010
49010
  }));
49011
49011
  }
49012
+ function heroToUnit(hero) {
49013
+ return {
49014
+ id: hero.id,
49015
+ position: { x: hero.x, y: hero.y },
49016
+ name: "Hero",
49017
+ team: "player",
49018
+ sprite: HERO_SPRITE,
49019
+ unitType: "amir",
49020
+ health: 1,
49021
+ maxHealth: 1
49022
+ };
49023
+ }
49012
49024
  function TowerDefenseBoard({
49013
49025
  entity,
49014
49026
  tiles: propTiles,
49015
49027
  path: propPath,
49016
49028
  towers: propTowers,
49017
49029
  creeps: propCreeps,
49030
+ hero: propHero,
49018
49031
  gold: propGold,
49019
49032
  lives: propLives,
49020
49033
  wave: propWave,
@@ -49030,6 +49043,7 @@ function TowerDefenseBoard({
49030
49043
  startWaveEvent,
49031
49044
  playAgainEvent,
49032
49045
  gameEndEvent,
49046
+ moveHeroEvent,
49033
49047
  className
49034
49048
  }) {
49035
49049
  const board = boardEntity(entity) ?? {};
@@ -49041,6 +49055,7 @@ function TowerDefenseBoard({
49041
49055
  const path = rawPath.length > 0 ? rawPath : DEFAULT_TD_PATH;
49042
49056
  const towers = propTowers ?? rows(board.towers);
49043
49057
  const creeps = propCreeps ?? rows(board.creeps);
49058
+ const hero = propHero ?? { id: "hero", x: 8, y: 8 };
49044
49059
  const gold = propGold ?? num(board.gold, 100);
49045
49060
  const lives = propLives ?? num(board.lives, 20);
49046
49061
  const wave = propWave ?? num(board.wave, 1);
@@ -49058,6 +49073,31 @@ function TowerDefenseBoard({
49058
49073
  if (result === "none") {
49059
49074
  emittedGameEnd.current = false;
49060
49075
  }
49076
+ const moveHeroEventRef = useRef(moveHeroEvent);
49077
+ moveHeroEventRef.current = moveHeroEvent;
49078
+ const resultRef = useRef(result);
49079
+ resultRef.current = result;
49080
+ useEffect(() => {
49081
+ function onKeyDown(e) {
49082
+ const evt = moveHeroEventRef.current;
49083
+ if (!evt || resultRef.current !== "none") return;
49084
+ let dx = 0;
49085
+ let dy = 0;
49086
+ if (e.key === "ArrowUp") {
49087
+ dy = -1;
49088
+ } else if (e.key === "ArrowDown") {
49089
+ dy = 1;
49090
+ } else if (e.key === "ArrowLeft") {
49091
+ dx = -1;
49092
+ } else if (e.key === "ArrowRight") {
49093
+ dx = 1;
49094
+ } else return;
49095
+ e.preventDefault();
49096
+ eventBus.emit(`UI:${evt}`, { dx, dy });
49097
+ }
49098
+ window.addEventListener("keydown", onKeyDown);
49099
+ return () => window.removeEventListener("keydown", onKeyDown);
49100
+ }, [eventBus]);
49061
49101
  const towerPositions = useMemo(() => new Set(towers.map((t2) => `${t2.x},${t2.y}`)), [towers]);
49062
49102
  const pathPositions = useMemo(() => new Set(path.map((p2) => `${p2.x},${p2.y}`)), [path]);
49063
49103
  const validMoves = useMemo(() => {
@@ -49069,7 +49109,8 @@ function TowerDefenseBoard({
49069
49109
  const isoTiles = useMemo(() => tilesToIso(tiles), [tiles]);
49070
49110
  const towerUnits = useMemo(() => towersToUnits(towers), [towers]);
49071
49111
  const creepUnits = useMemo(() => creepsToUnits(creeps), [creeps]);
49072
- const isoUnits = useMemo(() => [...towerUnits, ...creepUnits], [towerUnits, creepUnits]);
49112
+ const heroUnit = useMemo(() => heroToUnit(hero), [hero]);
49113
+ const isoUnits = useMemo(() => [...towerUnits, ...creepUnits, heroUnit], [towerUnits, creepUnits, heroUnit]);
49073
49114
  const pathFeatures = useMemo(() => pathToFeatures(path), [path]);
49074
49115
  const handleTileClick = useCallback((x, y) => {
49075
49116
  if (result !== "none") return;
@@ -49168,7 +49209,7 @@ function TowerDefenseBoard({
49168
49209
  ] }) })
49169
49210
  ] });
49170
49211
  }
49171
- var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE;
49212
+ var CDN6, TD_GRID_W, TD_GRID_H, TERRAIN_SPRITES, DEFAULT_TD_PATH, DEFAULT_TD_TILES, TOWER_SPRITE, CREEP_SPRITE, HERO_SPRITE;
49172
49213
  var init_TowerDefenseBoard = __esm({
49173
49214
  "components/game/organisms/TowerDefenseBoard.tsx"() {
49174
49215
  "use client";
@@ -49242,8 +49283,9 @@ var init_TowerDefenseBoard = __esm({
49242
49283
  { x: 13, y: 15 }
49243
49284
  ];
49244
49285
  DEFAULT_TD_TILES = buildDefaultTDTiles();
49245
- TOWER_SPRITE = `${CDN6}units/guardian.png`;
49246
- CREEP_SPRITE = `${CDN6}units/scrapper.png`;
49286
+ TOWER_SPRITE = `${CDN6}sprite-sheets/guardian-sprite-sheet-se.png`;
49287
+ CREEP_SPRITE = `${CDN6}sprite-sheets/scrapper-sprite-sheet-se.png`;
49288
+ HERO_SPRITE = `${CDN6}sprite-sheets/amir-sprite-sheet-se.png`;
49247
49289
  TowerDefenseBoard.displayName = "TowerDefenseBoard";
49248
49290
  }
49249
49291
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.57.0",
3
+ "version": "5.58.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [