using System; using System.Linq; using System.Threading.Tasks; using PhoenixLib.Events; using PhoenixLib.Logging; using WingsAPI.Data.Drops; using WingsAPI.Game.Extensions.ItemExtension.Inventory; using WingsAPI.Game.Extensions.ItemExtension.Item; using WingsEmu.Game; using WingsEmu.Game._enum; using WingsEmu.Game._Guri; using WingsEmu.Game._Guri.Event; using WingsEmu.Game._i18n; using WingsEmu.Game.Battle; using WingsEmu.Game.Characters; using WingsEmu.Game.Characters.Events; using WingsEmu.Game.Entities; using WingsEmu.Game.Entities.Extensions; using WingsEmu.Game.Extensions; using WingsEmu.Game.Helpers.Damages; using WingsEmu.Game.Items; using WingsEmu.Game.Managers; using WingsEmu.Game.Managers.StaticData; using WingsEmu.Game.Networking; using WingsEmu.Game.Npcs.Event; using WingsEmu.Game.Quests.Event; using WingsEmu.Packets.Enums; using WingsEmu.Packets.Enums.Chat; namespace WingsEmu.Plugins.BasicImplementations.Guri; public class HarverstGuriHandler : IGuriHandler { private readonly IAsyncEventPipeline _asyncEventPipeline; private readonly IDelayManager _delayManager; private readonly IGameItemInstanceFactory _gameItemInstanceFactory; private readonly IGameLanguageService _gameLanguageService; private readonly IItemsManager _itemsManager; private readonly IRandomGenerator _randomGenerator; private readonly IServerManager _serverManager; public HarverstGuriHandler(IServerManager serverManager, IGameLanguageService gameLanguageService, IRandomGenerator randomGenerator, IItemsManager itemsManager, IGameItemInstanceFactory gameItemInstanceFactory, IDelayManager delayManager, IAsyncEventPipeline asyncEventPipeline) { _randomGenerator = randomGenerator; _serverManager = serverManager; _gameLanguageService = gameLanguageService; _itemsManager = itemsManager; _gameItemInstanceFactory = gameItemInstanceFactory; _delayManager = delayManager; _asyncEventPipeline = asyncEventPipeline; } public long GuriEffectId => 400; public async Task ExecuteAsync(IClientSession session, GuriEvent guriPacket) { if (guriPacket == null) { return; } if (guriPacket.Data == 0) { return; } if (!session.HasCurrentMapInstance) { return; } INpcEntity npcEntity = session.CurrentMapInstance.GetNpcById(guriPacket.Data); if (npcEntity == null) { Log.Debug($"Npc not found. GuriEffectId : {GuriEffectId}"); return; } if (!npcEntity.IsAlive()) { await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.ABUSING, "[ITEM_HARVEST] Tried to harvest a dead NPC."); return; } if (!npcEntity.IsInRange(session.PlayerEntity.PositionX, session.PlayerEntity.PositionY, 5)) { await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.ABUSING, "[ITEM_HARVEST] Tried to harvest an NPC that is too far away."); return; } if (!await _delayManager.CanPerformAction(session.PlayerEntity, DelayedActionType.Mining)) { return; } await _delayManager.CompleteAction(session.PlayerEntity, DelayedActionType.Mining); if (npcEntity.CurrentCollection <= 0) { int delayTime = (int)(npcEntity.LastCollection - DateTime.UtcNow).TotalSeconds; session.SendMsg(_gameLanguageService.GetLanguageFormat(GameDialogKey.HARVEST_SHOUTMESSAGE_FAIL_TRY_AGAIN, session.UserLanguage, delayTime), MsgMessageType.Middle); 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; } } double chance = _randomGenerator.RandomNumber(0, 100_000); DropDTO drop; if (npcEntity.Drops.Count <= 1) { drop = npcEntity.Drops.FirstOrDefault(s => s.MonsterVNum == npcEntity.NpcVNum); if (drop != null && chance > drop.DropChance) { session.SendMsg(_gameLanguageService.GetLanguage(GameDialogKey.HARVEST_SHOUTMESSAGE_TRY_FAIL, session.UserLanguage), MsgMessageType.Middle); return; } } else { var randomBag = new RandomBag(_randomGenerator); foreach (DropDTO dropDto in npcEntity.Drops) { randomBag.AddEntry(dropDto, dropDto.DropChance); } drop = randomBag.GetRandom(); } if (drop == null) { session.SendMsg(_gameLanguageService.GetLanguage(GameDialogKey.HARVEST_SHOUTMESSAGE_TRY_FAIL, session.UserLanguage), MsgMessageType.Middle); return; } int vnum = drop.ItemVNum; if (npcEntity.VNumRequired != 0 && npcEntity.AmountRequired != 0) { await session.RemoveItemFromInventory(npcEntity.VNumRequired, npcEntity.AmountRequired); } npcEntity.CurrentCollection--; GameItemInstance newItem = _gameItemInstanceFactory.CreateItem(vnum, drop.Amount); session.SendMsg( _gameLanguageService.GetLanguageFormat(GameDialogKey.INVENTORY_CHATMESSAGE_X_ITEM_ACQUIRED, session.UserLanguage, newItem.Amount.ToString(), _gameLanguageService.GetItemName(newItem.GameItem, session)), MsgMessageType.Middle); switch ((MonsterVnum)npcEntity.NpcVNum) { case MonsterVnum.POISON_PLANT_OF_DAMNATION: case MonsterVnum.ICE_FLOWER: npcEntity.MapInstance.Broadcast(npcEntity.GenerateOut()); await _asyncEventPipeline.ProcessEventAsync(new MapNpcGenerateDeathEvent(npcEntity, null)); Position newPosition = npcEntity.MapInstance.GetRandomPosition(); npcEntity.FirstX = newPosition.X; npcEntity.FirstY = newPosition.Y; break; case MonsterVnum.ROBBER_GANG_CHEST: npcEntity.MapInstance.Broadcast(npcEntity.GenerateOut()); await _asyncEventPipeline.ProcessEventAsync(new MapNpcGenerateDeathEvent(npcEntity, null)); break; } // Quest logic bool isHarvestObjective = session.PlayerEntity.GetCurrentQuestsByType(QuestType.COLLECT) .Any(s => s.Quest.Objectives.Any(o => newItem.ItemVNum == o.Data1 && npcEntity.NpcVNum == o.Data0 && s.ObjectiveAmount[o.ObjectiveIndex].CurrentAmount <= s.ObjectiveAmount[o.ObjectiveIndex].RequiredAmount)); if (!isHarvestObjective) { await session.AddNewItemToInventory(newItem, true, sendGiftIsFull: true); return; } if (session.PlayerEntity.IsInGroup()) { foreach (IPlayerEntity member in session.PlayerEntity.GetGroup().Members) { await member.Session.EmitEventAsync(new QuestHarvestEvent { ItemVnum = newItem.ItemVNum, NpcVnum = npcEntity.NpcVNum }); } } else { await session.EmitEventAsync(new QuestHarvestEvent { ItemVnum = newItem.ItemVNum, NpcVnum = npcEntity.NpcVNum }); } } }