server-master/srcs/_plugins/Plugin.Raids/Handlers/RaidInstanceFinishEventHandler.cs
2026-02-10 18:21:30 +01:00

188 lines
No EOL
6.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using PhoenixLib.Events;
using WingsAPI.Game.Extensions.Quests;
using WingsAPI.Packets.Enums;
using WingsEmu.DTOs.Quests;
using WingsEmu.Game._i18n;
using WingsEmu.Game.Battle;
using WingsEmu.Game.Entities;
using WingsEmu.Game.Extensions;
using WingsEmu.Game.Managers;
using WingsEmu.Game.Networking;
using WingsEmu.Game.Quests;
using WingsEmu.Game.Quests.Event;
using WingsEmu.Game.Raids;
using WingsEmu.Game.Raids.Configuration;
using WingsEmu.Game.Raids.Enum;
using WingsEmu.Game.Raids.Events;
using WingsEmu.Game.Revival;
using WingsEmu.Packets.Enums;
using WingsEmu.Packets.Enums.Chat;
namespace Plugin.Raids;
public class RaidInstanceFinishEventHandler : IAsyncEventProcessor<RaidInstanceFinishEvent>
{
private readonly IAsyncEventPipeline _eventPipeline;
private readonly IGameLanguageService _languageService;
private readonly IQuestManager _questManager;
private readonly RaidConfiguration _raidConfiguration;
private readonly IRaidManager _raidManager;
private readonly ISessionManager _sessionManager;
public RaidInstanceFinishEventHandler(RaidConfiguration raidConfiguration, IRaidManager raidManager, IAsyncEventPipeline eventPipeline, ISessionManager sessionManager,
IGameLanguageService languageService, IQuestManager questManager)
{
_raidConfiguration = raidConfiguration;
_raidManager = raidManager;
_eventPipeline = eventPipeline;
_sessionManager = sessionManager;
_languageService = languageService;
_questManager = questManager;
}
public async Task HandleAsync(RaidInstanceFinishEvent e, CancellationToken cancellation)
{
if (e.RaidParty.Finished)
{
return;
}
_raidManager.UnregisterRaidFromRaidPublishList(e.RaidParty);
RaidWindowType windowType = RaidWindowType.MISSION_FAIL;
DateTime currentTime = DateTime.UtcNow;
if (e.RaidFinishType != RaidFinishType.Disbanded)
{
foreach (RaidSubInstance subInstance in e.RaidParty.Instance.RaidSubInstances.Values)
{
foreach (IMonsterEntity monsterEntity in subInstance.MapInstance.GetAliveMonsters())
{
if (monsterEntity.IsBoss)
{
continue;
}
subInstance.MapInstance.DespawnMonster(monsterEntity);
subInstance.MapInstance.RemoveMonster(monsterEntity);
}
}
}
switch (e.RaidFinishType)
{
case RaidFinishType.Disbanded:
await _eventPipeline.ProcessEventAsync(new RaidInstanceDestroyEvent(e.RaidParty), cancellation);
return;
case RaidFinishType.MissionClear:
windowType = RaidWindowType.MISSION_CLEAR;
e.RaidParty.Instance.SetFinishSlowMoDate(currentTime + _raidConfiguration.RaidSlowMoDelay);
break;
case RaidFinishType.TimeIsUp:
windowType = RaidWindowType.TIMES_UP;
break;
case RaidFinishType.NoLivesLeft:
windowType = RaidWindowType.NO_LIVES_LEFT;
break;
}
IClientSession[] sessions = e.RaidParty.Members.ToArray();
foreach (IClientSession session in sessions)
{
if (!session.PlayerEntity.IsAlive())
{
await session.EmitEventAsync(new RevivalReviveEvent());
}
if (e.RaidFinishType == RaidFinishType.MissionClear)
{
session.TrySendRaidBossDeadPackets();
await session.EmitEventAsync(new RaidWonEvent());
await CheckRaidQuest(session, e.RaidParty.Type);
}
session.SendRaidUiPacket(e.RaidParty.Type, windowType);
session.SendRemoveClockPacket();
session.SendRaidPacket(RaidPacketType.LIST_MEMBERS);
}
if (e.RaidFinishType == RaidFinishType.MissionClear)
{
IMonsterEntity raidBoss = FindBossMap(e.RaidParty);
BroadcastRaidFinishMessage(e.RaidParty);
await e.RaidParty.Leader.EmitEventAsync(new RaidTargetKilledEvent { DamagerCharactersIds = raidBoss.PlayersDamage.Keys.ToArray() });
await _eventPipeline.ProcessEventAsync(new RaidGiveRewardsEvent(e.RaidParty, raidBoss, e.RaidParty.Instance.RaidReward), cancellation);
}
else if (e.RaidFinishType != RaidFinishType.Disbanded)
{
await e.RaidParty.Leader.EmitEventAsync(new RaidLostEvent());
}
foreach (IClientSession session in sessions)
{
session.SendRaidmbf();
session.RefreshRaidMemberList();
}
e.RaidParty.FinishRaid(currentTime + _raidConfiguration.RaidMapDestroyDelay);
}
private async Task CheckRaidQuest(IClientSession session, RaidType raidType)
{
IEnumerable<CharacterQuest> characterQuests = session.PlayerEntity.GetCurrentQuestsByTypes(new[] { QuestType.WIN_RAID_AND_TALK_TO_NPC });
foreach (CharacterQuest quest in characterQuests)
{
foreach (QuestObjectiveDto objective in quest.Quest.Objectives)
{
if (raidType != (RaidType)objective.Data0)
{
continue;
}
CharacterQuestObjectiveDto questObjectiveDto = quest.ObjectiveAmount[objective.ObjectiveIndex];
int amountLeft = questObjectiveDto.RequiredAmount - questObjectiveDto.CurrentAmount;
if (amountLeft == 0)
{
break;
}
questObjectiveDto.CurrentAmount++;
session.RefreshQuestProgress(_questManager, quest.QuestId);
await session.EmitEventAsync(new QuestObjectiveUpdatedEvent
{
CharacterQuest = quest
});
}
}
}
private void BroadcastRaidFinishMessage(RaidParty raidParty)
{
_sessionManager.Broadcast(x => x.GenerateMsgPacket(string.Format(
_languageService.GetLanguage(GameDialogKey.RAID_SHOUTMESSAGE_COMPLETED, x.UserLanguage), raidParty.Leader.PlayerEntity.Name, x.GenerateRaidName(_languageService, raidParty.Type)),
MsgMessageType.Middle));
}
private IMonsterEntity FindBossMap(RaidParty raidParty)
{
IMonsterEntity raidBoss = null;
foreach (RaidSubInstance subInstance in raidParty.Instance.RaidSubInstances.Values)
{
foreach (IMonsterEntity monsterEntity in subInstance.DeadBossMonsters)
{
raidBoss = monsterEntity;
break;
}
}
return raidBoss;
}
}