Exemple #1
0
    public static void ApplyStatusExplosionEffect(Actor target, Actor source, EffectType statusToExplode, List <ActorEffect> listToExplode = null)
    {
        LayerMask mask = target.GetActorType() == ActorType.ALLY ? (LayerMask)LayerMask.GetMask("Hero") : (LayerMask)LayerMask.GetMask("Enemy");

        if (listToExplode == null)
        {
            listToExplode = target.GetStatusEffectAll(statusToExplode);
        }

        float                  explodeDamage    = 0f;
        ElementType            explodeElement   = ElementType.PHYSICAL;
        EffectApplicationFlags restrictionFlags = EffectApplicationFlags.NONE;

        if (statusToExplode == EffectType.BLEED)
        {
            restrictionFlags |= EffectApplicationFlags.CANNOT_BLEED;
            explodeElement    = ElementType.PHYSICAL;
            foreach (BleedEffect bleedEffect in listToExplode)
            {
                explodeDamage       += bleedEffect.damagePerSecond * bleedEffect.duration * 0.5f;
                bleedEffect.duration = 0;
                target.RemoveStatusEffect(bleedEffect, true);
            }
        }

        if (explodeDamage == 0)
        {
            return;
        }

        Collider2D[] hits = Physics2D.OverlapCircleAll(target.transform.position, 0.75f, mask);
        foreach (Collider2D hit in hits)
        {
            Actor aoeTarget = hit.gameObject.GetComponent <Actor>();

            if (aoeTarget.Data.IsDead)
            {
                continue;
            }

            Dictionary <ElementType, MinMaxRange> damageDict = new Dictionary <ElementType, MinMaxRange>
            {
                { explodeElement, new MinMaxRange((int)explodeDamage, (int)explodeDamage) }
            };

            aoeTarget.ApplyDamage(source.ScaleSecondaryDamageValue(aoeTarget, damageDict, ExplosionTags), source.Data.OnHitData, isHit: true, true, statusToExplode, restrictionFlags);
        }
    }
