//
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//
namespace MUnique.OpenMU.GameLogic.PlayerActions;
using MUnique.OpenMU.GameLogic.Views.World;
using MUnique.OpenMU.Pathfinding;
///
/// Action to warp to another place through a gate.
///
public class WizardTeleportAction
{
private const ushort TeleportSkillId = 6;
private const ushort TeleportTargetSkillId = 15;
private static readonly byte[] PreventingMagicEffects =
{
0x39, // Stone
0x3D, // Stun
0x48, // Sleep
0x92, // Freeze2
0x93, // Earth Binds
};
///
/// Tries to teleport to the specified target with the teleport skill.
///
/// The player.
/// The target.
public async ValueTask TryTeleportWithSkillAsync(Player player, Point target)
{
// todo: additional checks:
// - During castle siege, can't teleport over the non-destroyed gates (simple y-axis check)
if (!player.IsAtSafezone()
&& player.IsActive()
&& player.SkillList?.GetSkill(TeleportSkillId) is { Skill: { } skill }
&& player.CurrentMap!.Terrain.WalkMap[target.X, target.Y]
&& !player.CurrentMap.Terrain.SafezoneMap[target.X, target.Y]
&& player.IsInRange(target, skill.Range)
&& CanPlayerBeTeleported(player)
&& await player.TryConsumeForSkillAsync(skill).ConfigureAwait(false))
{
_ = Task.Run(() => player.TeleportAsync(target, skill));
}
else
{
await player.InvokeViewPlugInAsync(p => p.ShowTeleportedAsync()).ConfigureAwait(false);
}
}
///
/// Tries to teleport the target with the 'Teleport Ally' skill.
///
/// The player.
/// The target identifier.
/// The target.
public async ValueTask TryTeleportTargetWithSkillAsync(Player player, ushort targetId, Point target)
{
if (!player.IsAtSafezone()
&& player.IsActive()
&& player.SkillList?.GetSkill(TeleportTargetSkillId) is { Skill: { } skill }
&& player.Party is not null
&& player.CurrentMap!.Terrain.WalkMap[target.X, target.Y]
&& !player.CurrentMap.Terrain.SafezoneMap[target.X, target.Y]
&& await player.GetObservingPlayerWithIdAsync(targetId).ConfigureAwait(false) is { } targetPlayer
&& targetPlayer.Party == player.Party
&& targetPlayer.IsActive()
&& CanPlayerBeTeleported(targetPlayer)
&& targetPlayer.IsInRange(target, skill.Range + 1)
&& await player.TryConsumeForSkillAsync(skill).ConfigureAwait(false))
{
_ = Task.Run(() => targetPlayer.TeleportAsync(target, skill));
}
}
private static bool CanPlayerBeTeleported(Player player)
{
var currentEffects = player.MagicEffectList.ActiveEffects;
if (currentEffects.Count == 0)
{
return true;
}
for (int i = 0; i < PreventingMagicEffects.Length; i++)
{
if (currentEffects.ContainsKey(PreventingMagicEffects[i]))
{
return false;
}
}
return true;
}
}