Beispiel #1
0
 void OnEntityDeath(HealthEntityCombatObject entity)
 {
     if (entity is PlayerCombatObject)
     {
         bool allPlayersDead = true;
         foreach (var player in players)
         {
             if (!player.IsDead)
             {
                 allPlayersDead = false;
                 break;
             }
         }
         if (allPlayersDead)
         {
             FindObjectOfType <AudioManager>().PlayClip(DefeatSound);
             StopCoroutine(EnemyTurnCoroutine);
             combatOver = true;
             StartCoroutine(EndBattleCoroutine(true));
         }
     }
     else if (entity is EnemyCombatObject)
     {
         OnEnemyDeath(entity);
     }
 }
Beispiel #2
0
    /// <summary>
    /// Get all entities in combat with the relationship as alignment to the reference entity.
    /// </summary>
    /// <param name="entity">The reference entity</param>
    /// <param name="alignment">Relationship with the required entity</param>
    /// <param name="targetSelf">Can target itself?</param>
    /// <param name="canTargetUntargetable">Can target untargetable targets?</param>
    /// <returns></returns>
    List <HealthEntityCombatObject> GetEntitiesWithRelationTo(HealthEntityCombatObject entity, TargetingData_Base.TargetAlignment alignment, bool targetSelf = false, bool canTargetUntargetable = false, bool canTargetDead = false)
    {
        List <HealthEntityCombatObject> entities = new List <HealthEntityCombatObject>();

        foreach (var e in AllEntities)
        {
            switch (alignment)
            {
            case TargetingData_Base.TargetAlignment.Both:
                if (ValidTarget(entity, canTargetUntargetable, canTargetDead))
                {
                    entities.Add(e);
                }
                break;

            default:
                if (e.GetFaction(alignment) == entity.alignment && (targetSelf && e == entity || e != entity) && ValidTarget(entity, canTargetUntargetable, canTargetDead))
                {
                    entities.Add(e);
                }
                break;
            }
        }

        return(entities);
    }
Beispiel #3
0
    /// <summary>
    /// Takes 2 parameters: List<HealthEntityCombatObject> targets, HealthEntityCombatObject attacker.
    /// </summary>
    /// <param name="parameters"></param>
    /// <returns></returns>
    public override OnPlayResult OnPlay(params object[] parameters)
    {
        List <HealthEntityCombatObject> targets  = parameters[0] as List <HealthEntityCombatObject>;
        HealthEntityCombatObject        attacker = parameters[1] as HealthEntityCombatObject;

        OnPlayResult onPlayResult = new OnPlayResult();

        foreach (var t in targets)
        {
            HealthEntityCombatObject.DamageInfo damageInfo = t.TakeDamage(Instantiate <AbilityStep_Damage>(this), attacker);
            onPlayResult.unshieldedDamage = damageInfo.damageDealt;
        }

        foreach (var t in targets)
        {
            GameObject particlePrefab = particleEffectPrefab;
            if (particleEffectPrefab == null)
            {
                particlePrefab = FindObjectOfType <CombatManager>().particlePrefab;
            }
            GameObject go = Instantiate(particlePrefab, t.transform);
            go.GetComponent <ParticlesEffect>().Init(0);
        }

        return(onPlayResult);
    }
    public override void OnAttacked(params object[] parameters)
    {
        HealthEntityCombatObject attacker = parameters[0] as HealthEntityCombatObject;

        AbilityStep_Damage dam = new AbilityStep_Damage();

        dam.amount         = amount;
        dam.damageType     = AbilityStep_Damage.DamageType.True;
        dam.damageTypePerc = AbilityStep_Damage.DamageTypePerc.Flat;
        attacker.TakeDamage(dam, null);
    }
    public override void TickPerTurn(params object[] parameters)
    {
        HealthEntityCombatObject target = parameters[0] as HealthEntityCombatObject;

        switch (type)
        {
        case AbilityStep_Restore.Type.Mana:
            ((PlayerCombatObject)target).ModifyMana(amount);
            break;
        }
    }
    public override void TickPerTurn(params object[] parameters)
    {
        HealthEntityCombatObject target = parameters[0] as HealthEntityCombatObject;

        AbilityStep_Damage dam = CreateInstance <AbilityStep_Damage>();

        dam.amount         = amount;
        dam.damageType     = AbilityStep_Damage.DamageType.True;
        dam.damageTypePerc = AbilityStep_Damage.DamageTypePerc.Flat;
        target.TakeDamage(dam, null);
    }
