public static void ActiveSkill(AbilityData _ability, Unit _Caster, bool normal = false) { //if (SkillDebugMode && _Caster.UnitType == UnitType.Unit && SimulationGameInfo.SimulationGameCheck) // Debug.Log("ActiveSkill applyTarget " + _ability.applyTarget + " , skillIdx " + _ability.skillIdx + " , notiIdx " + _ability.notiIdx); if (_ability.applyTarget == 0)// 나만 { if (_Caster.Usable) { ApplySkill((SkillType)_ability.skillType, _ability, _Caster, _Caster, normal); } } else if (_ability.applyTarget == 2) //< 논타겟(발사체에서 주로사용) { ApplySkill((SkillType)_ability.skillType, _ability, _Caster, null, normal); } else //< 그외 모두 { ushort radius = 0; radius = (ushort)(_ability.radius);/* + _LowDataMgr.GetSkillAction(_ability.Idx).range)*/ //< 뭐든간에 프로젝트타일이라면 조금더 늘려줌 if ((SkillType)_ability.skillType == SkillType.Projecttile) { radius += (ushort)((float)radius * 2); } //< 조건이 되는 모든 리스트를 구한다. List <SelectUnitData> _SelectUnitDatas = new List <SelectUnitData>(); List <Unit> targetList = GetTargetList(_ability.applyTarget, _Caster); for (int i = 0; i < targetList.Count; i++) { //< 각도 체크 if (_ability.angle > 0 && _ability.angle <= 360) { if (SceneManager.instance.IsRTNetwork && (SkillType)_ability.skillType == SkillType.Projecttile) { //네트워크 임시 프로젝타일 if (!MathHelper.InAngle(_Caster.transform.forward.normalized, _Caster.transform.position, targetList[i].transform.position, 60)) { continue; } } else { if (!MathHelper.InAngle(_Caster.transform.forward.normalized, _Caster.transform.position, targetList[i].transform.position, _ability.angle)) { continue; } } } //< 범위 체크 //if (_ability.radius > 0) if (radius > 0) { if (!MathHelper.IsInRange((targetList[i].transform.position - _Caster.transform.position), radius, _Caster.Radius, targetList[i].Radius)) { continue; } } SelectUnitData newData = new SelectUnitData(); newData.magnitude = (targetList[i].transform.position - _Caster.transform.position).magnitude; newData.Owner = targetList[i]; _SelectUnitDatas.Add(newData); } //< 제일 가까운 대상에게 사용한다. int limitTarget = _ability.targetCount == 0 ? 100 : (int)_ability.targetCount; //< 이펙트스킬이라면 이펙트카운트로 대입 if ((SkillType)_ability.skillType == SkillType.EffectSkill) { limitTarget = _ability.eCount; } //멀티플레이가 아닐때만 여기서 처리 - 멀티플레이일경우 미스처리는 서버에서 한다 if (!SceneManager.instance.IsRTNetwork) { //일단 버프는 빗나가지않게만 처리 나중에 어케할지결정 if (_ability.callBuffIdx == 0) { //선택된애들중에 명중률 계산해서 미스나면 삭제 for (int i = _SelectUnitDatas.Count - 1; i >= 0; i--) { //float HitRate = _Caster.CharInfo.HitRate - _SelectUnitDatas[i].Owner.CharInfo.DodgeRate; //bool isHit = (HitRate * 0.01f) >= Random.value; // ( (피격자의 회피 수치 – 공격자의 명중 수치) * Evade_f.Value1_f / (공격자의 명중 수치) ) + Evade_f.Value2_f // 만약 (피격자의 회피 수치 – 공격자의 명중 수치) < 0일때 0을 취함. // 만약 회피 확률 < 0 일때,회피 확율 = 0 // 만약 회피 확률 > EvadeC_f.Value1_f 일떄 회피확률 = EvadeC_f.Value1_f // 2017.8.24. kyh //새 명중률 계산 float DodgeRate = 0; if (_SelectUnitDatas[i].Owner.CharInfo.DodgeRate - _Caster.CharInfo.HitRate < 0) { DodgeRate = 0; } else { // old //DodgeRate = ((_SelectUnitDatas[i].Owner.CharInfo.DodgeRate - _Caster.CharInfo.HitRate) / (500 + _Caster.CharInfo.HitRate)); // new // ( (피격자의 회피 수치 – 공격자의 명중 수치) * Evade_f.Value1_f / (공격자의 명중 수치) ) + Evade_f.Value2_f // 2017.8.24. kyh float evade1 = _LowDataMgr.instance.GetFormula(FormulaType.EVADE, 1); float evade2 = _LowDataMgr.instance.GetFormula(FormulaType.EVADE, 2); DodgeRate = ((_SelectUnitDatas[i].Owner.CharInfo.DodgeRate - _Caster.CharInfo.HitRate) * evade1 / _Caster.CharInfo.HitRate) + evade2; } if (DodgeRate > _LowDataMgr.instance.GetFormula(FormulaType.EVADE_CAP, 1)) { DodgeRate = _LowDataMgr.instance.GetFormula(FormulaType.EVADE_CAP, 1); } bool isEvade = DodgeRate >= Random.value; //회피했다 if (isEvade) { //현재 값을 지우고 머리위에 회피를 띄우자 G_GameInfo.GameInfo.BoardPanel.ShowBuff(_SelectUnitDatas[i].Owner.gameObject, _Caster.gameObject, _LowDataMgr.instance.GetStringCommon(21)); _SelectUnitDatas.Remove(_SelectUnitDatas[i]); } } } } _SelectUnitDatas.Sort(delegate(SelectUnitData tmp1, SelectUnitData tmp2) { return(tmp1.magnitude.CompareTo(tmp2.magnitude)); }); List <Unit> targetResult = new List <Unit>(); //타겟제한에 따라 공격을 하니 네트워크 모드 일경우 여기부터 리스트를 뽑아서 따로 보내주자 for (int i = 0; i < _SelectUnitDatas.Count; i++) { //if (SceneManager.isRTNetworkMode == GAME_MODE.FREEFIGHT) if (SceneManager.instance.IsRTNetwork) { targetResult.Add(_SelectUnitDatas[i].Owner); //<---단순 리스트만 받아간다. } else { //< 스킬 사용 ApplySkill((SkillType)_ability.skillType, _ability, _Caster, _SelectUnitDatas[i].Owner, normal); } limitTarget--; if (limitTarget <= 0) { break; } } if (SceneManager.instance.IsRTNetwork) { //멀티플레이이고 이게 내 유닛이라면 서버로 데미지 계산 요청 if (_Caster.m_rUUID == G_GameInfo.PlayerController.Leader.m_rUUID || _Caster.IsPartner == true && _Caster.TeamID == G_GameInfo.PlayerController.Leader.TeamID) { if (targetResult.Count == 0) { return; } List <Sw.TargetInfo> targets = new List <Sw.TargetInfo>(); targets.Clear(); for (int i = 0; i < targetResult.Count; i++) { var Target = new Sw.TargetInfo(); if (targetResult[i].UnitType == UnitType.Npc || targetResult[i].UnitType == UnitType.Boss) { Target.UnTargetType = (int)Sw.ROLE_TYPE.ROLE_TYPE_NPC; } else if (targetResult[i].UnitType == UnitType.Unit && !targetResult[i].IsPartner) { Target.UnTargetType = (int)Sw.ROLE_TYPE.ROLE_TYPE_USER; } else if (targetResult[i].UnitType == UnitType.Unit && targetResult[i].IsPartner) { Target.UnTargetType = (int)Sw.ROLE_TYPE.ROLE_TYPE_HERO; } Target.UllTargetId = (long)targetResult[i].m_rUUID; Vector3 my = _Caster.cachedTransform.position; Vector3 target = targetResult[i].transform.position; my.y = target.y = 0; Vector3 pushingDir = (target - my).normalized * 3f; //(transform.position - attackerGO.transform.position).normalized; target = target + pushingDir; Vector3 MinPos = NaviTileInfo.instance.GetMinPos(); Target.UnPosX = (int)(Mathf.Abs(MinPos.x - target.x) / NaviTileInfo.instance.GetTileSize()); Target.UnPosY = (int)(Mathf.Abs(MinPos.z - target.z) / NaviTileInfo.instance.GetTileSize()); Target.UnPush = 1; targets.Add(Target); } //어택일경우는 데미지 체크를 보냄 if ((SkillType)_ability.skillType == SkillType.Attack || (SkillType)_ability.skillType == SkillType.AttackBuff) { //데미지일 경우 //iFunClient.instance.ReqDamage(_Caster.m_rUUID, _LowDataMgr.GetSkillAction(_ability.Idx).idx, _ability.notiIdx, _Caster.transform.position, _Caster.transform.eulerAngles.y, a_list); NetworkClient.instance.SendPMsgRoleAttackC((int)_LowDataMgr.GetSkillAction(_ability.Idx).idx, 0, (int)_ability.notiIdx, 1, ref targets); } else if ((SkillType)_ability.skillType == SkillType.Projecttile) { //프로젝타일 일경우 //iFunClient.instance.ReqDamage(_Caster.m_rUUID, _LowDataMgr.GetSkillAction(_ability.Idx).idx, _ability.notiIdx, _Caster.transform.position, _Caster.transform.eulerAngles.y, a_list); } else if ((SkillType)_ability.skillType == SkillType.Buff) { //버프일 경우 //iFunClient.instance.ReqBuff(_Caster.m_rUUID, _LowDataMgr.GetSkillAction(_ability.Idx).idx, _ability.notiIdx); } else if ((SkillType)_ability.skillType == SkillType.EffectSkill) { //장판스킬일경우 - 없다는데 봐야알지 } else if ((SkillType)_ability.skillType == SkillType.Heal) { //힐스킬일경우 - 없다는데 봐야알지 } } } } }
//< 범위안에 모든적을 공격한다. void AllTakeDamage(bool targetCountCheck = true) { Vector3 a_TargetPos; Vector3 a_ArrowPos = ModelObj.transform.position; byte targetCount = (byte)(projectileInfo.penetrateCount == 0 ? (byte)50 : projectileInfo.penetrateCount); float radius = projectileInfo.radius; List <Unit> targets = G_GameInfo.CharacterMgr.liveList_All((byte)(Owner.TeamID == 0 ? 1 : 0)); for (int j = 0; j < targets.Count; j++) { if (targets[j] == null || targets[j].IsDie) { continue; } //< 범위안에 있을경우 대미지! a_TargetPos = targets[j].transform.position; a_ArrowPos.y = a_TargetPos.y = 0; if ((a_TargetPos - a_ArrowPos).magnitude < radius) { Explode(targets[j]); if (targetCountCheck) { targetCount--; if (targetCount == 0) { break; } } } } if (SceneManager.instance.IsRTNetwork && (Owner.m_rUUID == NetData.instance._userInfo._charUUID)) { //묶어서 여기에서 보냄 List <Sw.TargetInfo> targetdata = new List <Sw.TargetInfo>(); targetdata.Clear(); for (int i = 0; i < netDamageList.Count; i++) { var Target = new Sw.TargetInfo(); if (netDamageList[i].UnitType == UnitType.Npc || netDamageList[i].UnitType == UnitType.Boss) { Target.UnTargetType = (int)Sw.ROLE_TYPE.ROLE_TYPE_NPC; } else if (netDamageList[i].UnitType == UnitType.Unit && !netDamageList[i].IsPartner) { Target.UnTargetType = (int)Sw.ROLE_TYPE.ROLE_TYPE_USER; } else if (netDamageList[i].UnitType == UnitType.Unit && netDamageList[i].IsPartner) { Target.UnTargetType = (int)Sw.ROLE_TYPE.ROLE_TYPE_HERO; } Target.UllTargetId = (long)netDamageList[i].m_rUUID; targetdata.Add(Target); } //어택일경우는 데미지 체크를 보냄 //if ((SkillType)abilityData.skillType == SkillType.Attack) { //데미지일 경우 NetworkClient.instance.SendPMsgRoleAttackC((int)_LowDataMgr.GetSkillAction(abilityData.Idx).idx, 0, (int)abilityData.notiIdx, 1, ref targetdata, (long)ProjectTileId); } targetdata.Clear(); //일단 데미지를 줬으니 리셋 netDamageList.Clear(); } }