using HarmonyLib;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Linq;
using UAI;
namespace Harmony.UtilityAI
{
public class Debugging
{
private static readonly string AdvFeatureClass = "AdvancedTroubleshootingFeatures";
private static readonly string Feature = "UtilityAILogging";
private static readonly bool LoggingEnabled = AdvLogging.LogEnabled(AdvFeatureClass, Feature);
//[HarmonyPatch(typeof(UAI.UAIAction))]
//[HarmonyPatch("GetScore")]
//public class UAIAction_GetScore
//{
// private static bool Prefix(UAIAction __instance, Context _context, object _target, float min = 0f)
// {
// if (!Configuration.CheckFeatureStatus(AdvFeatureClass, Feature))
// return true;
// var considerations = __instance.GetConsiderations();
// var tasks = __instance.GetTasks();
// float num = 1f;
// if (considerations.Count == 0)
// return true;
// if (tasks.Count == 0)
// return true;
// AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Start Evaluation {__instance.Name} for {_context.Self.EntityName} ( {_context.Self.entityId} ) :: Action {__instance.Name} Weight: {__instance.Weight} ");
// global::EntityAlive entityAlive = UAIUtils.ConvertToEntityAlive(_target);
// if (entityAlive != null)
// AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"\tTarget Entity: {entityAlive.EntityName} {entityAlive.entityId}");
// for (int i = 0; i < considerations.Count; i++)
// {
// if (0f > num || num < min)
// {
// AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"\tConsiderations num {num} falls below minimum or 0: {min}");
// break;
// }
// num *= considerations[i].ComputeResponseCurve(considerations[i].GetScore(_context, _target));
// AdvLogging.DisplayLog(AdvFeatureClass, Feature, string.Format("\t{0} {1} {2} : Consideration Score {3}, Cumulative Score: {4}", new object[]
// {
// __instance.Name,
// __instance.GetTasks()[0].Name,
// considerations[i].Name,
// considerations[i].GetScore(_context, _target),
// num
// }));
// }
// float result = (num + (1f - num) * (float)(1 - 1 / considerations.Count) * num) * __instance.Weight;
// AdvLogging.DisplayLog(AdvFeatureClass, Feature, string.Format("\tFinal Score for Action: {0}", result));
// AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"End Evaluation {__instance.Name} ");
// return true;
// }
//}
///
/// This patch adds the package to the dictionary of stored attributes in SCoreUtils.
/// We will need those attributes later to see if the user specified package filters.
///
[HarmonyPatch(typeof(UAIFromXml))]
[HarmonyPatch("parseAIPackageNode")]
public static class UAIFromXml_parseAIPackageNode
{
public static void Postfix(XElement _element)
{
if (_element == null)
return;
if (!_element.HasAttribute("name"))
return;
var name = _element.GetAttribute("name");
if (UAIBase.AIPackages.TryGetValue(name, out var package))
{
SCoreUtils.StoreAttributes(package, _element);
}
}
}
///
/// This patch adds the action to the dictionary of stored attributes in SCoreUtils.
/// We will need those attributes later to see if the user specified action filters.
///
[HarmonyPatch(typeof(UAIFromXml))]
[HarmonyPatch("parseActionNode")]
public static class UAIFromXml_parseActionNode
{
public static void Postfix(UAIPackage _package, XElement _element)
{
if (_element == null || _package == null)
return;
if (!_element.HasAttribute("name"))
return;
var name = _element.GetAttribute("name");
var actions = _package.GetActions();
if (actions == null)
return;
for (int i = 0; i < actions.Count; i++)
{
var action = actions[i];
if (action.Name == name)
{
SCoreUtils.StoreAttributes(_package, action, _element);
break;
}
}
}
}
///
///
/// This patch replaces the DecideAction method with one that will skip targets which are
/// not passed through the package and/or action filters.
///
///
/// Note that filters are inclusive, not exclusive; and that targets may be filtered by
/// packages and actions, and must pass through both filters.
///
///
[HarmonyPatch(typeof(UAI.UAIPackage))]
[HarmonyPatch("DecideAction")]
public class UAIPackage_DecideAction
{
// for out parameters, use ref instead of out. ref the __result otherwise the default of 0 is returned.
private static bool Prefix(UAI.UAIPackage __instance, ref float __result, Context _context, ref UAIAction _chosenAction, ref object _chosenTarget, List ___actionList)
{
if (LoggingEnabled)
{
AdvLogging.DisplayLog(AdvFeatureClass, Feature, "\n**** START ************************ ");
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"UAIPackage: {_context.Self.entityId} {_context.Self.EntityName}");
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"EntityTargets: {_context.ConsiderationData.EntityTargets.Count} WayPoint: {_context.ConsiderationData.WaypointTargets.Count}");
}
float highScore = 0f;
_chosenAction = null;
_chosenTarget = null;
int availableActions = 0;
int actionRans = 0;
var packageEntityFilter = SCoreUtils.GetEntityFilter(__instance, null, _context.Self);
var packageWaypointFilter = SCoreUtils.GetWaypointFilter(__instance, null, _context.Self);
if (LoggingEnabled)
{
if (packageEntityFilter != null)
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Package {__instance.Name} entity filter: {packageEntityFilter}");
if (packageWaypointFilter != null)
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Package {__instance.Name} waypoint filter: {packageWaypointFilter}");
}
for (int i = 0; i < ___actionList.Count; i++)
{
var actionEntityFilter = SCoreUtils.GetEntityFilter(__instance, ___actionList[i], _context.Self);
var actionWaypointFilter = SCoreUtils.GetWaypointFilter(__instance, ___actionList[i], _context.Self);
if (LoggingEnabled)
{
if (actionEntityFilter != null)
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Action {___actionList[i].Name} entity filter: {actionEntityFilter}");
if (actionWaypointFilter != null)
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Action {___actionList[i].Name} waypoint filter: {actionWaypointFilter}");
}
int entitiesConsidered = 0;
int targetIndex = 0;
while (targetIndex < _context.ConsiderationData.EntityTargets.Count && entitiesConsidered <= UAIBase.MaxEntitiesToConsider)
{
var target = _context.ConsiderationData.EntityTargets[targetIndex];
availableActions++;
if (packageEntityFilter != null && !packageEntityFilter.Test(target))
{
if (LoggingEnabled)
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Target entity excluded by package filter: {target}");
targetIndex++;
continue;
}
if (actionEntityFilter != null && !actionEntityFilter.Test(target))
{
if (LoggingEnabled)
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Target entity excluded by action filter: {target}");
targetIndex++;
continue;
}
float score = ___actionList[i].GetScore(_context, target, 0f);
if (score > highScore)
{
highScore = score;
_chosenAction = ___actionList[i];
_chosenTarget = _context.ConsiderationData.EntityTargets[targetIndex];
}
entitiesConsidered++;
targetIndex++;
actionRans++;
}
int waypointsConsidered = 0;
int waypointIndex = 0;
while (waypointIndex < _context.ConsiderationData.WaypointTargets.Count && waypointsConsidered <= UAIBase.MaxWaypointsToConsider)
{
var target = _context.ConsiderationData.WaypointTargets[waypointIndex];
availableActions++;
if (packageWaypointFilter != null && !packageWaypointFilter.Test(target))
{
if (LoggingEnabled)
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Target waypoint excluded by package filter: {target}");
waypointIndex++;
continue;
}
if (actionWaypointFilter != null && !actionWaypointFilter.Test(target))
{
if (LoggingEnabled)
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Target waypoint excluded by action filter: {target}");
waypointIndex++;
continue;
}
float score2 = ___actionList[i].GetScore(_context, target, 0f);
if (score2 > highScore)
{
highScore = score2;
_chosenAction = ___actionList[i];
_chosenTarget = target;
}
waypointsConsidered++;
waypointIndex++;
actionRans++;
}
}
if (LoggingEnabled)
{
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"{_context.Self.EntityName} : I had a total of {availableActions} actions available, but I only evaluated {actionRans}");
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"************* Final Decision: {_context.Self.EntityName} ( {_context.Self.entityId} ) ********************* ");
if (_chosenAction != null)
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Chosen Action: {_chosenAction.Name} Score {highScore}");
else
AdvLogging.DisplayLog(AdvFeatureClass, Feature, " No Chosen action!");
if (_chosenTarget != null)
AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Chosen Target: {_chosenTarget} Score: {highScore}");
else
AdvLogging.DisplayLog(AdvFeatureClass, Feature, " No Chosen target!");
AdvLogging.DisplayLog(AdvFeatureClass, Feature, "********************************** ");
}
__result = highScore;
return false;
}
//private static void Postfix(UAI.UAIPackage __instance, Context _context, UAIAction _chosenAction, object _chosenTarget)
//{
// if (!Configuration.CheckFeatureStatus(AdvFeatureClass, Feature))
// return;
// if (_chosenAction != null)
// AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"Chosen Action: {_chosenAction.Name}");
// AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"UAIPackage: {_context.Self.entityId} {_context.Self.EntityName}");
// AdvLogging.DisplayLog(AdvFeatureClass, Feature, $"EntityTargets: {_context.ConsiderationData.EntityTargets.Count} WayPoint: {_context.ConsiderationData.WaypointTargets.Count}");
// AdvLogging.DisplayLog(AdvFeatureClass, Feature, "**** END ************************ \n");
//}
}
}
}