Beispiel #7
0
    public void SelectTarget(HealthEntityCombatObject entity)
    {
        // Break if there is no selected card.
        if (currentSelectedCard == null)
        {
            return;
        }

        //HideTargettingButtons();
        chosenTargets.Add(entity);
        targetFound = true;
    }
Beispiel #8
0
 public void AddTarget(HealthEntityCombatObject entity, System.Action HideTargetingButtonsCallback)
 {
     chosenTargets.Add(entity);
     if (!multipleSpecificMode)
     {
         targetFound = true;
         HideTargetingButtonsCallback();
     }
     else
     {
         multipleSpecificModeList.Add(entity);
         if (multipleSpecificModeList.Count == numberOfSpecificTargets)
         {
             targetFound = true;
             HideTargetingButtonsCallback();
         }
     }
 }
Beispiel #9
0
    void OnEnemyDeath(HealthEntityCombatObject entity)
    {
        EnemyCombatObject enemy = entity as EnemyCombatObject;

        FindObjectOfType <AudioManager>().PlayRandomClip(enemy.deathSounds);

        enemies.Remove(enemy);
        int i = 0;

        foreach (var e in enemies)
        {
            e.enemyIndex = i;
            i++;
        }
        if (enemies.Count == 0)
        {
            FindObjectOfType <AudioManager>().PlayClip(VictorySound);
            combatOver = true;
            StartCoroutine(EndBattleCoroutine(false));
        }
    }
Beispiel #10
0
    /// <summary>
    /// Figure out if the entity is a valid target regarding some arguments.
    /// </summary>
    /// <param name="entity">Referenced entity</param>
    /// <param name="canTargetUntargetable">Bypass the untargetable restriction</param>
    /// <param name="canTargetDead">Bypass the dead restriction</param>
    /// <returns></returns>
    bool ValidTarget(HealthEntityCombatObject entity, bool canTargetUntargetable, bool canTargetDead)
    {
        // If dead
        if (entity.IsDead && canTargetDead)
        {
            return(true);
        }
        // If NOT dead
        else if (!entity.IsDead)
        {
            if (canTargetUntargetable)
            {
                return(true);
            }
            else if (entity.IsTargetable())
            {
                return(true);
            }
        }

        return(false);
    }
