override public void TriggerEffect() { if (skillListToExecute == null || skillListToExecute.Count == 0) { return; } int r = UnityEngine.Random.Range(0, totalExecWeight); int curWeight = 0; for (int i = 0; i < skillListToExecute.Count; i++) { curWeight += skillListToExecute[i].weight; if (r <= curWeight) { SkillBase s = skill.owner.skillList.Find(x => x.skillData.id == skillListToExecute[i].id); if (s) { s.CheckCastCondition(); s.Execute(); } break; } } if (skill.onTriggerEvent != null) { skill.onTriggerEvent(skill, skillEvent); } }
virtual public bool Damage(BattleUnit attacker, double finalAttackPower, SkillBase.DamageType damageType = SkillBase.DamageType.NotDefined, SkillBase skill = null, string tag = "") { if (isSuperArmor) { //Debug.Log(attacker.heroData.heroName +"의 공격 막아짐 데미지 :" + finalAttackPower); return(false); } if (skill != null && counterSkillList.Count > 0) { for (int i = 0; i < counterSkillList.Count; i++) { SkillBase counterSkill = counterSkillList[i]; if (counterSkill.skillData.effectType == "CounterMeleePhysical") { if (skill.skillData.damageType == SkillBase.DamageType.Physical && skill.skillData.rangeType == SkillBase.RangeType.Melee && skill.skillData.triggerType == SkillBase.TriggerType.None && skill.skillData.collectTargetType == SkillBase.CollectTargetType.Target) { BattleHero h = attacker as BattleHero; counterSkill.castTarget = h; counterSkill.CheckCastCondition(); if (!counterSkill.isCoolTime && counterSkill.IsCastTargetInSkillRange()) { counterSkill.Execute(); return(false); } } } if (counterSkill.skillData.effectType == "CounterRangePhysical") { if (skill.skillData.damageType == SkillBase.DamageType.Physical && skill.skillData.rangeType == SkillBase.RangeType.Range && skill.skillData.triggerType == SkillBase.TriggerType.None) { BattleHero h = attacker as BattleHero; counterSkill.castTarget = h; counterSkill.CheckCastCondition(); if (!counterSkill.isCoolTime && counterSkill.IsCastTargetInSkillRange()) { counterSkill.Execute(); if (onHit != null) { onHit(finalAttackPower, "ImmuneDamage"); } return(false); } } } if (counterSkill.skillData.triggerType == SkillBase.TriggerType.OnHit && counterSkill.skillData.effectType == "Ninja_CounterAttack") { if (damageType != SkillBase.DamageType.Pure) { BattleHero h = attacker as BattleHero; counterSkill.castTarget = h; counterSkill.CheckCastCondition(); //Debug.Log(counterSkill.currentCoolTime + "/" + counterSkill.isCoolTime); if (counterSkill.canCastSkill && !counterSkill.isCoolTime && counterSkill.IsCastTargetInSkillRange()) { SkillData skillData = counterSkill.skillData; if (!string.IsNullOrEmpty(skillData.coolTime1ID)) { coolTimeController.ApplyCoolTime(skillData.coolTime1ID, skillData.coolTime1); } if (!string.IsNullOrEmpty(skillData.coolTime2ID)) { coolTimeController.ApplyCoolTime(skillData.coolTime2ID, skillData.coolTime2); } //counterSkill.onStart += OnStartSkill; //counterSkill.onFinish += OnFinishSkill; //Debug.Log("반격!"); // 닌자 반격 스킬 counterSkill.Execute(); //캐릭터 위치에 따라 뒤집기 bool isFlip = false; if (attacker is BattleHero) { isFlip = h.flipX; float x = isFlip ? 1f : -1f; transform.position = attacker.transform.position + (Vector3.right * 3 * x); } if (this is BattleHero) { BattleHero owner = this as BattleHero; owner.flipX = isFlip; } return(false); } } } else if (counterSkill.skillData.triggerType == SkillBase.TriggerType.OnHit && counterSkill.skillData.effectType == "CounterDash") { if (damageType != SkillBase.DamageType.Pure) { counterSkill.CheckCastCondition(); //Debug.Log(counterSkill.currentCoolTime + "/" + counterSkill.isCoolTime); if (!counterSkill.isCoolTime) { SkillData skillData = counterSkill.skillData; if (!string.IsNullOrEmpty(skillData.coolTime1ID)) { coolTimeController.ApplyCoolTime(skillData.coolTime1ID, skillData.coolTime1); } if (!string.IsNullOrEmpty(skillData.coolTime2ID)) { coolTimeController.ApplyCoolTime(skillData.coolTime2ID, skillData.coolTime2); } //Debug.Log("뱀파이어 회피"); BattleHero hero = this as BattleHero; bool isFlip = hero.flipX; float x = isFlip ? 1f : -1f; //카운터 대쉬 이기에 무적처리함 isSuperArmor = true; counterSkill.Execute(); return(false); } } } else if (counterSkill.skillData.triggerType == SkillBase.TriggerType.OnHit && counterSkill.skillData.effectType == "Saladin_TimeReverse") { if (damageType != SkillBase.DamageType.Pure && finalAttackPower > counterSkill.owner.curHP) { counterSkill.CheckCastCondition(); //Debug.Log(counterSkill.currentCoolTime + "/" + counterSkill.isCoolTime); if (!counterSkill.isCoolTime) { if (beforeHP[order] == 0) { curHP = maxHP; } else { curHP = beforeHP[order]; } counterSkill.Execute(); return(false); } } } } } //공격력 식 재계산.. //전체 피해감소 double atk = attacker.stats.GetValueOf(StatType.AttackPower); double penetrateRatio = System.Math.Min(attacker.stats.GetValueOf(StatType.PenetrateRatio) * 0.0001, 0.99); double def = stats.GetValueOf(StatType.DefensePower) * (1 - penetrateRatio); double damageReduction = atk / def; //데미지 감소 적용 if (damageType == SkillBase.DamageType.Magical || damageType == SkillBase.DamageType.Physical) { float resist = 0f; if (damageType == SkillBase.DamageType.Magical) { resist = (float)stats.GetValueOf(StatType.ReduceMagicalDamageRate) * 0.0001f; } else if (damageType == SkillBase.DamageType.Physical) { resist = (float)stats.GetValueOf(StatType.ReducePhysicalDamageRate) * 0.0001f; } float reduceDamageRate = (float)stats.GetValueOf(StatType.ReduceDamageRate) * 0.0001f; finalAttackPower = finalAttackPower * damageReduction * Mathf.Max(1f - reduceDamageRate, 0f) * Mathf.Max(1f - resist, 0f); //Debug.Log(attacker.heroData.baseData.name + ", " + heroData.baseData.name + ", " + atk + ", " + def + ", " + finalAttackPower); } //보스 피해량 증가 if (isBoss) { double increaseDamageRate = attacker.stats.GetValueOf(StatType.IncreaseDamageRateBoss) * 0.0001f; finalAttackPower = finalAttackPower * (1d + increaseDamageRate); } //무적 버프 처리를 위해 먼저 한 번 검색 if (curHP < finalAttackPower) { for (int a = 0; a < buffController.buffList.Count; a++) { Buff buff = buffController.buffList[a]; if (buff.baseData.trigger != "OnTakeDeadlyDamage") { continue; } if (buff.triggerProbability < UnityEngine.Random.Range(1, 10001)) { continue; } BattleUnit target = null; if (buff.baseData.triggerTarget == "BuffTarget") { target = this; } if (target && !target.isDie) { target.buffController.AttachBuff(target, buff.baseData.triggerBuff, 1, buff); } } SkillBase skillBase = counterSkillList.Find(x => x.skillData.triggerType == SkillBase.TriggerType.OnDie); if (skillBase) { Buff buff = buffController.buffList.Find(x => x.id == "Buff_Shaman_Passive"); if (buff != null && buff.isActive /* && buff.stack > 0*/) { //Debug.Log("회생"); skillBase.Execute(); buffController.DetachBuff(buff);// .stack--; return(false); } } } // 공중 영웅 추가 데미지 버프 처리 Buff buffAirHero = attacker.buffController.buffList.Find(x => x.baseData.linkerType == "airHero" && x.isActive); if (buffAirHero != null && heroData.heroBattleType == HeroData.HeroBattleType.Air) { finalAttackPower *= (1 + (buffAirHero.statModifier.value * 0.0001d)); } Buff buffDis = attacker.buffController.buffList.Find(x => x.baseData.linkerType == "distance" && x.isActive); if (buffDis != null) { float maxDis = 20f; float dis = Vector2.Distance(attacker.transform.position, this.transform.position); dis = Mathf.Min(dis, maxDis); finalAttackPower *= (1 + (buffDis.statModifier.value * 0.0001d) * (maxDis - dis)); //Debug.Log("거리 : " + dis + "/ " + (buffDis.statModifier.value * 0.0001d) * ((1 + maxDis - dis))); } //무적 버프 Buff buffImmuneDamage = buffController.buffList.Find(x => x.baseData.effect == "ImmuneDamage" && x.isActive); if (buffImmuneDamage != null) { buffImmuneDamage.stack--; //Debug.Log(heroData.heroName + ") 공격 막음"); finalAttackPower = 0; if (onHit != null) { onHit(finalAttackPower, "ImmuneDamage"); } if (buffImmuneDamage.stack <= 0) { //Debug.Log("제거됨"); buffController.DetachBuff(buffImmuneDamage.id); } } else { //얻어 맞았다는 콜백 호출 if (onHit != null) { onHit(finalAttackPower, tag); } } //Stat dodgeStat = stats.GetParam(StatType.Dodge); Buff buffDodge = buffController.buffList.Find(x => x.baseData.stat == StatType.Dodge); if (buffDodge != null) { //Debug.Log(heroData.heroName + " / "+ buffDodge.id + " / " + buffDodge.baseData.triggerProbability); double prbability = buffDodge.GetPower(buffDodge, buffDodge.baseData.triggerProbability); //Debug.Log("회피성공률 : " + prbability); if (prbability >= UnityEngine.Random.Range(1, 10001)) { //Debug.Log("성공"); if (buffDodge.baseData.effect == "Miss") { finalAttackPower = 0; if (onHit != null) { onHit(finalAttackPower, "Miss"); } } else { //얻어 맞았다는 콜백 호출 if (onHit != null) { onHit(finalAttackPower, tag); } } } } //흡혈, 데미지 반사는 공격자가 살아있을 때만 if (finalAttackPower > 1 && attacker && attacker.master && !attacker.master.isDie) { if (!attacker.master.isDie) { //공격자는 준 피해에 비례해서 흡혈 함 Stat statLifeDrain = attacker.master.stats.GetParam(StatType.LifeDrainRate); if (statLifeDrain != null) { double lifeDrain = statLifeDrain.value * 0.0001f;// attacker.master.lifeDrainRate; if (lifeDrain > 0f) { attacker.master.LifeDrain(finalAttackPower * lifeDrain); } } //얻어 맞은 애는 공격자 한테 데미지 반사 시킴 Stat statReflect = attacker.master.stats.GetParam(StatType.ReflectDamageRate); if (statReflect != null) { double reflect = statReflect.value * 0.0001f;// finalAttackPower * reflectDamageRate; if (reflect > 0f) { attacker.master.ReflectDamage(this, reflect); } } } //공격자의 OnHit 설정되어 있는 버프 trigger 발동 for (int a = 0; a < attacker.master.buffController.buffList.Count; a++) { Buff buff = attacker.master.buffController.buffList[a]; if (buff.baseData.trigger != "OnHit") { continue; } if (buff.triggerProbability < UnityEngine.Random.Range(1, 10001)) { continue; } BattleUnit target = null; if (buff.baseData.triggerTarget == "SkillTarget") { target = this; } else if (buff.baseData.triggerTarget == "BuffTarget") { target = attacker.master; } if (target && !target.isDie) { target.buffController.AttachBuff(attacker.master, buff.baseData.triggerBuff, 1, buff); } } //뚜까맞은애의 OnTakeDamage 설정되어 있는 버프 trigger 발동 for (int a = 0; a < buffController.buffList.Count; a++) { Buff buff = buffController.buffList[a]; if (buff.baseData.trigger != "OnTakeDamage") { continue; } if (buff.triggerProbability < UnityEngine.Random.Range(1, 10001)) { continue; } BattleUnit target = null; if (buff.baseData.triggerTarget == "SkillTarget") { target = attacker.master; } else if (buff.baseData.triggerTarget == "BuffTarget") { target = this; } if (target && !target.isDie) { target.buffController.AttachBuff(this, buff.baseData.triggerBuff, 1, buff); } } if (skill && skill.skillData != null && skill.skillData.rangeType == SkillBase.RangeType.Range) { //뚜까맞은애의 OnTakeDamage 설정되어 있는 버프 trigger 발동 for (int a = 0; a < attacker.master.buffController.buffList.Count; a++) { Buff buff = attacker.master.buffController.buffList[a]; if (buff.baseData.trigger != "OnHitRange") { continue; } if (buff.triggerProbability < UnityEngine.Random.Range(1, 10001)) { continue; } BattleUnit target = null; if (buff.baseData.triggerTarget == "SkillTarget") { target = this; } else if (buff.baseData.triggerTarget == "BuffTarget") { target = attacker.master; } if (target && !target.isDie) { target.buffController.AttachBuff(attacker.master, buff.baseData.triggerBuff, 1, buff); } } } } //Todo: 방어력 등에 의한 실제 받아야 할 피해 계산 //데미지가 사망에 이르는 정도인지 체크. 공격자의 OnKill 설정되어 있는 버프 trigger 발동 if (finalAttackPower >= maxHP) { for (int a = 0; a < attacker.master.buffController.buffList.Count; a++) { Buff buff = attacker.master.buffController.buffList[a]; if (buff.baseData.trigger != "OnInstantKill") { continue; } if (buff.triggerProbability < UnityEngine.Random.Range(1, 10001)) { continue; } if (buff.baseData.triggerTarget == "OwnerTeam") { CustomList <BattleHero> targetList = attacker.master.team == Team.Red ? battleGroup.redTeamList : battleGroup.blueTeamList; for (int b = 0; b < targetList.Count; b++) { BattleUnit target = targetList[b]; if (target && !target.isDie) { target.buffController.AttachBuff(attacker.master, buff.baseData.triggerBuff, 1, buff); } } } else { BattleUnit target = null; if (buff.baseData.triggerTarget == "SkillTarget") { target = this; } else if (buff.baseData.triggerTarget == "BuffTarget") { target = attacker.master; } target = attacker.master; if (target && !target.isDie) { target.buffController.AttachBuff(attacker.master, buff.baseData.triggerBuff, 1, buff); } } } } if (curHP < finalAttackPower) { for (int a = 0; a < attacker.master.buffController.buffList.Count; a++) { Buff buff = attacker.master.buffController.buffList[a]; if (buff.baseData.trigger != "OnKill") { continue; } if (buff.triggerProbability < UnityEngine.Random.Range(1, 10001)) { continue; } BattleUnit target = null; if (buff.baseData.triggerTarget == "SkillTarget") { target = this; } else if (buff.baseData.triggerTarget == "BuffTarget") { target = attacker.master; } else if (buff.baseData.triggerTarget == "OwnerTeam") { CustomList <BattleHero> targetList = attacker.master.team == Team.Red ? battleGroup.redTeamList : battleGroup.blueTeamList; for (int b = 0; b < targetList.Count; b++) { BattleUnit _target = targetList[b]; if (_target && !_target.isDie) { _target.buffController.AttachBuff(attacker.master, buff.baseData.triggerBuff, 1, buff); } } } if (target != null) { if (target && !target.isDie) { target.buffController.AttachBuff(attacker.master, buff.baseData.triggerBuff, 1, buff); } } //Debug.Log("공격력 : " + attacker.master.stats.GetValueOf(StatType.AttackPower) + " / 방어력 : " + attacker.master.stats.GetValueOf(StatType.DefensePower)); } } //체력 감소 curHP -= finalAttackPower; if (damageType == SkillBase.DamageType.Physical || damageType == SkillBase.DamageType.Magical) { attacker.master.cumulativeDamage += finalAttackPower; } return(true); }
IEnumerator MoveToTarget() { //스킬 초기화 안 되어 있으면 초기화 한 다음에 날아감. if (!isInitializedSkillList) { InitSkillList(); } //yield return StartCoroutine(InitSkillList()); //발사 주체와 목표물 설정 안 되면 날아가지 않음 while (!master || !target) { yield return(null); } //파티클 있으면 플레이 시키고 ParticleSystem p = GetComponentInChildren <ParticleSystem>(); if (p) { p.Play(); } //애니메이션 있으면 플레이 시키고 Animation anim = GetComponentInChildren <Animation>(); if (anim) { anim.Play(); } //사운드 재생 AudioSource audio = GetComponentInChildren <AudioSource>(); if (audio) { audio.Play(); } Vector3 targetPoint = target.transform.position; //transform.LookAt(targetPoint, Vector3.forward); Vector3 a = new Vector3(0, 0, 80); Vector3 b = new Vector3(0, 0, -80); float force = 10; if (target.transform.position.x < transform.position.x) { force = -force; } isMoveForwardRight = target.transform.position.x < transform.position.x; float startTime = Time.time; while (startTime > 0) { float t = (Time.time - startTime) / flyTime; if (isCurve) { transform.eulerAngles = Vector3.Lerp(a, b, t); transform.position = GetPointOnBezierCurve(startPos, startPos + (Vector3.up * curveHeight), targetPoint + (Vector3.up * curveHeight), targetPoint, t); } else { transform.position = Vector3.MoveTowards(transform.position, transform.position + (Vector3.right * force), flySpeed * Time.deltaTime); //transform.position = Vector2.Lerp(transform.position, transform.position + transform.right, 3 * t); } if (isCanCounter) { if (isDisChacking) { if (ChackingDistance()) { break; } } } else if (isPush) { for (int i = 0; i < skillList.Count; i++) { SkillBase skill = skillList[i]; skill.owner = owner; skill.CheckCastCondition(); if (skill.isCoolTime == false && skill.skillData.autoExecute) { skill.Execute(); } } } if (t > 1) { break; } yield return(null); } bool isCounter = false; if (isCanCounter && owner.master.team != target.team) { BattleUnit.Team team = owner.master.team; SkillBase counterRangeSkill = target.counterSkillList.Find(x => x.skillData.effectType == "CounterRange"); if (counterRangeSkill != null && counterRangeSkill.isCoolTime == false) { //Debug.Log(owner.master.heroData.heroName + "의 공격 카운터 !!"); isCounter = true; counterRangeSkill.Execute(); BattleUnit attacker = target; target = owner.master; //캐릭터 위치에 따라 뒤집기 if (attacker is BattleHero) { BattleHero h = attacker as BattleHero; bool isFlip = h.flipX; float z = isFlip ? 180f : 0f; //transform.Rotate(new Vector3(0, 0, z)); Quaternion quaternion = new Quaternion(0, 0, z, 0); transform.rotation = quaternion; } float distance = target.GetDistanceFrom(this); while (distance > 1) { distance = target.GetDistanceFrom(this); transform.position = Vector3.MoveTowards(transform.position, target.collider.transform.position, 1); //transform.position = Vector3.Lerp(transform.position,target.transform.position,t); yield return(null); } //Debug.Log(owner.master.heroData.heroName + " 끝"); //Debug.Log("팀 변경 " + owner.master.team + "->" + attacker.team); owner.master.team = attacker.team; } } if (isPush == false) { for (int i = 0; i < skillList.Count; i++) { skillList[i].owner = owner; skillList[i].castTarget = target as BattleHero; skillList[i].Execute(); } } if (isCounter) { //Debug.Log("팀 변경 " + owner.master.team + "->" + team); owner.master.team = team; } //발사체 명중 시 파티클 재생 if (hitParticle) { GameObject hitEffectObj = Battle.GetObjectInPool(hitParticle.name); //풀링 안되어 있으면 함. if (!hitEffectObj) { hitEffectObj = Instantiate(hitParticle, target.transform.position, Quaternion.identity, owner.transform.parent) as GameObject; hitEffectObj.name = hitParticle.name; //if(!hitEffectObj.GetComponent<SelfDestroyParticle>()) // hitEffectObj.AddComponent<SelfDestroyParticle>(); hitEffectObj.SetActive(false); hitEffectObj.AddComponent <BattleGroupElement>(); Battle.AddObjectToPool(hitEffectObj); } if (hitEffectObj) { Vector3 hitPos = target.GetClosestPoint(transform.position); hitEffectObj.transform.position = hitPos; hitEffectObj.transform.localScale = Vector3.one; //발사체 오브젝트 활성 hitEffectObj.SetActive(true); hitEffectObj.GetComponent <BattleGroupElement>().SetBattleGroup(owner.battleGroup); ParticleSystem p2 = hitEffectObj.GetComponentInChildren <ParticleSystem>(); if (p2) { p2.Play(); } Animation _anim = hitEffectObj.GetComponentInChildren <Animation>(); if (_anim) { anim.Play(); } } } //파티클 끄기. (뿅하고 끄면 이상함) if (particle) { particle.Stop(); } //파티클 완전히 꺼질 때 까지 대기. 즉시 꺼지기 설정되어 있으면 이 과정 생략 while (particle && !particle.isStopped) { yield return(null); } //그리고 디스폰 Despawn(); }