@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.
@@ -14581,6 +14581,8 @@ function IsometricCanvas({
14581
14581
  showMinimap = true,
14582
14582
  enableCamera = true,
14583
14583
  unitScale = 1,
14584
+ spriteHeightRatio = 1.5,
14585
+ spriteMaxWidthRatio = 0.6,
14584
14586
  // Asset resolution
14585
14587
  getTerrainSprite,
14586
14588
  getFeatureSprite,
@@ -14971,8 +14973,8 @@ function IsometricCanvas({
14971
14973
  const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
14972
14974
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
14973
14975
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
14974
- const unitDrawH = scaledFloorHeight * 1.5 * unitScale;
14975
- const maxUnitW = scaledTileWidth * 0.6 * unitScale;
14976
+ const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
14977
+ const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
14976
14978
  const ar = img ? img.naturalWidth / img.naturalHeight : 0.5;
14977
14979
  let drawH = unitDrawH;
14978
14980
  let drawW = unitDrawH * ar;
@@ -15356,6 +15358,8 @@ function BattleBoard({
15356
15358
  assetManifest: propAssetManifest,
15357
15359
  scale = 0.45,
15358
15360
  unitScale = 1,
15361
+ spriteHeightRatio = 1.5,
15362
+ spriteMaxWidthRatio = 0.6,
15359
15363
  header,
15360
15364
  sidebar,
15361
15365
  actions,
@@ -15646,7 +15650,9 @@ function BattleBoard({
15646
15650
  hasActiveEffects: hasActiveEffects2,
15647
15651
  effectSpriteUrls,
15648
15652
  resolveUnitFrame,
15649
- unitScale
15653
+ unitScale,
15654
+ spriteHeightRatio,
15655
+ spriteMaxWidthRatio
15650
15656
  }
15651
15657
  ),
15652
15658
  overlay && overlay(ctx)
@@ -44379,6 +44385,8 @@ var init_GameCanvas3D2 = __esm({
44379
44385
  attackTargets = [],
44380
44386
  selectedTileIds = [],
44381
44387
  selectedUnitId = null,
44388
+ unitScale = 1,
44389
+ scale = 0.45,
44382
44390
  children
44383
44391
  }, ref) => {
44384
44392
  const containerRef = React90.useRef(null);
@@ -44595,12 +44603,18 @@ var init_GameCanvas3D2 = __esm({
44595
44603
  },
44596
44604
  [selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
44597
44605
  );
44606
+ const UNIT_BASE_MODEL_SCALE = 0.5;
44607
+ const UNIT_BASE_BILLBOARD_HEIGHT = 1.2;
44608
+ const UNIT_BASE_PRIMITIVE_RADIUS = 0.3;
44598
44609
  const DefaultUnitRenderer = React90.useCallback(
44599
44610
  ({ unit, position }) => {
44600
44611
  const isSelected = selectedUnitId === unit.id;
44601
44612
  const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
44602
44613
  const hasAtlas = unitAtlasUrl(unit) !== null;
44603
44614
  const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
44615
+ const modelScale = UNIT_BASE_MODEL_SCALE * unitScale;
44616
+ const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale;
44617
+ const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale;
44604
44618
  return /* @__PURE__ */ jsxRuntime.jsxs(
44605
44619
  "group",
44606
44620
  {
@@ -44618,7 +44632,8 @@ var init_GameCanvas3D2 = __esm({
44618
44632
  UnitSpriteBillboard,
44619
44633
  {
44620
44634
  sheetUrl: initialFrame.sheetUrl,
44621
- resolveFrame: () => resolveUnitFrame(unit.id)
44635
+ resolveFrame: () => resolveUnitFrame(unit.id),
44636
+ height: billboardHeight
44622
44637
  }
44623
44638
  ) })
44624
44639
  ) : unit.modelUrl ? (
@@ -44627,22 +44642,22 @@ var init_GameCanvas3D2 = __esm({
44627
44642
  ModelLoader,
44628
44643
  {
44629
44644
  url: unit.modelUrl,
44630
- scale: 0.5,
44645
+ scale: modelScale,
44631
44646
  fallbackGeometry: "box",
44632
44647
  castShadow: true
44633
44648
  }
44634
44649
  )
44635
44650
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
44636
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.3, 0], children: [
44637
- /* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.3, 0.3, 0.1, 8] }),
44651
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius, 0], children: [
44652
+ /* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [primitiveRadius, primitiveRadius, primitiveRadius * 0.33, 8] }),
44638
44653
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
44639
44654
  ] }),
44640
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.6, 0], children: [
44641
- /* @__PURE__ */ jsxRuntime.jsx("capsuleGeometry", { args: [0.2, 0.4, 4, 8] }),
44655
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius * 2, 0], children: [
44656
+ /* @__PURE__ */ jsxRuntime.jsx("capsuleGeometry", { args: [primitiveRadius * 0.67, primitiveRadius * 1.33, 4, 8] }),
44642
44657
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
44643
44658
  ] }),
44644
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.9, 0], children: [
44645
- /* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [0.12, 8, 8] }),
44659
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius * 3, 0], children: [
44660
+ /* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [primitiveRadius * 0.4, 8, 8] }),
44646
44661
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
44647
44662
  ] })
44648
44663
  ] }),
@@ -44675,7 +44690,7 @@ var init_GameCanvas3D2 = __esm({
44675
44690
  }
44676
44691
  );
44677
44692
  },
44678
- [selectedUnitId, handleUnitClick, resolveUnitFrame]
44693
+ [selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale]
44679
44694
  );
44680
44695
  const DefaultFeatureRenderer = React90.useCallback(
44681
44696
  ({
@@ -44818,33 +44833,35 @@ var init_GameCanvas3D2 = __esm({
44818
44833
  fadeStrength: 1
44819
44834
  }
44820
44835
  ),
44821
- tiles.map((tile, index) => {
44822
- const position = gridToWorld(
44823
- tile.x,
44824
- tile.z ?? tile.y ?? 0,
44825
- tile.elevation ?? 0
44826
- );
44827
- const Renderer = CustomTileRenderer || DefaultTileRenderer;
44828
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
44829
- }),
44830
- features.map((feature, index) => {
44831
- const position = gridToWorld(
44832
- feature.x,
44833
- feature.z ?? feature.y ?? 0,
44834
- (feature.elevation ?? 0) + 0.5
44835
- );
44836
- const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
44837
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
44838
- }),
44839
- units.map((unit) => {
44840
- const position = gridToWorld(
44841
- unit.x ?? 0,
44842
- unit.z ?? unit.y ?? 0,
44843
- (unit.elevation ?? 0) + 0.5
44844
- );
44845
- const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
44846
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { unit, position }, unit.id);
44847
- }),
44836
+ /* @__PURE__ */ jsxRuntime.jsxs("group", { scale, children: [
44837
+ tiles.map((tile, index) => {
44838
+ const position = gridToWorld(
44839
+ tile.x,
44840
+ tile.z ?? tile.y ?? 0,
44841
+ tile.elevation ?? 0
44842
+ );
44843
+ const Renderer = CustomTileRenderer || DefaultTileRenderer;
44844
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
44845
+ }),
44846
+ features.map((feature, index) => {
44847
+ const position = gridToWorld(
44848
+ feature.x,
44849
+ feature.z ?? feature.y ?? 0,
44850
+ (feature.elevation ?? 0) + 0.5
44851
+ );
44852
+ const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
44853
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
44854
+ }),
44855
+ units.map((unit) => {
44856
+ const position = gridToWorld(
44857
+ unit.x ?? 0,
44858
+ unit.z ?? unit.y ?? 0,
44859
+ (unit.elevation ?? 0) + 0.5
44860
+ );
44861
+ const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
44862
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { unit, position }, unit.id);
44863
+ })
44864
+ ] }),
44848
44865
  children,
44849
44866
  /* @__PURE__ */ jsxRuntime.jsx(
44850
44867
  drei.OrbitControls,
@@ -44887,6 +44904,8 @@ function GameBoard3D({
44887
44904
  features = [],
44888
44905
  cameraMode = "perspective",
44889
44906
  backgroundColor = "#2a1a1a",
44907
+ unitScale = 1,
44908
+ scale = 0.45,
44890
44909
  tileClickEvent,
44891
44910
  unitClickEvent,
44892
44911
  attackEvent,
@@ -44987,6 +45006,8 @@ function GameBoard3D({
44987
45006
  selectedUnitId,
44988
45007
  validMoves,
44989
45008
  attackTargets,
45009
+ unitScale,
45010
+ scale,
44990
45011
  className: "game-board-3d__canvas w-full min-h-[85vh]"
44991
45012
  }
44992
45013
  ),
@@ -46972,6 +46993,8 @@ function RoguelikeBoard({
46972
46993
  assetManifest: propAssetManifest,
46973
46994
  scale = 0.45,
46974
46995
  unitScale = 1,
46996
+ spriteHeightRatio = 1.5,
46997
+ spriteMaxWidthRatio = 0.6,
46975
46998
  moveEvent,
46976
46999
  playAgainEvent,
46977
47000
  gameEndEvent,
@@ -47119,7 +47142,9 @@ function RoguelikeBoard({
47119
47142
  scale,
47120
47143
  assetBaseUrl: propAssetManifest?.baseUrl ?? CDN4,
47121
47144
  assetManifest: propAssetManifest,
47122
- unitScale
47145
+ unitScale,
47146
+ spriteHeightRatio,
47147
+ spriteMaxWidthRatio
47123
47148
  }
47124
47149
  ) }),
47125
47150
  !isGameOver && /* @__PURE__ */ jsxRuntime.jsx(HStack, { className: "justify-center gap-2 p-3", gap: "none", children: [
@@ -51491,6 +51516,9 @@ function TowerDefenseBoard({
51491
51516
  waveActive: propWaveActive,
51492
51517
  towerCost = 25,
51493
51518
  scale = 0.45,
51519
+ unitScale = 1,
51520
+ spriteHeightRatio = 1.5,
51521
+ spriteMaxWidthRatio = 0.6,
51494
51522
  placeTowerEvent,
51495
51523
  startWaveEvent,
51496
51524
  playAgainEvent,
@@ -51598,7 +51626,10 @@ function TowerDefenseBoard({
51598
51626
  onTileClick: handleTileClick,
51599
51627
  onTileHover: (x, y) => setHoveredTile({ x, y }),
51600
51628
  onTileLeave: () => setHoveredTile(null),
51601
- scale
51629
+ scale,
51630
+ unitScale,
51631
+ spriteHeightRatio,
51632
+ spriteMaxWidthRatio
51602
51633
  }
51603
51634
  ),
51604
51635
  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)` }) })
@@ -51934,6 +51965,8 @@ function WorldMapBoard({
51934
51965
  isLoading,
51935
51966
  scale = 0.4,
51936
51967
  unitScale = 2.5,
51968
+ spriteHeightRatio = 1.5,
51969
+ spriteMaxWidthRatio = 0.6,
51937
51970
  allowMoveAllHeroes = false,
51938
51971
  isInRange = defaultIsInRange,
51939
51972
  heroSelectEvent,
@@ -52171,6 +52204,8 @@ function WorldMapBoard({
52171
52204
  effectSpriteUrls,
52172
52205
  resolveUnitFrame,
52173
52206
  unitScale,
52207
+ spriteHeightRatio,
52208
+ spriteMaxWidthRatio,
52174
52209
  diamondTopY,
52175
52210
  enableCamera
52176
52211
  }
@@ -57857,7 +57892,10 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57857
57892
  if (binding.config) {
57858
57893
  guardCtx.config = binding.config;
57859
57894
  }
57860
- const passed = runtime.interpolateValue(tick.guard, runtime.createContextFromBindings(guardCtx));
57895
+ const passed = evaluator.evaluateGuard(
57896
+ tick.guard,
57897
+ runtime.createContextFromBindings(guardCtx)
57898
+ );
57861
57899
  if (!passed) {
57862
57900
  tickLog.debug("guard-blocked", { traitName, tick: tick.name, state: currentState });
57863
57901
  return;
package/dist/avl/index.js CHANGED
@@ -10,7 +10,7 @@ import * as LucideIcons2 from 'lucide-react';
10
10
  import { Loader2, X, Code, FileText, WrapText, Check, Copy, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ZoomOut, ZoomIn, Download, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, ArrowLeft, HelpCircle, PauseCircle, Search, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, Bug, Send, ChevronUp, ChevronDown, Wrench, Tag, User, DollarSign, Zap, Sword, Move, Heart, Shield } from 'lucide-react';
11
11
  import { createPortal } from 'react-dom';
12
12
  import { UISlotProvider, useUISlots, useTheme } from '@almadar/ui/context';
13
- import { evaluate, createMinimalContext } from '@almadar/evaluator';
13
+ import { evaluateGuard, evaluate, createMinimalContext } from '@almadar/evaluator';
14
14
  import { Link, Outlet, useLocation } from 'react-router-dom';
15
15
  import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
16
16
  import dark from 'react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus.js';
@@ -47,7 +47,7 @@ import { Canvas, useLoader, useFrame, useThree } from '@react-three/fiber';
47
47
  import { Billboard, Grid as Grid$1, OrbitControls } from '@react-three/drei';
48
48
  import { getPatternDefinition, getComponentForPattern as getComponentForPattern$1, isEntityAwarePattern } from '@almadar/patterns';
49
49
  import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
50
- import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, interpolateValue, createContextFromBindings } from '@almadar/runtime';
50
+ import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, createContextFromBindings } from '@almadar/runtime';
51
51
 
52
52
  var __defProp = Object.defineProperty;
53
53
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -14534,6 +14534,8 @@ function IsometricCanvas({
14534
14534
  showMinimap = true,
14535
14535
  enableCamera = true,
14536
14536
  unitScale = 1,
14537
+ spriteHeightRatio = 1.5,
14538
+ spriteMaxWidthRatio = 0.6,
14537
14539
  // Asset resolution
14538
14540
  getTerrainSprite,
14539
14541
  getFeatureSprite,
@@ -14924,8 +14926,8 @@ function IsometricCanvas({
14924
14926
  const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
14925
14927
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
14926
14928
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
14927
- const unitDrawH = scaledFloorHeight * 1.5 * unitScale;
14928
- const maxUnitW = scaledTileWidth * 0.6 * unitScale;
14929
+ const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
14930
+ const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
14929
14931
  const ar = img ? img.naturalWidth / img.naturalHeight : 0.5;
14930
14932
  let drawH = unitDrawH;
14931
14933
  let drawW = unitDrawH * ar;
@@ -15309,6 +15311,8 @@ function BattleBoard({
15309
15311
  assetManifest: propAssetManifest,
15310
15312
  scale = 0.45,
15311
15313
  unitScale = 1,
15314
+ spriteHeightRatio = 1.5,
15315
+ spriteMaxWidthRatio = 0.6,
15312
15316
  header,
15313
15317
  sidebar,
15314
15318
  actions,
@@ -15599,7 +15603,9 @@ function BattleBoard({
15599
15603
  hasActiveEffects: hasActiveEffects2,
15600
15604
  effectSpriteUrls,
15601
15605
  resolveUnitFrame,
15602
- unitScale
15606
+ unitScale,
15607
+ spriteHeightRatio,
15608
+ spriteMaxWidthRatio
15603
15609
  }
15604
15610
  ),
15605
15611
  overlay && overlay(ctx)
@@ -44332,6 +44338,8 @@ var init_GameCanvas3D2 = __esm({
44332
44338
  attackTargets = [],
44333
44339
  selectedTileIds = [],
44334
44340
  selectedUnitId = null,
44341
+ unitScale = 1,
44342
+ scale = 0.45,
44335
44343
  children
44336
44344
  }, ref) => {
44337
44345
  const containerRef = useRef(null);
@@ -44548,12 +44556,18 @@ var init_GameCanvas3D2 = __esm({
44548
44556
  },
44549
44557
  [selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
44550
44558
  );
44559
+ const UNIT_BASE_MODEL_SCALE = 0.5;
44560
+ const UNIT_BASE_BILLBOARD_HEIGHT = 1.2;
44561
+ const UNIT_BASE_PRIMITIVE_RADIUS = 0.3;
44551
44562
  const DefaultUnitRenderer = useCallback(
44552
44563
  ({ unit, position }) => {
44553
44564
  const isSelected = selectedUnitId === unit.id;
44554
44565
  const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
44555
44566
  const hasAtlas = unitAtlasUrl(unit) !== null;
44556
44567
  const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
44568
+ const modelScale = UNIT_BASE_MODEL_SCALE * unitScale;
44569
+ const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale;
44570
+ const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale;
44557
44571
  return /* @__PURE__ */ jsxs(
44558
44572
  "group",
44559
44573
  {
@@ -44571,7 +44585,8 @@ var init_GameCanvas3D2 = __esm({
44571
44585
  UnitSpriteBillboard,
44572
44586
  {
44573
44587
  sheetUrl: initialFrame.sheetUrl,
44574
- resolveFrame: () => resolveUnitFrame(unit.id)
44588
+ resolveFrame: () => resolveUnitFrame(unit.id),
44589
+ height: billboardHeight
44575
44590
  }
44576
44591
  ) })
44577
44592
  ) : unit.modelUrl ? (
@@ -44580,22 +44595,22 @@ var init_GameCanvas3D2 = __esm({
44580
44595
  ModelLoader,
44581
44596
  {
44582
44597
  url: unit.modelUrl,
44583
- scale: 0.5,
44598
+ scale: modelScale,
44584
44599
  fallbackGeometry: "box",
44585
44600
  castShadow: true
44586
44601
  }
44587
44602
  )
44588
44603
  ) : /* @__PURE__ */ jsxs(Fragment, { children: [
44589
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.3, 0], children: [
44590
- /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.3, 0.1, 8] }),
44604
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius, 0], children: [
44605
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [primitiveRadius, primitiveRadius, primitiveRadius * 0.33, 8] }),
44591
44606
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
44592
44607
  ] }),
44593
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.6, 0], children: [
44594
- /* @__PURE__ */ jsx("capsuleGeometry", { args: [0.2, 0.4, 4, 8] }),
44608
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius * 2, 0], children: [
44609
+ /* @__PURE__ */ jsx("capsuleGeometry", { args: [primitiveRadius * 0.67, primitiveRadius * 1.33, 4, 8] }),
44595
44610
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
44596
44611
  ] }),
44597
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.9, 0], children: [
44598
- /* @__PURE__ */ jsx("sphereGeometry", { args: [0.12, 8, 8] }),
44612
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius * 3, 0], children: [
44613
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [primitiveRadius * 0.4, 8, 8] }),
44599
44614
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
44600
44615
  ] })
44601
44616
  ] }),
@@ -44628,7 +44643,7 @@ var init_GameCanvas3D2 = __esm({
44628
44643
  }
44629
44644
  );
44630
44645
  },
44631
- [selectedUnitId, handleUnitClick, resolveUnitFrame]
44646
+ [selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale]
44632
44647
  );
44633
44648
  const DefaultFeatureRenderer = useCallback(
44634
44649
  ({
@@ -44771,33 +44786,35 @@ var init_GameCanvas3D2 = __esm({
44771
44786
  fadeStrength: 1
44772
44787
  }
44773
44788
  ),
44774
- tiles.map((tile, index) => {
44775
- const position = gridToWorld(
44776
- tile.x,
44777
- tile.z ?? tile.y ?? 0,
44778
- tile.elevation ?? 0
44779
- );
44780
- const Renderer = CustomTileRenderer || DefaultTileRenderer;
44781
- return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
44782
- }),
44783
- features.map((feature, index) => {
44784
- const position = gridToWorld(
44785
- feature.x,
44786
- feature.z ?? feature.y ?? 0,
44787
- (feature.elevation ?? 0) + 0.5
44788
- );
44789
- const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
44790
- return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
44791
- }),
44792
- units.map((unit) => {
44793
- const position = gridToWorld(
44794
- unit.x ?? 0,
44795
- unit.z ?? unit.y ?? 0,
44796
- (unit.elevation ?? 0) + 0.5
44797
- );
44798
- const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
44799
- return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
44800
- }),
44789
+ /* @__PURE__ */ jsxs("group", { scale, children: [
44790
+ tiles.map((tile, index) => {
44791
+ const position = gridToWorld(
44792
+ tile.x,
44793
+ tile.z ?? tile.y ?? 0,
44794
+ tile.elevation ?? 0
44795
+ );
44796
+ const Renderer = CustomTileRenderer || DefaultTileRenderer;
44797
+ return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
44798
+ }),
44799
+ features.map((feature, index) => {
44800
+ const position = gridToWorld(
44801
+ feature.x,
44802
+ feature.z ?? feature.y ?? 0,
44803
+ (feature.elevation ?? 0) + 0.5
44804
+ );
44805
+ const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
44806
+ return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
44807
+ }),
44808
+ units.map((unit) => {
44809
+ const position = gridToWorld(
44810
+ unit.x ?? 0,
44811
+ unit.z ?? unit.y ?? 0,
44812
+ (unit.elevation ?? 0) + 0.5
44813
+ );
44814
+ const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
44815
+ return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
44816
+ })
44817
+ ] }),
44801
44818
  children,
44802
44819
  /* @__PURE__ */ jsx(
44803
44820
  OrbitControls,
@@ -44840,6 +44857,8 @@ function GameBoard3D({
44840
44857
  features = [],
44841
44858
  cameraMode = "perspective",
44842
44859
  backgroundColor = "#2a1a1a",
44860
+ unitScale = 1,
44861
+ scale = 0.45,
44843
44862
  tileClickEvent,
44844
44863
  unitClickEvent,
44845
44864
  attackEvent,
@@ -44940,6 +44959,8 @@ function GameBoard3D({
44940
44959
  selectedUnitId,
44941
44960
  validMoves,
44942
44961
  attackTargets,
44962
+ unitScale,
44963
+ scale,
44943
44964
  className: "game-board-3d__canvas w-full min-h-[85vh]"
44944
44965
  }
44945
44966
  ),
@@ -46925,6 +46946,8 @@ function RoguelikeBoard({
46925
46946
  assetManifest: propAssetManifest,
46926
46947
  scale = 0.45,
46927
46948
  unitScale = 1,
46949
+ spriteHeightRatio = 1.5,
46950
+ spriteMaxWidthRatio = 0.6,
46928
46951
  moveEvent,
46929
46952
  playAgainEvent,
46930
46953
  gameEndEvent,
@@ -47072,7 +47095,9 @@ function RoguelikeBoard({
47072
47095
  scale,
47073
47096
  assetBaseUrl: propAssetManifest?.baseUrl ?? CDN4,
47074
47097
  assetManifest: propAssetManifest,
47075
- unitScale
47098
+ unitScale,
47099
+ spriteHeightRatio,
47100
+ spriteMaxWidthRatio
47076
47101
  }
47077
47102
  ) }),
47078
47103
  !isGameOver && /* @__PURE__ */ jsx(HStack, { className: "justify-center gap-2 p-3", gap: "none", children: [
@@ -51444,6 +51469,9 @@ function TowerDefenseBoard({
51444
51469
  waveActive: propWaveActive,
51445
51470
  towerCost = 25,
51446
51471
  scale = 0.45,
51472
+ unitScale = 1,
51473
+ spriteHeightRatio = 1.5,
51474
+ spriteMaxWidthRatio = 0.6,
51447
51475
  placeTowerEvent,
51448
51476
  startWaveEvent,
51449
51477
  playAgainEvent,
@@ -51551,7 +51579,10 @@ function TowerDefenseBoard({
51551
51579
  onTileClick: handleTileClick,
51552
51580
  onTileHover: (x, y) => setHoveredTile({ x, y }),
51553
51581
  onTileLeave: () => setHoveredTile(null),
51554
- scale
51582
+ scale,
51583
+ unitScale,
51584
+ spriteHeightRatio,
51585
+ spriteMaxWidthRatio
51555
51586
  }
51556
51587
  ),
51557
51588
  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)` }) })
@@ -51887,6 +51918,8 @@ function WorldMapBoard({
51887
51918
  isLoading,
51888
51919
  scale = 0.4,
51889
51920
  unitScale = 2.5,
51921
+ spriteHeightRatio = 1.5,
51922
+ spriteMaxWidthRatio = 0.6,
51890
51923
  allowMoveAllHeroes = false,
51891
51924
  isInRange = defaultIsInRange,
51892
51925
  heroSelectEvent,
@@ -52124,6 +52157,8 @@ function WorldMapBoard({
52124
52157
  effectSpriteUrls,
52125
52158
  resolveUnitFrame,
52126
52159
  unitScale,
52160
+ spriteHeightRatio,
52161
+ spriteMaxWidthRatio,
52127
52162
  diamondTopY,
52128
52163
  enableCamera
52129
52164
  }
@@ -57810,7 +57845,10 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57810
57845
  if (binding.config) {
57811
57846
  guardCtx.config = binding.config;
57812
57847
  }
57813
- const passed = interpolateValue(tick.guard, createContextFromBindings(guardCtx));
57848
+ const passed = evaluateGuard(
57849
+ tick.guard,
57850
+ createContextFromBindings(guardCtx)
57851
+ );
57814
57852
  if (!passed) {
57815
57853
  tickLog.debug("guard-blocked", { traitName, tick: tick.name, state: currentState });
57816
57854
  return;
@@ -182,6 +182,10 @@ export interface GameCanvas3DProps {
182
182
  selectedTileIds?: string[];
183
183
  /** Selected unit ID */
184
184
  selectedUnitId?: string | null;
185
+ /** Unit draw-size multiplier. 1 = default tile-proportional size. */
186
+ unitScale?: number;
187
+ /** Board zoom/group scale. Applied to the scene group. Default 0.45. */
188
+ scale?: number;
185
189
  }
186
190
  /** Imperative handle for GameCanvas3D */
187
191
  export interface GameCanvas3DHandle {
@@ -91,6 +91,10 @@ export interface IsometricCanvasProps {
91
91
  enableCamera?: boolean;
92
92
  /** Extra scale multiplier for unit draw size. 1 = default. */
93
93
  unitScale?: number;
94
+ /** Ratio of unit draw height to scaledFloorHeight. Default 1.5. */
95
+ spriteHeightRatio?: number;
96
+ /** Max unit draw width as a ratio of scaledTileWidth. Default 0.6. */
97
+ spriteMaxWidthRatio?: number;
94
98
  /** Board width in tiles (overrides tile-derived size) */
95
99
  boardWidth?: number;
96
100
  /** Board height in tiles (overrides tile-derived size) */
@@ -125,7 +129,7 @@ export interface IsometricCanvasProps {
125
129
  effects?: Record<string, string>;
126
130
  };
127
131
  }
128
- export declare function IsometricCanvas({ className, isLoading, error, tiles: _tilesPropRaw, units: _unitsPropRaw, features: _featuresPropRaw, selectedUnitId, validMoves, attackTargets, hoveredTile, onTileClick, onUnitClick, onTileHover, onTileLeave, tileClickEvent, unitClickEvent, tileHoverEvent, tileLeaveEvent, scale, debug, backgroundImage, showMinimap, enableCamera, unitScale, getTerrainSprite, getFeatureSprite, getUnitSprite, resolveUnitFrame, effectSpriteUrls, onDrawEffects, hasActiveEffects, diamondTopY: diamondTopYProp, assetBaseUrl, assetManifest, }: IsometricCanvasProps): React.JSX.Element;
132
+ export declare function IsometricCanvas({ className, isLoading, error, tiles: _tilesPropRaw, units: _unitsPropRaw, features: _featuresPropRaw, selectedUnitId, validMoves, attackTargets, hoveredTile, onTileClick, onUnitClick, onTileHover, onTileLeave, tileClickEvent, unitClickEvent, tileHoverEvent, tileLeaveEvent, scale, debug, backgroundImage, showMinimap, enableCamera, unitScale, spriteHeightRatio, spriteMaxWidthRatio, getTerrainSprite, getFeatureSprite, getUnitSprite, resolveUnitFrame, effectSpriteUrls, onDrawEffects, hasActiveEffects, diamondTopY: diamondTopYProp, assetBaseUrl, assetManifest, }: IsometricCanvasProps): React.JSX.Element;
129
133
  export declare namespace IsometricCanvas {
130
134
  var displayName: string;
131
135
  }