Beispiel #11
0
    List <List <HealthEntityCombatObject> > SelectAbilityTargetEnemy(EnemyCombatObject enemy)
    {
        List <List <HealthEntityCombatObject> > targetsPerAbilityStep = new List <List <HealthEntityCombatObject> >();

        AbilityStepsWithTargetingData_Enemy[] abilityStepsWithTargetingData = enemy.NextAbility.abilityStepsWithTargetingData;

        // Let's cycle through all ability steps in order to determine targets.
        foreach (var abilityStepWithTargetingData in abilityStepsWithTargetingData)
        {
            List <HealthEntityCombatObject> selectedTargets = new List <HealthEntityCombatObject>();

            TargetData targetData = GetValidTargets(enemy, abilityStepWithTargetingData.targetingData);

            if (targetData.previousStepTargets > -1)
            {
                foreach (var entity in targetsPerAbilityStep[targetData.previousStepTargets])
                {
                    selectedTargets.Add(entity);
                }
            }
            else if (targetData.targetDecided)
            {
                foreach (var e in targetData.entities)
                {
                    selectedTargets.Add(e);
                }
            }
            else
            {
                switch (abilityStepWithTargetingData.targetingData.targets)
                {
                case TargetingData_Base.Target.One:
                    // Choose a random target for now
                    selectedTargets.Add(targetData.entities[Random.Range(0, targetData.entities.Count)]);
                    break;

                case TargetingData_Base.Target.Multiple:
                    // Choose a random target for now
                    selectedTargets.Add(targetData.entities[Random.Range(0, targetData.entities.Count)]);
                    break;

                case TargetingData_Base.Target.MultipleSpecific:
                    // Choose a random target for now

                    // If it happens that there are less available targets than our ability wants us to target,
                    // add them all.
                    if (abilityStepWithTargetingData.targetingData.numberOfTargets < targetData.entities.Count)
                    {
                        foreach (var entity in targetData.entities)
                        {
                            selectedTargets.Add(entity);
                        }
                    }
                    else
                    {
                        List <HealthEntityCombatObject> st = new List <HealthEntityCombatObject>(selectedTargets);
                        for (int i = 0; i < abilityStepWithTargetingData.targetingData.numberOfTargets; i++)
                        {
                            HealthEntityCombatObject entity = targetData.entities[Random.Range(0, targetData.entities.Count)];
                            selectedTargets.Add(entity);
                            st.Remove(entity);
                        }
                    }
                    break;
                }
            }

            targetsPerAbilityStep.Add(selectedTargets);
        }

        // We have all chosen targets.
        // We now have to check whether any of those are multiple hits.
        for (int i = 0; i < targetsPerAbilityStep.Count; i++)
        {
            TargetingData_Base targetingData = enemy.NextAbility.abilityStepsWithTargetingData[i].targetingData;

            if (targetingData.targetAlignment == TargetingData_Base.TargetAlignment.Friendly)
            {
                if (targetingData.targets == TargetingData_Base.Target.Multiple)
                {
                    EnemyCombatObject        chosenTarget  = (EnemyCombatObject)targetsPerAbilityStep[i][0];
                    List <EnemyCombatObject> nearbyEnemies = GetNearbyEnemies(chosenTarget, targetingData.numberOfTargets);
                    foreach (var e in nearbyEnemies)
                    {
                        targetsPerAbilityStep[i].Add(e);
                    }
                }
            }
        }

        return(targetsPerAbilityStep);
    }
Beispiel #12
0
    public override void OnUnafflicted(params object[] parameters)
    {
        HealthEntityCombatObject afflictee = parameters[0] as HealthEntityCombatObject;

        afflictee.Stats.UnmodifyStat(stat, amount);
    }
Beispiel #13
0
 public void ButtonInput_SelectTarget(HealthEntityCombatObject entity)
 {
     battleManager.AddTarget(entity, HideAllTargettingButtons);
 }
