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 fury", "Cools off"), ["ash_fever"] = ("Catches ash fever", "Recovers from ash fever"), ["being_suspicious"] = ("Starts acting suspicious", "Stops looking so suspicious"), ["budding"] = ("Begins budding", "Splits off a bud offspring"), ["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"] = ("is drowning", "Gets air again"), ["egg"] = ("Becomes an egg", "Hatches from an 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"] = ("Has a bad dream", "Lets a bad dream fade"), ["had_good_dream"] = ("Has a good dream", "Lets a good dream fade"), ["had_nightmare"] = ("Has a nightmare", "Lets a nightmare fade"), ["handsome_migrant"] = ("Turns heads as a handsome migrant", "Stops drawing migrant attention"), ["inspired"] = ("Feels inspired", "Comes down from 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"] = ("Is converted into a possessed follower", "Breaks free of follower possession"), ["powerup"] = ("Powers up", "Loses the power-up"), ["pregnant"] = ("Becomes pregnant", "Gives birth"), ["pregnant_parthenogenesis"] = ("Becomes pregnant by parthenogenesis", "Gives birth alone"), ["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", "Finishes rooting and sprouts offspring"), ["tantrum"] = ("Throws a tantrum", "Calms down from the tantrum"), ["uprooting"] = ("Emerges as a young plant", "Settles after emerging"), ["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; } }