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

314 lines
No EOL
11 KiB
C#

using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using PhoenixLib.Events;
using WingsAPI.Game.Extensions.Groups;
using WingsEmu.Game._enum;
using WingsEmu.Game._i18n;
using WingsEmu.Game._ItemUsage.Configuration;
using WingsEmu.Game.Battle;
using WingsEmu.Game.Buffs;
using WingsEmu.Game.Buffs.Events;
using WingsEmu.Game.Characters;
using WingsEmu.Game.Entities;
using WingsEmu.Game.Extensions;
using WingsEmu.Game.Extensions.Mates;
using WingsEmu.Game.Helpers.Damages;
using WingsEmu.Game.Mates;
using WingsEmu.Game.Networking;
using WingsEmu.Game.Skills;
using WingsEmu.Packets.Enums;
using WingsEmu.Packets.Enums.Chat;
using WingsEmu.Plugins.BasicImplementations.Vehicles;
namespace WingsEmu.Plugins.BasicImplementations.Event.Buffs;
public class BuffRemoveEventHandler : IAsyncEventProcessor<BuffRemoveEvent>
{
private readonly IBuffFactory _buffFactory;
private readonly IGameLanguageService _gameLanguage;
private readonly ISacrificeManager _sacrificeManager;
private readonly ISpPartnerConfiguration _spPartner;
private readonly ITeleportManager _teleportManager;
private readonly IVehicleConfigurationProvider _vehicle;
public BuffRemoveEventHandler(ISpPartnerConfiguration spPartner, IGameLanguageService gameLanguage, IBuffFactory buffFactory, ITeleportManager teleportManager,
ISacrificeManager sacrificeManager, IVehicleConfigurationProvider vehicle)
{
_spPartner = spPartner;
_gameLanguage = gameLanguage;
_buffFactory = buffFactory;
_teleportManager = teleportManager;
_sacrificeManager = sacrificeManager;
_vehicle = vehicle;
}
public async Task HandleAsync(BuffRemoveEvent e, CancellationToken cancellation)
{
if (e.Buffs == null)
{
return;
}
IBattleEntity battleEntity = e.Entity;
foreach (Buff buff in e.Buffs)
{
if (buff == null)
{
continue;
}
if (!battleEntity.BuffComponent.HasBuff(buff.BuffId))
{
continue;
}
if (buff.IsSavingOnDisconnect() && buff.RemainingTimeInMilliseconds() > 0)
{
continue;
}
switch (buff.CardId)
{
case (short)BuffVnums.SPIRIT_OF_SACRIFICE:
{
IBattleEntity target = _sacrificeManager.GetTarget(battleEntity);
if (target != null)
{
_sacrificeManager.RemoveSacrifice(battleEntity, target);
}
break;
}
case (short)BuffVnums.NOBLE_GESTURE:
{
IBattleEntity caster = _sacrificeManager.GetCaster(battleEntity);
if (caster != null)
{
_sacrificeManager.RemoveSacrifice(caster, battleEntity);
}
break;
}
}
battleEntity.BuffComponent.RemoveBuff(buff.BuffId);
battleEntity.BCardComponent.RemoveBuffBCards(buff);
battleEntity.ShadowAppears(true, buff);
ProcessEndBuffDamage(battleEntity, buff);
if (buff.IsConstEffect)
{
battleEntity.BroadcastConstBuffEffect(buff, 0);
}
if ((buff.IsPartnerBuff() || buff.IsBigBuff() && !buff.IsPartnerBuff() || buff.IsNoDuration() || buff.IsRefreshAtExpiration()) && !e.RemovePermanentBuff)
{
Buff newBuff = _buffFactory.CreateBuff(buff.CardId, buff.Caster, buff.Duration, buff.BuffFlags);
await battleEntity.AddBuffAsync(newBuff);
continue;
}
if (battleEntity is not IPlayerEntity character)
{
bool buffRunAway = buff.BCards.Any(x => x.Type == (short)BCardType.SpecialActions && x.SubType == (byte)AdditionalTypes.SpecialActions.RunAway);
switch (battleEntity)
{
case INpcEntity npcEntity:
if (buffRunAway)
{
npcEntity.IsRunningAway = false;
}
break;
case IMonsterEntity monsterEntity:
monsterEntity.RefreshStats();
if (buffRunAway)
{
monsterEntity.IsRunningAway = false;
}
break;
case IMateEntity mateEntity:
mateEntity.RefreshStatistics();
mateEntity.Owner?.Session.SendPetInfo(mateEntity, _gameLanguage);
mateEntity.Owner?.Session.SendCondMate(mateEntity);
break;
}
continue;
}
IClientSession session = character.Session;
bool refreshHpMp = true;
switch (buff.CardId)
{
case (short)BuffVnums.PRAYER_OF_DEFENCE:
case (short)BuffVnums.ENERGY_ENHANCEMENT:
case (short)BuffVnums.BEAR_SPIRIT:
if (e.ShowMessage)
{
break;
}
refreshHpMp = false;
break;
case (short)BuffVnums.FAIRY_BOOSTER:
session.RefreshFairy();
break;
case (short)BuffVnums.SPEED_BOOSTER when session.PlayerEntity.IsOnVehicle:
session.PlayerEntity.VehicleSpeed -= (byte)BuffVehicle(session.PlayerEntity);
break;
case (short)BuffVnums.MAGIC_SPELL:
session.SendMsCPacket(0);
session.PlayerEntity.RemoveAngelElement();
character.CleanComboState();
for (int i = (int)BuffVnums.FLAME; i < (int)BuffVnums.DARKNESS; i++)
{
if (!session.PlayerEntity.BuffComponent.HasBuff(i))
{
continue;
}
session.PlayerEntity.RemoveBuffAsync(false, session.PlayerEntity.BuffComponent.GetBuff(i)).ConfigureAwait(false).GetAwaiter().GetResult();
}
break;
case (short)BuffVnums.AMBUSH_PREPARATION_1:
case (short)BuffVnums.AMBUSH_PREPARATION_2:
if (buff.RemainingTimeInMilliseconds() <= 0)
{
character.ChangeScoutState(ScoutStateType.None);
}
break;
case (short)BuffVnums.AMBUSH_RAID:
character.ChangeScoutState(ScoutStateType.None);
break;
case (short)BuffVnums.AMBUSH:
character.TriggerAmbush = false;
if (buff.RemainingTimeInMilliseconds() <= 0)
{
character.ChangeScoutState(ScoutStateType.None);
}
break;
}
if (!buff.IsBigBuff())
{
session.SendBfPacket(buff);
}
else
{
session.SendEmptyStaticBuffUiPacket(buff);
}
if (e.ShowMessage)
{
string message = _gameLanguage.GetLanguage(GameDialogKey.BUFF_CHATMESSAGE_EFFECT_TERMINATED, session.UserLanguage);
string cardName = _gameLanguage.GetLanguage(GameDataType.Card, buff.Name, session.UserLanguage);
session.SendChatMessage(string.Format(message, cardName), ChatMessageColorType.Buff);
}
session.RefreshStatChar(refreshHpMp);
session.RefreshStat();
session.SendCondPacket();
if (buff.BCards.Any(x => x.Type == (byte)BCardType.FearSkill && x.SubType == (byte)AdditionalTypes.FearSkill.AttackRangedIncreased))
{
session.SendIncreaseRange();
}
Position position = _teleportManager.GetPosition(session.PlayerEntity.Id);
if (position.X != 0 && position.Y != 0 && buff.CardId == (short)BuffVnums.MEMORIAL)
{
short savedX = _teleportManager.GetPosition(character.Id).X;
short savedY = _teleportManager.GetPosition(character.Id).Y;
_teleportManager.RemovePosition(session.PlayerEntity.Id);
character.BroadcastEffectGround(EffectType.ArchmageTeleportSet, savedX, savedY, true);
}
await character.CheckAct52Buff(_buffFactory);
if (buff.BCards.Any(x => x.Type == (short)BCardType.FearSkill && x.SubType == (byte)AdditionalTypes.FearSkill.MoveAgainstWill))
{
session.SendOppositeMove(false);
}
if (!buff.BCards.Any(s =>
s.Type == (short)BCardType.SpecialActions && s.SubType == (byte)AdditionalTypes.SpecialActions.Hide)
&& buff.CardId != (short)BuffVnums.AMBUSH && buff.CardId != (short)BuffVnums.AMBUSH_RAID)
{
continue;
}
if (buff.CardId == (short)BuffVnums.AMBUSH && character.TriggerAmbush)
{
continue;
}
if (!session.PlayerEntity.IsOnVehicle)
{
session.BroadcastInTeamMembers(_gameLanguage, _spPartner);
session.RefreshParty(_spPartner);
}
session.UpdateVisibility();
}
}
private void ProcessEndBuffDamage(IBattleEntity battleEntity, Buff buff)
{
if (!battleEntity.EndBuffDamages.Any())
{
return;
}
battleEntity.RemoveEndBuffDamage((short)buff.CardId);
}
private int BuffVehicle(IPlayerEntity c)
{
VehicleConfiguration vehicle = _vehicle.GetByMorph(c.Morph, c.Gender);
if (vehicle?.VehicleBoostType == null)
{
return 0;
}
int speedToRemove = 0;
foreach (VehicleBoost boost in vehicle.VehicleBoostType)
{
switch (boost.BoostType)
{
case BoostType.INCREASE_SPEED:
if (!boost.FirstValue.HasValue)
{
break;
}
speedToRemove = boost.FirstValue.Value;
break;
case BoostType.CREATE_BUFF_ON_END:
if (!boost.FirstValue.HasValue)
{
break;
}
c.AddBuffAsync(_buffFactory.CreateBuff(boost.FirstValue.Value, c)).ConfigureAwait(false).GetAwaiter().GetResult();
break;
}
}
return speedToRemove;
}
}