Пример #1
0
    // Returns true if the target is being attacked from the rear.
    // Doesn't include attacks from the left or right.
    private bool IsBackstab(ObjectMechanics target)
    {
        float rotation1 = target.transform.eulerAngles.y;
        float rotation2 = transform.eulerAngles.y;

        return(VeryApproximateMatch(Mathf.Abs(rotation1 - rotation2), 0.0f) || VeryApproximateMatch(Mathf.Abs(rotation1 - rotation2), 360.0f));
    }
Пример #2
0
 public void PerformAttackWithStatusEffect(ObjectMechanics target, StatusEffect.EffectType type, int duration, int powerLevel = -1, float damageMultiplier = 1.0f)
 {
     if (HitAndDamage(target, false, damageMultiplier))
     {
         new StatusEffect(type, duration, target, powerLevel);
     }
 }
Пример #3
0
    IEnumerator AttackAfterDelay(float time, ObjectMechanics targetMechanics)
    {
        yield return(new WaitForSeconds(time));

        if (targetMechanics != null) // If the target wasn't destroyed by the first attack.
        {
            mechanics.PerformAttackWithStatusEffect(targetMechanics, StatusEffect.EffectType.SLOWED, 2, -1, 0.5f);
        }
        yield break;
    }
Пример #4
0
    private bool IsCrit(ObjectMechanics target, bool isBackstab)
    {
        int chance = CritChance();

        if (isBackstab)
        {
            chance *= 2;
        }
        return(PercentRoll(chance));
    }
Пример #5
0
    IEnumerator AttackAfterDelay(float time, ObjectMechanics targetMechanics)
    {
        yield return(new WaitForSeconds(time));

        if (targetMechanics != null) // If the target wasn't destroyed by the first attack.
        {
            mechanics.PerformBasicAttack(targetMechanics, false);
        }
        yield break;
    }
Пример #6
0
    void ResolveAttack(GameObject target)
    {
        spentActionPoints += MIN_AP_COST;
        ObjectMechanics targetMechanics = target.GetComponent <CreatureMechanics>();

        if (targetMechanics == null)
        {
            targetMechanics = target.GetComponent <ObjectMechanics>();
        }
        AttackEffects(targetMechanics);
    }
Пример #7
0
 // Some status effects have varying power levels, others default to -1
 public StatusEffect(EffectType effectType, int durationRounds, ObjectMechanics effectTarget, int effectPowerLevel = -1)
 {
     // Only CreatureMechanics can get status effects.
     if (effectTarget.GetType() == typeof(ObjectMechanics))
     {
         return;
     }
     roundsRemaining = durationRounds;
     type            = effectType;
     target          = (CreatureMechanics)effectTarget;
     powerLevel      = effectPowerLevel;
     target.RegisterStatusEffect(this);
 }
Пример #8
0
    private float HeightAdvantageMultiplier(ObjectMechanics target)
    {
        float relativeHeight = transform.position.y - target.transform.position.y;

        if (relativeHeight > 0.25f)
        {
            return(1.2f);
        }
        if (relativeHeight > 0f)
        {
            return(1.1f);
        }
        return(1.0f);
    }
Пример #9
0
    // Main attack function. Applies damage and returns true if there is a hit.
    // Returns false if there is a miss.
    private bool HitAndDamage(ObjectMechanics target, bool isConcentrationEligible, float damageMultiplier)
    {
        if (isConcentrationEligible)
        {
            BoostConcentration();
        }
        Animate("IsAttacking");
        if (!PercentRoll(HitChance()))
        {
            SoundManager.PlaySound(attackSound);
            target.Animate("IsDodging");
            DisplayPopupAfterDelay(0.2f, "Miss");
            return(false);
        }
        if (PercentRoll(target.DodgeChance()))
        {
            SoundManager.PlaySound(attackSound);
            target.Animate("IsDodging");
            target.DisplayPopupAfterDelay(0.2f, "Dodge");
            return(false);
        }
        int  dam      = DamageInflicted();
        bool backstab = false;

        if (IsVulnerable(target))
        {
            if (isConcentrationEligible)
            {
                BoostConcentration();
            }
            backstab = true;
            dam     += BonusRearDamage();
        }
        // Critical hits apply a +100% multiplier, after all fixed modifiers are considered.
        if (IsCrit(target, backstab))
        {
            dam += dam;
            DisplayPopupAfterDelay(0.2f, "Crit");
        }
        else if (backstab) // Only display the backstab popup if it's not a crit.
        {
            DisplayPopupAfterDelay(0.2f, "Backstab");
        }
        damageMultiplier *= HeightAdvantageMultiplier(target);
        dam = (int)((float)dam * damageMultiplier);
        target.ReceiveDamage(dam);
        return(true);
    }
