Implement basic AI check for whether a move would fail
This commit is contained in:
@@ -5,4 +5,9 @@ namespace PkmnLib.Plugin.Gen7.AI;
|
||||
[AttributeUsage(AttributeTargets.Method), MeansImplicitUse]
|
||||
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)
|
||||
{
|
||||
// Check if the move type has a static function in the following format:
|
||||
// public static void AIMoveEffectScore(MoveOption option, ref int score);
|
||||
var method = type.GetMethods(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(m =>
|
||||
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)
|
||||
var failureMethod = type.GetMethods(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(m =>
|
||||
m.GetCustomAttribute<AIMoveFailureFunctionAttribute>() != null);
|
||||
if (failureMethod != 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 scoreParam = Expression.Parameter(typeof(int).MakeByRefType(), "score");
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user