using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using WingsAPI.Game.Extensions.ItemExtension.Item; using WingsAPI.Game.Extensions.MinilandExtensions; using WingsAPI.Game.Extensions.PacketGeneration; using WingsAPI.Game.Extensions.Quests; using WingsEmu.Core.Extensions; using WingsEmu.DTOs.ServerDatas; using WingsEmu.Game; using WingsEmu.Game._enum; using WingsEmu.Game._i18n; using WingsEmu.Game.Battle; using WingsEmu.Game.Characters; using WingsEmu.Game.Entities; using WingsEmu.Game.Extensions; using WingsEmu.Game.Managers; using WingsEmu.Game.Managers.ServerData; using WingsEmu.Game.Managers.StaticData; using WingsEmu.Game.Monster; using WingsEmu.Game.Networking; using WingsEmu.Game.Quests; using WingsEmu.Game.Quests.Event; using WingsEmu.Game.RainbowBattle.Event; using WingsEmu.Packets.ClientPackets; using WingsEmu.Packets.Enums; using WingsEmu.Packets.Enums.Chat; namespace WingsEmu.Plugins.PacketHandling.Game.Npc; public class RequestNpcPacketHandler : GenericGamePacketHandlerBase { private static readonly QuestType[] DialogQuests = { QuestType.DIALOG, QuestType.DIALOG_2, QuestType.DELIVER_ITEM_TO_NPC, QuestType.GIVE_ITEM_TO_NPC, QuestType.GIVE_ITEM_TO_NPC_2, QuestType.GIVE_NPC_GOLD, QuestType.DIALOG_WHILE_WEARING, QuestType.DIALOG_WHILE_HAVING_ITEM, QuestType.WIN_RAID_AND_TALK_TO_NPC }; private readonly IDelayManager _delayManager; private readonly IGameLanguageService _gameLanguageService; private readonly IItemsManager _itemsManager; private readonly IQuestManager _questManager; private readonly IRecipeManager _recipeManager; private readonly ITeleporterManager _teleporterManager; public RequestNpcPacketHandler(IDelayManager delayManager, ITeleporterManager teleporterManager, IRecipeManager recipeManager, IGameLanguageService gameLanguageService, IItemsManager itemsManager, IQuestManager questManager) { _delayManager = delayManager; _teleporterManager = teleporterManager; _recipeManager = recipeManager; _gameLanguageService = gameLanguageService; _itemsManager = itemsManager; _questManager = questManager; } protected override async Task HandlePacketAsync(IClientSession session, RequestNpcPacket packet) { long owner = packet.TargetNpcId; if (!session.HasCurrentMapInstance) { return; } if (session.PlayerEntity.IsSeal) { return; } if (packet.VisualType == VisualType.Player) { // User Shop session.SendTargetNpcDialog(owner, (int)DialogVnums.SHOP_PLAYER); return; } // Npc Shop , ignore if has drop INpcEntity npcEntity = session.CurrentMapInstance.GetNpcById(packet.TargetNpcId); if (npcEntity == null) { return; } if (npcEntity.MinilandOwner != null) { if (npcEntity.MinilandOwner.Id == session.PlayerEntity.Id) { session.ChangeMap(session.PlayerEntity.Miniland); return; } IPlayerEntity minilandOwner = npcEntity.MinilandOwner; string message = $"{minilandOwner.Name} - {minilandOwner.Session.GetMinilandCleanMessage(_gameLanguageService)}"; session.SendQnaPacket($"mjoin 1 {minilandOwner.Id} 1", message); return; } #region Quest bool showNpcDialog = session.ShowNpcDialog(npcEntity, _questManager); IEnumerable npcTalkQuests = session.PlayerEntity.GetCurrentQuestsByTypes(DialogQuests); foreach (CharacterQuest npcTalkQuest in npcTalkQuests) { await session.EmitEventAsync(new QuestNpcTalkEvent(npcTalkQuest, npcEntity, _questManager.IsNpcBlueAlertQuest(npcTalkQuest.QuestId))); } #endregion if (npcEntity.MonsterRaceType == MonsterRaceType.Fixed) { switch (npcEntity.MonsterRaceSubType) { case (byte)MonsterSubRace.Fixed.CannonBall: await session.EmitEventAsync(new RainbowBattleCaptureFlagEvent { NpcEntity = npcEntity }); return; case (byte)MonsterSubRace.Fixed.Unknown3: // collect if (npcEntity.Drops.All(s => s?.MonsterVNum == null)) { return; } if (npcEntity.VNumRequired != 0 && npcEntity.AmountRequired != 0) { if (!session.PlayerEntity.HasItem(npcEntity.VNumRequired, npcEntity.AmountRequired)) { string itemName = _itemsManager.GetItem(npcEntity.VNumRequired).GetItemName(_gameLanguageService, session.UserLanguage); session.SendMsg(_gameLanguageService.GetLanguageFormat(GameDialogKey.INVENTORY_SHOUTMESSAGE_NOT_ENOUGH_ITEMS, session.UserLanguage, npcEntity.AmountRequired, itemName), MsgMessageType.Middle); return; } } DateTime actionDate = await _delayManager.RegisterAction(session.PlayerEntity, DelayedActionType.Mining, TimeSpan.FromSeconds(npcEntity.CollectionDanceTime)); session.SendDelay(actionDate.GetTotalMillisecondUntilNow(), npcEntity.NpcVNum is (short)MonsterVnum.ROBBER_GANG_CHEST ? GuriType.OpeningTreasureChest : GuriType.Mining, $"guri 400 {npcEntity.Id}"); break; case (byte)MonsterSubRace.Fixed.Unknown1: // teleport { if (npcEntity.VNumRequired != 0 && npcEntity.AmountRequired != 0) { if (!session.PlayerEntity.HasItem(npcEntity.VNumRequired, npcEntity.AmountRequired)) { string itemName = _itemsManager.GetItem(npcEntity.VNumRequired).GetItemName(_gameLanguageService, session.UserLanguage); session.SendMsg(_gameLanguageService.GetLanguageFormat(GameDialogKey.INVENTORY_SHOUTMESSAGE_NOT_ENOUGH_ITEMS, session.UserLanguage, npcEntity.AmountRequired, itemName), MsgMessageType.Middle); return; } } TeleporterDTO tp = _teleporterManager.GetTeleportByNpcId(npcEntity.Id)?.FirstOrDefault(t => t?.Type == TeleporterType.TELEPORT_ON_MAP); if (tp == null) { return; } actionDate = await _delayManager.RegisterAction(session.PlayerEntity, DelayedActionType.UseTeleporter); session.SendDelay(actionDate.GetTotalMillisecondUntilNow(), GuriType.ButtonSwitch, $"guri 710 {tp.MapX} {tp.MapY} {npcEntity.Id}"); break; } case (byte)MonsterSubRace.Fixed.MiniLandStructure: IReadOnlyList recipes = _recipeManager.GetRecipesByNpcMonsterVnum(npcEntity.NpcVNum); if (recipes == null) { if (showNpcDialog) { session.SendNpcDialog(npcEntity); } return; } session.SendWopenPacket(WindowType.CRAFTING_ITEMS); session.SendRecipeNpcList(recipes); break; default: if (showNpcDialog) { session.SendNpcDialog(npcEntity); } break; } return; } if (!showNpcDialog) { return; } session.SendNpcDialog(npcEntity); } }