using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using TMPro; using UnityEngine; public class ActionTextBox : MonoBehaviour { public enum ActionType { Melee, Ranged, Misses, DamagingSpell, HealingSpell, RefillingSpell, BuffingSpell, DebuffingSpell, Run, DamagingItemOnSingle, DamagingItemOnType, DamagingItemOnAll, HealingItemOnSingle, HealingItemOnType, HealingItemOnAll, RefillingItemOnSingle, RefillingItemOnType, RefillingItemOnAll, BuffingItemOnSingle, BuffingItemOnType, BuffingItemOnAll, DebuffingItemOnSingle, DebuffingItemOnType, DebuffingItemOnAll, SpellFailed, ReviveOne, ReviveAll } [SerializeField] private float timeShown; // How much time the text should be shown on the screen before disappearing private TextMeshProUGUI actionText; // The text container for the actions that are currently being performed private string currentText; // The text to input into the container private readonly float delta = .2f; private float time; private bool textShown; private void Awake() { actionText = GetComponentInChildren<TextMeshProUGUI>(); actionText.text = string.Empty; actionText.enabled = false; timeShown = Mathf.Clamp(timeShown, .5f, float.MaxValue); } private void Update() { if (time > 0.0f) time -= delta * Time.deltaTime; else if (time < 0.0f && actionText.enabled) { actionText.enabled = false; textShown = true; } } public void UpdateActionTextBasic(string activeUser, string target, ActionType action, int damage = 0) { switch (action) { case ActionType.Melee: currentText = $"{activeUser} swings at {target} for {damage}!"; break; case ActionType.Ranged: if (activeUser.Equals("Blizzard")) { if (damage is not 0) currentText = $"{activeUser} freezes {target} for {damage}!"; else currentText = $"{target} did not succumb to the {activeUser}!"; break; } currentText = $"{activeUser} shoots at {target} for {damage}!"; break; case ActionType.Misses: currentText = $"{activeUser} missed {target}!"; break; case ActionType.Run: currentText = $"{activeUser} runs away!"; break; } ActivateText(); } public void UpdateActionTextSpell(string activeUser, string target, ActionType action, Spell spell, int value = 0) { switch (action) { case ActionType.DamagingSpell: if (value <= 0) currentText = $"{activeUser} casted {spell.SpellName} on {target}, but it failed!"; else currentText = $"{activeUser} casted {spell.SpellName} on {target} for {value} {spell.SpellType} damage!"; break; case ActionType.HealingSpell: if (value <= 0) currentText = $"{activeUser} casted {spell.SpellName} on {target}, but it failed!"; else currentText = $"{activeUser} casted {spell.SpellName} on {target} to heal for {value}!"; break; case ActionType.RefillingSpell: if (value <= 0) currentText = $"{activeUser} casted {spell.SpellName} on {target}, but it failed!"; else currentText = $"{activeUser} casted {spell.SpellName} on {target} to refill for {value}!"; break; case ActionType.BuffingSpell: currentText = $"{activeUser} casted {spell.SpellName} to empower {target}!"; break; case ActionType.DebuffingSpell: currentText = $"{activeUser} casted {spell.SpellName} to debilitate {target}!"; break; case ActionType.SpellFailed: currentText = $"{activeUser} atttempted to cast {spell.SpellName} on {target} but failed!"; break; case ActionType.ReviveOne: currentText = $"{activeUser} has revived {target} using {spell.SpellName}!"; break; case ActionType.ReviveAll: currentText = $"{activeUser} has revived all of their allies using {spell.SpellName}!"; break; } ActivateText(); } public void UpdateActionTextItem(string activeUser, Entity entity, Consumable con, ActionType action, int value = 0) { switch (action) { case ActionType.DamagingItemOnSingle: currentText = $"{activeUser} used {con.ItemName} on {entity.GetName()} to damage for {value} points!"; break; case ActionType.DamagingItemOnType: if (entity is Ally) currentText = $"{activeUser} used {con.ItemName} on all allies to damage for {value} points!"; else currentText = $"{activeUser} used {con.ItemName} on all enemies to damage for {value} points!"; break; case ActionType.DamagingItemOnAll: currentText = $"{activeUser} used {con.ItemName} on everyone to damage for {value} points!"; break; case ActionType.HealingItemOnSingle: currentText = $"{activeUser} used {con.ItemName} on {entity.GetName()} to heal for {value} points!"; break; case ActionType.HealingItemOnType: if (entity is Ally) currentText = $"{activeUser} used {con.ItemName} on all allies to heal for {value} points!"; else currentText = $"{activeUser} used {con.ItemName} on all enemies to heal for {value} points!"; break; case ActionType.HealingItemOnAll: currentText = $"{activeUser} used {con.ItemName} on everyone to heal for {value} points!"; break; case ActionType.RefillingItemOnSingle: currentText = $"{activeUser} used {con.ItemName} on {entity.GetName()} to refill for {value} Mana points!"; break; case ActionType.RefillingItemOnType: if (entity is Ally) currentText = $"{activeUser} used {con.ItemName} on all allies to refill for {value} Mana points!"; else currentText = $"{activeUser} used {con.ItemName} on all enemies to refill for {value} Mana points!"; break; case ActionType.RefillingItemOnAll: currentText = $"{activeUser} used {con.ItemName} on everyone to refill for {value} Mana points!"; break; case ActionType.BuffingItemOnSingle: currentText = $"{activeUser} used {con.ItemName} to empower {entity.GetName()}!"; break; case ActionType.BuffingItemOnType: if (entity is Ally) currentText = $"{activeUser} used {con.ItemName} to empower all allies!"; else currentText = $"{activeUser} used {con.ItemName} to empower all enemies!"; break; case ActionType.BuffingItemOnAll: currentText = $"{activeUser} used {con.ItemName} to empower everyone!"; break; case ActionType.DebuffingItemOnSingle: currentText = $"{activeUser} used {con.ItemName} to debilitate {entity.GetName()}!"; break; case ActionType.DebuffingItemOnType: if (entity is Ally) currentText = $"{activeUser} used {con.ItemName} to debilitate all allies!"; else currentText = $"{activeUser} used {con.ItemName} to debilitate all enemies!"; break; case ActionType.DebuffingItemOnAll: currentText = $"{activeUser} used {con.ItemName} to debilitate everyone!"; break; } ActivateText(); } public async Task UpdateActionTextFlee(string activeUser, bool isSuccessful) { await DotText(); if (isSuccessful) currentText = $"{activeUser} was successful in running from battle!"; else currentText = $"{activeUser} was unsuccessful in running away from battle!"; ActivateText(.75f); await Task.CompletedTask; } public void UpdateActionTextUnique(int idFlag, int damage = -1, Entity target = null, Entity attacker = null, object extraInfo = null) { switch (idFlag) { // Blizzard Summoning Flag case 1: currentText = $"A blizzard has begun to rage!"; break; // Golem Successful Summoning Flag case 2: currentText = $"A Golem has been summoned!"; break; // Golem Unsuccessful Summoning Flag case 3: currentText = $"A Golem failed to be summoned!"; break; // Life Contract was successfully made case 4: currentText = $"A pact has been made..."; break; // Order: Rupture has failed case 5: currentText = $"All entities are unaffected by your order..."; break; // Order: Rupture has succeeded case 6: currentText = $"Affected entities writhe in agony, maximum damage inflicted was {damage}!"; break; // Single Target Cure case 7: currentText = $"{target.GetName()} was cured of all status ailments!"; break; // Multi Target Cure case 8: currentText = $"All entities were cured of all status ailments!"; break; // Normal Impalement Damage case 9: currentText = $"The rod digs deeper inside {target.GetName()}... dealing {damage} damage..."; break; // Snow Impalement Damage case 10: currentText = $"The rod grows frigid inside {target.GetName()}... dealing {damage} damage..."; break; // Blizzard Impalement Damage case 11: currentText = $"The rod burns icily inside {target.GetName()}... dealing {damage} damage..."; break; // Rainy Impalement Damage case 12: currentText = $"The rod sparks randomly inside {target.GetName()}... dealing {damage} damage..."; break; // Monsoon Impalement Damage case 13: currentText = $"{target.GetName()} is struck by lightning due to the rod! Dealing {damage} damage..."; break; // Impalement does no damage case 14: currentText = $"{target.GetName()} remains unaffected by the rod."; break; // Failed to accumulate damage from Life Contract case 15: currentText = $"A debt must be repaid... {target.GetName()} suffered {damage} from its failed pact..."; break; // Succeeded to accumulate damage from Life Contract case 16: currentText = $"{target.GetName()} has been inflicted {damage} from a successful contract..."; break; // Entity has been executed case 17: currentText = $"{target.GetName()} has been executed..."; break; // Successful Demon Soldier Summoning case 18: currentText = $"Demonic forces have been summoned!"; break; // Unsuccessful Demon Soldier Summoning case 19: currentText = $"The forces of hell do not heed {attacker.GetName()}'s call..."; break; // Successful Rain transition case 20: currentText = $"Water drips from the heavens..."; break; // Mind Control, not other allies case 21: currentText = $"{attacker.GetName()} is in a daze..."; break; // Sacrificial Rite Failure case 22: currentText = $"The ritual is unable to be performed..."; break; // Sacrificial Rite Success case 23: currentText = $"{attacker.GetName()} split their veins in an offering to dark entities..."; break; // Rampage case 24: currentText = $"{attacker.GetName()} went on a rampage and did {damage} total!"; break; // Engorge Success case 25: currentText = $"{attacker.GetName()} devoured {target.GetName()}..."; break; // Engorge Failure case 26: currentText = $"{target.GetName()} evaded {attacker.GetName()}'s hunger..."; break; // Psionic Overload case 27: currentText = $"{attacker.GetName()} flooded their allies with psychic energy..."; break; // Standoff Preparation case 28: currentText = $"{attacker.GetName()} breathes deeply and places their hand near their holster..."; break; // Standoff Firing! case 29: currentText = $"{target.GetName()} is dealt a suprising blow from {attacker.GetName()} for {damage}!"; break; // Preparing Precise Shot case 30: currentText = $"{attacker.GetName()} breathes deeply..."; break; // Firing Precise Shot case 31: currentText = $"{target.GetName()} was inflicted with a lethal blow for {damage} by {attacker.GetName()}!"; break; // Erratic Bursts case 32: currentText = $"Crackling Energy bursts from {attacker.GetName()}, dealing {damage}!"; break; // Indominatable Roar case 33: currentText = $"A chilling roar from {attacker.GetName()} echoes throughout the battlefield..."; break; // Successful Pillage case 34: currentText = $"YARRR! The bilgerat, {target.GetName()}, was plundered for {damage}! We acquired {((Item)extraInfo).ItemName}!"; break; // Unsuccessful Pillage case 35: currentText = $"Ayyee... the landlubber, {target.GetName()}, evaded your pillaging..."; break; // Afterimage case 36: currentText = $"An afterimage from {attacker.GetName()} deals {damage} more damage to {target.GetName()}!"; break; // Summon Drought case 37: currentText = $"The sun shines brightly over the battlefield..."; break; // Successful Damned Soul summoning case 38: currentText = $"Screams echo from hell as a Damned Soul is summoned to the field..."; break; // Unsuccessful Damned Soul summoning case 39: currentText = $"Screams echo around you in frustration..."; break; // Chain Lightning Initial case 40: currentText = $"Lightning flashes erratically and hits {target.GetName()} for {damage}!"; break; // Chain Lightning Secondary case 41: currentText = $"Lightning arcs to {target.GetName()} for {damage}..."; break; } ActivateText(); } private async Task DotText() { currentText = "."; ActivateText(.5f); await Task.Delay(500); currentText = ". ."; ActivateText(.5f); await Task.Delay(500); currentText = ". . ."; ActivateText(.5f); await Task.Delay(500); await Task.CompletedTask; } private void ActivateText() { actionText.text = currentText; actionText.enabled = true; time = timeShown; textShown = false; } private void ActivateText(float timeToShow) { actionText.text = currentText; actionText.enabled = true; time = timeToShow; textShown = false; } public async Task GetTextShownStatus() { try { while (!textShown && time > -.5f) { if (time < float.Epsilon) time -= Time.deltaTime; await Task.Yield(); } await Task.CompletedTask; } catch (Exception ex) { throw new Exception("Exception was caught", ex); } } /// <summary> /// Signals when a saving throw leads to spell failure /// </summary> /// <param name="spellFailure">The spell that failed</param> public void SignalFailedSpellText(Spell spellFailure) { currentText = $"{spellFailure.SpellName} was used but its effects failed!"; ActivateText(); } }