Beispiel #14
0
    IEnumerator SelectTargets_Power(NativePowerScriptableObject nativePower)
    {
        PlayerCombatObject       playerOnTurn = currentCardOwner;
        HealthEntityCombatObject caster       = playerOnTurn;

        stepNumber = 0;

        targetsPerAbilityStep = new List <List <HealthEntityCombatObject> >();

        AbilityStepsWithTargetingData_Player[] abilities = nativePower.abilityStepsWithTargetingData;

        // Let's cycle through all ability steps in order to determine targets.
        foreach (var abilityStepWithTargetingData in abilities)
        {
            chosenTargets = new List <HealthEntityCombatObject>();
            targetFound   = false;

            TargetData targetData = GetValidTargets(caster, abilityStepWithTargetingData.targetingData);
            if (targetData.multipleSpecificMode)
            {
                multipleSpecificMode     = true;
                numberOfSpecificTargets  = targetData.multipleSpecificNumber;
                multipleSpecificModeList = new List <HealthEntityCombatObject>();
            }
            else
            {
                multipleSpecificMode = false;
            }

            if (targetData.previousStepTargets > -1)
            {
                targetFound = true;
                foreach (var entity in targetsPerAbilityStep[targetData.previousStepTargets])
                {
                    chosenTargets.Add(entity);
                }
            }
            else if (targetData.targetDecided)
            {
                targetFound = true;
                foreach (var e in targetData.entities)
                {
                    chosenTargets.Add(e);
                }
            }
            else
            {
                if (targetData.entities.Count == 1 && targetData.entities[0] is PlayerCombatObject)
                {
                    targetFound = true;
                    chosenTargets.Add(targetData.entities[0]);
                }
                else
                {
                    infoText.text = abilityStepWithTargetingData.targetingData.textForChoosing;
                    ShowTargetingButton(targetData.entities);
                }
            }

            while (targetFound == false)
            {
                yield return(null);
            }

            stepNumber++;
            targetsPerAbilityStep.Add(chosenTargets);
        }

        // We have all chosen targets.
        // We now have to check whether any of those are multiple hits.

        for (int i = 0; i < targetsPerAbilityStep.Count; i++)
        {
            TargetingData_Base targetingData = nativePower.abilityStepsWithTargetingData[i].targetingData;

            if (targetingData.targetAlignment == TargetingData_Base.TargetAlignment.Hostile)
            {
                if (targetingData.targets == TargetingData_Base.Target.Multiple)
                {
                    EnemyCombatObject        chosenTarget  = (EnemyCombatObject)targetsPerAbilityStep[i][0];
                    List <EnemyCombatObject> nearbyEnemies = GetNearbyEnemies(chosenTarget, targetingData.numberOfTargets);
                    foreach (var e in nearbyEnemies)
                    {
                        targetsPerAbilityStep[i].Add(e);
                    }
                }
            }
        }

        // Now we have full lists of all targets for each attribute.
        // Let's do the card trick.

        DoPowerTrick();

        yield return(null);
    }
    public DamageInfo TakeDamage(AbilityStep_Damage stepInfo, HealthEntityCombatObject attacker)
    {
        var result = DamageCalculator.CaclulateFlatDamage(stepInfo, attacker, this);

        /*
         * if (IsDead)
         * {
         *      return default(DamageInfo);
         * }
         *
         * if (IsImmuneToDamage())
         * {
         *      Animator.SetTrigger("Block");
         *      DamageNumberCanvas canv = GameObject.Instantiate(FindObjectOfType<CombatManager>().damageNumberCanvasPrefab).GetComponent<DamageNumberCanvas>();
         *      canv.Display("Immune", Color.magenta);
         *      canv.transform.position = transform.position;
         *      return default(DamageInfo);
         * }
         */
        DamageInfo damageInfo = new DamageInfo();        /*
                                                          *
                                                          * int amount = stepInfo.amount;
                                                          * amount = Mathf.Max(0, amount);
                                                          * if (attacker != null)
                                                          * {
                                                          * amount = (int)(amount * attacker.Stats.rawDamageMultiplier.Value);
                                                          * }
                                                          *
                                                          * float random = Random.Range(0f, 1f);
                                                          * float attackerCritChance = attacker.Stats.criticalChance.Value;
                                                          *
                                                          * foreach (var statusEffect in StatusEffects)
                                                          * {
                                                          * foreach (var behaviour in statusEffect.behaviour)
                                                          * {
                                                          * if (behaviour is WeakenBehaviour weaken)
                                                          * {
                                                          * attackerCritChance *= weaken.modifyCritChanceAgainst;
                                                          * }
                                                          * }
                                                          * }
                                                          *
                                                          * bool crit = false;
                                                          * if (attacker != null && random < attackerCritChance && stepInfo.canCriticallyStrike)
                                                          * {
                                                          * crit = true;
                                                          * amount *= 2;
                                                          * }
                                                          *
                                                          * switch (stepInfo.damageTypePerc)
                                                          * {
                                                          * case AbilityStep_Damage.DamageTypePerc.PercentageMaxHP:
                                                          * amount = (int)(MaxHealth * (amount / 100f));
                                                          * break;
                                                          * case AbilityStep_Damage.DamageTypePerc.None:
                                                          * amount = 0;
                                                          * break;
                                                          * }
                                                          *
                                                          * switch (stepInfo.damageType)
                                                          * {
                                                          * case AbilityStep_Damage.DamageType.Physical:
                                                          * amount = (int)Mathf.Ceil(amount * (1 - Mathf.Clamp01(Stats.armor.Value - ((attacker != null) ? attacker.Stats.armorPenetration.Value : 0))));
                                                          * break;
                                                          * case AbilityStep_Damage.DamageType.Magic:
                                                          * amount = (int)Mathf.Ceil(amount * (1 - Mathf.Clamp01(Stats.magicResist.Value - ((attacker != null) ? attacker.Stats.magicPenetration.Value : 0))));
                                                          * break;
                                                          * case AbilityStep_Damage.DamageType.None:
                                                          * amount = 0;
                                                          * break;
                                                          * }*/

        //int amountRemaining = amount;

        switch (result.name)
        {
        case DamageCalculator.ClashResult.Name.Failed:
            return(default);

        case DamageCalculator.ClashResult.Name.Immune:
            Animator.SetTrigger("Block");
            DamageNumberCanvas canv = GameObject.Instantiate(FindObjectOfType <CombatManager>().damageNumberCanvasPrefab).GetComponent <DamageNumberCanvas>();
            canv.Display("Immune", Color.magenta);
            canv.transform.position = transform.position;
            return(default);
        }

        ReduceBlock(ref result.damage);

        /*
         * amountRemaining -= Block;
         * ModifyBlock(-amount);
         *
         * amountRemaining = Mathf.Clamp(amountRemaining, 0, amountRemaining);*/

        if (result.damage > 0)
        {
            damageInfo.damageDealt = result.damage;

            DamageNumberCanvas canv = GameObject.Instantiate(FindObjectOfType <CombatManager>().damageNumberCanvasPrefab).GetComponent <DamageNumberCanvas>();
            if (result.criticalHit)
            {
                canv.Display("CRIT! " + damageInfo.damageDealt.ToString(), Color.red);
            }
            else
            {
                canv.Display(damageInfo.damageDealt.ToString(), Color.red);
            }
            canv.transform.position = transform.position;

            Entity.Health -= damageInfo.damageDealt;
            Entity.Health  = Mathf.Clamp(Health, 0, MaxHealth);

            if (Entity.Health > 0)
            {
                Animator.SetTrigger("Hit");
            }
        }
        else
        {
            Animator.SetTrigger("Block");
            DamageNumberCanvas canv = GameObject.Instantiate(FindObjectOfType <CombatManager>().damageNumberCanvasPrefab).GetComponent <DamageNumberCanvas>();
            canv.Display("Blocked", Color.grey);
            canv.transform.position = transform.position;
        }

        if (attacker != null)
        {
            if (OnAttackedBehaviour != null)
            {
                OnAttackedBehaviour(attacker);
            }
        }

        if (Health <= 0)
        {
            Die();
            OnDeath(this);
        }

        RefreshUI();

        return(damageInfo);
    }
