worldbox-observer-mod/IdleSpectator/ActivityActionComposer.cs

71 lines
2.2 KiB
C#

using System;
namespace IdleSpectator;
/// <summary>Single deterministic action-selection pipeline.</summary>
public static class ActivityActionComposer
{
public static string Compose(
ActivityContext ctx,
string key,
string rawFact,
bool hasTarget,
long subjectId,
int lineIndex)
{
ctx ??= ActivityContext.Empty;
ProseVoice voice = EnsureVoice(ctx);
string verb = ActivityVerbMap.Resolve(key);
if (string.IsNullOrEmpty(verb))
{
// Future unknown tasks still get the mob's authored work voice.
// The exhaustive runtime audit blocks every current task from reaching this branch.
verb = "work";
}
string[] bag = ActivityActionLexicon.GetBag(voice, verb, hasTarget, ctx.Terrain);
string phrase = Pick(bag, subjectId, lineIndex);
return ActivityModifierVoiceOverlay.Apply(phrase, voice, verb, subjectId, lineIndex);
}
private static ProseVoice EnsureVoice(ActivityContext ctx)
{
if (ctx.Voice != null
&& ctx.Voice.LiveSpeciesId.Equals(ctx.SpeciesId ?? "", StringComparison.Ordinal))
{
return ctx.Voice;
}
ProseVoice voice = ActivityVoiceResolver.Resolve(ctx.SpeciesId);
ctx.Voice = voice;
ctx.BaseSpeciesId = voice.BaseSpeciesId;
ctx.ModifierTag = ActivityVoiceResolver.ModifierName(voice.Modifier);
ctx.Family = voice.BaseFamily;
ctx.MannerTag = ActivityVoiceResolver.TagName(voice.EffectiveActionTag);
ctx.IsCiv = voice.BaseIsCiv;
ctx.IsHumanoid = voice.BaseIsHumanoid;
ctx.IsAnimal = voice.BaseIsAnimal;
return voice;
}
private static string Pick(
string[] bag,
long subjectId,
int lineIndex)
{
if (bag == null || bag.Length == 0)
{
return "moves along{place_at}{job_as}";
}
if (bag.Length == 1)
{
return bag[0];
}
int actorVariation = (int)((subjectId ^ (lineIndex * 397L)) & 1L);
int index = actorVariation % Math.Min(2, bag.Length);
return bag[index];
}
}