Implement basic AI check for whether a move would fail
This commit is contained in:
parent
a3a4993407
commit
364d4b9080
@ -5,4 +5,9 @@ namespace PkmnLib.Plugin.Gen7.AI;
|
|||||||
[AttributeUsage(AttributeTargets.Method), MeansImplicitUse]
|
[AttributeUsage(AttributeTargets.Method), MeansImplicitUse]
|
||||||
public class AIMoveScoreFunctionAttribute : Attribute
|
public class AIMoveScoreFunctionAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method), MeansImplicitUse]
|
||||||
|
public class AIMoveFailureFunctionAttribute : Attribute
|
||||||
|
{
|
||||||
}
|
}
|
@ -20,18 +20,37 @@ public static class ExplicitAIFunctions
|
|||||||
|
|
||||||
if (attribute.Category == ScriptCategory.Move)
|
if (attribute.Category == ScriptCategory.Move)
|
||||||
{
|
{
|
||||||
// Check if the move type has a static function in the following format:
|
var failureMethod = type.GetMethods(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(m =>
|
||||||
// public static void AIMoveEffectScore(MoveOption option, ref int score);
|
m.GetCustomAttribute<AIMoveFailureFunctionAttribute>() != null);
|
||||||
var method = type.GetMethods(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(m =>
|
if (failureMethod != null)
|
||||||
m.GetCustomAttribute<AIMoveScoreFunctionAttribute>() != null && m.ReturnType == typeof(void) &&
|
|
||||||
m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType == typeof(MoveOption) &&
|
|
||||||
m.GetParameters()[1].ParameterType == typeof(int).MakeByRefType());
|
|
||||||
if (method != null)
|
|
||||||
{
|
{
|
||||||
|
if (failureMethod.ReturnType != typeof(bool) || failureMethod.GetParameters().Length != 1 ||
|
||||||
|
failureMethod.GetParameters()[0].ParameterType != typeof(MoveOption))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Method {failureMethod.Name} in {type.Name} must return bool and take a single MoveOption parameter.");
|
||||||
|
}
|
||||||
|
var optionParam = Expression.Parameter(typeof(MoveOption), "option");
|
||||||
|
var functionExpression = Expression.Lambda<AIBoolHandler>(
|
||||||
|
Expression.Call(null, failureMethod, optionParam), optionParam).Compile();
|
||||||
|
handlers.MoveFailureCheck.Add(attribute.Name, functionExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
var scoreMethod = type.GetMethods(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(m =>
|
||||||
|
m.GetCustomAttribute<AIMoveScoreFunctionAttribute>() != null);
|
||||||
|
if (scoreMethod != null)
|
||||||
|
{
|
||||||
|
if (scoreMethod.ReturnType != typeof(void) || scoreMethod.GetParameters().Length != 2 ||
|
||||||
|
scoreMethod.GetParameters()[0].ParameterType != typeof(MoveOption) ||
|
||||||
|
scoreMethod.GetParameters()[1].ParameterType != typeof(int).MakeByRefType())
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Method {scoreMethod.Name} in {type.Name} must return void and take a MoveOption and an int by reference parameter.");
|
||||||
|
}
|
||||||
var optionParam = Expression.Parameter(typeof(MoveOption), "option");
|
var optionParam = Expression.Parameter(typeof(MoveOption), "option");
|
||||||
var scoreParam = Expression.Parameter(typeof(int).MakeByRefType(), "score");
|
var scoreParam = Expression.Parameter(typeof(int).MakeByRefType(), "score");
|
||||||
var functionExpression = Expression.Lambda<AIScoreMoveHandler>(
|
var functionExpression = Expression.Lambda<AIScoreMoveHandler>(
|
||||||
Expression.Call(null, method, optionParam, scoreParam), optionParam, scoreParam).Compile();
|
Expression.Call(null, scoreMethod, optionParam, scoreParam), optionParam, scoreParam).Compile();
|
||||||
handlers.MoveEffectScore.Add(attribute.Name, functionExpression);
|
handlers.MoveEffectScore.Add(attribute.Name, functionExpression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,9 @@ public abstract class ChangeUserStats : Script, IScriptOnInitialize, IScriptOnSe
|
|||||||
move.User.ChangeStatBoost(_stat, _amount, true, false);
|
move.User.ChangeStatBoost(_stat, _amount, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static bool WouldMoveFail(MoveOption option, Statistic stat) =>
|
||||||
|
option.Move.User.StatBoost.GetStatistic(stat) == StatBoostStatisticSet.MaxStatBoost;
|
||||||
|
|
||||||
protected static void GetMoveEffectScore(MoveOption option, Statistic stat, ref int score)
|
protected static void GetMoveEffectScore(MoveOption option, Statistic stat, ref int score)
|
||||||
{
|
{
|
||||||
if (option.Move.Move.SecondaryEffect == null ||
|
if (option.Move.Move.SecondaryEffect == null ||
|
||||||
@ -56,6 +59,9 @@ public class ChangeUserAttack : ChangeUserStats
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AIMoveFailureFunction]
|
||||||
|
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.Attack);
|
||||||
|
|
||||||
[AIMoveScoreFunction]
|
[AIMoveScoreFunction]
|
||||||
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
||||||
GetMoveEffectScore(option, Statistic.Attack, ref score);
|
GetMoveEffectScore(option, Statistic.Attack, ref score);
|
||||||
@ -68,6 +74,9 @@ public class ChangeUserDefense : ChangeUserStats
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AIMoveFailureFunction]
|
||||||
|
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.Defense);
|
||||||
|
|
||||||
[AIMoveScoreFunction]
|
[AIMoveScoreFunction]
|
||||||
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
||||||
GetMoveEffectScore(option, Statistic.Defense, ref score);
|
GetMoveEffectScore(option, Statistic.Defense, ref score);
|
||||||
@ -80,6 +89,9 @@ public class ChangeUserSpecialAttack : ChangeUserStats
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AIMoveFailureFunction]
|
||||||
|
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.SpecialAttack);
|
||||||
|
|
||||||
[AIMoveScoreFunction]
|
[AIMoveScoreFunction]
|
||||||
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
||||||
GetMoveEffectScore(option, Statistic.SpecialAttack, ref score);
|
GetMoveEffectScore(option, Statistic.SpecialAttack, ref score);
|
||||||
@ -92,6 +104,9 @@ public class ChangeUserSpecialDefense : ChangeUserStats
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AIMoveFailureFunction]
|
||||||
|
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.SpecialDefense);
|
||||||
|
|
||||||
[AIMoveScoreFunction]
|
[AIMoveScoreFunction]
|
||||||
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
||||||
GetMoveEffectScore(option, Statistic.SpecialDefense, ref score);
|
GetMoveEffectScore(option, Statistic.SpecialDefense, ref score);
|
||||||
@ -104,6 +119,9 @@ public class ChangeUserSpeed : ChangeUserStats
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AIMoveFailureFunction]
|
||||||
|
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.Speed);
|
||||||
|
|
||||||
[AIMoveScoreFunction]
|
[AIMoveScoreFunction]
|
||||||
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
||||||
GetMoveEffectScore(option, Statistic.Speed, ref score);
|
GetMoveEffectScore(option, Statistic.Speed, ref score);
|
||||||
@ -116,6 +134,9 @@ public class ChangeUserAccuracy : ChangeUserStats
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AIMoveFailureFunction]
|
||||||
|
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.Accuracy);
|
||||||
|
|
||||||
[AIMoveScoreFunction]
|
[AIMoveScoreFunction]
|
||||||
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
||||||
GetMoveEffectScore(option, Statistic.Accuracy, ref score);
|
GetMoveEffectScore(option, Statistic.Accuracy, ref score);
|
||||||
@ -128,6 +149,9 @@ public class ChangeUserEvasion : ChangeUserStats
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AIMoveFailureFunction]
|
||||||
|
public static bool AIMoveWillFail(MoveOption option) => WouldMoveFail(option, Statistic.Evasion);
|
||||||
|
|
||||||
[AIMoveScoreFunction]
|
[AIMoveScoreFunction]
|
||||||
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
public static void AIMoveEffectScore(MoveOption option, ref int score) =>
|
||||||
GetMoveEffectScore(option, Statistic.Evasion, ref score);
|
GetMoveEffectScore(option, Statistic.Evasion, ref score);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user