private void HandleSkillOnTarget(Skill originalSkill, BaseCharacterMono target)
        {
            var skillToUse = GeneralMethods.CopySkill(originalSkill);

            //Debug.Log("Handled skill hit for " + target.Character.Name);
            if (skillToUse.Caster != null)
            {
                DamageOutcome outcome      = new DamageOutcome(new Damage(), AttackOutcome.Success);
                var           damageToDeal = skillToUse.Damage;
                if (damageToDeal.MaxTotal > 0)
                {
                    var projSkillHandler = this as ProjectileSkillHandler;
                    if (projSkillHandler != null)
                    {
                        var projSkill = (ProjectileSkill)_skill;
                        if (projSkill.IsPiercing)
                        {
                            damageToDeal.ApplyMultiplier(projSkill.PiercingScaling[projSkillHandler.PierceCounter]);
                        }
                    }

                    if (skillToUse.CasterMono != null)
                    {
                        outcome = skillToUse.CasterMono.Controller.RPGCombat.DamageTarget(target, damageToDeal);
                        var cc = target.Character as CombatCharacter;
                        if (cc != null)
                        {
                            var targetTaunt = cc.TauntHandler;
                            if (!targetTaunt.Tracker.ContainsKey(skillToUse.CasterMono))
                            {
                                targetTaunt.Tracker.Add(skillToUse.CasterMono, 1);
                            }

                            targetTaunt.Tracker[skillToUse.CasterMono] += skillToUse.BonusTaunt;
                        }
                    }
                    else
                    {
                        outcome = target.Character.VitalHandler.TakeDamage(skillToUse.Caster, damageToDeal);
                    }
                }



                var onCritProcs = new List <Rm_ProcEffect>();
                var onHitProcs  = new List <Rm_ProcEffect>();

                var procs = skillToUse.Caster.ProcEffects;

                if (skillToUse.HasProcEffect)
                {
                    switch (skillToUse.ProcEffect.ProcCondition)
                    {
                    case Rm_ProcCondition.Every_N_Hits:
                    case Rm_ProcCondition.Chance_On_Hit:
                    case Rm_ProcCondition.On_Hit:
                        onHitProcs.Add(skillToUse.ProcEffect);
                        break;

                    case Rm_ProcCondition.Chance_On_Critical_Hit:
                        onCritProcs.Add(skillToUse.ProcEffect);
                        break;
                    }
                }

                foreach (var procEffect in procs)
                {
                    switch (procEffect.ProcCondition)
                    {
                    case Rm_ProcCondition.Every_N_Hits:
                    case Rm_ProcCondition.Chance_On_Hit:
                    case Rm_ProcCondition.On_Hit:
                        onHitProcs.Add(procEffect);
                        break;

                    case Rm_ProcCondition.Chance_On_Critical_Hit:
                        onCritProcs.Add(procEffect);
                        break;
                    }
                }

                if (damageToDeal.MaxTotal == 0 || outcome != null && (outcome.AttackOutcome == AttackOutcome.Success || outcome.AttackOutcome == AttackOutcome.Critical))
                {
                    foreach (var proc in onHitProcs)
                    {
                        IncrementSkillCounters(skillToUse);
                        HandleProc(proc, target);
                    }

                    if (skillToUse.ApplyDOTOnHit)
                    {
                        var canApply = Random.Range(0, 100 + 1) <= (int)(skillToUse.ChanceToApplyDOT * 100);
                        if (canApply)
                        {
                            skillToUse.DamageOverTime.SkillMetaID = skillToUse.SkillMetaID;
                            skillToUse.DamageOverTime.Attacker    = skillToUse.Caster;
                            target.Character.AddDoT(skillToUse.DamageOverTime);
                        }
                    }

                    if (skillToUse.RunEventOnHit)
                    {
                        if (!string.IsNullOrEmpty(skillToUse.EventOnHitID))
                        {
                            Debug.Log("Not implemented: do event:" + skillToUse.EventOnHitID);
                        }
                    }

                    if (skillToUse.SkillType == SkillType.Aura)
                    {
                        var auraSkill = (AuraSkill)skillToUse;
                        target.Character.ToggleAura(auraSkill, true);
                    }
                    else if (skillToUse.SkillType == SkillType.Restoration)
                    {
                        var restoSkill = (RestorationSkill)skillToUse;
                        target.Character.AddRestoration(restoSkill.Restoration);
                    }

                    if (skillToUse.AppliesBuffDebuff)
                    {
                        target.Character.AddTimedPassiveEffect(skillToUse.Effect);
                    }

                    if (skillToUse.ApplyStatusEffect)
                    {
                        var apply = Random.Range(0, 100 + 1) <= (int)(skillToUse.ChanceToApplyStatusEffect * 100);
                        if (apply)
                        {
                            var statusEffect = Rm_RPGHandler.Instance.Repositories.StatusEffects.Get(skillToUse.StatusEffectID);
                            if (statusEffect != null)
                            {
                                statusEffect.Effect.HasDuration = skillToUse.ApplyStatusEffectWithDuration;
                                if (statusEffect.Effect.HasDuration)
                                {
                                    statusEffect.Effect.Duration = skillToUse.ApplyStatusEffectDuration;
                                }
                                target.Character.AddStatusEffect(statusEffect);
                            }
                        }
                    }

                    if (skillToUse.RemoveStatusEffect)
                    {
                        var apply = Random.Range(0, 100 + 1) <= (int)(skillToUse.ChanceToRemoveStatusEffect * 100);
                        if (apply)
                        {
                            target.Character.RemoveStatusEffect(skillToUse.RemoveStatusEffectID);
                        }
                    }

                    var impact = GeneralMethods.SpawnPrefab(skillToUse.ImpactPrefabPath, target.transform.position, Quaternion.identity, target.transform);
                    if (impact != null)
                    {
                        impact.GetComponent <DestroyHelper>().Init(DestroyCondition.Time, 0.3f);
                    }
                    AudioPlayer.Instance.Play(skillToUse.ImpactSound.Audio, AudioType.SoundFX, target.transform.position, target.transform);
                }

                if (outcome != null && outcome.AttackOutcome == AttackOutcome.Critical)
                {
                    foreach (var proc in onCritProcs)
                    {
                        IncrementSkillCounters(skillToUse);
                        HandleProc(proc, target);
                    }
                }
            }
        }
