server-master/srcs/_plugins/WingsEmu.Plugins.BasicImplementation/Event/Items/PlayerItemToPartnerItemEventHandler.cs
2026-02-10 18:21:30 +01:00

153 lines
No EOL
6.9 KiB
C#

using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using PhoenixLib.Events;
using WingsAPI.Game.Extensions.ItemExtension.Inventory;
using WingsEmu.DTOs.Items;
using WingsEmu.Game._enum;
using WingsEmu.Game._i18n;
using WingsEmu.Game.Characters.Events;
using WingsEmu.Game.Extensions;
using WingsEmu.Game.Inventory;
using WingsEmu.Game.Inventory.Event;
using WingsEmu.Game.Items;
using WingsEmu.Game.Networking;
using WingsEmu.Packets.Enums;
using WingsEmu.Packets.Enums.Chat;
namespace WingsEmu.Plugins.BasicImplementations.Event.Items;
public class PlayerItemToPartnerItemEventHandler : IAsyncEventProcessor<PlayerItemToPartnerItemEvent>
{
private static readonly int[] _partnerItems =
{
(int)ItemVnums.PARTNER_WEAPON_MELEE, (int)ItemVnums.PARTNER_WEAPON_RANGED, (int)ItemVnums.PARTNER_WEAPON_MAGIC, (int)ItemVnums.PARTNER_ARMOR_MAGIC, (int)ItemVnums.PARTNER_ARMOR_RANGED,
(int)ItemVnums.PARTNER_ARMOR_MELEE
};
private readonly IGameLanguageService _languageService;
public PlayerItemToPartnerItemEventHandler(IGameLanguageService languageService) => _languageService = languageService;
public async Task HandleAsync(PlayerItemToPartnerItemEvent e, CancellationToken cancellation)
{
IClientSession session = e.Sender;
InventoryItem item = session.PlayerEntity.GetItemBySlotAndType(e.Slot, e.InventoryType);
if (item == null)
{
return;
}
if (item.ItemInstance.Type != ItemInstanceType.WearableInstance)
{
return;
}
GameItemInstance itemToTransform = item.ItemInstance;
const ItemVnums donaVNum = ItemVnums.DONA_RIVER_SAND;
int price = 300 * itemToTransform.GameItem.LevelMinimum + 2000; // Formula by friends111 :peepoLove:
if (itemToTransform.GameItem.EquipmentSlot != EquipmentType.Armor
&& itemToTransform.GameItem.EquipmentSlot != EquipmentType.MainWeapon
&& itemToTransform.GameItem.EquipmentSlot != EquipmentType.SecondaryWeapon)
{
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.NORMAL, "Tried to transform a PlayerItem to a PartnerItem, and that PlayerItem is not the 'transformable' type" +
"(in theory there is a Client-side check for that)");
return;
}
if (_partnerItems.Contains(itemToTransform.ItemVNum))
{
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.NORMAL, "Tried to transform a PartnerItem to a PartnerItem (not possible with normal client)");
return;
}
if (session.PlayerEntity.Gold < price)
{
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.ABUSING, "Seems like the balance the client thinks he has is superior to what the server has. (not sufficient" +
" gold to pay the PlayerItem to PartnerItem transformation)");
return;
}
if (!session.PlayerEntity.HasItem((short)donaVNum, itemToTransform.GameItem.LevelMinimum))
{
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.ABUSING, "Tried to transform a PlayerItem to a PartnerItem without sufficient amount of" +
$" 'Dona River Sand' ({((short)donaVNum).ToString()}), and the Client-side check should have prevented that.");
return;
}
if (itemToTransform.EquipmentOptions != null && itemToTransform.EquipmentOptions.Any())
{
session.SendChatMessage(_languageService.GetLanguage(GameDialogKey.ITEM_CHATMESSAGE_CANNOT_BE_WITH_SHELL, session.UserLanguage), ChatMessageColorType.Red);
session.SendShopEndPacket(ShopEndType.Npc);
return;
}
GameItemInstance newItem = itemToTransform;
switch (itemToTransform.GameItem.EquipmentSlot)
{
case EquipmentType.Armor:
switch (itemToTransform.GameItem.Class)
{
case (int)ItemClassType.Swordsman:
case (int)ItemClassType.MartialArtist:
newItem.ItemVNum = (int)ItemVnums.PARTNER_ARMOR_MELEE;
break;
case (int)ItemClassType.Archer:
newItem.ItemVNum = (int)ItemVnums.PARTNER_ARMOR_RANGED;
break;
case (int)ItemClassType.Mage:
newItem.ItemVNum = (int)ItemVnums.PARTNER_ARMOR_MAGIC;
break;
default:
session.SendShopEndPacket(ShopEndType.Npc);
return;
}
break;
case EquipmentType.SecondaryWeapon:
case EquipmentType.MainWeapon:
switch (itemToTransform.GameItem.Class)
{
case (int)ItemClassType.Swordsman:
newItem.ItemVNum = itemToTransform.GameItem.EquipmentSlot == (int)EquipmentType.MainWeapon ? (int)ItemVnums.PARTNER_WEAPON_MELEE : (int)ItemVnums.PARTNER_WEAPON_RANGED;
break;
case (int)ItemClassType.Archer:
newItem.ItemVNum = itemToTransform.GameItem.EquipmentSlot == (int)EquipmentType.MainWeapon ? (int)ItemVnums.PARTNER_WEAPON_RANGED : (int)ItemVnums.PARTNER_WEAPON_MELEE;
break;
case (int)ItemClassType.Mage:
newItem.ItemVNum = itemToTransform.GameItem.EquipmentSlot == (int)EquipmentType.MainWeapon ? (int)ItemVnums.PARTNER_WEAPON_MAGIC : (int)ItemVnums.PARTNER_WEAPON_RANGED;
break;
case (int)ItemClassType.MartialArtist:
newItem.ItemVNum = (int)ItemVnums.PARTNER_WEAPON_MELEE;
break;
default:
session.SendShopEndPacket(ShopEndType.Npc);
return;
}
break;
default:
session.SendShopEndPacket(ShopEndType.Npc);
return;
}
if (newItem.Type == ItemInstanceType.WearableInstance)
{
newItem.EquipmentOptions?.Clear();
newItem.OriginalItemVnum = item.ItemInstance.GameItem.Id;
newItem.BoundCharacterId = null;
}
await session.RemoveItemFromInventory((short)donaVNum, itemToTransform.GameItem.LevelMinimum);
session.PlayerEntity.Gold -= price;
InventoryItem getItem = session.PlayerEntity.GetItemBySlotAndType(e.Slot, e.InventoryType);
await session.RemoveItemFromInventory(item: getItem);
await session.AddNewItemToInventory(newItem);
session.RefreshGold();
session.SendShopEndPacket(ShopEndType.Npc);
session.SendMsg(_languageService.GetLanguage(GameDialogKey.INFORMATION_SHOUTMESSAGE_PARTNER_ITEM_DONE, session.UserLanguage), MsgMessageType.Middle);
}
}