210 lines
No EOL
7.7 KiB
C#
210 lines
No EOL
7.7 KiB
C#
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<DropDTO>(_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
|
|
});
|
|
}
|
|
}
|
|
} |