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); } } } }
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)); }
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); } } } }