This commit is contained in:
@@ -351,6 +351,21 @@ public class BattleImpl : ScriptSource, IBattle
|
||||
if (switchChoice.SwitchTo == switchChoice.User)
|
||||
return false;
|
||||
}
|
||||
else if (choice is IItemChoice itemChoice)
|
||||
{
|
||||
if (!Library.ScriptResolver.TryResolveBattleItemScript(itemChoice.Item, out var itemScript))
|
||||
return false;
|
||||
if (!itemScript.IsItemUsable)
|
||||
return false;
|
||||
if (itemScript.TargetType != ItemTargetType.None)
|
||||
{
|
||||
var target = itemChoice.GetTargetPokemon(this);
|
||||
if (target is null || !itemScript.IsTargetValid(target))
|
||||
return false;
|
||||
if (!itemScript.TargetType.IsValidTarget(this, choice.User, target))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
@@ -11,40 +11,67 @@ public interface IItemChoice : ITurnChoice
|
||||
/// <summary>
|
||||
/// The item that is used.
|
||||
/// </summary>
|
||||
public IItem Item { get; }
|
||||
IItem Item { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The side the move is targeted at.
|
||||
/// The target Pokémon of the item, if any.
|
||||
/// </summary>
|
||||
byte? TargetSide { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The position the move is targeted at.
|
||||
/// </summary>
|
||||
byte? TargetPosition { get; }
|
||||
IPokemon? GetTargetPokemon(IBattle battle);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IItemChoice"/>
|
||||
public class ItemChoice : TurnChoice, IItemChoice
|
||||
{
|
||||
/// <inheritdoc cref="ItemChoice"/>
|
||||
public ItemChoice(IPokemon user, IItem item, byte? targetSide, byte? targetPosition) : base(user)
|
||||
private ItemChoice(IPokemon user, IItem item, byte? targetSide, byte? targetPosition, IPokemon? targetPokemon) :
|
||||
base(user)
|
||||
{
|
||||
Item = item;
|
||||
TargetSide = targetSide;
|
||||
TargetPosition = targetPosition;
|
||||
TargetPokemon = targetPokemon;
|
||||
}
|
||||
|
||||
public static ItemChoice CreateWithoutTarget(IPokemon user, IItem item) =>
|
||||
new(user, item, null, null, null);
|
||||
|
||||
public static ItemChoice CreateForOpponent(IPokemon user, IItem item, byte targetSide, byte targetPosition) =>
|
||||
new(user, item, targetSide, targetPosition, null);
|
||||
|
||||
public static ItemChoice CreateForPartyMember(IPokemon user, IItem item, IPokemon targetPokemon) =>
|
||||
new(user, item, null, null, targetPokemon);
|
||||
|
||||
/// <summary>
|
||||
/// The item that is used.
|
||||
/// </summary>
|
||||
public IItem Item { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte? TargetSide { get; }
|
||||
public IPokemon? GetTargetPokemon(IBattle battle)
|
||||
{
|
||||
if (TargetPokemon != null)
|
||||
return TargetPokemon;
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte? TargetPosition { get; }
|
||||
if (!TargetSide.HasValue || !TargetPosition.HasValue)
|
||||
return null;
|
||||
var side = battle.Sides[TargetSide.Value];
|
||||
return side.Pokemon[TargetPosition.Value];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The target side of the item, if any.
|
||||
/// </summary>
|
||||
private byte? TargetSide { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The target position of the item, if any.
|
||||
/// </summary>
|
||||
private byte? TargetPosition { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The target Pokémon of the item, if any. This is used for party members.
|
||||
/// </summary>
|
||||
private IPokemon? TargetPokemon { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int ScriptCount => User.ScriptCount;
|
||||
|
||||
67
PkmnLib.Dynamic/Models/ItemTargetType.cs
Normal file
67
PkmnLib.Dynamic/Models/ItemTargetType.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
namespace PkmnLib.Dynamic.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Types of targets an item can have.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ItemTargetType
|
||||
{
|
||||
/// <summary>
|
||||
/// The item does not require a target.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The item targets Pokémon that are part of the user's own team.
|
||||
/// </summary>
|
||||
OwnPokemon = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The item targets allied Pokémon.
|
||||
/// </summary>
|
||||
AllyPokemon = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The item targets opposing Pokémon.
|
||||
/// </summary>
|
||||
FoePokemon = 4,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper methods for ItemTargetType.
|
||||
/// </summary>
|
||||
public static class ItemTargetTypeHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if the given target is valid based on the ItemTargetType.
|
||||
/// </summary>
|
||||
public static bool IsValidTarget(this ItemTargetType targetType, IBattle battle, IPokemon user, IPokemon target)
|
||||
{
|
||||
if (targetType == ItemTargetType.None)
|
||||
return true;
|
||||
|
||||
if (targetType.HasFlag(ItemTargetType.OwnPokemon))
|
||||
{
|
||||
var userParty = battle.Parties.FirstOrDefault(x => x.Party.Contains(user));
|
||||
var targetParty = battle.Parties.FirstOrDefault(x => x.Party.Contains(target));
|
||||
if (userParty is not null && targetParty is not null && userParty == targetParty)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (targetType.HasFlag(ItemTargetType.AllyPokemon))
|
||||
{
|
||||
if (user.BattleData?.BattleSide == target.BattleData?.BattleSide)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (targetType.HasFlag(ItemTargetType.FoePokemon))
|
||||
{
|
||||
var userParty = battle.Parties.FirstOrDefault(x => x.Party.Contains(user));
|
||||
var targetParty = battle.Parties.FirstOrDefault(x => x.Party.Contains(target));
|
||||
if (userParty is not null && targetParty is not null && userParty != targetParty)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user