worldbox-observer-mod/IdleSpectator/Events/EventOutcome.cs

156 lines
3.3 KiB
C#

using System;
using ai.behaviours;
namespace IdleSpectator;
/// <summary>
/// Shared outcome checks for Layer A/B event confirmation.
/// Patches observe; this layer answers "did the semantic event actually happen?"
/// before any feed Emit. Do not treat <see cref="BehResult.Continue"/> as success.
/// </summary>
public static class EventOutcome
{
/// <summary>Cheap before-snapshot for Prefix → Postfix confirmation.</summary>
public struct ActorFlags
{
public bool Valid;
public bool Alive;
public bool HasFamily;
public bool HasLover;
}
public static ActorFlags Snapshot(Actor actor)
{
var flags = new ActorFlags();
if (actor == null)
{
return flags;
}
flags.Valid = true;
try
{
flags.Alive = actor.isAlive();
if (!flags.Alive)
{
return flags;
}
flags.HasFamily = actor.hasFamily();
flags.HasLover = actor.hasLover();
}
catch
{
flags.Valid = false;
}
return flags;
}
public static bool IsLiving(Actor actor)
{
try
{
return actor != null && actor.isAlive();
}
catch
{
return false;
}
}
/// <summary>Behaviour node finished without Stop. Never implies semantic success.</summary>
public static bool BehaviourRan(BehResult result)
{
return result != BehResult.Stop;
}
public static bool GainedFamily(ActorFlags before, Actor actor)
{
if (!before.Valid || !before.Alive || !IsLiving(actor))
{
return false;
}
try
{
return !before.HasFamily && actor.hasFamily();
}
catch
{
return false;
}
}
public static bool LostFamily(ActorFlags before, Actor actor)
{
if (!before.Valid || !before.Alive || !IsLiving(actor))
{
return false;
}
try
{
return before.HasFamily && !actor.hasFamily();
}
catch
{
return false;
}
}
public static bool GainedLover(ActorFlags before, Actor actor)
{
if (!before.Valid || !before.Alive || !IsLiving(actor))
{
return false;
}
try
{
return !before.HasLover && actor.hasLover();
}
catch
{
return false;
}
}
public static bool LostLover(ActorFlags before, Actor actor)
{
if (!before.Valid || !before.Alive || !IsLiving(actor))
{
return false;
}
try
{
return before.HasLover && !actor.hasLover();
}
catch
{
return false;
}
}
/// <summary>
/// Still seeking: behaviour continued and the unit did not acquire a lover
/// (success path is <c>set_lover</c> / love status).
/// </summary>
public static bool StillSeekingLover(Actor actor, BehResult result)
{
if (!BehaviourRan(result) || !IsLiving(actor))
{
return false;
}
try
{
return !actor.hasLover();
}
catch
{
return false;
}
}
}