195 lines
No EOL
5.8 KiB
C#
195 lines
No EOL
5.8 KiB
C#
// WingsEmu
|
|
//
|
|
// Developed by NosWings Team
|
|
|
|
using System;
|
|
using WingsEmu.DTOs.Maps;
|
|
using WingsEmu.Game;
|
|
using WingsEmu.Game.Battle;
|
|
using WingsEmu.Game.Buffs;
|
|
using WingsEmu.Game.Characters;
|
|
using WingsEmu.Game.Entities;
|
|
using WingsEmu.Game.Extensions;
|
|
using WingsEmu.Game.Helpers.Damages;
|
|
using WingsEmu.Game.Maps;
|
|
using WingsEmu.Packets.Enums;
|
|
|
|
namespace WingsEmu.Plugins.BasicImplementations.BCards.Handlers;
|
|
|
|
public class BCardJumpBackPushHandler : IBCardEffectAsyncHandler
|
|
{
|
|
private readonly IRandomGenerator _random;
|
|
|
|
public BCardJumpBackPushHandler(IRandomGenerator random) => _random = random;
|
|
|
|
public BCardType HandledType => BCardType.JumpBackPush;
|
|
|
|
public void Execute(IBCardEffectContext ctx)
|
|
{
|
|
IBattleEntity sender = ctx.Sender;
|
|
IBattleEntity target = ctx.Target;
|
|
int firstData = ctx.BCard.FirstData;
|
|
|
|
if (_random.RandomNumber() > firstData)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int secondData = ctx.BCard.SecondData;
|
|
switch (ctx.BCard.SubType)
|
|
{
|
|
case (byte)AdditionalTypes.JumpBackPush.JumpBackChance:
|
|
short sX = target.PositionX;
|
|
short sY = target.PositionY;
|
|
short tX = sender.PositionX;
|
|
short tY = sender.PositionY;
|
|
|
|
int distance = sender.GetDistance(target);
|
|
if (distance <= 0)
|
|
{
|
|
distance = 1;
|
|
}
|
|
|
|
int d = distance + secondData;
|
|
|
|
short maxX = (short)(sX - d * (sX - tX) / distance);
|
|
short maxY = (short)(sY - d * (sY - tY) / distance);
|
|
|
|
int dx = Math.Abs(maxX - tX);
|
|
int sx = tX < maxX ? 1 : -1;
|
|
int dy = -Math.Abs(maxY - tY);
|
|
int sy = tY < maxY ? 1 : -1;
|
|
int err = dx + dy;
|
|
|
|
short lastX = tX;
|
|
short lastY = tY;
|
|
|
|
while (true)
|
|
{
|
|
if (sender.MapInstance.IsBlockedZone(tX, tY))
|
|
{
|
|
tX = lastX;
|
|
tY = lastY;
|
|
break;
|
|
}
|
|
|
|
lastX = tX;
|
|
lastY = tY;
|
|
|
|
if (tX == maxX && tY == maxY)
|
|
{
|
|
break;
|
|
}
|
|
|
|
int e2 = 2 * err;
|
|
if (e2 >= dy)
|
|
{
|
|
err += dy;
|
|
tX += (short)sx;
|
|
}
|
|
|
|
if (e2 > dx)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
err += dx;
|
|
tY += (short)sy;
|
|
}
|
|
|
|
if (sender is IPlayerEntity playerEntity && playerEntity.MapInstance != null && playerEntity.MapInstance.HasMapFlag(MapFlags.IS_BASE_MAP))
|
|
{
|
|
playerEntity.MapX = tX;
|
|
playerEntity.MapY = tY;
|
|
}
|
|
|
|
sender.MapInstance?.Broadcast(sender.GeneratePushPacket(tX, tY, 2));
|
|
sender.ChangePosition(new Position(tX, tY));
|
|
break;
|
|
case (byte)AdditionalTypes.JumpBackPush.PushBackChance:
|
|
if (!target.IsAlive())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (target is IMonsterEntity mapMonster && !mapMonster.CanBePushed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
(int resistance, _) = target.BCardComponent.GetAllBCardsInformation(BCardType.AbsorbedSpirit, (byte)AdditionalTypes.AbsorbedSpirit.ResistForcedMovement, target.Level);
|
|
if (resistance != 0 && _random.RandomNumber() <= resistance)
|
|
{
|
|
return;
|
|
}
|
|
|
|
sX = target.PositionX;
|
|
sY = target.PositionY;
|
|
tX = sender.PositionX;
|
|
tY = sender.PositionY;
|
|
|
|
distance = sender.GetDistance(target);
|
|
if (distance <= 0)
|
|
{
|
|
distance = 1;
|
|
}
|
|
|
|
d = distance + secondData;
|
|
|
|
maxX = (short)(tX + d * (sX - tX) / distance);
|
|
maxY = (short)(tY + d * (sY - tY) / distance);
|
|
|
|
dx = Math.Abs(maxX - tX);
|
|
sx = tX < maxX ? 1 : -1;
|
|
dy = -Math.Abs(maxY - tY);
|
|
sy = tY < maxY ? 1 : -1;
|
|
err = dx + dy;
|
|
|
|
lastX = tX;
|
|
lastY = tY;
|
|
|
|
while (true)
|
|
{
|
|
if (sender.MapInstance.IsBlockedZone(tX, tY))
|
|
{
|
|
tX = lastX;
|
|
tY = lastY;
|
|
break;
|
|
}
|
|
|
|
lastX = tX;
|
|
lastY = tY;
|
|
|
|
if (tX == maxX && tY == maxY)
|
|
{
|
|
break;
|
|
}
|
|
|
|
int e2 = 2 * err;
|
|
if (e2 >= dy)
|
|
{
|
|
err += dy;
|
|
tX += (short)sx;
|
|
}
|
|
|
|
if (e2 > dx)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
err += dx;
|
|
tY += (short)sy;
|
|
}
|
|
|
|
if (target is IPlayerEntity player && player.MapInstance != null && player.MapInstance.HasMapFlag(MapFlags.IS_BASE_MAP))
|
|
{
|
|
player.MapX = tX;
|
|
player.MapY = tY;
|
|
}
|
|
|
|
sender.MapInstance?.Broadcast(target.GeneratePushPacket(tX, tY, 2));
|
|
target.ChangePosition(new Position(tX, tY));
|
|
break;
|
|
}
|
|
}
|
|
} |