Exemplo n.º 2
0
        public DamageOutcome TakeDamage(BaseCharacter attacker, Damage damage, bool evaluateDamageToDeal = true)
        {
            if (attacker != null && attacker.IsFriendly(Character))
            {
                return(new DamageOutcome(new Damage()
                {
                    MinDamage = 0, MaxDamage = 0, ElementalDamages = new List <ElementalDamage>()
                }, new DamageDealt(0, new Dictionary <string, int>()), AttackOutcome.FriendlyFire, false));
            }

            if (Character.ImmuneTo(damage.SkillMetaID))
            {
                return(new DamageOutcome(new Damage()
                {
                    MinDamage = 0, MaxDamage = 0, ElementalDamages = new List <ElementalDamage>()
                }, new DamageDealt(0, new Dictionary <string, int>()), AttackOutcome.Immune, false));
            }

            Damage        damageObj = null;
            DamageDealt   damageToDeal;
            DamageOutcome result      = null;
            DamageDealt   damageDealt = null;

            result = CombatCalcEvaluator.Instance.Evaluate(attacker, Character, damage);
            var killedTarget = false;

            if (result.AttackOutcome == AttackOutcome.Success || result.AttackOutcome == AttackOutcome.Critical)
            {
                damageObj    = result.DamageToDeal;
                damageToDeal = result.DamageDealt;

                if (!string.IsNullOrEmpty(damageObj.SkillMetaID))
                {
                    var susceptibility = Character.AllSusceptibilites.Where(s => s.ID == damageObj.SkillMetaID).Sum(s => s.AdditionalDamage);
                    var multiplier     = Mathf.Max(0, 1 + susceptibility);
                    damageToDeal.ApplyMultiplier(multiplier);
                }

                if (Character is PlayerCharacter)
                {
                    var difficulty     = GetObject.PlayerSave.Difficulty;
                    var diffMultiplier = Rm_RPGHandler.Instance.Player.Difficulties.FirstOrDefault(d => d.ID == difficulty);
                    if (diffMultiplier != null)
                    {
                        damageToDeal.ApplyMultiplier(diffMultiplier.DamageMultiplier);
                    }
                }

                damageDealt = damageToDeal;

                Health.CurrentValue -= damageDealt.Total;
                killedTarget         = false;

                if (Health.CurrentValue <= 0)
                {
                    Health.CurrentValue = 0;
                    Character.Alive     = false;
                    killedTarget        = true;
                }
            }


            //todo:enemies to player only
            if (Rm_RPGHandler.Instance.Combat.EnableFloatingCombatText && !(Character.CharacterMono is PlayerMono))
            {
                var pos = Character.CharacterMono.transform;

                //Default damage
                if (result.AttackOutcome == AttackOutcome.Success || result.AttackOutcome == AttackOutcome.Critical)
                {
                    if (damageDealt.Physical > 0)
                    {
                        var go = Object.Instantiate(_floatingCombatText, pos.position + pos.up, Quaternion.identity) as GameObject;
                        go.GetComponent <FloatingCombatText>().SetUp(damageDealt.Physical.ToString());
                    }


                    var distanceBetweenValuesconst = Rm_RPGHandler.Instance.Combat.FloatDistBetweenVals;
                    var distanceBetweenValues      = distanceBetweenValuesconst;
                    foreach (var dmg in damageDealt.Elementals)
                    {
                        var eleDef = GetElement(dmg.Key);
                        if (eleDef != null && dmg.Value > 0)
                        {
                            var eleGo = Object.Instantiate(_floatingCombatText, pos.position + pos.up + new Vector3(0, distanceBetweenValues, 0), Quaternion.identity) as GameObject;
                            eleGo.GetComponent <FloatingCombatText>().SetUp(string.Format("<color={0}>{1}</color>", eleDef.Color.ToString(), dmg.Value));
                            distanceBetweenValues += distanceBetweenValuesconst;
                        }
                    }
                }
                else
                {
                    if (result.AttackOutcome != AttackOutcome.FriendlyFire && result.AttackOutcome != AttackOutcome.Critical &&
                        result.AttackOutcome != AttackOutcome.Success)
                    {
                        var go = Object.Instantiate(_floatingCombatText, pos.position + pos.up, Quaternion.identity) as GameObject;
                        go.GetComponent <FloatingCombatText>().SetUp(result.AttackOutcome.ToString());
                    }
                }

                //add delay and iterate through damages to deal > 0 that are elemental, adding more delay for each one displayed
                //add random X/Y pos on the floating text
            }


            return(new DamageOutcome(damageObj, damageDealt, AttackOutcome.Success, killedTarget));
        }