Exemple #2
0
    public void ApplyAfterHitEffects(Dictionary <ElementType, float> damage, OnHitDataContainer onHitData, EffectApplicationFlags restrictionFlags)
    {
        onHitData.ApplyTriggerEffects(TriggerType.ON_HIT, this);

        float HealthForThreshold = Data.MaximumHealth * Data.AfflictedStatusThreshold;

        if (Data.HasSpecialBonus(BonusType.USE_SHIELD_FOR_STATUS_THRESHOLD))
        {
            HealthForThreshold = Data.MaximumManaShield * Data.AfflictedStatusThreshold;
        }

        if (damage.ContainsKey(ElementType.PHYSICAL) && damage[ElementType.PHYSICAL] > 0)
        {
            if (!restrictionFlags.HasFlag(EffectApplicationFlags.CANNOT_BLEED) &&
                onHitData.DidEffectProc(EffectType.BLEED, Data.AfflictedStatusAvoidance))
            {
                onHitData.ApplyEffectToTarget(this, EffectType.BLEED, damage[ElementType.PHYSICAL] * onHitData.effectData[EffectType.BLEED].Effectiveness * Data.AfflictedStatusDamageResistance * BleedEffect.BASE_DAMAGE_MULTIPLIER);
            }
            if (!restrictionFlags.HasFlag(EffectApplicationFlags.CANNOT_POISON) &&
                onHitData.DidEffectProc(EffectType.POISON, Data.AfflictedStatusAvoidance))
            {
                onHitData.ApplyEffectToTarget(this, EffectType.POISON, damage[ElementType.PHYSICAL] * onHitData.effectData[EffectType.POISON].Effectiveness * Data.AfflictedStatusDamageResistance * PoisonEffect.BASE_DAMAGE_MULTIPLIER);
            }
        }

        if (!restrictionFlags.HasFlag(EffectApplicationFlags.CANNOT_BURN) &&
            damage.ContainsKey(ElementType.FIRE) &&
            damage[ElementType.FIRE] > 0 &&
            onHitData.DidEffectProc(EffectType.BURN, Data.AfflictedStatusAvoidance))
        {
            //float percent = (damage[ElementType.FIRE] * onHitData.GetEffectEffectiveness(EffectType.BURN) * Data.AfflictedStatusDamageResistance) / damage[ElementType.FIRE];
            //Debug.Log(damage[ElementType.FIRE] + " BURN  " + damage[ElementType.FIRE] * onHitData.GetEffectEffectiveness(EffectType.BURN) * Data.AfflictedStatusDamageResistance + "   " + percent.ToString("F3"));
            onHitData.ApplyEffectToTarget(this, EffectType.BURN, damage[ElementType.FIRE] * onHitData.effectData[EffectType.BURN].Effectiveness * Data.AfflictedStatusDamageResistance * BurnEffect.BASE_DAMAGE_MULTIPLIER);
        }

        if (!restrictionFlags.HasFlag(EffectApplicationFlags.CANNOT_CHILL) &&
            damage.ContainsKey(ElementType.COLD) &&
            damage[ElementType.COLD] > 0 &&
            onHitData.DidEffectProc(EffectType.CHILL, Data.AfflictedStatusAvoidance))
        {
            float percentageDealt = damage[ElementType.COLD] / HealthForThreshold;

            float chillEffectPower = ChillEffect.BASE_CHILL_EFFECT * Math.Min(percentageDealt / ChillEffect.BASE_CHILL_THRESHOLD, 1f) * onHitData.effectData[EffectType.CHILL].Effectiveness;
            //Debug.Log(damage[ElementType.COLD] + " " + percentageDealt + " " + chillEffectPower);
            onHitData.ApplyEffectToTarget(this, EffectType.CHILL, chillEffectPower);
        }

        if (!restrictionFlags.HasFlag(EffectApplicationFlags.CANNOT_ELECTROCUTE) &&
            damage.ContainsKey(ElementType.LIGHTNING) &&
            damage[ElementType.LIGHTNING] > 0 &&
            onHitData.DidEffectProc(EffectType.ELECTROCUTE, Data.AfflictedStatusAvoidance))
        {
            onHitData.ApplyEffectToTarget(this, EffectType.ELECTROCUTE, damage[ElementType.LIGHTNING] * onHitData.effectData[EffectType.ELECTROCUTE].Effectiveness * Data.AfflictedStatusDamageResistance * ElectrocuteEffect.BASE_DAMAGE_MULTIPLIER);
        }

        if (!restrictionFlags.HasFlag(EffectApplicationFlags.CANNOT_FRACTURE) &&
            damage.ContainsKey(ElementType.EARTH) &&
            damage[ElementType.EARTH] > 0 &&
            onHitData.DidEffectProc(EffectType.FRACTURE, Data.AfflictedStatusAvoidance))
        {
            float percentageDealt     = damage[ElementType.EARTH] / HealthForThreshold;
            float fractureEffectPower = FractureEffect.BASE_FRACTURE_EFFECT * Math.Min(percentageDealt / FractureEffect.BASE_FRACTURE_THRESHOLD, 1f) * onHitData.effectData[EffectType.FRACTURE].Effectiveness;

            onHitData.ApplyEffectToTarget(this, EffectType.FRACTURE, fractureEffectPower);
        }

        if (!restrictionFlags.HasFlag(EffectApplicationFlags.CANNOT_PACIFY) &&
            damage.ContainsKey(ElementType.DIVINE) &&
            damage[ElementType.DIVINE] > 0 &&
            onHitData.DidEffectProc(EffectType.PACIFY, Data.AfflictedStatusAvoidance))
        {
            float percentageDealt   = damage[ElementType.DIVINE] / HealthForThreshold;
            float pacifyEffectPower = PacifyEffect.BASE_PACIFY_EFFECT * Math.Min(percentageDealt / PacifyEffect.BASE_PACIFY_THRESHOLD, 1f) * onHitData.effectData[EffectType.PACIFY].Effectiveness;

            onHitData.ApplyEffectToTarget(this, EffectType.PACIFY, pacifyEffectPower);
        }

        if (!restrictionFlags.HasFlag(EffectApplicationFlags.CANNOT_RADIATION) &&
            damage.ContainsKey(ElementType.VOID) &&
            damage[ElementType.VOID] > 0 &&
            onHitData.DidEffectProc(EffectType.RADIATION, Data.AfflictedStatusAvoidance))
        {
            onHitData.ApplyEffectToTarget(this, EffectType.RADIATION, damage[ElementType.VOID] * onHitData.effectData[EffectType.RADIATION].Effectiveness * Data.AfflictedStatusDamageResistance * RadiationEffect.BASE_DAMAGE_MULTIPLIER);
        }
    }
