server-master/srcs/_plugins/WingsEmu.Plugins.BasicImplementation/Event/Monster/MonsterDeathEventHandler.cs
2026-02-10 18:21:30 +01:00

230 lines
No EOL
8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using PhoenixLib.Events;
using WingsAPI.Scripting.Object.Timespace;
using WingsEmu.DTOs.BCards;
using WingsEmu.Game._enum;
using WingsEmu.Game.Act4;
using WingsEmu.Game.Battle;
using WingsEmu.Game.Battle.Managers;
using WingsEmu.Game.Buffs;
using WingsEmu.Game.Characters;
using WingsEmu.Game.Characters.Events;
using WingsEmu.Game.Entities;
using WingsEmu.Game.Extensions;
using WingsEmu.Game.Maps;
using WingsEmu.Game.Mates;
using WingsEmu.Game.Monster.Event;
using WingsEmu.Game.Networking;
using WingsEmu.Game.Quests.Event;
using WingsEmu.Game.TimeSpaces;
using WingsEmu.Game.TimeSpaces.Events;
using WingsEmu.Game.Triggers;
using WingsEmu.Packets.Enums;
namespace WingsEmu.Plugins.BasicImplementations.Event.Monster;
public class MonsterDeathEventHandler : IAsyncEventProcessor<MonsterDeathEvent>
{
private readonly IAct4FlagManager _act4FlagManager;
private readonly IAsyncEventPipeline _asyncEventPipeline;
private readonly IBCardEffectHandlerContainer _bCardEffectHandlerContainer;
private readonly IPhantomPositionManager _phantomPositionManager;
private readonly ITimeSpaceManager _timeSpaceManager;
public MonsterDeathEventHandler(IBCardEffectHandlerContainer bCardEffectHandlerContainer, IAsyncEventPipeline asyncEventPipeline,
ITimeSpaceManager timeSpaceManager, IAct4FlagManager act4FlagManager, IPhantomPositionManager phantomPositionManager)
{
_bCardEffectHandlerContainer = bCardEffectHandlerContainer;
_asyncEventPipeline = asyncEventPipeline;
_timeSpaceManager = timeSpaceManager;
_act4FlagManager = act4FlagManager;
_phantomPositionManager = phantomPositionManager;
}
public async Task HandleAsync(MonsterDeathEvent e, CancellationToken cancellation)
{
IMonsterEntity monsterEntity = e.MonsterEntity;
DateTime dateTimeNow = DateTime.UtcNow;
monsterEntity.IsStillAlive = false;
monsterEntity.Hp = 0;
monsterEntity.Death = dateTimeNow;
monsterEntity.Killer = e.Killer;
if (monsterEntity.SummonerType is not VisualType.Player)
{
monsterEntity.MapInstance.IncreaseMonsterDeathsOnMap();
}
monsterEntity.MapInstance.DeactivateMode(monsterEntity);
if (monsterEntity.DeathEffect != 0)
{
monsterEntity.BroadcastEffectInRange(monsterEntity.DeathEffect);
}
if (monsterEntity.IsPhantom())
{
_phantomPositionManager.AddPosition(monsterEntity.UniqueId, monsterEntity.Position);
}
await monsterEntity.TriggerEvents(BattleTriggers.OnDeath);
if (!e.IsByCommand)
{
IEnumerable<BCardDTO> triggerBCard = monsterEntity.BCards.Where(b => b.TriggerType == BCardNpcMonsterTriggerType.ON_DEATH);
foreach (BCardDTO bCard in triggerBCard)
{
_bCardEffectHandlerContainer.Execute(monsterEntity, monsterEntity, bCard, triggerType: BCardNpcMonsterTriggerType.ON_DEATH);
}
}
if (monsterEntity.MapInstance.MapInstanceType == MapInstanceType.TimeSpaceInstance)
{
await CheckTargetMonstersInRoom(monsterEntity);
await _asyncEventPipeline.ProcessEventAsync(new TimeSpaceCheckMonsterEvent(monsterEntity), cancellation);
}
monsterEntity.Mp = 0;
switch (e.Killer)
{
case IPlayerEntity player:
await player.Session.EmitEventAsync(new KillBonusEvent
{
MonsterEntity = monsterEntity
});
if (player.IsInGroup())
{
foreach (IPlayerEntity member in player.GetGroup().Members.ToArray())
{
await member.Session.EmitEventAsync(new QuestMonsterDeathEvent { MonsterEntity = monsterEntity });
}
}
else
{
await player.Session.EmitEventAsync(new QuestMonsterDeathEvent { MonsterEntity = monsterEntity });
}
player.HitsByMonsters.TryRemove(monsterEntity.Id, out _);
break;
case IMateEntity mate:
await mate.Owner.Session.EmitEventAsync(new KillBonusEvent
{
MonsterEntity = monsterEntity
});
if (mate.Owner.IsInGroup())
{
foreach (IPlayerEntity member in mate.Owner.GetGroup().Members.ToArray())
{
await member.Session.EmitEventAsync(new QuestMonsterDeathEvent { MonsterEntity = monsterEntity });
}
}
else
{
await mate.Owner.Session.EmitEventAsync(new QuestMonsterDeathEvent { MonsterEntity = monsterEntity });
}
break;
case IMonsterEntity mapMonster:
if (!mapMonster.SummonerId.HasValue)
{
break;
}
if (mapMonster.IsMateTrainer)
{
break;
}
if (mapMonster.SummonerType != VisualType.Player)
{
break;
}
IClientSession summoner = mapMonster.MapInstance.GetCharacterById(mapMonster.SummonerId.Value)?.Session;
if (summoner == null)
{
break;
}
if (monsterEntity.MonsterVNum == (short)MonsterVnum.BOMB)
{
summoner.PlayerEntity.SkillComponent.BombEntityId = null;
}
await summoner.EmitEventAsync(new KillBonusEvent
{
MonsterEntity = monsterEntity
});
if (summoner.PlayerEntity.IsInGroup())
{
foreach (IPlayerEntity member in summoner.PlayerEntity.GetGroup().Members.ToArray())
{
await member.Session.EmitEventAsync(new QuestMonsterDeathEvent { MonsterEntity = monsterEntity });
}
}
else
{
await summoner.EmitEventAsync(new QuestMonsterDeathEvent { MonsterEntity = monsterEntity });
}
break;
}
switch ((MonsterVnum)monsterEntity.MonsterVNum)
{
case MonsterVnum.DEMON_CAMP:
_act4FlagManager.RemoveDemonFlag();
break;
case MonsterVnum.ANGEL_CAMP:
_act4FlagManager.RemoveAngelFlag();
break;
}
await monsterEntity.RemoveAllBuffsAsync(true);
monsterEntity.MapInstance.ForgetAll(monsterEntity, dateTimeNow);
}
private async Task CheckTargetMonstersInRoom(IMonsterEntity monsterEntity)
{
if (!monsterEntity.IsTarget)
{
return;
}
Guid guid = monsterEntity.MapInstance.Id;
TimeSpaceParty timeSpace = _timeSpaceManager.GetTimeSpaceByMapInstanceId(guid);
if (timeSpace == null)
{
return;
}
if (timeSpace.Instance.TimeSpaceObjective.KillMonsterVnum.HasValue && monsterEntity.MonsterVNum == timeSpace.Instance.TimeSpaceObjective.KillMonsterVnum.Value)
{
timeSpace.Instance.TimeSpaceObjective.KilledMonsterAmount++;
await _asyncEventPipeline.ProcessEventAsync(new TimeSpaceRefreshObjectiveProgressEvent
{
MapInstanceId = guid
});
}
if (monsterEntity.MapInstance.GetAliveMonsters(x => x.IsTarget).Any())
{
return;
}
TimeSpaceSubInstance timeSpaceSubInstance = _timeSpaceManager.GetSubInstance(guid);
if (timeSpaceSubInstance == null)
{
return;
}
await timeSpaceSubInstance.TriggerEvents(TimespaceConstEventKeys.OnAllTargetMobsDead);
}
}