This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user