@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.
@@ -10842,6 +10842,8 @@ function IsometricCanvas({
10842
10842
  showMinimap = true,
10843
10843
  enableCamera = true,
10844
10844
  unitScale = 1,
10845
+ spriteHeightRatio = 1.5,
10846
+ spriteMaxWidthRatio = 0.6,
10845
10847
  // Asset resolution
10846
10848
  getTerrainSprite,
10847
10849
  getFeatureSprite,
@@ -11232,8 +11234,8 @@ function IsometricCanvas({
11232
11234
  const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
11233
11235
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
11234
11236
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
11235
- const unitDrawH = scaledFloorHeight * 1.5 * unitScale;
11236
- const maxUnitW = scaledTileWidth * 0.6 * unitScale;
11237
+ const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
11238
+ const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
11237
11239
  const ar = img ? img.naturalWidth / img.naturalHeight : 0.5;
11238
11240
  let drawH = unitDrawH;
11239
11241
  let drawW = unitDrawH * ar;
@@ -11617,6 +11619,8 @@ function BattleBoard({
11617
11619
  assetManifest: propAssetManifest,
11618
11620
  scale = 0.45,
11619
11621
  unitScale = 1,
11622
+ spriteHeightRatio = 1.5,
11623
+ spriteMaxWidthRatio = 0.6,
11620
11624
  header,
11621
11625
  sidebar,
11622
11626
  actions,
@@ -11907,7 +11911,9 @@ function BattleBoard({
11907
11911
  hasActiveEffects: hasActiveEffects2,
11908
11912
  effectSpriteUrls,
11909
11913
  resolveUnitFrame,
11910
- unitScale
11914
+ unitScale,
11915
+ spriteHeightRatio,
11916
+ spriteMaxWidthRatio
11911
11917
  }
11912
11918
  ),
11913
11919
  overlay && overlay(ctx)
@@ -41878,6 +41884,8 @@ var init_GameCanvas3D2 = __esm({
41878
41884
  attackTargets = [],
41879
41885
  selectedTileIds = [],
41880
41886
  selectedUnitId = null,
41887
+ unitScale = 1,
41888
+ scale = 0.45,
41881
41889
  children
41882
41890
  }, ref) => {
41883
41891
  const containerRef = React81.useRef(null);
@@ -42094,12 +42102,18 @@ var init_GameCanvas3D2 = __esm({
42094
42102
  },
42095
42103
  [selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
42096
42104
  );
42105
+ const UNIT_BASE_MODEL_SCALE = 0.5;
42106
+ const UNIT_BASE_BILLBOARD_HEIGHT = 1.2;
42107
+ const UNIT_BASE_PRIMITIVE_RADIUS = 0.3;
42097
42108
  const DefaultUnitRenderer = React81.useCallback(
42098
42109
  ({ unit, position }) => {
42099
42110
  const isSelected = selectedUnitId === unit.id;
42100
42111
  const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
42101
42112
  const hasAtlas = unitAtlasUrl(unit) !== null;
42102
42113
  const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
42114
+ const modelScale = UNIT_BASE_MODEL_SCALE * unitScale;
42115
+ const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale;
42116
+ const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale;
42103
42117
  return /* @__PURE__ */ jsxRuntime.jsxs(
42104
42118
  "group",
42105
42119
  {
@@ -42117,7 +42131,8 @@ var init_GameCanvas3D2 = __esm({
42117
42131
  UnitSpriteBillboard,
42118
42132
  {
42119
42133
  sheetUrl: initialFrame.sheetUrl,
42120
- resolveFrame: () => resolveUnitFrame(unit.id)
42134
+ resolveFrame: () => resolveUnitFrame(unit.id),
42135
+ height: billboardHeight
42121
42136
  }
42122
42137
  ) })
42123
42138
  ) : unit.modelUrl ? (
@@ -42126,22 +42141,22 @@ var init_GameCanvas3D2 = __esm({
42126
42141
  ModelLoader,
42127
42142
  {
42128
42143
  url: unit.modelUrl,
42129
- scale: 0.5,
42144
+ scale: modelScale,
42130
42145
  fallbackGeometry: "box",
42131
42146
  castShadow: true
42132
42147
  }
42133
42148
  )
42134
42149
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
42135
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.3, 0], children: [
42136
- /* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.3, 0.3, 0.1, 8] }),
42150
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius, 0], children: [
42151
+ /* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [primitiveRadius, primitiveRadius, primitiveRadius * 0.33, 8] }),
42137
42152
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
42138
42153
  ] }),
42139
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.6, 0], children: [
42140
- /* @__PURE__ */ jsxRuntime.jsx("capsuleGeometry", { args: [0.2, 0.4, 4, 8] }),
42154
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius * 2, 0], children: [
42155
+ /* @__PURE__ */ jsxRuntime.jsx("capsuleGeometry", { args: [primitiveRadius * 0.67, primitiveRadius * 1.33, 4, 8] }),
42141
42156
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
42142
42157
  ] }),
42143
- /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.9, 0], children: [
42144
- /* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [0.12, 8, 8] }),
42158
+ /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, primitiveRadius * 3, 0], children: [
42159
+ /* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [primitiveRadius * 0.4, 8, 8] }),
42145
42160
  /* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color })
42146
42161
  ] })
42147
42162
  ] }),
@@ -42174,7 +42189,7 @@ var init_GameCanvas3D2 = __esm({
42174
42189
  }
42175
42190
  );
42176
42191
  },
42177
- [selectedUnitId, handleUnitClick, resolveUnitFrame]
42192
+ [selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale]
42178
42193
  );
42179
42194
  const DefaultFeatureRenderer = React81.useCallback(
42180
42195
  ({
@@ -42317,33 +42332,35 @@ var init_GameCanvas3D2 = __esm({
42317
42332
  fadeStrength: 1
42318
42333
  }
42319
42334
  ),
42320
- tiles.map((tile, index) => {
42321
- const position = gridToWorld(
42322
- tile.x,
42323
- tile.z ?? tile.y ?? 0,
42324
- tile.elevation ?? 0
42325
- );
42326
- const Renderer = CustomTileRenderer || DefaultTileRenderer;
42327
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
42328
- }),
42329
- features.map((feature, index) => {
42330
- const position = gridToWorld(
42331
- feature.x,
42332
- feature.z ?? feature.y ?? 0,
42333
- (feature.elevation ?? 0) + 0.5
42334
- );
42335
- const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
42336
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
42337
- }),
42338
- units.map((unit) => {
42339
- const position = gridToWorld(
42340
- unit.x ?? 0,
42341
- unit.z ?? unit.y ?? 0,
42342
- (unit.elevation ?? 0) + 0.5
42343
- );
42344
- const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
42345
- return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { unit, position }, unit.id);
42346
- }),
42335
+ /* @__PURE__ */ jsxRuntime.jsxs("group", { scale, children: [
42336
+ tiles.map((tile, index) => {
42337
+ const position = gridToWorld(
42338
+ tile.x,
42339
+ tile.z ?? tile.y ?? 0,
42340
+ tile.elevation ?? 0
42341
+ );
42342
+ const Renderer = CustomTileRenderer || DefaultTileRenderer;
42343
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
42344
+ }),
42345
+ features.map((feature, index) => {
42346
+ const position = gridToWorld(
42347
+ feature.x,
42348
+ feature.z ?? feature.y ?? 0,
42349
+ (feature.elevation ?? 0) + 0.5
42350
+ );
42351
+ const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
42352
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
42353
+ }),
42354
+ units.map((unit) => {
42355
+ const position = gridToWorld(
42356
+ unit.x ?? 0,
42357
+ unit.z ?? unit.y ?? 0,
42358
+ (unit.elevation ?? 0) + 0.5
42359
+ );
42360
+ const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
42361
+ return /* @__PURE__ */ jsxRuntime.jsx(Renderer, { unit, position }, unit.id);
42362
+ })
42363
+ ] }),
42347
42364
  children,
42348
42365
  /* @__PURE__ */ jsxRuntime.jsx(
42349
42366
  drei.OrbitControls,
@@ -42386,6 +42403,8 @@ function GameBoard3D({
42386
42403
  features = [],
42387
42404
  cameraMode = "perspective",
42388
42405
  backgroundColor = "#2a1a1a",
42406
+ unitScale = 1,
42407
+ scale = 0.45,
42389
42408
  tileClickEvent,
42390
42409
  unitClickEvent,
42391
42410
  attackEvent,
@@ -42486,6 +42505,8 @@ function GameBoard3D({
42486
42505
  selectedUnitId,
42487
42506
  validMoves,
42488
42507
  attackTargets,
42508
+ unitScale,
42509
+ scale,
42489
42510
  className: "game-board-3d__canvas w-full min-h-[85vh]"
42490
42511
  }
42491
42512
  ),
@@ -44471,6 +44492,8 @@ function RoguelikeBoard({
44471
44492
  assetManifest: propAssetManifest,
44472
44493
  scale = 0.45,
44473
44494
  unitScale = 1,
44495
+ spriteHeightRatio = 1.5,
44496
+ spriteMaxWidthRatio = 0.6,
44474
44497
  moveEvent,
44475
44498
  playAgainEvent,
44476
44499
  gameEndEvent,
@@ -44618,7 +44641,9 @@ function RoguelikeBoard({
44618
44641
  scale,
44619
44642
  assetBaseUrl: propAssetManifest?.baseUrl ?? CDN4,
44620
44643
  assetManifest: propAssetManifest,
44621
- unitScale
44644
+ unitScale,
44645
+ spriteHeightRatio,
44646
+ spriteMaxWidthRatio
44622
44647
  }
44623
44648
  ) }),
44624
44649
  !isGameOver && /* @__PURE__ */ jsxRuntime.jsx(HStack, { className: "justify-center gap-2 p-3", gap: "none", children: [
@@ -48990,6 +49015,9 @@ function TowerDefenseBoard({
48990
49015
  waveActive: propWaveActive,
48991
49016
  towerCost = 25,
48992
49017
  scale = 0.45,
49018
+ unitScale = 1,
49019
+ spriteHeightRatio = 1.5,
49020
+ spriteMaxWidthRatio = 0.6,
48993
49021
  placeTowerEvent,
48994
49022
  startWaveEvent,
48995
49023
  playAgainEvent,
@@ -49097,7 +49125,10 @@ function TowerDefenseBoard({
49097
49125
  onTileClick: handleTileClick,
49098
49126
  onTileHover: (x, y) => setHoveredTile({ x, y }),
49099
49127
  onTileLeave: () => setHoveredTile(null),
49100
- scale
49128
+ scale,
49129
+ unitScale,
49130
+ spriteHeightRatio,
49131
+ spriteMaxWidthRatio
49101
49132
  }
49102
49133
  ),
49103
49134
  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)` }) })
@@ -49433,6 +49464,8 @@ function WorldMapBoard({
49433
49464
  isLoading,
49434
49465
  scale = 0.4,
49435
49466
  unitScale = 2.5,
49467
+ spriteHeightRatio = 1.5,
49468
+ spriteMaxWidthRatio = 0.6,
49436
49469
  allowMoveAllHeroes = false,
49437
49470
  isInRange = defaultIsInRange,
49438
49471
  heroSelectEvent,
@@ -49670,6 +49703,8 @@ function WorldMapBoard({
49670
49703
  effectSpriteUrls,
49671
49704
  resolveUnitFrame,
49672
49705
  unitScale,
49706
+ spriteHeightRatio,
49707
+ spriteMaxWidthRatio,
49673
49708
  diamondTopY,
49674
49709
  enableCamera
49675
49710
  }
@@ -51911,7 +51946,10 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51911
51946
  if (binding.config) {
51912
51947
  guardCtx.config = binding.config;
51913
51948
  }
51914
- const passed = runtime.interpolateValue(tick.guard, runtime.createContextFromBindings(guardCtx));
51949
+ const passed = evaluator.evaluateGuard(
51950
+ tick.guard,
51951
+ runtime.createContextFromBindings(guardCtx)
51952
+ );
51915
51953
  if (!passed) {
51916
51954
  tickLog.debug("guard-blocked", { traitName, tick: tick.name, state: currentState });
51917
51955
  return;
@@ -10,7 +10,7 @@ import { Loader2, X, Lightbulb, CheckCircle, List, Printer, ChevronRight, Chevro
10
10
  import { createPortal } from 'react-dom';
11
11
  import { useTranslate, useEventBus as useEventBus$1 } from '@almadar/ui/hooks';
12
12
  import { useUISlots, UISlotProvider, 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 ELK from 'elkjs/lib/elk.bundled.js';
16
16
  import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
@@ -48,7 +48,7 @@ import { GLTFLoader as GLTFLoader$1 } from 'three/examples/jsm/loaders/GLTFLoade
48
48
  import { Canvas, useLoader, useFrame, useThree } from '@react-three/fiber';
49
49
  import { Billboard, Grid as Grid$1, OrbitControls } from '@react-three/drei';
50
50
  import { getPatternDefinition, getComponentForPattern as getComponentForPattern$1 } from '@almadar/patterns';
51
- import { StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, interpolateValue, createContextFromBindings, InMemoryPersistence } from '@almadar/runtime';
51
+ import { StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, createContextFromBindings, InMemoryPersistence } from '@almadar/runtime';
52
52
  import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
53
53
 
54
54
  var __defProp = Object.defineProperty;
@@ -10795,6 +10795,8 @@ function IsometricCanvas({
10795
10795
  showMinimap = true,
10796
10796
  enableCamera = true,
10797
10797
  unitScale = 1,
10798
+ spriteHeightRatio = 1.5,
10799
+ spriteMaxWidthRatio = 0.6,
10798
10800
  // Asset resolution
10799
10801
  getTerrainSprite,
10800
10802
  getFeatureSprite,
@@ -11185,8 +11187,8 @@ function IsometricCanvas({
11185
11187
  const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
11186
11188
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
11187
11189
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
11188
- const unitDrawH = scaledFloorHeight * 1.5 * unitScale;
11189
- const maxUnitW = scaledTileWidth * 0.6 * unitScale;
11190
+ const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
11191
+ const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
11190
11192
  const ar = img ? img.naturalWidth / img.naturalHeight : 0.5;
11191
11193
  let drawH = unitDrawH;
11192
11194
  let drawW = unitDrawH * ar;
@@ -11570,6 +11572,8 @@ function BattleBoard({
11570
11572
  assetManifest: propAssetManifest,
11571
11573
  scale = 0.45,
11572
11574
  unitScale = 1,
11575
+ spriteHeightRatio = 1.5,
11576
+ spriteMaxWidthRatio = 0.6,
11573
11577
  header,
11574
11578
  sidebar,
11575
11579
  actions,
@@ -11860,7 +11864,9 @@ function BattleBoard({
11860
11864
  hasActiveEffects: hasActiveEffects2,
11861
11865
  effectSpriteUrls,
11862
11866
  resolveUnitFrame,
11863
- unitScale
11867
+ unitScale,
11868
+ spriteHeightRatio,
11869
+ spriteMaxWidthRatio
11864
11870
  }
11865
11871
  ),
11866
11872
  overlay && overlay(ctx)
@@ -41831,6 +41837,8 @@ var init_GameCanvas3D2 = __esm({
41831
41837
  attackTargets = [],
41832
41838
  selectedTileIds = [],
41833
41839
  selectedUnitId = null,
41840
+ unitScale = 1,
41841
+ scale = 0.45,
41834
41842
  children
41835
41843
  }, ref) => {
41836
41844
  const containerRef = useRef(null);
@@ -42047,12 +42055,18 @@ var init_GameCanvas3D2 = __esm({
42047
42055
  },
42048
42056
  [selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
42049
42057
  );
42058
+ const UNIT_BASE_MODEL_SCALE = 0.5;
42059
+ const UNIT_BASE_BILLBOARD_HEIGHT = 1.2;
42060
+ const UNIT_BASE_PRIMITIVE_RADIUS = 0.3;
42050
42061
  const DefaultUnitRenderer = useCallback(
42051
42062
  ({ unit, position }) => {
42052
42063
  const isSelected = selectedUnitId === unit.id;
42053
42064
  const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
42054
42065
  const hasAtlas = unitAtlasUrl(unit) !== null;
42055
42066
  const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
42067
+ const modelScale = UNIT_BASE_MODEL_SCALE * unitScale;
42068
+ const billboardHeight = UNIT_BASE_BILLBOARD_HEIGHT * unitScale;
42069
+ const primitiveRadius = UNIT_BASE_PRIMITIVE_RADIUS * unitScale;
42056
42070
  return /* @__PURE__ */ jsxs(
42057
42071
  "group",
42058
42072
  {
@@ -42070,7 +42084,8 @@ var init_GameCanvas3D2 = __esm({
42070
42084
  UnitSpriteBillboard,
42071
42085
  {
42072
42086
  sheetUrl: initialFrame.sheetUrl,
42073
- resolveFrame: () => resolveUnitFrame(unit.id)
42087
+ resolveFrame: () => resolveUnitFrame(unit.id),
42088
+ height: billboardHeight
42074
42089
  }
42075
42090
  ) })
42076
42091
  ) : unit.modelUrl ? (
@@ -42079,22 +42094,22 @@ var init_GameCanvas3D2 = __esm({
42079
42094
  ModelLoader,
42080
42095
  {
42081
42096
  url: unit.modelUrl,
42082
- scale: 0.5,
42097
+ scale: modelScale,
42083
42098
  fallbackGeometry: "box",
42084
42099
  castShadow: true
42085
42100
  }
42086
42101
  )
42087
42102
  ) : /* @__PURE__ */ jsxs(Fragment, { children: [
42088
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.3, 0], children: [
42089
- /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.3, 0.1, 8] }),
42103
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius, 0], children: [
42104
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [primitiveRadius, primitiveRadius, primitiveRadius * 0.33, 8] }),
42090
42105
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
42091
42106
  ] }),
42092
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.6, 0], children: [
42093
- /* @__PURE__ */ jsx("capsuleGeometry", { args: [0.2, 0.4, 4, 8] }),
42107
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius * 2, 0], children: [
42108
+ /* @__PURE__ */ jsx("capsuleGeometry", { args: [primitiveRadius * 0.67, primitiveRadius * 1.33, 4, 8] }),
42094
42109
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
42095
42110
  ] }),
42096
- /* @__PURE__ */ jsxs("mesh", { position: [0, 0.9, 0], children: [
42097
- /* @__PURE__ */ jsx("sphereGeometry", { args: [0.12, 8, 8] }),
42111
+ /* @__PURE__ */ jsxs("mesh", { position: [0, primitiveRadius * 3, 0], children: [
42112
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [primitiveRadius * 0.4, 8, 8] }),
42098
42113
  /* @__PURE__ */ jsx("meshStandardMaterial", { color })
42099
42114
  ] })
42100
42115
  ] }),
@@ -42127,7 +42142,7 @@ var init_GameCanvas3D2 = __esm({
42127
42142
  }
42128
42143
  );
42129
42144
  },
42130
- [selectedUnitId, handleUnitClick, resolveUnitFrame]
42145
+ [selectedUnitId, handleUnitClick, resolveUnitFrame, unitScale]
42131
42146
  );
42132
42147
  const DefaultFeatureRenderer = useCallback(
42133
42148
  ({
@@ -42270,33 +42285,35 @@ var init_GameCanvas3D2 = __esm({
42270
42285
  fadeStrength: 1
42271
42286
  }
42272
42287
  ),
42273
- tiles.map((tile, index) => {
42274
- const position = gridToWorld(
42275
- tile.x,
42276
- tile.z ?? tile.y ?? 0,
42277
- tile.elevation ?? 0
42278
- );
42279
- const Renderer = CustomTileRenderer || DefaultTileRenderer;
42280
- return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
42281
- }),
42282
- features.map((feature, index) => {
42283
- const position = gridToWorld(
42284
- feature.x,
42285
- feature.z ?? feature.y ?? 0,
42286
- (feature.elevation ?? 0) + 0.5
42287
- );
42288
- const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
42289
- return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
42290
- }),
42291
- units.map((unit) => {
42292
- const position = gridToWorld(
42293
- unit.x ?? 0,
42294
- unit.z ?? unit.y ?? 0,
42295
- (unit.elevation ?? 0) + 0.5
42296
- );
42297
- const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
42298
- return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
42299
- }),
42288
+ /* @__PURE__ */ jsxs("group", { scale, children: [
42289
+ tiles.map((tile, index) => {
42290
+ const position = gridToWorld(
42291
+ tile.x,
42292
+ tile.z ?? tile.y ?? 0,
42293
+ tile.elevation ?? 0
42294
+ );
42295
+ const Renderer = CustomTileRenderer || DefaultTileRenderer;
42296
+ return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
42297
+ }),
42298
+ features.map((feature, index) => {
42299
+ const position = gridToWorld(
42300
+ feature.x,
42301
+ feature.z ?? feature.y ?? 0,
42302
+ (feature.elevation ?? 0) + 0.5
42303
+ );
42304
+ const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
42305
+ return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
42306
+ }),
42307
+ units.map((unit) => {
42308
+ const position = gridToWorld(
42309
+ unit.x ?? 0,
42310
+ unit.z ?? unit.y ?? 0,
42311
+ (unit.elevation ?? 0) + 0.5
42312
+ );
42313
+ const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
42314
+ return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
42315
+ })
42316
+ ] }),
42300
42317
  children,
42301
42318
  /* @__PURE__ */ jsx(
42302
42319
  OrbitControls,
@@ -42339,6 +42356,8 @@ function GameBoard3D({
42339
42356
  features = [],
42340
42357
  cameraMode = "perspective",
42341
42358
  backgroundColor = "#2a1a1a",
42359
+ unitScale = 1,
42360
+ scale = 0.45,
42342
42361
  tileClickEvent,
42343
42362
  unitClickEvent,
42344
42363
  attackEvent,
@@ -42439,6 +42458,8 @@ function GameBoard3D({
42439
42458
  selectedUnitId,
42440
42459
  validMoves,
42441
42460
  attackTargets,
42461
+ unitScale,
42462
+ scale,
42442
42463
  className: "game-board-3d__canvas w-full min-h-[85vh]"
42443
42464
  }
42444
42465
  ),
@@ -44424,6 +44445,8 @@ function RoguelikeBoard({
44424
44445
  assetManifest: propAssetManifest,
44425
44446
  scale = 0.45,
44426
44447
  unitScale = 1,
44448
+ spriteHeightRatio = 1.5,
44449
+ spriteMaxWidthRatio = 0.6,
44427
44450
  moveEvent,
44428
44451
  playAgainEvent,
44429
44452
  gameEndEvent,
@@ -44571,7 +44594,9 @@ function RoguelikeBoard({
44571
44594
  scale,
44572
44595
  assetBaseUrl: propAssetManifest?.baseUrl ?? CDN4,
44573
44596
  assetManifest: propAssetManifest,
44574
- unitScale
44597
+ unitScale,
44598
+ spriteHeightRatio,
44599
+ spriteMaxWidthRatio
44575
44600
  }
44576
44601
  ) }),
44577
44602
  !isGameOver && /* @__PURE__ */ jsx(HStack, { className: "justify-center gap-2 p-3", gap: "none", children: [
@@ -48943,6 +48968,9 @@ function TowerDefenseBoard({
48943
48968
  waveActive: propWaveActive,
48944
48969
  towerCost = 25,
48945
48970
  scale = 0.45,
48971
+ unitScale = 1,
48972
+ spriteHeightRatio = 1.5,
48973
+ spriteMaxWidthRatio = 0.6,
48946
48974
  placeTowerEvent,
48947
48975
  startWaveEvent,
48948
48976
  playAgainEvent,
@@ -49050,7 +49078,10 @@ function TowerDefenseBoard({
49050
49078
  onTileClick: handleTileClick,
49051
49079
  onTileHover: (x, y) => setHoveredTile({ x, y }),
49052
49080
  onTileLeave: () => setHoveredTile(null),
49053
- scale
49081
+ scale,
49082
+ unitScale,
49083
+ spriteHeightRatio,
49084
+ spriteMaxWidthRatio
49054
49085
  }
49055
49086
  ),
49056
49087
  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)` }) })
@@ -49386,6 +49417,8 @@ function WorldMapBoard({
49386
49417
  isLoading,
49387
49418
  scale = 0.4,
49388
49419
  unitScale = 2.5,
49420
+ spriteHeightRatio = 1.5,
49421
+ spriteMaxWidthRatio = 0.6,
49389
49422
  allowMoveAllHeroes = false,
49390
49423
  isInRange = defaultIsInRange,
49391
49424
  heroSelectEvent,
@@ -49623,6 +49656,8 @@ function WorldMapBoard({
49623
49656
  effectSpriteUrls,
49624
49657
  resolveUnitFrame,
49625
49658
  unitScale,
49659
+ spriteHeightRatio,
49660
+ spriteMaxWidthRatio,
49626
49661
  diamondTopY,
49627
49662
  enableCamera
49628
49663
  }
@@ -51864,7 +51899,10 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51864
51899
  if (binding.config) {
51865
51900
  guardCtx.config = binding.config;
51866
51901
  }
51867
- const passed = interpolateValue(tick.guard, createContextFromBindings(guardCtx));
51902
+ const passed = evaluateGuard(
51903
+ tick.guard,
51904
+ createContextFromBindings(guardCtx)
51905
+ );
51868
51906
  if (!passed) {
51869
51907
  tickLog.debug("guard-blocked", { traitName, tick: tick.name, state: currentState });
51870
51908
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.55.0",
3
+ "version": "5.56.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [