worldbox-observer-mod/IdleSpectator/ActivityModifierVoiceOverlay.cs

184 lines
7.6 KiB
C#

using System;
namespace IdleSpectator;
/// <summary>
/// Adds a meaningful transformed-variant tone without replacing the recovered base mob voice.
/// Native authored forms keep their own complete voice and do not pass through this overlay.
/// </summary>
public static class ActivityModifierVoiceOverlay
{
private const string ContextTokens = "{place_at}{job_as}";
public static string Apply(
string basePhrase,
ProseVoice voice,
string verb,
long subjectId,
int lineIndex)
{
if (string.IsNullOrEmpty(basePhrase)
|| voice == null
|| voice.Modifier == ActivityModifier.None
|| voice.LiveSpeciesId.Equals(voice.BaseSpeciesId, StringComparison.OrdinalIgnoreCase))
{
return basePhrase;
}
string[] bag = OverlayBag(voice.Modifier, voice.BaseBodyTag, verb);
if (bag == null || bag.Length == 0)
{
return basePhrase;
}
int index = (int)((subjectId ^ (lineIndex * 397L)) & 1L) % bag.Length;
string core = basePhrase.EndsWith(ContextTokens, StringComparison.Ordinal)
? basePhrase.Substring(0, basePhrase.Length - ContextTokens.Length)
: basePhrase;
return core + bag[index] + ContextTokens;
}
private static string[] OverlayBag(
ActivityModifier modifier,
ActivityBodyTag body,
string verb)
{
return modifier switch
{
ActivityModifier.Undead => UndeadBag(body, verb),
ActivityModifier.Elemental => ElementalBag(verb),
ActivityModifier.Mush => MushBag(verb),
ActivityModifier.Tumor => TumorBag(verb),
ActivityModifier.Alien => AlienBag(verb),
ActivityModifier.Construct => ConstructBag(verb),
_ => null
};
}
private static string[] UndeadBag(ActivityBodyTag body, string verb)
{
if (verb == "move")
{
return body switch
{
ActivityBodyTag.Canine => V(
", its paws landing in stiff, uneven beats",
", its muzzle fixed ahead as its gait falters"),
ActivityBodyTag.Feline => V(
", each silent step held rigid too long",
", its once-fluid gait broken into sharp jolts"),
ActivityBodyTag.Bird => V(
", its lifeless wings beating out of rhythm",
", each ragged motion ending in a hard twitch"),
ActivityBodyTag.Insect => V(
", its joints clicking in lifeless sequence",
", each small step snapping into the next"),
ActivityBodyTag.Plant => V(
", its withered growth dragging behind",
", every deadened limb moving in rigid turns"),
ActivityBodyTag.Dragon => V(
", its ruined frame carrying deathly weight",
", every ancient joint grinding through the motion"),
_ => V(
", its gait broken by stiff, uneven jolts",
", every step landing with lifeless weight")
};
}
return verb switch
{
"wait" => V(
", holding an unnaturally rigid posture",
", without breath or any easy motion"),
"play" => V(
", repeating each motion in empty jerks",
", the movement breaking into stiff, empty rhythms"),
"eat" => V(
", driven by a hunger that never eases",
", consuming each bite without satisfaction"),
"sleep" => V(
", lying rigid even at rest",
", never fully losing its restless tension"),
"hunt" => V(
", pursuing without tiring",
", never slowing as the chase continues"),
"fight" => V(
", striking without fear or pain",
", pressing the attack with deathless persistence"),
"social" => V(
", answering with hollow, halting sounds",
", holding close in an uneasy silence"),
"laugh" => V(
", the sound collapsing into a dry rasp",
", each note ending in a hollow groan"),
"work" => V(
", continuing in tireless, rigid motions",
", never pausing as its joints grind on"),
_ => V(
", its body moving with lifeless stiffness",
", each motion marked by restless undeath")
};
}
private static string[] ElementalBag(string verb)
{
return verb switch
{
"wait" => V(", flickering without becoming still", ", its glow rising and falling"),
"sleep" => V(", dimming to a banked glow", ", its brightness settling low"),
"eat" => V(", drawing the meal into its inner heat", ", feeding the flame within"),
"fight" => V(", shedding sparks with every strike", ", flaring brighter through the clash"),
_ => V(", edged by quick tongues of flame", ", trailing brief curls of heat")
};
}
private static string[] MushBag(string verb)
{
return verb switch
{
"wait" => V(", faint spores drifting from every pause", ", its soft growth gently pulsing"),
"eat" => V(", drawing nourishment through fibrous growth", ", feeding in slow, spreading pulses"),
"fight" => V(", bursting spores through every impact", ", its soft mass recoiling and swelling"),
_ => V(", shedding a faint wake of spores", ", its softened form flexing with each motion")
};
}
private static string[] TumorBag(string verb)
{
return verb switch
{
"wait" => V(", its swollen mass quivering in place", ", uneven pulses passing through its body"),
"eat" => V(", absorbing the meal into its growing mass", ", folding each bite into hungry tissue"),
"fight" => V(", its mass surging behind every blow", ", new growth tightening through the clash"),
_ => V(", its form shifting in uneven pulses", ", swollen tissue rolling through each motion")
};
}
private static string[] AlienBag(string verb)
{
return verb switch
{
"wait" => V(", holding a posture that is difficult to read", ", its unfamiliar joints locking at odd angles"),
"social" => V(", answering in precise, unfamiliar signals", ", mirroring the exchange with uncanny timing"),
"fight" => V(", changing angles without warning", ", every strike arriving with uncanny precision"),
_ => V(", following an unfamiliar rhythm", ", each motion precise but difficult to predict")
};
}
private static string[] ConstructBag(string verb)
{
return verb switch
{
"wait" => V(", every mechanism settling into a fixed hold", ", its joints locking into measured stillness"),
"sleep" => V(", its moving parts falling dormant", ", the last small mechanisms winding down"),
"fight" => V(", every joint driving the next strike", ", its rigid frame absorbing the impact"),
"work" => V(", repeating each step with exact precision", ", its mechanisms keeping a flawless cadence"),
_ => V(", every joint moving in measured sequence", ", its mechanisms keeping a precise cadence")
};
}
private static string[] V(string first, string second)
{
return new[] { first, second };
}
}