Beispiel #16
0
    TargetData GetValidTargets(HealthEntityCombatObject caster, TargetingData_Base targetingData)
    {
        TargetData targetData = new TargetData();

        targetData.previousStepTargets = -1;
        List <HealthEntityCombatObject> targets = new List <HealthEntityCombatObject>();

        if (targetingData.targetingType == TargetingData_Base.TargetingType.NoTargeting)
        {
            // There is no targeting. Don't bother.
        }
        // We will use other step's targets.
        else if (targetingData.targetingType == TargetingData_Base.TargetingType.PreviousStep)
        {
            targetData.previousStepTargets = targetingData.useTargetsFromStepNumber;
        }
        // If the target is only self, do not check for anything else.
        else if (targetingData.onlySelf)
        {
            targets.Add(caster);
            targetData.targetDecided = true;
        }
        else
        {
            // Can we add self?
            bool selfIncluded = targetingData.selfIncluded;

            // Let's skip the check if we can only target ourselves.
            if (targetingData.onlySelf)
            {
                targets.Add(caster);
            }
            // We can target more than ourselves. Let's first check if we can target at all.
            else if (targetingData.targets != TargetingData_Base.Target.All)
            {
                switch (targetingData.targetAlignment)
                {
                case TargetingData_Base.TargetAlignment.Both:
                    switch (targetingData.targets)
                    {
                    case TargetingData_Base.Target.One:
                        // Select one from friendlies and from enemies.
                        foreach (var f in GetEntitiesWithRelationTo(caster, TargetingData_Base.TargetAlignment.Both, selfIncluded))
                        {
                            targets.Add(f);
                        }
                        break;

                    case TargetingData_Base.Target.MultipleSpecific:
                        // Select multiple specific from friendlies or enemies.

                        // Add ourselves to the list.
                        if (targetingData.selfIncluded)
                        {
                        }
                        break;
                    }
                    break;

                case TargetingData_Base.TargetAlignment.Friendly:
                    switch (targetingData.targets)
                    {
                    case TargetingData_Base.Target.One:
                        // Select one from friendlies taking into account whether to add self.
                        foreach (var f in GetEntitiesWithRelationTo(caster, TargetingData_Base.TargetAlignment.Friendly, selfIncluded))
                        {
                            targets.Add(f);
                        }
                        break;

                    case TargetingData_Base.Target.MultipleSpecific:
                        // Select multiple specific friendlies taking into account whether to add self.
                        break;

                    case TargetingData_Base.Target.Multiple:
                        // Select multiple friendlies taking into account whether to add self.
                        foreach (var f in GetEntitiesWithRelationTo(caster, TargetingData_Base.TargetAlignment.Friendly, selfIncluded))
                        {
                            targets.Add(f);
                        }
                        break;
                    }
                    break;

                case TargetingData_Base.TargetAlignment.Hostile:
                    switch (targetingData.targets)
                    {
                    case TargetingData_Base.Target.One:
                        // Select one from enemies.
                        foreach (var e in GetEntitiesWithRelationTo(caster, TargetingData_Base.TargetAlignment.Hostile))
                        {
                            targets.Add(e);
                        }
                        break;

                    case TargetingData_Base.Target.MultipleSpecific:
                        // Select multiple specific from enemies.
                        targetData.multipleSpecificMode   = true;
                        targetData.multipleSpecificNumber = targetingData.numberOfTargets;
                        foreach (var e in GetEntitiesWithRelationTo(caster, TargetingData_Base.TargetAlignment.Hostile))
                        {
                            targets.Add(e);
                        }
                        break;

                    case TargetingData_Base.Target.Multiple:
                        // Select multiple from enemies.
                        foreach (var e in GetEntitiesWithRelationTo(caster, TargetingData_Base.TargetAlignment.Hostile))
                        {
                            targets.Add(e);
                        }
                        break;
                    }
                    break;
                }
            }
            // We cannot target so we choose all.
            else
            {
                switch (targetingData.targetAlignment)
                {
                case TargetingData_Base.TargetAlignment.Both:
                    // Select all targets.
                    foreach (var a in GetEntitiesWithRelationTo(caster, TargetingData_Base.TargetAlignment.Both, selfIncluded))
                    {
                        targets.Add(a);
                    }
                    break;

                case TargetingData_Base.TargetAlignment.Friendly:
                    // Select all allies taking into account if self included
                    foreach (var a in GetEntitiesWithRelationTo(caster, TargetingData_Base.TargetAlignment.Friendly, selfIncluded, false, targetingData.canTargetDead))
                    {
                        targets.Add(a);
                    }
                    break;

                case TargetingData_Base.TargetAlignment.Hostile:
                    // Select all enemies.
                    foreach (var e in GetEntitiesWithRelationTo(caster, TargetingData_Base.TargetAlignment.Hostile))
                    {
                        targets.Add(e);
                    }
                    break;
                }
                targetData.targetDecided = true;
            }
        }

        targetData.entities = targets;

        return(targetData);
    }
