230 lines
No EOL
8 KiB
C#
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);
|
|
}
|
|
} |