fix(movement): invalidate burden on enchantment changes

This commit is contained in:
Erik 2026-07-31 10:16:27 +02:00
parent 2b9dfec9d7
commit d6e8b60303
13 changed files with 231 additions and 25 deletions

View file

@ -614,9 +614,8 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
d.Character.Spellbook,
d.Inventory.Objects,
() => d.PlayerIdentity.ServerGuid,
() => d.Character.LocalPlayer.GetAttribute(
LocalPlayerState.AttributeKind.Strength)
is { } strength ? (int?)strength.Current : null,
() => d.Character.LocalPlayer.GetEffectiveAttribute(
LocalPlayerState.AttributeKind.Strength),
() => late.Session.LinkStatus,
d.ClientTime,
() => late.Session.CurrentSession?.RequestLinkStatusPing(),
@ -656,9 +655,9 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
() => d.PlayerIdentity.ServerGuid,
iconComposer.GetIcon,
iconComposer.GetDragIcon,
() => d.Character.LocalPlayer.GetAttribute(
LocalPlayerState.AttributeKind.Strength)
is { } strength ? (int?)strength.Current : null,
() => d.Character.LocalPlayer.GetEffectiveAttribute(
LocalPlayerState.AttributeKind.Strength),
d.Character.Spellbook,
guid => late.Session.CurrentSession?.SendUse(guid),
(item, container, placement) =>
late.Session.CurrentSession?.SendPutItemInContainer(

View file

@ -91,7 +91,7 @@ public sealed class IndicatorBarController : IRetainedPanelController
_miniGame.OnClick = () => bindings.TogglePanel(RetailPanelCatalog.MiniGame);
_endCharacterSession.OnClick = bindings.RequestEndCharacterSession;
bindings.Spellbook.EnchantmentsChanged += UpdateEnchantments;
bindings.Spellbook.EnchantmentsChanged += OnEnchantmentsChanged;
bindings.Objects.ObjectAdded += OnObjectChanged;
bindings.Objects.ObjectUpdated += OnObjectChanged;
bindings.Objects.ObjectRemoved += OnObjectChanged;
@ -229,6 +229,11 @@ public sealed class IndicatorBarController : IRetainedPanelController
private void OnObjectMoved(ClientObjectMove _) => UpdateBurden();
private void OnContainerContentsReplaced(uint _) => UpdateBurden();
private void OnObjectsCleared() => UpdateBurden();
private void OnEnchantmentsChanged()
{
UpdateEnchantments();
UpdateBurden();
}
private void UpdateBurden()
{
@ -253,7 +258,7 @@ public sealed class IndicatorBarController : IRetainedPanelController
{
if (_disposed) return;
_disposed = true;
_bindings.Spellbook.EnchantmentsChanged -= UpdateEnchantments;
_bindings.Spellbook.EnchantmentsChanged -= OnEnchantmentsChanged;
_bindings.Objects.ObjectAdded -= OnObjectChanged;
_bindings.Objects.ObjectUpdated -= OnObjectChanged;
_bindings.Objects.ObjectRemoved -= OnObjectChanged;

View file

@ -3,6 +3,7 @@ using System.Numerics;
using AcDream.App.UI;
using AcDream.Core.Items;
using AcDream.Core.Selection;
using AcDream.Core.Spells;
namespace AcDream.App.UI.Layout;
@ -43,6 +44,7 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
private readonly Func<ItemType, uint, uint, uint, uint, uint> _iconIds;
private readonly Func<ItemType, uint, uint, uint, uint, uint>? _dragIconIds;
private readonly Func<int?> _strength;
private readonly Spellbook? _burdenSpellbook;
private readonly Func<string>? _ownerName;
private readonly UiItemList? _contentsGrid;
@ -96,13 +98,15 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
Action<uint, uint>? notifyMergeAttempt,
ItemInteractionController? itemInteraction,
Action? onClose,
StackSplitQuantityState? stackSplitQuantity)
StackSplitQuantityState? stackSplitQuantity,
Spellbook? burdenSpellbook)
{
_objects = objects;
_playerGuid = playerGuid;
_iconIds = iconIds;
_dragIconIds = dragIconIds;
_strength = strength;
_burdenSpellbook = burdenSpellbook;
_ownerName = ownerName;
_sendUse = sendUse;
_sendPutItemInContainer = sendPutItemInContainer;
@ -195,6 +199,8 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
_objects.ObjectUpdated += OnObjectChanged;
_objects.Cleared += OnObjectsCleared;
_selection.Changed += OnSelectionChanged;
if (_burdenSpellbook is not null)
_burdenSpellbook.EnchantmentsChanged += RefreshBurden;
if (_itemInteraction is not null)
{
_itemInteraction.StateChanged += OnInteractionStateChanged;
@ -244,14 +250,15 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
ItemInteractionController? itemInteraction = null,
Action? onClose = null,
StackSplitQuantityState? stackSplitQuantity = null,
Func<ItemType, uint, uint, uint, uint, uint>? dragIconIds = null)
Func<ItemType, uint, uint, uint, uint, uint>? dragIconIds = null,
Spellbook? burdenSpellbook = null)
=> new InventoryController(layout, objects, playerGuid, iconIds, dragIconIds, strength, selection,
ownerName, datFont,
contentsEmptySprite, sideBagEmptySprite, mainPackEmptySprite,
sendUse, sendPutItemInContainer,
sendStackableSplitToContainer, sendStackableMerge,
notifyMergeAttempt, itemInteraction,
onClose, stackSplitQuantity);
onClose, stackSplitQuantity, burdenSpellbook);
private void OnObjectChanged(ClientObject o)
{
@ -944,6 +951,8 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
_objects.ObjectUpdated -= OnObjectChanged;
_objects.Cleared -= OnObjectsCleared;
_selection.Changed -= OnSelectionChanged;
if (_burdenSpellbook is not null)
_burdenSpellbook.EnchantmentsChanged -= RefreshBurden;
if (_contentsGrid is not null)
{
_contentsGrid.PrimaryItemPressed = null;

View file

@ -122,6 +122,7 @@ public sealed record InventoryRuntimeBindings(
Func<ItemType, uint, uint, uint, uint, uint> ResolveIcon,
Func<ItemType, uint, uint, uint, uint, uint> ResolveDragIcon,
Func<int?> Strength,
Spellbook Spellbook,
Action<uint>? SendUse,
Action<uint, uint, int>? SendPutItemInContainer,
Action<uint, uint, uint, uint>? SendStackableSplitToContainer,
@ -1816,7 +1817,8 @@ public sealed class RetailUiRuntime : IDisposable
notifyMergeAttempt, b.ItemInteraction,
() => CloseWindow(WindowNames.Inventory),
StackSplitQuantity,
b.ResolveDragIcon);
b.ResolveDragIcon,
b.Spellbook);
InventoryPanelController = inventory;
PaperdollController paperdoll = PaperdollController.Bind(
layout, b.Objects, b.PlayerGuid, b.ResolveIcon, b.Selection, b.ItemInteraction,

View file

@ -229,6 +229,10 @@ public sealed class LiveSessionEventRouter : ILiveSessionEventRouting
if (kind == LocalPlayerState.AttributeKind.Strength)
RecomputeBurden(inventory, character);
});
SubscribeParameterless(
h => character.Character.Spellbook.EnchantmentsChanged += h,
h => character.Character.Spellbook.EnchantmentsChanged -= h,
() => RecomputeBurden(inventory, character));
// Current-stamina push — CACQualities::InqRunRate/InqJumpVelocity's
// stamina==0 effective-skill-zeroing gate (pseudocode doc §5).
@ -370,8 +374,8 @@ public sealed class LiveSessionEventRouter : ILiveSessionEventRouting
{
uint player = inventory.PlayerGuid();
ClientObject? playerObject = inventory.Objects.Get(player);
int strength = (int)(character.Character.LocalPlayer
.GetAttribute(LocalPlayerState.AttributeKind.Strength)?.Current ?? 0u);
int strength = character.Character.LocalPlayer
.GetEffectiveAttribute(LocalPlayerState.AttributeKind.Strength) ?? 0;
int aug = playerObject?.Properties.GetInt(
(uint)PropertyInt.AugmentationIncreasedCarryingCapacity) ?? 0;
int capacity = EncumbranceSystem.EncumbranceCapacity(strength, aug);