diff --git a/PkmnLib.Dynamic/Models/Battle.cs b/PkmnLib.Dynamic/Models/Battle.cs
index 23ea685..da563a9 100644
--- a/PkmnLib.Dynamic/Models/Battle.cs
+++ b/PkmnLib.Dynamic/Models/Battle.cs
@@ -236,7 +236,9 @@ public class BattleImpl : ScriptSource, IBattle
// TODO: Hook to change number of PP needed.
if (moveChoice.ChosenMove.CurrentPp < 1)
return false;
- // TODO: Validate target
+ if (!TargetResolver.IsValidTarget(moveChoice.TargetSide, moveChoice.TargetPosition,
+ moveChoice.ChosenMove.MoveData.Target, moveChoice.User))
+ return false;
}
return true;
diff --git a/PkmnLib.Dynamic/Models/BattleFlow/TargetResolver.cs b/PkmnLib.Dynamic/Models/BattleFlow/TargetResolver.cs
index e13c45b..e77b0e7 100644
--- a/PkmnLib.Dynamic/Models/BattleFlow/TargetResolver.cs
+++ b/PkmnLib.Dynamic/Models/BattleFlow/TargetResolver.cs
@@ -26,6 +26,60 @@ public static class TargetResolver
};
}
+ ///
+ /// Validates whether a given target is valid for a move choice. Returns true if the target is valid.
+ ///
+ public static bool IsValidTarget(byte side, byte position, MoveTarget target, IPokemon user)
+ {
+ var userBattleData = user.BattleData;
+ if (userBattleData == null)
+ throw new ArgumentNullException(nameof(user.BattleData));
+ var userSide = userBattleData.SideIndex;
+ var userPosition = userBattleData.Position;
+
+ switch (target)
+ {
+ case MoveTarget.Adjacent:
+ case MoveTarget.AllAdjacent:
+ {
+ var diff = Math.Abs(position - userPosition);
+ if (diff == 0)
+ return userSide == side;
+ return diff <= 1;
+ }
+ case MoveTarget.AdjacentAlly:
+ {
+ if (userSide != side)
+ return false;
+ return Math.Abs(position - userPosition) == 1;
+ }
+ case MoveTarget.AdjacentAllySelf:
+ {
+ if (userSide != side)
+ return false;
+ return Math.Abs(position - userPosition) <= 1;
+ }
+ case MoveTarget.AdjacentOpponent:
+ case MoveTarget.AllAdjacentOpponent:
+ {
+ if (userSide == side)
+ return false;
+ return Math.Abs(position - userPosition) <= 1;
+ }
+ case MoveTarget.All:
+ case MoveTarget.Any:
+ case MoveTarget.RandomOpponent:
+ return true;
+ case MoveTarget.AllAlly:
+ return userSide == side;
+ case MoveTarget.AllOpponent:
+ return userSide != side;
+ case MoveTarget.SelfUse:
+ return userSide == side && userPosition == position;
+ }
+ throw new ArgumentOutOfRangeException(nameof(target), target, null);
+ }
+
private static IReadOnlyList GetAllTargets(IBattle battle) =>
battle.Sides.SelectMany(x => x.Pokemon).ToList();
diff --git a/PkmnLib.Dynamic/StaticHelpers.cs b/PkmnLib.Dynamic/StaticHelpers.cs
index ef24ba4..e0574aa 100644
--- a/PkmnLib.Dynamic/StaticHelpers.cs
+++ b/PkmnLib.Dynamic/StaticHelpers.cs
@@ -9,10 +9,10 @@ public static class StaticHelpers
/// A function to get the current date and time. This can be replaced in cases where the date and time
/// may not be the same as the system time.
///
- public static Func DateTimeProvider { get; set; } = () => DateTime.Now;
+ public static Func DateTimeProvider { get; set; } = () => DateTimeOffset.Now;
///
/// Get the current date and time.
///
- public static DateTime GetCurrentDateTime() => DateTimeProvider();
+ public static DateTimeOffset GetCurrentDateTime() => DateTimeProvider();
}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Libraries/Gen7MiscLibrary.cs b/Plugins/PkmnLib.Plugin.Gen7/Libraries/Gen7MiscLibrary.cs
index b44c068..072a650 100644
--- a/Plugins/PkmnLib.Plugin.Gen7/Libraries/Gen7MiscLibrary.cs
+++ b/Plugins/PkmnLib.Plugin.Gen7/Libraries/Gen7MiscLibrary.cs
@@ -24,7 +24,7 @@ public class Gen7MiscLibrary : IMiscLibrary
///
public TimeOfDay GetTimeOfDay()
{
- var time = StaticHelpers.GetCurrentDateTime();
+ var time = StaticHelpers.GetCurrentDateTime().LocalDateTime;
var hour = time.Hour;
return hour switch
{