diff --git a/src/GameLogic/PlayerActions/Items/ItemStackAction.cs b/src/GameLogic/PlayerActions/Items/ItemStackAction.cs
index 4af072a5d..e9c5fa69e 100644
--- a/src/GameLogic/PlayerActions/Items/ItemStackAction.cs
+++ b/src/GameLogic/PlayerActions/Items/ItemStackAction.cs
@@ -11,10 +11,13 @@ namespace MUnique.OpenMU.GameLogic.PlayerActions.Items;
///
public class ItemStackAction
{
+ private const int CombineFeePerTen = 500_000;
+ private const int DismantleFee = 1_000_000;
+
///
/// Stacks several items to one stacked item.
///
- /// The player which is stacking.
+ /// The player that is stacking.
/// The id of the stacking.
/// The size of the requested stack.
public async ValueTask StackItemsAsync(Player player, byte stackId, byte stackSize)
@@ -39,6 +42,13 @@ public async ValueTask StackItemsAsync(Player player, byte stackId, byte stackSi
var jewels = player.Inventory.Items.Where(item => item.Definition == mix.SingleJewel).Take(stackSize).ToList();
if (jewels.Count == stackSize)
{
+ var fee = GetCombineFee(stackSize);
+ if (!player.TryRemoveMoney(fee))
+ {
+ await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.NotEnoughMoney)).ConfigureAwait(false);
+ return;
+ }
+
foreach (var jewel in jewels)
{
await player.Inventory.RemoveItemAsync(jewel).ConfigureAwait(false);
@@ -51,6 +61,7 @@ public async ValueTask StackItemsAsync(Player player, byte stackId, byte stackSi
stacked.Durability = 1;
await player.Inventory.AddItemAsync(stacked).ConfigureAwait(false);
await player.InvokeViewPlugInAsync(p => p.ItemAppearAsync(stacked)).ConfigureAwait(false);
+ await player.InvokeViewPlugInAsync(p => p.UpdateMoneyAsync()).ConfigureAwait(false);
}
else
{
@@ -59,7 +70,7 @@ public async ValueTask StackItemsAsync(Player player, byte stackId, byte stackSi
}
///
- /// Unstacks the stacked item from the specified slot.
+ /// Unstack the stacked item from the specified slot.
///
/// The player.
/// The stack identifier.
@@ -91,6 +102,12 @@ public async ValueTask UnstackItemsAsync(Player player, byte stackId, byte slot)
return;
}
+ if (!player.TryRemoveMoney(DismantleFee))
+ {
+ await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.NotEnoughMoney)).ConfigureAwait(false);
+ return;
+ }
+
byte pieces = (byte)((stacked.Level + 1) * 10);
var freeSlots = player.Inventory!.FreeSlots.Take(pieces).ToList();
@@ -111,13 +128,17 @@ public async ValueTask UnstackItemsAsync(Player player, byte stackId, byte slot)
await player.Inventory.AddItemAsync(freeSlot, jewel).ConfigureAwait(false);
await player.InvokeViewPlugInAsync(p => p.ItemAppearAsync(jewel)).ConfigureAwait(false);
}
+
+ await player.InvokeViewPlugInAsync(p => p.UpdateMoneyAsync()).ConfigureAwait(false);
}
+ private static int GetCombineFee(byte stackSize) => (stackSize / 10) * CombineFeePerTen;
+
private bool IsCorrectNpcOpened(Player player)
{
if (player.OpenedNpc is null || player.OpenedNpc.Definition.NpcWindow != NpcWindow.Lahap)
{
- player.Logger.LogWarning("Probably Hacker tried to Mix/Unmix Jewels without talking to Lahap. Dupe Method. Acc: [{0}] Character: [{1}]", player.Account?.LoginName, player.SelectedCharacter?.Name);
+ player.Logger.LogWarning("Probably Hacker tried to Combine/Dismantle Jewels without talking to Lahap. Dupe Method. Acc: [{accountName}] Character: [{characterName}]", player.Account?.LoginName, player.SelectedCharacter?.Name);
return false;
}
@@ -129,7 +150,7 @@ private bool IsCorrectNpcOpened(Player player)
var mix = player.GameContext.Configuration.JewelMixes.FirstOrDefault(m => m.Number == mixId);
if (mix is null)
{
- player.Logger.LogWarning($"Unkown mix type [{mixId}], Player Name: [{player.SelectedCharacter?.Name}], Account Name: [{player.Account?.LoginName}]");
+ player.Logger.LogWarning("Unknown mix type [{mixType}], Player Name: [{characterName}], Account Name: [{accountName}]", mixId, player.SelectedCharacter?.Name, player.Account?.LoginName);
}
return mix;