예제 #1
0
    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);
    }
예제 #2
0
    /// <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);
    }
예제 #3
0
        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);
        }
예제 #4
0
    /// <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);
    }
예제 #5
0
    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();
        }
    }
예제 #6
0
    /// <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;
                        }
                    }
                }
            }
        }
    }
예제 #7
0
    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();
        }
    }
예제 #8
0
 /// <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));
 }
예제 #9
0
 public static void AttackRandom(BattleController battleController, CombatantController source)
 {
     battleController.ExecuteTurnWithAttack(source.BattleID, UnityEngine.Random.Range(0, battleController.GetNumHeroes()));
 }
예제 #10
0
 public static void DoNothing(BattleController battleController, CombatantController source)
 {
     battleController.PassTurn();
 }
예제 #11
0
 override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
 {
     combatant = animator.gameObject.GetComponent <CombatantController>();
 }
예제 #12
0
 void Start()
 {
     _controller = GetComponent <CombatantController>();
 }