using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using WingsAPI.Game.Extensions.ItemExtension.Inventory; using WingsAPI.Game.Extensions.Quests; using WingsEmu.DTOs.BCards; using WingsEmu.DTOs.Items; using WingsEmu.DTOs.Quests; using WingsEmu.DTOs.ServerDatas; using WingsEmu.Game._enum; using WingsEmu.Game._i18n; using WingsEmu.Game._ItemUsage.Configuration; using WingsEmu.Game._ItemUsage.Event; using WingsEmu.Game.Battle; using WingsEmu.Game.Buffs; using WingsEmu.Game.Characters.Events; using WingsEmu.Game.Entities; using WingsEmu.Game.Extensions; using WingsEmu.Game.Inventory; using WingsEmu.Game.Inventory.Event; using WingsEmu.Game.Items; using WingsEmu.Game.Networking; using WingsEmu.Game.Quests; using WingsEmu.Game.Quests.Event; using WingsEmu.Packets.ClientPackets; using WingsEmu.Packets.Enums; using WingsEmu.Packets.Enums.Chat; using WingsEmu.Plugins.BasicImplementations.Vehicles; namespace WingsEmu.Plugins.PacketHandling.Game.Inventory; public class UseItemPacketHandler : GenericGamePacketHandlerBase { private readonly IBCardEffectHandlerContainer _bCardEffectHandlerContainer; private readonly ICostumeScrollConfiguration _costumeScrollConfiguration; private readonly IGameLanguageService _gameLanguage; private readonly IItemBoxManager _itemBoxManager; private readonly IVehicleConfigurationProvider _vehicleConfiguration; public UseItemPacketHandler(IGameLanguageService gameLanguage, IItemBoxManager itemBoxManager, IVehicleConfigurationProvider vehicleConfiguration, ICostumeScrollConfiguration costumeScrollConfiguration, IBCardEffectHandlerContainer bCardEffectHandlerContainer) { _gameLanguage = gameLanguage; _itemBoxManager = itemBoxManager; _vehicleConfiguration = vehicleConfiguration; _costumeScrollConfiguration = costumeScrollConfiguration; _bCardEffectHandlerContainer = bCardEffectHandlerContainer; } protected override async Task HandlePacketAsync(IClientSession session, UseItemPacket useItemPacket) { if (session.PlayerEntity.IsInExchange()) { await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.NORMAL, "Tried to use item while being in exchange"); return; } if (session.PlayerEntity.HasShopOpened) { await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.NORMAL, "Tried to use item while having shop open"); return; } if (session.PlayerEntity.IsSeal) { return; } if (session.PlayerEntity.CheatComponent.IsInvisible) { return; } if (!session.PlayerEntity.IsAlive()) { return; } if ((byte)useItemPacket.Type >= 9) { return; } InventoryItem inv = session.PlayerEntity.GetItemBySlotAndType(useItemPacket.Slot, useItemPacket.Type); string[] split = useItemPacket.OriginalContent.Split(' ', '^'); if (inv == null) { return; } /* * You can use only potions and snack being on vehicle / be morphed and: * Speed Booster / Limited and vehicle * Costume scroll */ if (inv.ItemInstance.Type == ItemInstanceType.NORMAL_ITEM) { if (!CanUseItemInVehicle(session, inv)) { session.SendChatMessage(session.GetLanguage(GameDialogKey.ITEM_CHATMESSAGE_ON_MOUNT), ChatMessageColorType.Yellow); return; } if (session.PlayerEntity.IsMorphed) { IGameItem gameItem = inv.ItemInstance.GameItem; IReadOnlyList morphs = _costumeScrollConfiguration.GetScrollMorphs((short)gameItem.Id); if (gameItem.ItemType is not ItemType.Potion and ItemType.Snack && (morphs == null || !morphs.Any())) { return; } } } if (inv.ItemInstance.GameItem.ItemType == ItemType.Special) { IGameItem gameItem = inv.ItemInstance.GameItem; foreach (BCardDTO c in gameItem.BCards) { _bCardEffectHandlerContainer.Execute(session.PlayerEntity, session.PlayerEntity, c); } ItemBoxDto itemBox = _itemBoxManager.GetItemBoxByItemVnumAndDesign(inv.ItemInstance.ItemVNum); if (itemBox != null && itemBox.Items.Count > 0) { if (split.Length == 9 || gameItem.ItemSubType == 3) { session.SendQnaPacket($"guri 4999 8023 {inv.Slot}", _gameLanguage.GetLanguage(GameDialogKey.ITEM_DIALOG_ASK_OPEN_BOX, session.UserLanguage)); return; } } } CheckQuests(session, inv.ItemInstance); switch (inv.ItemInstance.Type) { case ItemInstanceType.SpecialistInstance when !inv.ItemInstance.GameItem.IsPartnerSpecialist: await session.EmitEventAsync(new InventoryEquipItemEvent(inv.Slot, true, InventoryType.Specialist)); return; case ItemInstanceType.WearableInstance when inv.ItemInstance.GameItem.ItemType == ItemType.Fashion && inv.InventoryType == InventoryType.Costume: await session.EmitEventAsync(new InventoryEquipItemEvent(inv.Slot, true, InventoryType.Costume)); return; default: await session.EmitEventAsync(new InventoryUseItemEvent { Item = inv, Option = split[1].ElementAt(0) == '#' ? (byte)255 : (byte)0, Packet = split }); break; } } private bool CanUseItemInVehicle(IClientSession session, InventoryItem item) { if (!session.PlayerEntity.IsOnVehicle) { return true; } if (item.ItemInstance.GameItem.ItemType is ItemType.Potion or ItemType.Snack) { return true; } if (item.ItemInstance.GameItem.Id is (short)ItemVnums.SPEED_BOOSTER or (short)ItemVnums.SPEED_BOOSTER_LIMITED) { return true; } if (item.ItemInstance.GameItem.ItemType is ItemType.Box && item.ItemInstance.GameItem.ItemSubType == 7) { return true; } return _vehicleConfiguration.GetByVehicleVnum(item.ItemInstance.GameItem.Id) != null; } private void CheckQuests(IClientSession session, GameItemInstance inv) { IEnumerable characterQuests = session.PlayerEntity.GetCurrentQuestsByType(QuestType.USE_ITEM_ON_TARGET); foreach (CharacterQuest quest in characterQuests) { IReadOnlyCollection objectives = quest.Quest.Objectives; foreach (QuestObjectiveDto objective in objectives) { if (inv.ItemVNum != objective.Data0) { continue; } IEntity entity = session.CurrentMapInstance.GetBattleEntity(session.PlayerEntity.LastEntity.Item1, session.PlayerEntity.LastEntity.Item2); if (entity == null) { continue; } CharacterQuestObjectiveDto questObjectiveDto = quest.ObjectiveAmount[objective.ObjectiveIndex]; if (entity.IsMonster()) { var monster = (IMonsterEntity)entity; if (monster.MonsterVNum != objective.Data1) { continue; } if (questObjectiveDto.CurrentAmount == 0) { questObjectiveDto.CurrentAmount++; session.EmitEventAsync(new QuestObjectiveUpdatedEvent { CharacterQuest = quest }); session.RemoveItemFromInventory(inv.ItemVNum); } } else if (entity.IsNpc()) { var npc = (INpcEntity)entity; if (npc.NpcVNum != objective.Data1) { continue; } if (questObjectiveDto.CurrentAmount == 0) { questObjectiveDto.CurrentAmount++; session.EmitEventAsync(new QuestObjectiveUpdatedEvent { CharacterQuest = quest }); session.RemoveItemFromInventory(inv.ItemVNum); } } if (session.PlayerEntity.IsQuestCompleted(quest)) { session.EmitEvent(new QuestCompletedEvent(quest)); } } } } }