using System;
using System.Collections.Generic;
namespace IdleSpectator;
///
/// Authored milestone-style gain/loss phrases for every live WorldBox status asset.
/// Runtime fallback is HUD-only safety; the harness audit requires authored coverage.
///
public static class ActivityStatusProse
{
private static readonly Dictionary Authored =
new Dictionary(StringComparer.OrdinalIgnoreCase)
{
["afterglow"] = ("Basks in an afterglow", "Lets the afterglow fade"),
["angry"] = ("Flies into a rage", "Cools off"),
["ash_fever"] = ("Catches ash fever", "Recovers from ash fever"),
["being_suspicious"] = ("Starts acting suspicious", "Stops looking so suspicious"),
["budding"] = ("Begins budding", "Finishes budding"),
["burning"] = ("Catches fire", "Stops burning"),
["caffeinated"] = ("Gets a caffeine rush", "Comes down from caffeine"),
["confused"] = ("Becomes confused", "Regains clarity"),
["cough"] = ("Starts coughing", "Stops coughing"),
["crying"] = ("Breaks into tears", "Dries their eyes"),
["cursed"] = ("Is cursed", "Shakes off the curse"),
["dash"] = ("Dashes forward", "Ends the dash"),
["dodge"] = ("Dodges aside", "Stops dodging"),
["drowning"] = ("Starts drowning", "Gets air again"),
["egg"] = ("Turns into an egg", "Hatches from the egg"),
["enchanted"] = ("Becomes enchanted", "Loses the enchantment"),
["fell_in_love"] = ("Falls in love", "Lets the infatuation pass"),
["festive_spirit"] = ("Catches the festive spirit", "Settles out of the festive mood"),
["flicked"] = ("Gets flicked", "Recovers from the flick"),
["frozen"] = ("Freezes solid", "Thaws out"),
["had_bad_dream"] = ("Wakes from a bad dream", "Shakes off the bad dream"),
["had_good_dream"] = ("Wakes from a good dream", "Lets the good dream fade"),
["had_nightmare"] = ("Wakes from a nightmare", "Shakes off the nightmare"),
["handsome_migrant"] = ("Turns heads as a handsome migrant", "Stops drawing migrant attention"),
["inspired"] = ("Feels inspired", "Loses the spark of inspiration"),
["invincible"] = ("Becomes invincible", "Loses invincibility"),
["just_ate"] = ("Just finished eating", "Is ready to eat again"),
["laughing"] = ("Bursts out laughing", "Stops laughing"),
["magnetized"] = ("Becomes magnetized", "Loses the magnetic pull"),
["motivated"] = ("Feels motivated", "Loses motivation"),
["on_guard"] = ("Goes on guard", "Drops guard"),
["poisoned"] = ("Is poisoned", "Purges the poison"),
["possessed"] = ("Is possessed", "Breaks free of possession"),
["possessed_follower"] = ("Falls under a possessed follower's sway", "Escapes the follower's sway"),
["powerup"] = ("Powers up", "Loses the power-up"),
["pregnant"] = ("Becomes pregnant", "Is no longer pregnant"),
["pregnant_parthenogenesis"] = ("Becomes pregnant by parthenogenesis", "Ends the parthenogenic pregnancy"),
["rage"] = ("Enters a rage", "Leaves the rage behind"),
["recovery_combat_action"] = ("Needs a moment after combat", "Is ready for combat again"),
["recovery_plot"] = ("Needs a moment after a plot", "Is ready to plot again"),
["recovery_social"] = ("Needs a moment after socializing", "Is ready to socialize again"),
["recovery_spell"] = ("Needs a moment after casting", "Is ready to cast again"),
["shield"] = ("Raises a shield", "Drops the shield"),
["singing"] = ("Starts singing", "Stops singing"),
["sleeping"] = ("Falls asleep", "Wakes up"),
["slowness"] = ("Is slowed", "Regains normal speed"),
["soul_harvested"] = ("Has their soul harvested", "Recovers from soul harvest"),
["spell_boost"] = ("Gains a spell boost", "Loses the spell boost"),
["spell_silence"] = ("Is silenced", "Can cast again"),
["starving"] = ("Is starving", "Is no longer starving"),
["strange_urge"] = ("Feels a strange urge", "The strange urge passes"),
["stunned"] = ("Is stunned", "Shakes off the stun"),
["surprised"] = ("Is surprised", "Recovers from surprise"),
["swearing"] = ("Starts swearing", "Stops swearing"),
["taking_roots"] = ("Starts taking root", "Pulls free of the roots"),
["tantrum"] = ("Throws a tantrum", "Calms down from the tantrum"),
["uprooting"] = ("Starts uprooting", "Finishes uprooting"),
["voices_in_my_head"] = ("Hears voices", "The voices fall quiet"),
};
public static bool HasAuthored(string statusId)
{
return !string.IsNullOrEmpty(statusId) && Authored.ContainsKey(statusId.Trim());
}
public static IEnumerable AuthoredIds => Authored.Keys;
///
/// Phrase without actor name. Authored when possible; otherwise localized/humanized fallback.
///
public static string Phrase(string statusId, bool gained, out bool authored)
{
authored = false;
string id = (statusId ?? "").Trim();
if (string.IsNullOrEmpty(id))
{
return gained ? "gains an unknown status" : "loses an unknown status";
}
if (Authored.TryGetValue(id, out (string gain, string loss) pair))
{
authored = true;
string phrase = gained ? pair.gain : pair.loss;
return string.IsNullOrEmpty(phrase)
? FallbackPhrase(id, gained)
: phrase;
}
return FallbackPhrase(id, gained);
}
public static string FallbackPhrase(string statusId, bool gained)
{
string title = StatusLabelFromId(statusId);
if (string.IsNullOrEmpty(title))
{
title = HumanizeId(statusId);
}
return gained ? ("Becomes " + title) : ("Is no longer " + title);
}
public static string StatusLabelFromId(string statusId)
{
if (string.IsNullOrEmpty(statusId))
{
return "";
}
try
{
StatusAsset asset = AssetManager.status?.get(statusId.Trim());
if (asset != null)
{
string locale = asset.getLocaleID();
if (!string.IsNullOrEmpty(locale))
{
string localized = LocalizedTextManager.getText(locale);
if (!string.IsNullOrEmpty(localized)
&& !localized.Equals(locale, StringComparison.Ordinal)
&& localized.IndexOf('_') < 0)
{
return localized.Trim().ToLowerInvariant();
}
}
}
}
catch
{
// Localization may be unavailable during early boot.
}
return HumanizeId(statusId);
}
public static string HumanizeId(string statusId)
{
if (string.IsNullOrEmpty(statusId))
{
return "unknown status";
}
return statusId.Replace('_', ' ').Trim().ToLowerInvariant();
}
public static string TaskKey(string statusId, bool gained)
{
string id = string.IsNullOrEmpty(statusId) ? "unknown" : statusId.Trim();
return (gained ? "status_gain:" : "status_loss:") + id;
}
public static bool TryParseTaskKey(string key, out string statusId, out bool gained)
{
statusId = "";
gained = false;
if (string.IsNullOrEmpty(key))
{
return false;
}
string k = key.Trim();
if (k.StartsWith("status_gain:", StringComparison.OrdinalIgnoreCase))
{
gained = true;
statusId = k.Substring("status_gain:".Length).Trim();
return !string.IsNullOrEmpty(statusId);
}
if (k.StartsWith("status_loss:", StringComparison.OrdinalIgnoreCase))
{
gained = false;
statusId = k.Substring("status_loss:".Length).Trim();
return !string.IsNullOrEmpty(statusId);
}
return false;
}
}