Пример #10
0
 private bool IsVulnerable(ObjectMechanics target)
 {
     if (StatusEffect.HasEffectType(ref target.statusEffects, StatusEffect.EffectType.PETRIFIED))
     {
         return(false);
     }
     if (!target.canBeBackstabbed)
     {
         return(false);
     }
     if (IsBackstab(target))
     {
         return(true);
     }
     if (StatusEffect.HasEffectType(ref target.statusEffects, StatusEffect.EffectType.KNOCKDOWN))
     {
         return(true);
     }
     if (StatusEffect.HasEffectType(ref target.statusEffects, StatusEffect.EffectType.BLINDED))
     {
         return(true);
     }
     return(false);
 }
Пример #11
0
 override protected void AttackEffects(ObjectMechanics targetMechanics)
 {
     new StatusEffect(StatusEffect.EffectType.FROZEN, 2, targetMechanics, -1);
     targetMechanics.DisplayPopup("Frozen");
 }
Пример #12
0
 override protected void AttackEffects(ObjectMechanics targetMechanics)
 {
     new StatusEffect(StatusEffect.EffectType.PETRIFIED, 3, targetMechanics, -1);
     targetMechanics.DisplayPopup("Petrified");
 }
Пример #13
0
 override protected void AttackEffects(ObjectMechanics targetMechanics)
 {
     mechanics.PerformAttackWithStatusEffect(targetMechanics, StatusEffect.EffectType.BURNING, 2);
 }
Пример #14
0
 override protected void AttackEffects(ObjectMechanics targetMechanics)
 {
     new StatusEffect(StatusEffect.EffectType.BLINDED, 2, targetMechanics, -1);
     targetMechanics.DisplayPopup("Blinded");
 }
Пример #15
0
 virtual protected void AttackEffects(ObjectMechanics targetStats)
 {
     mechanics.PerformBasicAttack(targetStats);
 }
Пример #16
0
 override protected void AttackEffects(ObjectMechanics targetMechanics)
 {
     new StatusEffect(StatusEffect.EffectType.EMPOWER, 2, targetMechanics, -1);
 }
Пример #17
0
 override protected void AttackEffects(ObjectMechanics targetMechanics)
 {
     mechanics.PerformBasicAttack(targetMechanics, false, 0.5f);
 }
Пример #18
0
 // Public wrapper for HitAndDamage
 public void PerformBasicAttack(ObjectMechanics target, bool isConcentrationEligible = true, float damageMultiplier = 1.0f)
 {
     HitAndDamage(target, isConcentrationEligible, damageMultiplier);
 }
Пример #19
0
 override protected void AttackEffects(ObjectMechanics targetMechanics)
 {
     mechanics.PerformAttackWithStatusEffect(targetMechanics, StatusEffect.EffectType.KNOCKDOWN, 1, -1, 0.5f);
     StartCoroutine(AttackAfterDelay(1.0f, targetMechanics));
 }
Пример #20
0
 override protected void AttackEffects(ObjectMechanics targetMechanics)
 {
     mechanics.PerformBasicAttack(targetMechanics, false);
     StartCoroutine(AttackAfterDelay(1.0f, targetMechanics));
 }
Пример #21
0
 override protected void AttackEffects(ObjectMechanics targetMechanics)
 {
     mechanics.PerformAttackWithStatusEffect(targetMechanics, StatusEffect.EffectType.KNOCKDOWN, 1, -1, 0.5f);
 }
Пример #22
0
 override protected void AttackEffects(ObjectMechanics targetMechanics)
 {
     new StatusEffect(StatusEffect.EffectType.BURNING, 5, targetMechanics, -1);
     targetMechanics.DisplayPopup("Ignited");
 }