Exemplo n.º 3
0
        private void HandleHitOnTarget(Damage damage, BaseCharacterMono target)
        {
            if (Caster != null)
            {
                DamageOutcome outcome      = new DamageOutcome(new Damage(), AttackOutcome.Success);
                var           damageToDeal = damage;
                if (damageToDeal.MaxTotal > 0)
                {
                    if (CasterMono != null)
                    {
                        outcome = CasterMono.Controller.RPGCombat.DamageTarget(target, damageToDeal);
                    }
                    else
                    {
                        outcome = target.Character.VitalHandler.TakeDamage(Caster, damageToDeal);
                    }
                }



                var onCritProcs = new List <Rm_ProcEffect>();
                var onHitProcs  = new List <Rm_ProcEffect>();

                var procs = Caster.ProcEffects;

                foreach (var procEffect in procs)
                {
                    switch (procEffect.ProcCondition)
                    {
                    case Rm_ProcCondition.Every_N_Hits:
                    case Rm_ProcCondition.Chance_On_Hit:
                    case Rm_ProcCondition.On_Hit:
                        onHitProcs.Add(procEffect);
                        break;

                    case Rm_ProcCondition.Chance_On_Critical_Hit:
                        onCritProcs.Add(procEffect);
                        break;
                    }
                }

                if (damageToDeal.MaxTotal == 0 || outcome != null && (outcome.AttackOutcome == AttackOutcome.Success || outcome.AttackOutcome == AttackOutcome.Critical))
                {
                    foreach (var proc in onHitProcs)
                    {
                        HandleProc(proc, target);
                    }
                    var impact = GeneralMethods.SpawnPrefab(ImpactPrefabPath, target.transform.position, Quaternion.identity, target.transform);
                    if (impact != null)
                    {
                        impact.GetComponent <DestroyHelper>().Init(DestroyCondition.Time, 0.3f);
                    }
                    AudioPlayer.Instance.Play(ImpactSound.Audio, AudioType.SoundFX, target.transform.position, target.transform);
                }

                if (outcome != null && outcome.AttackOutcome == AttackOutcome.Critical)
                {
                    foreach (var proc in onCritProcs)
                    {
                        HandleProc(proc, target);
                    }
                }
            }
        }