// // Licensed under the MIT License. See LICENSE file in the project root for full license information. // namespace MUnique.OpenMU.GameLogic.Offline; using MUnique.OpenMU.GameLogic.MuHelper; using MUnique.OpenMU.GameLogic.PlayerActions.Items; /// /// Handles auto-repair of equipped items for the offline player. /// internal sealed class RepairHandler { /// /// The durability health threshold (inclusive, in percent) below which a repair is triggered. /// Mirrors the client's DEFAULT_DURABILITY_THRESHOLD constant in MuHelper.cpp. /// private const int DurabilityRepairThresholdPercent = 50; private readonly Player _player; private readonly IMuHelperSettings? _config; private readonly ItemRepairAction _repairAction = new(); /// /// Initializes a new instance of the class. /// /// The player. /// The MU Helper configuration. public RepairHandler(Player player, IMuHelperSettings? config) { this._player = player; this._config = config; } /// /// Performs repairs on equipped items if the configuration allows it /// and the item's durability is at or below %. /// public async ValueTask PerformRepairsAsync() { if (this._config is not { RepairItem: true }) { this._player.Logger.LogDebug("Auto-repair is disabled by MU Helper configuration for character {CharacterName}.", this._player.Name); return; } for (byte i = InventoryConstants.FirstEquippableItemSlotIndex; i <= InventoryConstants.LastEquippableItemSlotIndex; i++) { if (i == InventoryConstants.PetSlot) { continue; } var item = this._player.Inventory?.GetItem(i); if (item is null) { continue; } if (!NeedsDurabilityRepair(item)) { continue; } await this._repairAction.RepairItemAsync(this._player, i).ConfigureAwait(false); } } /// /// Returns when the item's durability health is at or below /// %, using ceiling-integer arithmetic /// to match the client formula: iHealth = (durability * 100 + max - 1) / max. /// private static bool NeedsDurabilityRepair(Item item) { var max = item.GetMaximumDurabilityOfOnePiece(); if (max == 0) { return false; } var durabilityHealthPercent = ((int)item.Durability * 100 + max - 1) / max; return durabilityHealthPercent <= DurabilityRepairThresholdPercent; } }