198 lines
No EOL
6.7 KiB
C#
198 lines
No EOL
6.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using WingsAPI.Game.Extensions.ItemExtension.Inventory;
|
|
using WingsAPI.Game.Extensions.Quicklist;
|
|
using WingsEmu.Game._i18n;
|
|
using WingsEmu.Game.Algorithm;
|
|
using WingsEmu.Game.Extensions;
|
|
using WingsEmu.Game.Inventory;
|
|
using WingsEmu.Game.Managers;
|
|
using WingsEmu.Game.Networking;
|
|
using WingsEmu.Game.Shops.Event;
|
|
using WingsEmu.Game.Skills;
|
|
using WingsEmu.Packets.ClientPackets;
|
|
using WingsEmu.Packets.Enums;
|
|
using WingsEmu.Packets.Enums.Chat;
|
|
|
|
namespace WingsEmu.Plugins.PacketHandling.Game.Npc;
|
|
|
|
public class SellPacketHandler : GenericGamePacketHandlerBase<SellPacket>
|
|
{
|
|
private static readonly HashSet<short> Basics = new() { 200, 201, 220, 221, 240, 241, 260, 261, 1525, 1529 };
|
|
private static readonly HashSet<short> Capture = new() { 209, 235, 236, 237, 1565 };
|
|
private readonly ICharacterAlgorithm _characterAlgorithm;
|
|
private readonly IGameLanguageService _language;
|
|
private readonly IServerManager _serverManager;
|
|
|
|
public SellPacketHandler(IServerManager serverManager, ICharacterAlgorithm characterAlgorithm, IGameLanguageService language)
|
|
{
|
|
_characterAlgorithm = characterAlgorithm;
|
|
_serverManager = serverManager;
|
|
_language = language;
|
|
}
|
|
|
|
protected override async Task HandlePacketAsync(IClientSession session, SellPacket sellPacket)
|
|
{
|
|
if (session.PlayerEntity.IsInExchange())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (session.PlayerEntity.IsShopping)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sellPacket.Amount.HasValue && sellPacket.Slot.HasValue)
|
|
{
|
|
await HandleItemPacket(session, sellPacket);
|
|
return;
|
|
}
|
|
|
|
HandleSkillPacket(session, sellPacket);
|
|
}
|
|
|
|
private void HandleSkillPacket(IClientSession session, SellPacket sellPacket)
|
|
{
|
|
if (session.PlayerEntity.UseSp)
|
|
{
|
|
session.SendMsg(session.GetLanguage(GameDialogKey.INFORMATION_SHOUTMESSAGE_REMOVE_SP), MsgMessageType.Middle);
|
|
return;
|
|
}
|
|
|
|
if (session.PlayerEntity.IsOnVehicle)
|
|
{
|
|
session.SendChatMessage(session.GetLanguage(GameDialogKey.SKILL_CHATMESSAGE_CANT_LEARN_MORPHED), ChatMessageColorType.Yellow);
|
|
return;
|
|
}
|
|
|
|
if (session.PlayerEntity.IsInExchange())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (session.PlayerEntity.HasShopOpened)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (session.PlayerEntity.Skills.Any(s => !session.PlayerEntity.SkillCanBeUsed(s, DateTime.UtcNow)))
|
|
{
|
|
session.SendMsg(session.GetLanguage(GameDialogKey.SKILL_SHOUTMESSAGE_CANT_LEARN_COOLDOWN), MsgMessageType.Middle);
|
|
return;
|
|
}
|
|
|
|
short vnum = sellPacket.Data;
|
|
|
|
if (!session.PlayerEntity.CharacterSkills.TryGetValue(vnum, out CharacterSkill skill))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (skill == null || IsBasicSkillOrCapture(vnum))
|
|
{
|
|
session.SendChatMessage(_language.GetLanguage(GameDialogKey.SKILL_CHATMESSAGE_NOT_TO_REFUND, session.UserLanguage), ChatMessageColorType.Yellow);
|
|
return;
|
|
}
|
|
|
|
if (skill.Skill.IsPassiveSkill())
|
|
{
|
|
session.SendChatMessage(_language.GetLanguage(GameDialogKey.SKILL_CHATMESSAGE_NOT_TO_REFUND, session.UserLanguage), ChatMessageColorType.Yellow);
|
|
return;
|
|
}
|
|
|
|
if (skill.Skill.UpgradeSkill != 0)
|
|
{
|
|
if (session.PlayerEntity.SkillComponent.SkillUpgrades.TryGetValue(skill.Skill.UpgradeSkill, out HashSet<IBattleEntitySkill> hashSet))
|
|
{
|
|
hashSet.Remove(skill);
|
|
}
|
|
}
|
|
|
|
foreach (CharacterSkill loadedSkill in session.PlayerEntity.CharacterSkills.Values)
|
|
{
|
|
if (skill.SkillVNum != loadedSkill.Skill.UpgradeSkill)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
session.PlayerEntity.CharacterSkills.TryRemove(loadedSkill.SkillVNum, out CharacterSkill value);
|
|
session.PlayerEntity.Skills.Remove(value);
|
|
}
|
|
|
|
session.PlayerEntity.CharacterSkills.TryRemove(skill.SkillVNum, out CharacterSkill _);
|
|
session.PlayerEntity.Skills.Remove(skill);
|
|
|
|
if (session.PlayerEntity.SkillComponent.SkillUpgrades.TryGetValue(vnum, out HashSet<IBattleEntitySkill> upgrades))
|
|
{
|
|
upgrades.Clear();
|
|
}
|
|
|
|
session.RefreshSkillList();
|
|
session.RefreshQuicklist();
|
|
session.RefreshLevel(_characterAlgorithm);
|
|
|
|
session.EmitEventAsync(new ShopSkillSoldEvent
|
|
{
|
|
SkillVnum = skill.SkillVNum
|
|
});
|
|
}
|
|
|
|
private async Task HandleItemPacket(IClientSession session, SellPacket sellPacket)
|
|
{
|
|
var type = (InventoryType)sellPacket.Data;
|
|
byte slot = sellPacket.Slot.Value;
|
|
ushort amount = sellPacket.Amount.Value;
|
|
|
|
InventoryItem inv = session.PlayerEntity.GetItemBySlotAndType(slot, type);
|
|
if (inv == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (amount > inv.ItemInstance.Amount)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (inv.ItemInstance.GameItem.Type == InventoryType.Miniland &&
|
|
session.PlayerEntity.Miniland != null && session.PlayerEntity.Miniland.MapDesignObjects.Any(s => s.InventorySlot == inv.Slot))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (inv.ItemInstance.GameItem.ReputPrice != 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!inv.ItemInstance.GameItem.IsSoldable)
|
|
{
|
|
session.SendSMemo(SmemoType.Error, _language.GetLanguage(GameDialogKey.INTERACTION_LOG_ITEM_NOT_SELLABLE, session.UserLanguage));
|
|
return;
|
|
}
|
|
|
|
long price = inv.ItemInstance.GameItem.ItemType == ItemType.Sell ? inv.ItemInstance.GameItem.Price : inv.ItemInstance.GameItem.Price / 20 <= 0 ? 1 : inv.ItemInstance.GameItem.Price / 20;
|
|
|
|
if (session.PlayerEntity.Gold + price * amount > _serverManager.MaxGold)
|
|
{
|
|
session.SendSMemo(SmemoType.Error, _language.GetLanguage(GameDialogKey.INFORMATION_MESSAGE_MAX_GOLD, session.UserLanguage));
|
|
return;
|
|
}
|
|
|
|
session.PlayerEntity.Gold += price * amount;
|
|
session.RefreshGold();
|
|
session.SendSMemo(SmemoType.Balance, _language.GetLanguage(GameDialogKey.SHOP_LOG_SELL_ITEM_VALID, session.UserLanguage));
|
|
await session.RemoveItemFromInventory(item: inv, amount: (short)amount);
|
|
await session.EmitEventAsync(new ShopNpcSoldItemEvent
|
|
{
|
|
ItemInstance = inv.ItemInstance,
|
|
Amount = (short)amount,
|
|
PricePerItem = price
|
|
});
|
|
}
|
|
|
|
private static bool IsBasicSkillOrCapture(short vnum) => Basics.Contains(vnum) || Capture.Contains(vnum);
|
|
} |