Exemple #3
0
    public void ApplyDamage(Dictionary <ElementType, float> damage, OnHitDataContainer onHitData, bool isHit,
                            bool isFromSecondaryEffect, EffectType?sourceType = null,
                            EffectApplicationFlags restrictionFlags           = EffectApplicationFlags.NONE)
    {
        float total = 0;

        if (Data.IsDead)
        {
            return;
        }

        if (Data.IsDead && isHit)
        {
            return;
        }

        Dictionary <ElementType, float> damageTaken = new Dictionary <ElementType, float>(damage);

        float damageTakenModifier  = Data.DamageTakenModifier;
        float blockDamageReduction = 1f;

        if (isHit)
        {
            if (!isFromSecondaryEffect)
            {
                damageTakenModifier *= onHitData.directHitDamage;
            }

            if (DidTargetBlock(this))
            {
                blockDamageReduction *= 1f - Data.BlockProtection;
                damageTakenModifier  *= blockDamageReduction;
                Data.OnHitData.ApplyTriggerEffects(TriggerType.ON_BLOCK, onHitData.SourceActor);
            }

            //if (isBoss)
            //damageTakenModifier *= onHitData.vsBossDamage;
        }

        foreach (ElementType elementType in damage.Keys)
        {
            bool isDamageTakenNonZero = false;
            if (elementType == ElementType.PHYSICAL && damage.ContainsKey(ElementType.PHYSICAL))
            {
                float armorReductionRate = 1.0f;
                if (isHit && Data.Armor > 0)
                {
                    armorReductionRate = 1.0f - (Data.Armor / (Data.Armor + damage[ElementType.PHYSICAL]));
                }
                float resistanceReductionRate = 1.0f - (Data.GetResistance(ElementType.PHYSICAL) / 100f);
                float physicalReduction       = (armorReductionRate * resistanceReductionRate) + (onHitData.GetNegation(ElementType.PHYSICAL) / 100f);
                //Debug.Log(Data.GetResistance(ElementType.PHYSICAL) + " " + onHitData.physicalNegation + " " + damage[ElementType.PHYSICAL]);
                float physicalDamage = physicalReduction * damage[ElementType.PHYSICAL] * damageTakenModifier;
                total += Math.Max(0, physicalDamage);
                damageTaken[ElementType.PHYSICAL] = (damage[ElementType.PHYSICAL] * blockDamageReduction);
                isDamageTakenNonZero = physicalDamage > 0;
            }
            else
            {
                if (damage.ContainsKey(elementType))
                {
                    float nonPhysicalDamage = (1f - (Data.GetResistance(elementType) - onHitData.GetNegation(elementType)) / 100f) * damage[elementType] * damageTakenModifier;
                    total += Math.Max(0, nonPhysicalDamage);
                    damageTaken[elementType] = (damage[elementType] * blockDamageReduction);
                    isDamageTakenNonZero     = nonPhysicalDamage > 0;
                }
            }

            if (isHit && isDamageTakenNonZero)
            {
                ParticleManager.Instance.EmitOnHitEffect(elementType, transform.position);
            }
        }

        float actualDamageTaken = total;

        if (sourceType == EffectType.POISON)
        {
            total = ModifyCurrentShield(total * Data.PoisonResistance, true) + (total * (1f - Data.PoisonResistance));
        }
        else
        {
            total = ModifyCurrentShield(total, true);
        }

        actualDamageTaken -= total;

        if (Data.HealthIsHitsToKill && isHit && total >= 1f)
        {
            ModifyCurrentHealth(1);

            actualDamageTaken += 1;
        }
        else if (total > 0)
        {
            MassShieldAura massShield = (MassShieldAura)GetStatusEffect(EffectType.MASS_SHIELD_AURA);
            if (massShield != null && massShield.Source != this)
            {
                total = massShield.TransferDamage(total * massShield.DamageTransferRate) + total * (1f - massShield.DamageTransferRate);
            }

            BodyguardAura bodyguard = (BodyguardAura)GetStatusEffect(EffectType.BODYGUARD_AURA);
            if (isHit && bodyguard != null && bodyguard.Source != this)
            {
                if (bodyguard.TransferDamage(total, out float damageMod))
                {
                    total *= 1f - bodyguard.DamageTransferRate;
                    foreach (ElementType element in Enum.GetValues(typeof(ElementType)))
                    {
                        if (damage.ContainsKey(element))
                        {
                            damage[element] *= damageMod;
                        }
                    }
                    bodyguard.Source.ApplyAfterHitEffects(damage, onHitData, restrictionFlags);
                }
            }

            actualDamageTaken += total;

            ModifyCurrentHealth(total);
        }

        if (onHitData.SourceActor != this)
        {
            if (Data.IsDead)
            {
                if (onHitData.SourceActor is HeroActor hero)
                {
                    hero.Data.killCount++;
                }

                onHitData.ApplyTriggerEffects(TriggerType.ON_KILL, this);

                if (isHit)
                {
                    onHitData.ApplyTriggerEffects(TriggerType.ON_HIT_KILL, this);
                }
            }
            else if (isHit)
            {
                Data.OnHitData.ApplyTriggerEffects(TriggerType.WHEN_HIT_BY, onHitData.SourceActor);
            }
        }

        if ((GameManager.Instance.PlayerStats.showDamageNumbers) && (isHit || sourceType == EffectType.RETALIATION_DAMAGE))
        {
            FloatingDamageText damageText = StageManager.Instance.BattleManager.DamageTextPool.GetDamageText();
            damageText.transform.SetParent(StageManager.Instance.WorldCanvas.transform, false);
            damageText.transform.position = this.transform.position;


            if (sourceType == EffectType.RETALIATION_DAMAGE)
            {
                damageText.SetDamageText(actualDamageTaken, Color.gray);
            }
            else
            {
                damageText.SetDamageText(actualDamageTaken, Color.white);
            }
        }

        if (isHit)
        {
            ApplyAfterHitEffects(damageTaken, onHitData, restrictionFlags);
        }
    }