public static void RandomAbility(BattleController battleController, CombatantController source) { // Use a random strife ability on a random player character AbilityData ability = source.StrifeAbilities[UnityEngine.Random.Range(0, source.StrifeAbilities.Count)]; battleController.ExecuteTurnWithAbilityOnRandomTarget(ability); }
/// <summary> /// Deals damage to a given target combatant based on the stats of a given /// source combatant. /// </summary> /// <param name="source">The attacking combatant.</param> /// <param name="target">The combatant being attacked.</param> private IEnumerator DoAttack(CombatantController source, CombatantController target) { // If these combatants are animating, wait for them to finish while (currentlyAnimatingCombatants.Contains(source.BattleID) || currentlyAnimatingCombatants.Contains(target.BattleID)) { Debug.Log("Waiting for combatants to finish animating!"); yield return(null); } // These combatants are ready to animate, so remove them from the anim // queue combatantsQueuedForAnim.Remove(source.BattleID); combatantsQueuedForAnim.Remove(target.BattleID); // Add the combatant IDs to the list of currently animating ones // so they don't get involved in any future animations throughout this // one currentlyAnimatingCombatants.Add(source.BattleID); currentlyAnimatingCombatants.Add(target.BattleID); Vector3 moveTarget = target.transform.position; if (target.Allegiance == Allegiance.PLAYER) { moveTarget += new Vector3(0.3f, 0f); } else { moveTarget += new Vector3(-0.3f, 0f); } Vector3 startPos = source.transform.position; // Move the combatant to "attack range" of its target yield return(MoveCombatantToPos(source, moveTarget, 0.5f)); source.SetAnimBool("attacking", true); yield return(new WaitForSeconds(source.GetAnimDuration("attacking"))); // Simply use the attack ability DoAbility(attackAbility, source, new List <CombatantController>() { target }); source.SetAnimBool("attacking", false); yield return(MoveCombatantToPos(source, startPos, 0.5f)); // These combatants are no longer animating, so remove them from the // list so they can be involved in future animations currentlyAnimatingCombatants.Remove(source.BattleID); currentlyAnimatingCombatants.Remove(target.BattleID); }
protected override void Awake() { base.Awake(); _sprite = GetComponent <tk2dSprite>(); _controller = GetComponent <CombatantController>(); _animator = GetComponent <CombatantAnimator>(); StrangeUtils.Bubble(_animator.DeathSignal, DeathSignal); StrangeUtils.Bubble(_animator.AttackCompleteSignal, AttackCompleteSignal); StrangeUtils.Bubble(_animator.DodgeCompleteSignal, DodgeCompleteSignal); }
/// <summary> /// Smoothly moves a combatant's sprite to the given location in world space /// over the given duration. /// </summary> /// <param name="source">The combatant moving.</param> /// <param name="target">The location being moved to.</param> /// <param name="duration">How long the combatant should be in motion for</param> /// <returns></returns> private IEnumerator MoveCombatantToPos(CombatantController source, Vector3 target, float duration) { source.SetAnimBool("moving", true); Vector3 startPos = source.transform.position; float dt = 0f; while (dt < duration) { dt += Time.smoothDeltaTime; source.transform.position = Vector3.Lerp(startPos, target, dt / duration); yield return(null); } source.transform.position = target; source.SetAnimBool("moving", false); }
private void KillCombatant(CombatantController target) { // Set their animation target.SetAnimBool("dead", true); // If all enemies or heroes are dead, end the battle int numDeadHeroes = 0; int numDeadEnemies = 0; for (int i = 0; i < GetNumHeroes(); ++i) { if (Combatants[i].HP <= 0) { numDeadHeroes++; } } for (int i = GetNumHeroes(); i < GetNumCombatants(); ++i) { if (Combatants[i].HP <= 0) { numDeadEnemies++; } } // Check if the battle is over if (numDeadHeroes == GetNumHeroes()) { State = BattleState.ENEMYWON; EndBattle(); } else if (numDeadEnemies == GetNumEnemies()) { State = BattleState.PLAYERWON; EndBattle(); } else { // Refresh turn order RefreshTurnOrder(); turnController.ForceRefreshTurnOrder(); } }
/// <summary> /// Executes an ability from a given combatant to the given target combatants. /// </summary> /// <param name="ability">The Ability object being executed</param> /// <param name="source">The combatant using the ability.</param> /// <param name="targets">A list of combatants being targeted by the ability.</param> private void DoAbility(AbilityData ability, CombatantController source, List <CombatantController> targets) { // Start the ability's animation Debug.Log("TODO: Ability animations!"); // Apply the ability to each target combatant foreach (CombatantController target in targets) { // Apply any effects the ability has on the target foreach (EffectData effect in ability.effects) { target.ApplyEffect(effect, source); // Generate any floating combat text if required floatingTextController.PlayTextForEffect(effect, GetCombatantTransform(target.BattleID)); } // If the target combatant died, set their animation state if (target.HP <= 0) { KillCombatant(target); } else { // Apply any auras the ability has on the target foreach (AuraData aura in ability.auras) { target.AddAura(aura, source); } } // Modify the caster's resource values if (source.Allegiance == Allegiance.PLAYER) { HeroController heroSource = (HeroController)source; if (heroSource.IsProtag) { // Jack's Calm and Strife generation are not mutually exclusive heroSource.Calm += ability.calmGen; heroSource.Strife += ability.strifeGen; } else { // Abilities which generate Calm and Strife exist, but should // not be usable by anyone other than the protagonist if (ability.calmGen != 0 && ability.strifeGen != 0) { Debug.LogError("Abilities which generate Calm and Strife should not be usable by non-protagonist!"); Debug.Break(); } // Non-protagonists lose one resource when they gain another if (ability.calmGen > 0) { if (heroSource.Strife > 0) { heroSource.Strife -= ability.calmGen; } else { heroSource.Calm += ability.calmGen; } } else if (ability.strifeGen > 0) { if (heroSource.Calm > 0) { heroSource.Calm -= ability.strifeGen; } else { heroSource.Strife += ability.strifeGen; } } } } } }
public void ApplyEffect(EffectData effect, CombatantController source) { if (effect.IsEmpty()) { Debug.Log("Empty effect - skipping"); return; } Debug.Log("Applying effect " + effect.name + " to combatant " + Name + "[" + BattleID + "]"); string statStr = effect.stat.ToLowerInvariant(); if (statStr == "hp") { // Calculate the magnitude of this effect int magnitude = effect.amount; // Scale it with strength if (magnitude > 0) { magnitude = (int)(magnitude + (source.Strength * effect.strengthScaling)); } else if (magnitude < 0) { magnitude = (int)(magnitude - (source.Strength * effect.strengthScaling)); } // Calculate if it crit or not if (effect.canCrit) { // Crit chance is a 3% base plus an amount based on agility float critChance = BASE_CRIT_CHANCE + (CRIT_AGIL_SCALING * source.Agility); critChance /= 100.0f; // Roll and see if this effect is critting if (Random.value >= 1.0f - critChance) { Debug.Log(source.Name + "'s " + effect.name + " effect crit!"); magnitude *= 2; } } // Apply the effect HP = Mathf.Max(HP + magnitude, 0); if (magnitude <= 0) { Debug.Log(Name + "[" + BattleID + "] took " + (-magnitude) + " damage from " + effect.name); } else { Debug.Log(Name + "[" + BattleID + "] was healed by " + magnitude + " from " + effect.name); } Debug.Log("It now has HP " + HP + "/" + MaxHP); } else if (statStr == "agility") { int magnitude = effect.amount; // Calculate if it crit or not if (effect.canCrit) { // Crit chance is a 3% base plus an amount based on agility float critChance = BASE_CRIT_CHANCE + (CRIT_AGIL_SCALING * source.Agility); critChance /= 100.0f; // Roll and see if this effect is critting if (Random.value >= 1.0f - critChance) { Debug.Log(source.Name + "'s " + effect.name + " effect crit!"); magnitude *= 2; } } // Cannot have less than 1 agility Agility = Mathf.Max(Agility + magnitude, 1); // Since agility has changed, turn order may have too battleController.RefreshTurnOrder(); } else { Debug.Log("Unsupported effect type received!"); Debug.Break(); } }
/// <summary> /// Adds an aura to this combatant's list of currently active auras. /// </summary> /// <param name="aura">The Aura object being added to this combatant's aura list.</param> /// <param name="caster">The CombatantController object applying the aura.</param> public void AddAura(AuraData aura, CombatantController caster) { Debug.Log("Adding aura " + aura.name + " to combatant " + Name + "[" + BattleID + "]"); ActiveAuraCasterPairs.Add(new KeyValuePair <CombatantController, AuraData>(caster, aura)); }
public static void AttackRandom(BattleController battleController, CombatantController source) { battleController.ExecuteTurnWithAttack(source.BattleID, UnityEngine.Random.Range(0, battleController.GetNumHeroes())); }
public static void DoNothing(BattleController battleController, CombatantController source) { battleController.PassTurn(); }
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { combatant = animator.gameObject.GetComponent <CombatantController>(); }
void Start() { _controller = GetComponent <CombatantController>(); }