PkmnLib.NET/Plugins/PkmnLib.Plugin.Gen7/AI/ExplicitAIFunctionRegistration.cs
Deukhoofd bf83b25238
All checks were successful
Build / Build (push) Successful in 58s
Implements AI Switching
2025-07-12 13:03:00 +02:00

77 lines
3.7 KiB
C#

using System.Linq.Expressions;
using System.Reflection;
using PkmnLib.Dynamic.AI.Explicit;
namespace PkmnLib.Plugin.Gen7.AI;
public static class ExplicitAIFunctionRegistration
{
public static void RegisterAIFunctions(ExplicitAIHandlers handlers)
{
var baseType = typeof(Script);
foreach (var type in typeof(ExplicitAIFunctionRegistration).Assembly.GetTypes()
.Where(t => baseType.IsAssignableFrom(t)))
{
var attribute = type.GetCustomAttribute<ScriptAttribute>();
if (attribute == null)
continue;
if (attribute.Category == ScriptCategory.Move)
{
InitializeMoveFailFunction(handlers, type, attribute);
InitializeMoveScoreFunction(handlers, type, attribute);
}
}
handlers.GeneralMoveAgainstTargetScore.Add("predicted_damage", AIDamageFunctions.PredictedDamageScore);
AISwitchFunctions.RegisterAISwitchFunctions(handlers);
}
#region Reflection based function initialization
private static void InitializeMoveFailFunction(ExplicitAIHandlers handlers, Type type, ScriptAttribute attribute)
{
var failureMethod = type.GetMethods(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(m =>
m.GetCustomAttribute<AIMoveFailureFunctionAttribute>() != null);
if (failureMethod == null)
return;
if (failureMethod.ReturnType != typeof(bool) || failureMethod.GetParameters().Length != 2 ||
failureMethod.GetParameters()[0].ParameterType != typeof(IExplicitAI) ||
failureMethod.GetParameters()[1].ParameterType != typeof(MoveOption))
{
throw new InvalidOperationException(
$"Method {failureMethod.Name} in {type.Name} must return bool and take an IExplicitAI and a MoveOption as parameters.");
}
var aiParam = Expression.Parameter(typeof(IExplicitAI), "ai");
var optionParam = Expression.Parameter(typeof(MoveOption), "option");
var functionExpression = Expression.Lambda<AIBoolHandler>(
Expression.Call(null, failureMethod, aiParam, optionParam), aiParam, optionParam).Compile();
handlers.MoveFailureCheck.Add(attribute.Name, functionExpression);
}
private static void InitializeMoveScoreFunction(ExplicitAIHandlers handlers, Type type, ScriptAttribute attribute)
{
var scoreMethod = type.GetMethods(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(m =>
m.GetCustomAttribute<AIMoveScoreFunctionAttribute>() != null);
if (scoreMethod == null)
return;
if (scoreMethod.ReturnType != typeof(void) || scoreMethod.GetParameters().Length != 3 ||
scoreMethod.GetParameters()[0].ParameterType != typeof(IExplicitAI) ||
scoreMethod.GetParameters()[1].ParameterType != typeof(MoveOption) ||
scoreMethod.GetParameters()[2].ParameterType != typeof(int).MakeByRefType())
{
throw new InvalidOperationException(
$"Method {scoreMethod.Name} in {type.Name} must return void and take an IExplicitAI, a MoveOption, and a ref int as parameters.");
}
var aiParam = Expression.Parameter(typeof(IExplicitAI), "ai");
var optionParam = Expression.Parameter(typeof(MoveOption), "option");
var scoreParam = Expression.Parameter(typeof(int).MakeByRefType(), "score");
var functionExpression = Expression.Lambda<AIScoreMoveHandler>(
Expression.Call(null, scoreMethod, aiParam, optionParam, scoreParam), aiParam, optionParam, scoreParam)
.Compile();
handlers.MoveEffectScore.Add(attribute.Name, functionExpression);
}
#endregion
}