Beispiel #17
0
    void Update()
    {
        // Calculate zoom.
        cameraController.targetZoom = Input.mouseScrollDelta.y;

        foreach (var enemy in battleManager.enemies)
        {
            enemy.ClickableTile.Refresh();
        }
        foreach (var player in battleManager.players)
        {
            player.ClickableTile.Refresh();
        }

        // Mouse cursor is over UI AND is not in any state.
        if (eventSystem.IsPointerOverGameObject() && mouseState == MouseState.Free)
        {
            // Let's get all the info on what is under the mouse.
            PointerEventData pointer = new PointerEventData(eventSystem);
            pointer.position = Input.mousePosition;
            List <RaycastResult> raycastResults = new List <RaycastResult>();

            // All results are stored in the raycastResults list.
            // Let's see if we need any of those.
            eventSystem.RaycastAll(pointer, raycastResults);

            // We need to see if we are over player hand.
            List <PlayerHand> playerHand = LookForPlayerHand(raycastResults);

            // If there is only one player hand under the cursor,
            // we can go ahead and tell the hand to update itself.
            if (playerHand.Count == 1)
            {
                currentHand = playerHand[0];

                if (currentHand != null)
                {
                    List <CardInHand> cardsUnderMouse = currentHand.GetAllCards(raycastResults);

                    CardInHand selectedCard;

                    currentHand.UpdateXD(cardsUnderMouse, out selectedCard);

                    if (selectedCard != null)
                    {
                        DisplayCard(true, selectedCard);
                    }
                }
            }
            // There are more hands under cursor OR there aren't any.
            else
            {
                UnhoverOverCard();
            }

            // If the mouse is over GUI, break out.
            foreach (var rr in raycastResults)
            {
                if (rr.gameObject.transform.root == GUI)
                {
                    return;
                }
            }
        }
        // Cursor is not in the UI OR is in another state.
        else if (!eventSystem.IsPointerOverGameObject() && mouseState == MouseState.Free)
        {
            UnhoverOverCard();

            Ray        ray = cameraController.camera.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            int        layerMask = 1 << (int)Layer.Clickable;

            foreach (var enemy in battleManager.enemies)
            {
                enemy.clickableTileClickable = true;

                /*
                 * if (battleManager.multipleSpecificMode)
                 * {
                 *      foreach (var entity in battleManager.multipleSpecificModeList)
                 *      {
                 *              ((EnemyCombatObject)entity).clickableTileClickable = false;
                 *              entity.ClickableTile.Selected = true;
                 *              ((EnemyCombatObject)entity).ClickableTile.GetComponent<Renderer>().material.color = Color.cyan;
                 *      }
                 * }
                 */
            }

            if (Physics.Raycast(ray, out hit, 100f, layerMask, QueryTriggerInteraction.Collide))
            {
                HealthEntityCombatObject entityHit = hit.transform.gameObject.GetComponentInParent <HealthEntityCombatObject>();

                if (entityHit != null)
                {
                    if (entityHit is PlayerCombatObject)
                    {
                        entityHit.ClickableTile.MouseOver(true);
                    }
                    if (entityHit is EnemyCombatObject)
                    {
                        if (battleManager.currentSelectedCard.card.abilityStepsWithTargetingData[battleManager.stepNumber].targetingData.targets == TargetingData_Base.Target.Multiple)
                        {
                            foreach (var enemy in battleManager.GetNearbyEnemies(((EnemyCombatObject)entityHit), battleManager.currentSelectedCard.card.abilityStepsWithTargetingData[battleManager.stepNumber].targetingData.numberOfTargets))
                            {
                                enemy.ClickableTile.MouseOver(true);
                            }
                        }
                        else if (battleManager.multipleSpecificMode)
                        {
                            foreach (var entity in battleManager.multipleSpecificModeList)
                            {
                                ((EnemyCombatObject)entity).ClickableTile.GetComponent <Renderer>().material.color = Color.cyan;
                            }
                        }
                        entityHit.ClickableTile.MouseOver(true);
                    }

                    if (Input.GetMouseButtonDown(0))
                    {
                        if (entityHit is EnemyCombatObject)
                        {
                            if (((EnemyCombatObject)entityHit).clickableTileClickable)
                            {
                                ButtonInput_SelectTarget(entityHit);
                            }
                        }
                        else
                        {
                            ButtonInput_SelectTarget(entityHit);
                        }
                    }
                }
            }
        }

        HandleCameraTransform();
    }
    public static ClashResult CaclulateFlatDamage(AbilityStep_Damage step, HealthEntityCombatObject attacker, HealthEntityCombatObject defender)
    {
        ClashResult result = new ClashResult();

        // If defender is dead, result fails.
        if (step == null || defender == null || defender.IsDead)
        {
            result.name = ClashResult.Name.Failed;
            return(result);
        }

        // If defender is immune to damage, result immune.
        if (defender.IsImmuneToDamage())
        {
            result.name = ClashResult.Name.Immune;
            return(result);
        }

        // Grab the damage amount.
        result.damage = step.amount;

        if (attacker != null)
        {
            // Multiply with raw damage of the attacker.
            result.damage = (int)(result.damage * attacker.Stats.rawDamageMultiplier.Value);

            // Check for vulnerable
            if (defender.IsVulnerable())
            {
                result.damage = (int)(result.damage * 1.5f);
            }

            // Crit calculator.
            if (step.canCriticallyStrike)
            {
                float attackerCritChance = attacker.Stats.criticalChance.Value;

                // Get negative crit multiplier on target.
                foreach (var behaviour in defender.GetCritMultiplierBehaviours())
                {
                    attackerCritChance *= behaviour.modifyCritChanceAgainst;
                }

                // Roll the crit and double the damage.
                float critValue = Random.Range(0f, 1f);

                // Critical is success.
                if (critValue < attackerCritChance)
                {
                    result.damage     *= 2;
                    result.criticalHit = true;
                }
            }

            // Calculate damage against armor or magic resist.
            switch (step.damageType)
            {
            case AbilityStep_Damage.DamageType.None:
                result.damage = 0;
                break;

            case AbilityStep_Damage.DamageType.Physical:
                // defender armor - attacker armor pen => clamped between 0-1.
                float defenderPenetratedArmor = Mathf.Clamp01(defender.Stats.armor.Value - attacker.Stats.armorPenetration.Value);
                result.damage = (int)(result.damage * (1 - defenderPenetratedArmor));
                break;

            case AbilityStep_Damage.DamageType.Magic:
                // defender MR - attacker mr pen => clamped between 0-1.
                float defenderPenetratedMR = Mathf.Clamp01(defender.Stats.magicResist.Value - attacker.Stats.magicPenetration.Value);
                result.damage = (int)(result.damage * (1 - defenderPenetratedMR));
                break;
            }
        }

        // Clamp it to 0.
        result.damage = Mathf.Max(0, result.damage);

        // If the clamped damage is 0, result immune.
        if (result.damage < 1)
        {
            result.name = ClashResult.Name.Immune;
            return(result);
        }

        result.name = ClashResult.Name.Damage;
        return(result);
    }