209 lines
No EOL
7.6 KiB
C#
209 lines
No EOL
7.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using PhoenixLib.Events;
|
|
using WingsEmu.Core.Extensions;
|
|
using WingsEmu.Game;
|
|
using WingsEmu.Game._enum;
|
|
using WingsEmu.Game.Battle.Managers;
|
|
using WingsEmu.Game.Characters;
|
|
using WingsEmu.Game.Entities;
|
|
using WingsEmu.Game.Entities.Event;
|
|
using WingsEmu.Game.Helpers.Damages;
|
|
using WingsEmu.Game.Managers.StaticData;
|
|
using WingsEmu.Game.Maps;
|
|
using WingsEmu.Game.Monster.Event;
|
|
using WingsEmu.Game.Npcs.Event;
|
|
using WingsEmu.Game.Triggers;
|
|
|
|
namespace WingsEmu.Plugins.BasicImplementations.Event.Monster;
|
|
|
|
public class MonsterSummonEventHandler : IAsyncEventProcessor<MonsterSummonEvent>
|
|
{
|
|
private readonly IMonsterEntityFactory _monsterEntityFactory;
|
|
private readonly INpcMonsterManager _npcMonsterManager;
|
|
private readonly IPhantomPositionManager _phantomPositionManager;
|
|
private readonly IRandomGenerator _randomGenerator;
|
|
|
|
public MonsterSummonEventHandler(IRandomGenerator randomGenerator, INpcMonsterManager npcMonsterManager, IMonsterEntityFactory monsterEntityFactory, IPhantomPositionManager phantomPositionManager)
|
|
{
|
|
_randomGenerator = randomGenerator;
|
|
_npcMonsterManager = npcMonsterManager;
|
|
_monsterEntityFactory = monsterEntityFactory;
|
|
_phantomPositionManager = phantomPositionManager;
|
|
}
|
|
|
|
public async Task HandleAsync(MonsterSummonEvent e, CancellationToken cancellation)
|
|
{
|
|
List<ToSummon> toSummon = new();
|
|
short? scaledAmount = e.ScaledWithPlayerAmount;
|
|
|
|
if (scaledAmount.HasValue)
|
|
{
|
|
for (int i = 0; i < scaledAmount.Value; i++)
|
|
{
|
|
toSummon.AddRange(e.Monsters);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
toSummon = e.Monsters.ToList();
|
|
}
|
|
|
|
foreach (ToSummon summon in toSummon)
|
|
{
|
|
IMonsterData npcMonster = _npcMonsterManager.GetNpc(summon.VNum);
|
|
if (npcMonster == null || _randomGenerator.RandomNumber() > summon.SummonChance)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (e.Map.IsSummonLimitReached(e.Summoner?.Id, summon.SummonType))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
IMonsterEntity mapMonster = summon.MonsterEntity ?? _monsterEntityFactory.CreateMonster(npcMonster, e.Map, new MonsterEntityBuilder
|
|
{
|
|
IsMateTrainer = summon.IsMateTrainer,
|
|
IsBonus = summon.IsBonusOrProtected,
|
|
IsBoss = summon.IsBossOrMate,
|
|
IsTarget = summon.IsTarget,
|
|
IsHostile = summon.IsHostile,
|
|
IsWalkingAround = summon.IsMoving,
|
|
IsVesselMonster = summon.IsVesselMonster,
|
|
SummonType = summon.SummonType,
|
|
SummonerId = e.Summoner?.Id,
|
|
SummonerType = e.Summoner?.Type,
|
|
FactionType = summon.FactionType ?? e.Summoner?.Faction,
|
|
HpMultiplier = summon.HpMultiplier,
|
|
MpMultiplier = summon.MpMultiplier,
|
|
SetHitChance = summon.SetHitChance != 0 && !summon.IsBossOrMate ? summon.SetHitChance : npcMonster.BasicHitChance,
|
|
Direction = summon.Direction,
|
|
GoToBossPosition = summon.GoToBossPosition,
|
|
IsInstantBattle = summon.IsInstantBattle,
|
|
Level = summon.Level
|
|
});
|
|
|
|
mapMonster.Target = summon.Target;
|
|
mapMonster.Waypoints = summon.Waypoints;
|
|
|
|
if (summon.TriggerEvents != null)
|
|
{
|
|
foreach ((string key, IAsyncEvent asyncEvent, bool removeOnUse) in summon.TriggerEvents)
|
|
{
|
|
mapMonster.AddEvent(key, asyncEvent, removeOnUse);
|
|
}
|
|
}
|
|
|
|
if (e.Summoner != null)
|
|
{
|
|
if (e.GetSummonerLevel)
|
|
{
|
|
mapMonster.Level = e.Summoner.Level;
|
|
}
|
|
|
|
if (e.Summoner is IPlayerEntity player && summon.VNum == (short)MonsterVnum.BOMB)
|
|
{
|
|
player.SkillComponent.BombEntityId = mapMonster.Id;
|
|
}
|
|
}
|
|
|
|
Position? phantomPosition = e.NpcId.HasValue ? _phantomPositionManager.GetPosition(e.NpcId.Value) : null;
|
|
Position spawnCell = phantomPosition ?? summon.SpawnCell ?? e.Map.GetRandomPosition();
|
|
|
|
if (summon.AtAroundMobId.HasValue && summon.AtAroundMobRange.HasValue)
|
|
{
|
|
IMonsterEntity originalEntity = e.Map.GetMonsterByUniqueId(summon.AtAroundMobId.Value);
|
|
byte range = summon.AtAroundMobRange.Value;
|
|
if (originalEntity is not null)
|
|
{
|
|
spawnCell = new Position((short)(originalEntity.PositionX + _randomGenerator.RandomNumber(-range, range)),
|
|
(short)(originalEntity.PositionY + _randomGenerator.RandomNumber(-range, range)));
|
|
|
|
if (originalEntity.MapInstance.IsBlockedZone(spawnCell.X, spawnCell.Y))
|
|
{
|
|
spawnCell = originalEntity.Position;
|
|
}
|
|
}
|
|
}
|
|
|
|
await mapMonster.EmitEventAsync(new MapJoinMonsterEntityEvent(mapMonster, spawnCell.X, spawnCell.Y, e.ShowEffect));
|
|
|
|
CheckBeriosPhantom(mapMonster);
|
|
|
|
DateTime now = DateTime.UtcNow;
|
|
mapMonster.AttentionTime = now + TimeSpan.FromSeconds(10);
|
|
if (!summon.RemoveTick)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
mapMonster.NextTick = DateTime.UtcNow.AddSeconds(-1000);
|
|
mapMonster.NextAttackReady = DateTime.UtcNow.AddSeconds(-1000);
|
|
}
|
|
}
|
|
|
|
private void CheckBeriosPhantom(IMonsterEntity mapMonster)
|
|
{
|
|
switch ((MonsterVnum)mapMonster.MonsterVNum)
|
|
{
|
|
case MonsterVnum.EMERALD_PHANTOM:
|
|
|
|
mapMonster.AddEvent(BattleTriggers.OnDeath, new NpcSummonEvent
|
|
{
|
|
Map = mapMonster.MapInstance,
|
|
MonsterId = mapMonster.UniqueId,
|
|
Npcs = Lists.Create(new ToSummon
|
|
{
|
|
VNum = (short)MonsterVnum.EMERALD_SHADOW_PHANTOM,
|
|
SpawnCell = mapMonster.Position,
|
|
IsMoving = true,
|
|
IsHostile = true
|
|
})
|
|
}, true);
|
|
|
|
break;
|
|
|
|
case MonsterVnum.SAPPHIRE_PHANTOM:
|
|
|
|
mapMonster.AddEvent(BattleTriggers.OnDeath, new NpcSummonEvent
|
|
{
|
|
Map = mapMonster.MapInstance,
|
|
MonsterId = mapMonster.UniqueId,
|
|
Npcs = Lists.Create(new ToSummon
|
|
{
|
|
VNum = (short)MonsterVnum.SAPPHIRE_SHADOW_PHANTOM,
|
|
SpawnCell = mapMonster.Position,
|
|
IsMoving = true,
|
|
IsHostile = true
|
|
})
|
|
}, true);
|
|
|
|
break;
|
|
|
|
case MonsterVnum.RUBY_PHANTOM:
|
|
|
|
mapMonster.AddEvent(BattleTriggers.OnDeath, new NpcSummonEvent
|
|
{
|
|
Map = mapMonster.MapInstance,
|
|
MonsterId = mapMonster.UniqueId,
|
|
Npcs = Lists.Create(new ToSummon
|
|
{
|
|
VNum = (short)MonsterVnum.RUBY_SHADOW_PHANTOM,
|
|
SpawnCell = mapMonster.Position,
|
|
IsMoving = true,
|
|
IsHostile = true
|
|
})
|
|
}, true);
|
|
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
} |