@almadar/ui 5.55.0 → 5.56.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.
@@ -11144,6 +11144,8 @@ function IsometricCanvas({
11144
11144
  showMinimap = true,
11145
11145
  enableCamera = true,
11146
11146
  unitScale = 1,
11147
+ spriteHeightRatio = 1.5,
11148
+ spriteMaxWidthRatio = 0.6,
11147
11149
  // Asset resolution
11148
11150
  getTerrainSprite,
11149
11151
  getFeatureSprite,
@@ -11534,8 +11536,8 @@ function IsometricCanvas({
11534
11536
  const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
11535
11537
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
11536
11538
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
11537
- const unitDrawH = scaledFloorHeight * 1.5 * unitScale;
11538
- const maxUnitW = scaledTileWidth * 0.6 * unitScale;
11539
+ const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
11540
+ const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
11539
11541
  const ar = img ? img.naturalWidth / img.naturalHeight : 0.5;
11540
11542
  let drawH = unitDrawH;
11541
11543
  let drawW = unitDrawH * ar;
@@ -11919,6 +11921,8 @@ function BattleBoard({
11919
11921
  assetManifest: propAssetManifest,
11920
11922
  scale = 0.45,
11921
11923
  unitScale = 1,
11924
+ spriteHeightRatio = 1.5,
11925
+ spriteMaxWidthRatio = 0.6,
11922
11926
  header,
11923
11927
  sidebar,
11924
11928
  actions,
@@ -12209,7 +12213,9 @@ function BattleBoard({
12209
12213
  hasActiveEffects: hasActiveEffects2,
12210
12214
  effectSpriteUrls,
12211
12215
  resolveUnitFrame,
12212
- unitScale
12216
+ unitScale,
12217
+ spriteHeightRatio,
12218
+ spriteMaxWidthRatio
12213
12219
  }
12214
12220
  ),
12215
12221
  overlay && overlay(ctx)
@@ -42180,6 +42186,8 @@ var init_GameCanvas3D2 = __esm({
42180
42186
  attackTargets = [],
42181
42187
  selectedTileIds = [],
42182
42188
  selectedUnitId = null,
42189
+ unitScale = 1,
42190
+ scale = 0.45,
42183
42191
  children
42184
42192
  }, ref) => {
42185
42193
  const containerRef = React82.useRef(null);
@@ -42396,12 +42404,18 @@ var init_GameCanvas3D2 = __esm({
42396
42404
  },
42397
42405
  [selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
42398
42406
  );
42407
+ const UNIT_BASE_MODEL_SCALE = 0.5;
42408
+ const UNIT_BASE_BILLBOARD_HEIGHT = 1.2;
42409
+ const UNIT_BASE_PRIMITIVE_RADIUS = 0.3;
42399
42410
  const DefaultUnitRenderer = React82.useCallback(
42400
42411
  ({ unit, position }) => {
42401
42412
  const isSelected = selectedUnitId === unit.id;
42402
42413
  const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
42403
42414
  const hasAtlas = unitAtlasUrl(unit) !== null;
42404
42415
  const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
42416
+ const modelScale = UNIT_BASE_MODEL_SCALE * unitScale;
42417
+ const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale;
42418
+ const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale;
42405
42419
  return /* @__PURE__ */ jsxRuntime.jsxs(
42406
42420
  "group",
42407
42421
  {
@@ -42419,7 +42433,8 @@ var init_GameCanvas3D2 = __esm({
42419
42433
  UnitSpriteBillboard,
42420
42434
  {
42421
42435
  sheetUrl: initialFrame.sheetUrl,
42422
- resolveFrame: () => resolveUnitFrame(unit.id)
42436
+ resolveFrame: () => resolveUnitFrame(unit.id),
42437
+ height: billboardHeight
42423
42438
  }
42424
42439
  ) })
42425
42440
  ) : unit.modelUrl ? (
@@ -42428,22 +42443,22 @@ var init_GameCanvas3D2 = __esm({
42428
42443
  ModelLoader,
42429
42444
  {
42430
42445
  url: unit.modelUrl,
42431
- scale: 0.5,
42446
+ scale: modelScale,
42432
42447
  fallbackGeometry: "box",
42433
42448
  castShadow: true
42434
42449
  }
42435
42450
  )
42436
42451
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
42437
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.3, 0], children: [
42438
- /* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.3, 0.3, 0.1, 8] }),
42452
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius, 0], children: [
42453
+ /* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [primitiveRadius, primitiveRadius, primitiveRadius * 0.33, 8] }),
42439
42454
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
42440
42455
  ] }),
42441
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.6, 0], children: [
42442
- /* @__PURE__ */ jsxRuntime.jsx("capsuleGeometry", { args: [0.2, 0.4, 4, 8] }),
42456
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius * 2, 0], children: [
42457
+ /* @__PURE__ */ jsxRuntime.jsx("capsuleGeometry", { args: [primitiveRadius * 0.67, primitiveRadius * 1.33, 4, 8] }),
42443
42458
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
42444
42459
  ] }),
42445
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.9, 0], children: [
42446
- /* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [0.12, 8, 8] }),
42460
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius * 3, 0], children: [
42461
+ /* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [primitiveRadius * 0.4, 8, 8] }),
42447
42462
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
42448
42463
  ] })
42449
42464
  ] }),
@@ -42476,7 +42491,7 @@ var init_GameCanvas3D2 = __esm({
42476
42491
  }
42477
42492
  );
42478
42493
  },
42479
- [selectedUnitId, handleUnitClick, resolveUnitFrame]
42494
+ [selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale]
42480
42495
  );
42481
42496
  const DefaultFeatureRenderer = React82.useCallback(
42482
42497
  ({
@@ -42619,33 +42634,35 @@ var init_GameCanvas3D2 = __esm({
42619
42634
  fadeStrength: 1
42620
42635
  }
42621
42636
  ),
42622
- tiles.map((tile, index) => {
42623
- const position = gridToWorld(
42624
- tile.x,
42625
- tile.z ?? tile.y ?? 0,
42626
- tile.elevation ?? 0
42627
- );
42628
- const Renderer = CustomTileRenderer || DefaultTileRenderer;
42629
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
42630
- }),
42631
- features.map((feature, index) => {
42632
- const position = gridToWorld(
42633
- feature.x,
42634
- feature.z ?? feature.y ?? 0,
42635
- (feature.elevation ?? 0) + 0.5
42636
- );
42637
- const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
42638
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
42639
- }),
42640
- units.map((unit) => {
42641
- const position = gridToWorld(
42642
- unit.x ?? 0,
42643
- unit.z ?? unit.y ?? 0,
42644
- (unit.elevation ?? 0) + 0.5
42645
- );
42646
- const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
42647
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { unit, position }, unit.id);
42648
- }),
42637
+ /* @__PURE__ */ jsxRuntime.jsxs("group", { scale, children: [
42638
+ tiles.map((tile, index) => {
42639
+ const position = gridToWorld(
42640
+ tile.x,
42641
+ tile.z ?? tile.y ?? 0,
42642
+ tile.elevation ?? 0
42643
+ );
42644
+ const Renderer = CustomTileRenderer || DefaultTileRenderer;
42645
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
42646
+ }),
42647
+ features.map((feature, index) => {
42648
+ const position = gridToWorld(
42649
+ feature.x,
42650
+ feature.z ?? feature.y ?? 0,
42651
+ (feature.elevation ?? 0) + 0.5
42652
+ );
42653
+ const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
42654
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
42655
+ }),
42656
+ units.map((unit) => {
42657
+ const position = gridToWorld(
42658
+ unit.x ?? 0,
42659
+ unit.z ?? unit.y ?? 0,
42660
+ (unit.elevation ?? 0) + 0.5
42661
+ );
42662
+ const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
42663
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { unit, position }, unit.id);
42664
+ })
42665
+ ] }),
42649
42666
  children,
42650
42667
  /* @__PURE__ */ jsxRuntime.jsx(
42651
42668
  drei.OrbitControls,
@@ -42688,6 +42705,8 @@ function GameBoard3D({
42688
42705
  features = [],
42689
42706
  cameraMode = "perspective",
42690
42707
  backgroundColor = "#2a1a1a",
42708
+ unitScale = 1,
42709
+ scale = 0.45,
42691
42710
  tileClickEvent,
42692
42711
  unitClickEvent,
42693
42712
  attackEvent,
@@ -42788,6 +42807,8 @@ function GameBoard3D({
42788
42807
  selectedUnitId,
42789
42808
  validMoves,
42790
42809
  attackTargets,
42810
+ unitScale,
42811
+ scale,
42791
42812
  className: "game-board-3d__canvas w-full min-h-[85vh]"
42792
42813
  }
42793
42814
  ),
@@ -44773,6 +44794,8 @@ function RoguelikeBoard({
44773
44794
  assetManifest: propAssetManifest,
44774
44795
  scale = 0.45,
44775
44796
  unitScale = 1,
44797
+ spriteHeightRatio = 1.5,
44798
+ spriteMaxWidthRatio = 0.6,
44776
44799
  moveEvent,
44777
44800
  playAgainEvent,
44778
44801
  gameEndEvent,
@@ -44920,7 +44943,9 @@ function RoguelikeBoard({
44920
44943
  scale,
44921
44944
  assetBaseUrl: propAssetManifest?.baseUrl ?? CDN4,
44922
44945
  assetManifest: propAssetManifest,
44923
- unitScale
44946
+ unitScale,
44947
+ spriteHeightRatio,
44948
+ spriteMaxWidthRatio
44924
44949
  }
44925
44950
  ) }),
44926
44951
  !isGameOver && /* @__PURE__ */ jsxRuntime.jsx(HStack, { className: "justify-center gap-2 p-3", gap: "none", children: [
@@ -49273,6 +49298,9 @@ function TowerDefenseBoard({
49273
49298
  waveActive: propWaveActive,
49274
49299
  towerCost = 25,
49275
49300
  scale = 0.45,
49301
+ unitScale = 1,
49302
+ spriteHeightRatio = 1.5,
49303
+ spriteMaxWidthRatio = 0.6,
49276
49304
  placeTowerEvent,
49277
49305
  startWaveEvent,
49278
49306
  playAgainEvent,
@@ -49380,7 +49408,10 @@ function TowerDefenseBoard({
49380
49408
  onTileClick: handleTileClick,
49381
49409
  onTileHover: (x, y) => setHoveredTile({ x, y }),
49382
49410
  onTileLeave: () => setHoveredTile(null),
49383
- scale
49411
+ scale,
49412
+ unitScale,
49413
+ spriteHeightRatio,
49414
+ spriteMaxWidthRatio
49384
49415
  }
49385
49416
  ),
49386
49417
  hoveredTile && canPlaceTower && validMoves.some((m) => m.x === hoveredTile.x && m.y === hoveredTile.y) && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "absolute bottom-4 left-1/2 -translate-x-1/2 z-10 bg-background/80 rounded px-3 py-1 backdrop-blur-sm pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", children: t("td.placeTower") ?? `Place tower (${towerCost} gold)` }) })
@@ -49716,6 +49747,8 @@ function WorldMapBoard({
49716
49747
  isLoading,
49717
49748
  scale = 0.4,
49718
49749
  unitScale = 2.5,
49750
+ spriteHeightRatio = 1.5,
49751
+ spriteMaxWidthRatio = 0.6,
49719
49752
  allowMoveAllHeroes = false,
49720
49753
  isInRange = defaultIsInRange,
49721
49754
  heroSelectEvent,
@@ -49953,6 +49986,8 @@ function WorldMapBoard({
49953
49986
  effectSpriteUrls,
49954
49987
  resolveUnitFrame,
49955
49988
  unitScale,
49989
+ spriteHeightRatio,
49990
+ spriteMaxWidthRatio,
49956
49991
  diamondTopY,
49957
49992
  enableCamera
49958
49993
  }
@@ -11097,6 +11097,8 @@ function IsometricCanvas({
11097
11097
  showMinimap = true,
11098
11098
  enableCamera = true,
11099
11099
  unitScale = 1,
11100
+ spriteHeightRatio = 1.5,
11101
+ spriteMaxWidthRatio = 0.6,
11100
11102
  // Asset resolution
11101
11103
  getTerrainSprite,
11102
11104
  getFeatureSprite,
@@ -11487,8 +11489,8 @@ function IsometricCanvas({
11487
11489
  const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
11488
11490
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
11489
11491
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
11490
- const unitDrawH = scaledFloorHeight * 1.5 * unitScale;
11491
- const maxUnitW = scaledTileWidth * 0.6 * unitScale;
11492
+ const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
11493
+ const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
11492
11494
  const ar = img ? img.naturalWidth / img.naturalHeight : 0.5;
11493
11495
  let drawH = unitDrawH;
11494
11496
  let drawW = unitDrawH * ar;
@@ -11872,6 +11874,8 @@ function BattleBoard({
11872
11874
  assetManifest: propAssetManifest,
11873
11875
  scale = 0.45,
11874
11876
  unitScale = 1,
11877
+ spriteHeightRatio = 1.5,
11878
+ spriteMaxWidthRatio = 0.6,
11875
11879
  header,
11876
11880
  sidebar,
11877
11881
  actions,
@@ -12162,7 +12166,9 @@ function BattleBoard({
12162
12166
  hasActiveEffects: hasActiveEffects2,
12163
12167
  effectSpriteUrls,
12164
12168
  resolveUnitFrame,
12165
- unitScale
12169
+ unitScale,
12170
+ spriteHeightRatio,
12171
+ spriteMaxWidthRatio
12166
12172
  }
12167
12173
  ),
12168
12174
  overlay && overlay(ctx)
@@ -42133,6 +42139,8 @@ var init_GameCanvas3D2 = __esm({
42133
42139
  attackTargets = [],
42134
42140
  selectedTileIds = [],
42135
42141
  selectedUnitId = null,
42142
+ unitScale = 1,
42143
+ scale = 0.45,
42136
42144
  children
42137
42145
  }, ref) => {
42138
42146
  const containerRef = useRef(null);
@@ -42349,12 +42357,18 @@ var init_GameCanvas3D2 = __esm({
42349
42357
  },
42350
42358
  [selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
42351
42359
  );
42360
+ const UNIT_BASE_MODEL_SCALE = 0.5;
42361
+ const UNIT_BASE_BILLBOARD_HEIGHT = 1.2;
42362
+ const UNIT_BASE_PRIMITIVE_RADIUS = 0.3;
42352
42363
  const DefaultUnitRenderer = useCallback(
42353
42364
  ({ unit, position }) => {
42354
42365
  const isSelected = selectedUnitId === unit.id;
42355
42366
  const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
42356
42367
  const hasAtlas = unitAtlasUrl(unit) !== null;
42357
42368
  const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
42369
+ const modelScale = UNIT_BASE_MODEL_SCALE * unitScale;
42370
+ const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale;
42371
+ const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale;
42358
42372
  return /* @__PURE__ */ jsxs(
42359
42373
  "group",
42360
42374
  {
@@ -42372,7 +42386,8 @@ var init_GameCanvas3D2 = __esm({
42372
42386
  UnitSpriteBillboard,
42373
42387
  {
42374
42388
  sheetUrl: initialFrame.sheetUrl,
42375
- resolveFrame: () => resolveUnitFrame(unit.id)
42389
+ resolveFrame: () => resolveUnitFrame(unit.id),
42390
+ height: billboardHeight
42376
42391
  }
42377
42392
  ) })
42378
42393
  ) : unit.modelUrl ? (
@@ -42381,22 +42396,22 @@ var init_GameCanvas3D2 = __esm({
42381
42396
  ModelLoader,
42382
42397
  {
42383
42398
  url: unit.modelUrl,
42384
- scale: 0.5,
42399
+ scale: modelScale,
42385
42400
  fallbackGeometry: "box",
42386
42401
  castShadow: true
42387
42402
  }
42388
42403
  )
42389
42404
  ) : /* @__PURE__ */ jsxs(Fragment, { children: [
42390
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.3, 0], children: [
42391
- /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.3, 0.1, 8] }),
42405
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius, 0], children: [
42406
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [primitiveRadius, primitiveRadius, primitiveRadius * 0.33, 8] }),
42392
42407
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
42393
42408
  ] }),
42394
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.6, 0], children: [
42395
- /* @__PURE__ */ jsx("capsuleGeometry", { args: [0.2, 0.4, 4, 8] }),
42409
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius * 2, 0], children: [
42410
+ /* @__PURE__ */ jsx("capsuleGeometry", { args: [primitiveRadius * 0.67, primitiveRadius * 1.33, 4, 8] }),
42396
42411
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
42397
42412
  ] }),
42398
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.9, 0], children: [
42399
- /* @__PURE__ */ jsx("sphereGeometry", { args: [0.12, 8, 8] }),
42413
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius * 3, 0], children: [
42414
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [primitiveRadius * 0.4, 8, 8] }),
42400
42415
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
42401
42416
  ] })
42402
42417
  ] }),
@@ -42429,7 +42444,7 @@ var init_GameCanvas3D2 = __esm({
42429
42444
  }
42430
42445
  );
42431
42446
  },
42432
- [selectedUnitId, handleUnitClick, resolveUnitFrame]
42447
+ [selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale]
42433
42448
  );
42434
42449
  const DefaultFeatureRenderer = useCallback(
42435
42450
  ({
@@ -42572,33 +42587,35 @@ var init_GameCanvas3D2 = __esm({
42572
42587
  fadeStrength: 1
42573
42588
  }
42574
42589
  ),
42575
- tiles.map((tile, index) => {
42576
- const position = gridToWorld(
42577
- tile.x,
42578
- tile.z ?? tile.y ?? 0,
42579
- tile.elevation ?? 0
42580
- );
42581
- const Renderer = CustomTileRenderer || DefaultTileRenderer;
42582
- return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
42583
- }),
42584
- features.map((feature, index) => {
42585
- const position = gridToWorld(
42586
- feature.x,
42587
- feature.z ?? feature.y ?? 0,
42588
- (feature.elevation ?? 0) + 0.5
42589
- );
42590
- const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
42591
- return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
42592
- }),
42593
- units.map((unit) => {
42594
- const position = gridToWorld(
42595
- unit.x ?? 0,
42596
- unit.z ?? unit.y ?? 0,
42597
- (unit.elevation ?? 0) + 0.5
42598
- );
42599
- const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
42600
- return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
42601
- }),
42590
+ /* @__PURE__ */ jsxs("group", { scale, children: [
42591
+ tiles.map((tile, index) => {
42592
+ const position = gridToWorld(
42593
+ tile.x,
42594
+ tile.z ?? tile.y ?? 0,
42595
+ tile.elevation ?? 0
42596
+ );
42597
+ const Renderer = CustomTileRenderer || DefaultTileRenderer;
42598
+ return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
42599
+ }),
42600
+ features.map((feature, index) => {
42601
+ const position = gridToWorld(
42602
+ feature.x,
42603
+ feature.z ?? feature.y ?? 0,
42604
+ (feature.elevation ?? 0) + 0.5
42605
+ );
42606
+ const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
42607
+ return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
42608
+ }),
42609
+ units.map((unit) => {
42610
+ const position = gridToWorld(
42611
+ unit.x ?? 0,
42612
+ unit.z ?? unit.y ?? 0,
42613
+ (unit.elevation ?? 0) + 0.5
42614
+ );
42615
+ const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
42616
+ return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
42617
+ })
42618
+ ] }),
42602
42619
  children,
42603
42620
  /* @__PURE__ */ jsx(
42604
42621
  OrbitControls,
@@ -42641,6 +42658,8 @@ function GameBoard3D({
42641
42658
  features = [],
42642
42659
  cameraMode = "perspective",
42643
42660
  backgroundColor = "#2a1a1a",
42661
+ unitScale = 1,
42662
+ scale = 0.45,
42644
42663
  tileClickEvent,
42645
42664
  unitClickEvent,
42646
42665
  attackEvent,
@@ -42741,6 +42760,8 @@ function GameBoard3D({
42741
42760
  selectedUnitId,
42742
42761
  validMoves,
42743
42762
  attackTargets,
42763
+ unitScale,
42764
+ scale,
42744
42765
  className: "game-board-3d__canvas w-full min-h-[85vh]"
42745
42766
  }
42746
42767
  ),
@@ -44726,6 +44747,8 @@ function RoguelikeBoard({
44726
44747
  assetManifest: propAssetManifest,
44727
44748
  scale = 0.45,
44728
44749
  unitScale = 1,
44750
+ spriteHeightRatio = 1.5,
44751
+ spriteMaxWidthRatio = 0.6,
44729
44752
  moveEvent,
44730
44753
  playAgainEvent,
44731
44754
  gameEndEvent,
@@ -44873,7 +44896,9 @@ function RoguelikeBoard({
44873
44896
  scale,
44874
44897
  assetBaseUrl: propAssetManifest?.baseUrl ?? CDN4,
44875
44898
  assetManifest: propAssetManifest,
44876
- unitScale
44899
+ unitScale,
44900
+ spriteHeightRatio,
44901
+ spriteMaxWidthRatio
44877
44902
  }
44878
44903
  ) }),
44879
44904
  !isGameOver && /* @__PURE__ */ jsx(HStack, { className: "justify-center gap-2 p-3", gap: "none", children: [
@@ -49226,6 +49251,9 @@ function TowerDefenseBoard({
49226
49251
  waveActive: propWaveActive,
49227
49252
  towerCost = 25,
49228
49253
  scale = 0.45,
49254
+ unitScale = 1,
49255
+ spriteHeightRatio = 1.5,
49256
+ spriteMaxWidthRatio = 0.6,
49229
49257
  placeTowerEvent,
49230
49258
  startWaveEvent,
49231
49259
  playAgainEvent,
@@ -49333,7 +49361,10 @@ function TowerDefenseBoard({
49333
49361
  onTileClick: handleTileClick,
49334
49362
  onTileHover: (x, y) => setHoveredTile({ x, y }),
49335
49363
  onTileLeave: () => setHoveredTile(null),
49336
- scale
49364
+ scale,
49365
+ unitScale,
49366
+ spriteHeightRatio,
49367
+ spriteMaxWidthRatio
49337
49368
  }
49338
49369
  ),
49339
49370
  hoveredTile && canPlaceTower && validMoves.some((m) => m.x === hoveredTile.x && m.y === hoveredTile.y) && /* @__PURE__ */ jsx(Box, { className: "absolute bottom-4 left-1/2 -translate-x-1/2 z-10 bg-background/80 rounded px-3 py-1 backdrop-blur-sm pointer-events-none", children: /* @__PURE__ */ jsx(Typography, { variant: "small", children: t("td.placeTower") ?? `Place tower (${towerCost} gold)` }) })
@@ -49669,6 +49700,8 @@ function WorldMapBoard({
49669
49700
  isLoading,
49670
49701
  scale = 0.4,
49671
49702
  unitScale = 2.5,
49703
+ spriteHeightRatio = 1.5,
49704
+ spriteMaxWidthRatio = 0.6,
49672
49705
  allowMoveAllHeroes = false,
49673
49706
  isInRange = defaultIsInRange,
49674
49707
  heroSelectEvent,
@@ -49906,6 +49939,8 @@ function WorldMapBoard({
49906
49939
  effectSpriteUrls,
49907
49940
  resolveUnitFrame,
49908
49941
  unitScale,
49942
+ spriteHeightRatio,
49943
+ spriteMaxWidthRatio,
49909
49944
  diamondTopY,
49910
49945
  enableCamera
49911
49946
  }