Project_WL/Assets/Script/Character/Actor.cs

2222 lines
87 KiB
C#
Raw Normal View History

2025-02-13 04:40:04 +00:00
using CodeStage.AntiCheat.ObscuredTypes;
2024-12-15 01:39:39 +00:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
2025-03-28 04:24:01 +00:00
using TrailsFX;
2024-12-15 01:39:39 +00:00
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Rendering;
2024-12-28 00:20:09 +00:00
using UnityEngine.SceneManagement;
2024-12-15 01:39:39 +00:00
public class Actor : MyCoroutine
{
public GameObject[] gos_Effect;
public eRole m_Role; // 프리팹 설정
public eSubRol m_SubRole; // 프리팹 설정
public eAttackType m_AttackType; // 프리팹 설정
protected NavMeshAgent m_NavMeshAgent;
protected BoxCollider m_BoxCollider;
eAnim _curanim;
protected eAnim CurAnim
{
get { return _curanim; }
set
{
_curanim = value;
//if (IsRole(eRole.PC)) Debug.Log("애님 변경 " + value);
}
}
public Animator m_animation;
protected ActorStatInfo m_Stat;
protected double receiveaccumulateDmg, m_Damage, m_attackCoolTime; // 내가 받은 피해, 내가 준 피해, 공격 쿨타임
2025-03-03 01:55:09 +00:00
protected Transform tf_HUD_HP, tf_HUD_Dmg, tf_Top;
2025-01-13 02:40:17 +00:00
protected Vector3 ObjSize;
2024-12-15 01:39:39 +00:00
[SerializeField]
Actor _target;
protected Actor m_Target
{
get { return _target; }
set
{
_target = value;
isTarget = value;
}
}
public bool isTarget = false;
protected Actor m_MyPet;
2024-12-15 01:39:39 +00:00
protected Dictionary<int, UseMagicInfo> dic_MagicData = new Dictionary<int, UseMagicInfo>();
protected UseMagicInfo m_Magic;
2025-02-25 06:28:10 +00:00
protected float m_NavSpeed, m_NavStopDistance, m_HitTime, FindOtherTargetTime = 7.5f, GoToTargetTime = 10f, m_fAttackMoveTime, m_DamageRate = 1f;
protected bool m_Enemy, IsPlaySkill, m_Auto, DeadStatus, hasAppliedDamage;
2024-12-15 01:39:39 +00:00
protected bool _isstop;
protected bool IsStop
{
get { return _isstop; }
set
{
_isstop = value;
2025-02-21 07:10:14 +00:00
//if (IsSubRole(eSubRol.Boss))
2025-02-21 23:47:07 +00:00
//if (IsRole(eRole.PC)) Debug.Log("IsStop 변경 " + value);
2024-12-15 01:39:39 +00:00
}
}
public bool m_IsLockTarget { get; set; }
protected bool m_bCanDodge, m_bImmortal;
protected int m_ID;
protected ServerData m_ServerData;
protected Renderer[] arr_Renderer;
protected TurnOff_GO[] arr_Effects;
protected Dictionary<eSkillExtraType, bool> dic_skillextra = new Dictionary<eSkillExtraType, bool>(); // 부가 효과 적용 여부
2024-12-15 01:39:39 +00:00
protected Dictionary<eCC, CCData> dic_ccData = new Dictionary<eCC, CCData>();
2025-02-13 22:49:30 +00:00
protected Dictionary<eCC, float> dic_ccValue = new Dictionary<eCC, float>();
2024-12-15 01:39:39 +00:00
protected Dictionary<eCC, Dictionary<Actor, double>> dic_ccAddRate = new Dictionary<eCC, Dictionary<Actor, double>>();
protected Dictionary<eCC, TurnOff_GO> dic_CCEffect = new Dictionary<eCC, TurnOff_GO>();
2025-02-13 04:40:04 +00:00
protected ObscuredInt _Reincarnation;
public int n_Reincarnation
{
get { return _Reincarnation; }
2025-02-21 01:07:35 +00:00
set
{
_Reincarnation = value;
_Reincarnation.RandomizeCryptoKey();
}
2025-02-13 04:40:04 +00:00
}
protected int n_SummonCount;
2025-02-21 01:07:35 +00:00
protected float NoDmgTime = 0f;
2025-01-17 00:28:44 +00:00
2024-12-15 01:39:39 +00:00
protected void Init_CC()
{
if (dic_ccData.Count == 0)
for (eCC i = 0; i < eCC.Max; i++)
dic_ccData.Add(i, new CCData());
foreach (var item in dic_ccData)
item.Value.Init();
2025-02-13 22:49:30 +00:00
foreach (var key in dic_ccValue.Keys.ToList())
dic_ccValue[key] = 0f;
2024-12-15 01:39:39 +00:00
dic_ccAddRate.Clear();
foreach (var key in dic_skillextra.Keys.ToList())
dic_skillextra[key] = false;
2025-03-01 03:41:56 +00:00
foreach (var item in dic_CCEffect)
dic_CCEffect[item.Key].Off_Imm();
2024-12-15 01:39:39 +00:00
}
protected void Check_CCAddRate(eCC cc, Actor actor, double v = 0)
{
if (!dic_ccAddRate.ContainsKey(cc)) dic_ccAddRate.Add(cc, new Dictionary<Actor, double>());
if (!dic_ccAddRate[cc].ContainsKey(actor)) dic_ccAddRate[cc].Add(actor, v);
}
protected double Get_CCAddRate(eCC cc, Actor actor)
{
return dic_ccAddRate.ContainsKey(cc) && dic_ccAddRate[cc].ContainsKey(actor) ? dic_ccAddRate[cc][actor] : 0;
}
protected Action<bool> act_MoveEnd;
protected List<ProjectileData> list_SkillData = new List<ProjectileData>();
ProjectileData m_SkillData;
2025-03-05 03:47:01 +00:00
public HUDUI m_HUDUI;
protected bool isHUDUI;
2024-12-15 01:39:39 +00:00
protected virtual void Awake()
{
m_NavMeshAgent = GetComponent<NavMeshAgent>();
m_BoxCollider = GetComponent<BoxCollider>();
m_animation = GetComponent<Animator>();
arr_Renderer = GetComponentsInChildren<Renderer>();
arr_Effects = GetComponentsInChildren<TurnOff_GO>(true);
for (int i = 0; i < 6; i++)
list_SkillData.Add(new ProjectileData { shooter = this });
// HUD 만들기
Make_HUDobj();
m_NavSpeed = m_NavMeshAgent.speed;
m_NavStopDistance = m_NavMeshAgent.stoppingDistance;
}
void Make_HUDobj()
{
float maxY = float.MinValue; // 가장 큰 y값을 저장할 변수
// 캐릭터 하위의 모든 Renderer를 찾음
Renderer[] renderers = GetComponentsInChildren<Renderer>();
// 각 Renderer의 Bounds.max.y를 비교
foreach (Renderer renderer in renderers)
{
float rendererMaxY = renderer.bounds.max.y;
if (rendererMaxY > maxY)
{
maxY = rendererMaxY;
}
}
2025-03-03 01:55:09 +00:00
Set_TF_HUD("HUD_HP", ref tf_HUD_HP, Get_position() + Vector3.down * 0.1f);
Set_TF_HUD("HUD_Dmg", ref tf_HUD_Dmg, Get_position() + Vector3.up * 0.5f);
Set_TF_HUD("HUD_Top", ref tf_Top, new Vector3(transform.position.x, maxY, transform.position.z));
2024-12-15 01:39:39 +00:00
}
protected virtual void Start()
{
}
protected virtual void OnEnable()
{
if (gos_Effect != null) DSUtil.InActivateGameObjects(gos_Effect);
StartCoroutine(Co_Update_ETC());
2024-12-15 01:39:39 +00:00
}
protected virtual void OnDestroy()
{
2025-03-05 03:47:01 +00:00
Off_Common();
2024-12-15 01:39:39 +00:00
}
virtual protected void Update() { }
2024-12-15 01:39:39 +00:00
2025-03-05 03:47:01 +00:00
void Off_Common()
{
if (isHUDUI)
{
m_HUDUI.Off(true);
isHUDUI = false;
}
}
IEnumerator Co_Update_ETC()
2024-12-15 01:39:39 +00:00
{
while (true)
2024-12-15 01:39:39 +00:00
{
yield return null;
2024-12-15 01:39:39 +00:00
2025-02-21 01:07:35 +00:00
if (NoDmgTime > 0f) NoDmgTime -= Time.deltaTime;
foreach (var item in dic_ccData)
2024-12-15 01:39:39 +00:00
{
if (item.Value.CCReduceTime > 0f)
2024-12-15 01:39:39 +00:00
{
item.Value.CCReduceTime -= 0.0001f;
if (item.Value.CCReduceTime < 0f)
item.Value.CCReduceTime = 0f;
}
if (item.Value.TimeUpdate && item.Value.CCTime > 0)
{
item.Value.CCTime -= Time.deltaTime;
if (item.Key == eCC.SilenceCurse)
2024-12-15 01:39:39 +00:00
{
item.Value.CC1Sec += Time.deltaTime;
if (item.Value.CC1Sec >= 1f)
{
item.Value.CC1Sec = 0f;
Heal_MP(-(Get_MaxMP() * item.Value.CCDmg));
}
}
if (item.Value.CCTime <= 0)
{
switch (item.Key)
{
case eCC.STR_Mul_Up: Off_StatUpBuff(eStat.STR); break;
case eCC.DEX_Mul_Up: Off_StatUpBuff(eStat.DEX); break;
case eCC.INT_Mul_Up: Off_StatUpBuff(eStat.INT); break;
case eCC.LUK_Mul_Up: Off_StatUpBuff(eStat.LUK); break;
2025-02-26 02:42:03 +00:00
case eCC.Barrier:
dic_ccData[item.Key].CCDmg = 0;
dic_CCEffect[item.Key].Off_Imm();
break;
}
2024-12-15 01:39:39 +00:00
}
}
}
}
}
2025-03-03 01:55:09 +00:00
void Set_TF_HUD(string goname, ref Transform tf, Vector3 pos)
{
var hud = new GameObject(goname);
tf = hud.transform;
tf.parent = transform;
tf.position = pos;
}
2025-01-17 00:28:44 +00:00
public bool isPlaying()
2024-12-15 01:39:39 +00:00
{
float normalizedTime = m_animation.GetCurrentAnimatorStateInfo(0).normalizedTime;
// normalizedTime을 0.0에서 1.0 사이로 맞춤
normalizedTime = Mathf.Repeat(normalizedTime, 1.0f);
// 애니메이션이 95% 이하로 진행 중인지 확인
return normalizedTime < 0.95f;
}
protected bool isPlaying(params eAnim[] anims)
{
var curState = m_animation.GetCurrentAnimatorStateInfo(0);
for (int i = 0; i < anims.Length; i++)
{
if (curState.IsName(MyValue.Get_AnimName(anims[i])))
return true;
}
return false;
}
public virtual void Set_Target(bool forcefind = false) { }
2024-12-15 01:39:39 +00:00
public virtual void Set(bool isEnemy, Actor owner, ServerData sdata, int _id, bool _stop, bool _ui = false)
{
if (IsRole(eRole.PC)) ObjSize = GetComponent<CapsuleCollider>().bounds.size;
else ObjSize = GetComponentInChildren<SkinnedMeshRenderer>().bounds.size;
gameObject.SetActive(true);
Init_CC();
DeadStatus = false;
m_Enemy = isEnemy;
m_ServerData = sdata;
CurAnim = eAnim.Idle;
Play_Idle();
m_ID = _id;
IsStop = _stop;
//m_NavMeshAgent.speed = m_NavSpeed;
receiveaccumulateDmg = m_Damage = 0;
}
public virtual void Off()
{
2025-03-05 03:47:01 +00:00
Off_Common();
2024-12-15 01:39:39 +00:00
gameObject.SetActive(false);
}
2025-03-05 03:47:01 +00:00
protected HUDUI Get_HUDUI()
{
if (!isHUDUI)
{
m_HUDUI = InGameInfo.Ins.Get_HUDUI();
isHUDUI = m_HUDUI;
}
return m_HUDUI;
}
2024-12-15 01:39:39 +00:00
public virtual void Set_Card(int index, int chapter) { }
public virtual void ReSet() { }
public virtual void Set_Stat(bool init)
{
if (DSUtil.CheckNull(m_Stat))
m_Stat = MyValue.MakeorGet_ActorStatInfo(m_Role, Get_ServerData(), null);
else
m_Stat.Reset();
m_NavMeshAgent.speed = (float)m_Stat.Get_Stat(eStat.FinalMoveSpeed);
}
protected void Add_MoveSpeed(float _v) { m_NavMeshAgent.speed = Mathf.Min(m_NavSpeed + _v, 8.5f); }
public virtual void Set_MaxHP_Minus_HP(double _hp) { m_Stat.Set_Stat(false, eStat.HP, _hp); }
public virtual void Set_Stat_SelectSkill(SelectSkillTableData _sstd) { }
public virtual void Stop(bool _stop)
{
2025-02-16 00:14:00 +00:00
if (IsStop && !_stop)
{
Change_MobStatus(eMobStatus.PatrolWait);
Check_Battle();
}
2024-12-15 01:39:39 +00:00
IsStop = _stop;
if (IsStop)
{
if (m_NavMeshAgent && m_NavMeshAgent.isOnNavMesh) m_NavMeshAgent.ResetPath();
Play_Idle();
}
}
public void Set_AttackCoolTime(float _rate)
{
var cooltime = m_Stat.Get_Stat(eStat.AttackCoolTime) * _rate;
if (m_attackCoolTime > cooltime)
m_attackCoolTime = cooltime;
}
2025-02-19 04:14:09 +00:00
public virtual DamageInfo Get_DamageInfo(ProjectileData _pd, bool forceCri = false)
2024-12-15 01:39:39 +00:00
{
var atkData = Get_CCData(eCC.ATK_Up);
var addAtk = atkData.CCTime > 0 ? atkData.CCDmg : 0f;
var dinfo = new DamageInfo();
dinfo.Beater = this;
dinfo.Beater_pd = _pd;
dinfo.BaseDmg = addAtk + (_pd.BaseDmg > 0 ? _pd.BaseDmg : m_Stat.Get_Stat(eStat.BaseDmg));
2025-02-13 23:52:05 +00:00
if (dic_ccValue.ContainsKey(eCC.ATK_Mul)) dinfo.BaseDmg += dinfo.BaseDmg * dic_ccValue[eCC.ATK_Mul];
var atkDownData = Get_CCData(eCC.ATK_Down);
if (atkDownData.CCTime > 0f) dinfo.BaseDmg -= dinfo.BaseDmg * atkDownData.CCDmg;
2025-01-20 06:47:44 +00:00
if (dic_ccData[eCC.MultiShot].CCTime > 0f)
dinfo.BaseDmg -= dinfo.BaseDmg * dic_ccData[eCC.MultiShot].CCDmg;
dinfo.NoCriDmg = dinfo.Damage = dinfo.BaseDmg * _pd.AddDmgPercent;
dinfo.PiercingDmg = dinfo.BaseDmg *
(m_Stat.Get_Stat(eStat.PIERCING_Multiplier) +
dinfo.Get_AddValue(eAddExtraType.Add_Piercing_Multiplier_bySpiriBless));
2024-12-15 01:39:39 +00:00
dinfo.TextColor = HUDBase.Get_TextColor(m_AttackType);
if (dic_ccData[eCC.PiercingBuff].CCTime > 0)
2024-12-16 06:01:17 +00:00
dinfo.PiercingDmg += dinfo.BaseDmg * m_Stat.Get_Stat(eStat.PiercingBuff_byAttack);
2024-12-15 01:39:39 +00:00
2024-12-16 06:01:17 +00:00
dinfo.Cal_Cri(m_AttackType, m_Stat, forceCri); // 크리티컬 판정
2024-12-15 01:39:39 +00:00
return dinfo;
}
public virtual void Get_Damage(DamageInfo _dinfo)
{
if (IsDead() || m_bImmortal) return;
if (_dinfo.Damage < 1) _dinfo.Damage = 1d;
//if (Get_HP() >= Get_MaxHP() && Get_HP() <= _dinfo.Damage) // 한 방에 사망
// Kill_OnePunch(_dinfo);
//VeryStrongDamage(_dinfo.Damage);
2024-12-15 01:39:39 +00:00
//if (!IsRole(eRole.PC)) _dinfo.Damage = 2500; // 테스트 : 데미지 고정
if (!DSUtil.CheckNull(_dinfo.Beater))
{
var beaterStat = _dinfo.Beater.Get_StatInfo();
double reduceDef = 0d, atk_fixed = 0d;
// 방어력 계산
double def = 0d;
switch (_dinfo.Beater.m_AttackType)
{
case eAttackType.Physics:
def = m_Stat.Get_Stat(eStat.FinalDef);
def -= beaterStat.Get_Stat(eStat.DEF_Ignore);
def -= def * (beaterStat.Get_Stat(eStat.DEF_Ignore_Rate) * beaterStat.Get_MainStatValue());
var hpper = (float)(m_Stat.Get_Stat(eStat.HP) / m_Stat.Get_Stat(eStat.MaxHP));
if (hpper <= m_Stat.Get_Stat(eStat.HeroBuffHP))
def += m_Stat.Get_Stat(eStat.DEF) * m_Stat.Get_Stat(eStat.HeroBuff_DEF);
2025-02-13 23:52:05 +00:00
if (dic_ccValue.ContainsKey(eCC.DEF_Mul)) def += def * dic_ccValue[eCC.DEF_Mul];
2024-12-15 01:39:39 +00:00
Check_CCAddRate(eCC.DEF_Down, _dinfo.Beater);
++dic_ccAddRate[eCC.DEF_Down][_dinfo.Beater];
if (dic_ccAddRate[eCC.DEF_Down][_dinfo.Beater] > beaterStat.Get_Stat(eStat.DEF_Down_Limit))
dic_ccAddRate[eCC.DEF_Down][_dinfo.Beater] = beaterStat.Get_Stat(eStat.DEF_Down_Limit);
reduceDef = beaterStat.Get_Stat(eStat.DEF_Down) * dic_ccAddRate[eCC.DEF_Down][_dinfo.Beater]; // 방어력 감소 체크
def -= reduceDef;
if (beaterStat.Get_Stat(eStat.DEF_Down_Step3) >= 1)
atk_fixed = reduceDef;
if (dic_ccData[eCC.DEF_Down].CCTime > 0f)
def -= dic_ccData[eCC.DEF_Down].CCDmg;
break;
case eAttackType.Magic:
def = m_Stat.Get_Stat(eStat.FinalMDef);
Check_CCAddRate(eCC.M_DEF_Down, _dinfo.Beater);
++dic_ccAddRate[eCC.M_DEF_Down][_dinfo.Beater];
if (dic_ccAddRate[eCC.M_DEF_Down][_dinfo.Beater] > beaterStat.Get_Stat(eStat.M_DEF_Down_Limit))
dic_ccAddRate[eCC.M_DEF_Down][_dinfo.Beater] = beaterStat.Get_Stat(eStat.M_DEF_Down_Limit);
2025-02-13 23:52:05 +00:00
if (dic_ccValue.ContainsKey(eCC.MDEF_Mul)) def += def * dic_ccValue[eCC.MDEF_Mul];
2024-12-15 01:39:39 +00:00
reduceDef = beaterStat.Get_Stat(eStat.M_DEF_Down) * dic_ccAddRate[eCC.M_DEF_Down][_dinfo.Beater]; // 마법저항력 감소 체크
def -= reduceDef;
if (beaterStat.Get_Stat(eStat.M_DEF_Down_Step3) >= 1)
atk_fixed = reduceDef;
if (dic_ccData[eCC.M_DEF_Down].CCTime > 0f)
def -= dic_ccData[eCC.M_DEF_Down].CCDmg;
break;
}
if (def > 0f)
{
double defmul = table_GlobalValue.Ins.Get_Int("Defense_Coefficient");
// 기존 def_cal 계산식에서 / 를 *로 변경
var def_cal = def * defmul * (0.0001 + def * defmul * 0.0001) * 1000000;
var dmg = Math.Round(def_cal * _dinfo.Damage * 0.000001); // /1000000을 *0.000001로 변경
_dinfo.Damage -= dmg;
}
else
{
var cal1 = 2d - Math.Pow(0.94d, def * 0.01);
2024-12-15 01:39:39 +00:00
var cal2 = cal1 * 1000000;
var cal3 = cal2 * _dinfo.Damage;
_dinfo.Damage = Math.Round(cal3 * 0.000001); // /1000000을 *0.000001로 변경
}
// 몬스터 데미지 추가
if (IsSubRole(eSubRol.None))
2024-12-15 01:39:39 +00:00
{
Check_CCAddRate(eCC.MobDamage, _dinfo.Beater);
++dic_ccAddRate[eCC.MobDamage][_dinfo.Beater];
if (dic_ccAddRate[eCC.MobDamage][_dinfo.Beater] > beaterStat.Get_Stat(eStat.MobDamage_Limit))
dic_ccAddRate[eCC.MobDamage][_dinfo.Beater] = beaterStat.Get_Stat(eStat.MobDamage_Limit);
_dinfo.Damage += _dinfo.Damage * beaterStat.Get_Stat(eStat.Monster_DMG_Multiplier) * dic_ccAddRate[eCC.MobDamage][_dinfo.Beater];
_dinfo.PiercingDmg += beaterStat.Get_Stat(eStat.BaseDmg) * beaterStat.Get_Stat(eStat.MOB_Piercing_Multiplier);
}
else if (IsSubRole(eSubRol.Boss))
2024-12-15 01:39:39 +00:00
{
Check_CCAddRate(eCC.BossDamage, _dinfo.Beater);
++dic_ccAddRate[eCC.BossDamage][_dinfo.Beater];
if (dic_ccAddRate[eCC.BossDamage][_dinfo.Beater] > beaterStat.Get_Stat(eStat.BossDamage_Limit))
dic_ccAddRate[eCC.BossDamage][_dinfo.Beater] = beaterStat.Get_Stat(eStat.BossDamage_Limit);
_dinfo.Damage += _dinfo.Damage * beaterStat.Get_Stat(eStat.BOSS_DMG_Multiplier) * dic_ccAddRate[eCC.BossDamage][_dinfo.Beater];
_dinfo.PiercingDmg += beaterStat.Get_Stat(eStat.BaseDmg) * beaterStat.Get_Stat(eStat.BOSS_Piercing_Multiplier);
}
// 고정 피해 계산
_dinfo.Damage += (int)_dinfo.Beater.m_Stat.Get_Stat(eStat.ATK_FIXED) + (int)atk_fixed - (int)m_Stat.Get_Stat(eStat.ATK_FIXED_DECREASE);
2025-02-12 23:16:26 +00:00
if (_dinfo.Beater.m_Stat.Get_Stat(eStat.ADD_ATK_FIXED) > 0)
_dinfo.Damage += Get_MaxHP() * _dinfo.Beater.m_Stat.Get_Stat(eStat.ADD_ATK_FIXED);
2024-12-15 01:39:39 +00:00
if (_dinfo.Damage < 1d) _dinfo.Damage = 1d;
}
_dinfo.PiercingDmg -= _dinfo.PiercingDmg * m_Stat.Get_Stat(eStat.PIERCING_Block);
_dinfo.Damage += _dinfo.PiercingDmg; // 관통 피해 추가
// 데미지 감소 적용
_dinfo.Damage -= _dinfo.Damage * m_Stat.Get_Stat(eStat.DMG_DECREASE);
2025-02-11 00:15:02 +00:00
if (_dinfo.Beater_pd.IsSkill())
_dinfo.Damage -= _dinfo.Damage * m_Stat.Get_Stat(eStat.SkillDmg_DECREASE);
else
_dinfo.Damage -= _dinfo.Damage * m_Stat.Get_Stat(eStat.BaseDmg_DECREASE);
2024-12-15 01:39:39 +00:00
if (dic_ccData[eCC.ManaShield].CCTime > 0d)
{ // 마나 실드
var reduceDmg = Mathf.Max(1, (int)(_dinfo.Damage * dic_ccData[eCC.ManaShield].CCDmg));
_dinfo.Damage -= reduceDmg;
var useMP = Mathf.Max(1, (int)(reduceDmg * dic_ccData[eCC.ManaShield].CCReduceTime));
Heal_MP(-useMP, true);
if (m_Stat.Get_Stat(eStat.MP) <= 0)
{
dic_ccData[eCC.ManaShield].CCTime = 0d;
dic_CCEffect[eCC.ManaShield].Off_Imm();
2024-12-15 01:39:39 +00:00
}
}
2024-12-28 00:20:09 +00:00
Cal_Damage(_dinfo);
Check_CC_byAttack(_dinfo);
2025-02-13 04:40:04 +00:00
Check_Extra(eSkillExtraTiming.GetHit);
2024-12-28 00:20:09 +00:00
if (IsRole(eRole.Mob)) MyValue.m_RealCamera.ShakeCamera(1); // 카메라 흔들림 추가
2024-12-15 01:39:39 +00:00
#if UNITY_EDITOR
2025-01-30 23:36:55 +00:00
if (SceneManager.GetActiveScene().name == "StatTest")
2024-12-15 01:39:39 +00:00
{
MainToStatTest.Ins.Set_Dmglabel(HUDBase.Get_TextColor(_dinfo.Beater.m_AttackType) + (_dinfo.Critical == eStat.CRI || _dinfo.Critical == eStat.M_CRI ? "" + _dinfo.Critical + " " : " ") + _dinfo.Damage);
return;
}
#endif
}
public virtual void Cal_Damage(DamageInfo _dinfo)
{
if (IsDead()) return;
2025-02-21 01:07:35 +00:00
if (NoDmgTime > 0f) _dinfo.Damage = 0d;
2024-12-15 01:39:39 +00:00
2025-01-31 03:21:18 +00:00
if (MyValue.MyChoiceMapData.Get_MapData().e_Dungeon == eDungeon.d3_Nightmare && IsSubRole(eSubRol.Boss))
{
var diff = MyValue.MyChoiceMapData.n_Difficult;
var addmul = diff == 1 ? 1 : diff == 2 ? 1.5d : 2.5d;
2025-02-02 05:19:34 +00:00
DungeonInfo.Ins.Add_TotalDmg(_dinfo.Damage * addmul);
2025-01-31 03:21:18 +00:00
}
2025-01-30 23:36:55 +00:00
else
{
if (dic_ccData[eCC.Barrier].CCDmg > 0)
{ // 배리어가 있으면 배리어부터 계산
_dinfo.TextColor = "Barrier";
dic_ccData[eCC.Barrier].CCDmg -= _dinfo.Damage;
if (dic_ccData[eCC.Barrier].CCDmg <= 0)
{ // 배리어를 넘어가는 데미지 계산
var dmg = Math.Abs(dic_ccData[eCC.Barrier].CCDmg);
if (dmg > 0) m_Stat.Set_Stat(false, eStat.HP, dmg);
dic_ccData[eCC.Barrier].CCDmg = 0;
dic_CCEffect[eCC.Barrier].Off_Imm();
}
}
else
m_Stat.Set_Stat(false, eStat.HP, _dinfo.Damage);
}
2025-01-30 23:36:55 +00:00
2024-12-15 01:39:39 +00:00
_dinfo.act_returnLastDmg?.Invoke(_dinfo.Damage);
_dinfo.act_CriAfterHit?.Invoke(_dinfo.Critical);
Add_ReceiveDmg(_dinfo.Damage);
_dinfo.Beater?.Add_MyRealDmg(_dinfo.Damage);
BossRaidCard_HP();
var pd = _dinfo.Beater_pd;
2025-03-01 03:21:02 +00:00
bool ispd = !DSUtil.CheckNull(pd);
2024-12-15 01:39:39 +00:00
if (m_Stat.Get_Stat(eStat.HP) <= 0d)
{
Check_Drain_byKill(_dinfo);
DeadStatus = _dinfo.IsDeadByThisDamage = true;
Set_Die();
if (_dinfo.Beater.IsRole(eRole.BattleNPC))
ServerInfo.Ins.m_ServerData.Add_TitleCondition(72, 73); // 칭호 : 승차감 좋은 버스, 택시
2025-03-01 03:21:02 +00:00
if (ispd && pd.IsSkill(eEffect.Skill_Ignited) && pd.CC_AddVal2 > 0)
2024-12-15 01:39:39 +00:00
{ // 버닝효과 체크, 버닝 효과 발동
var ccData = Get_CCData(eCC.Burn);
if (ccData.CCTime > 0f)
{
2025-03-01 03:21:02 +00:00
var other = ActorInfo.Ins.Get_Nearest_AllyActor(IsEnemy(), Get_position(), 5f);
2024-12-15 01:39:39 +00:00
if (!DSUtil.CheckNull(other))
{
other.DotDamage(eCC.Burn, pd.shooter.Get_DamageInfo(pd), ccData.CCTime,
pd.m_SkillListTableData.f_ExtraValue2 + pd.CC_AddVal1, pd.m_SkillListTableData.f_ExtraValue3);
pd.m_ProjectileBase.Show_Effect(other, (float)ccData.CCTime);
2024-12-15 01:39:39 +00:00
}
}
}
}
else
{
2025-03-01 03:21:02 +00:00
if (!ispd || ispd && !pd.IsSkill(eEffect.Skill_Ignited) && !pd.IsSkill(eEffect.Select_BodyonFire))
2024-12-15 01:39:39 +00:00
Play_Hit();
}
2024-12-28 00:20:09 +00:00
#if UNITY_EDITOR
if (SceneManager.GetActiveScene().name == "StatTest")
2024-12-28 00:20:09 +00:00
return;
#endif
2024-12-15 01:39:39 +00:00
// UI 설정
2025-03-05 03:47:01 +00:00
Get_HUDUI().Set_HPSlider(this);
2024-12-15 01:39:39 +00:00
InGameInfo.Ins.Get_HUDDMGUI().Set(tf_HUD_Dmg, _dinfo.TextColor, _dinfo.Damage, _dinfo.Critical);
//if (IsRole(eRole.Boss)) { GameUI.Ins.IngameUI.m_BossInfoUI.Set_HP(m_Stat.Get_Stat(eStat.HP), m_Stat.Get_Stat(eStat.MaxHP)); } // TODO 정인호 : 보스 hp ui
}
public void Add_MyRealDmg(double _dmg) { m_Damage += _dmg; }
public double Get_RealDamage() { return m_Damage; }
public virtual void Add_ReceiveDmg(double _dmg) { receiveaccumulateDmg += _dmg; }
public double Get_ReceiveDmg() { return receiveaccumulateDmg; }
protected virtual void Kill_OnePunch(DamageInfo dinfo) { }
protected virtual void VeryStrongDamage(double dmg) { }
public virtual void OnTrigger_Damage(Actor _actor) { }
protected virtual void Set_Die()
{
Cancel_Freeze(0f);
foreach (var key in dic_ccCoroutine.Keys.ToList()) dic_ccCoroutine[key] = null;
Play_Die();
Set_Coroutine(After_Die, 3f); // TODO 정인호 : 애니메이터에서 애니메이션 길이값 가져오는 법이 있긴 한데 일관성이 없음
if (m_BoxCollider) m_BoxCollider.enabled = false;
m_NavMeshAgent.enabled = false;
m_IsLockTarget = false;
Set_Outline(false);
}
protected virtual void After_Die()
{
2025-02-21 01:07:35 +00:00
Check_Extra(eSkillExtraTiming.AfterDie); // 부활 체크 (Reincarnation 은 여기서 처리)
2025-02-13 04:40:04 +00:00
if (!IsDead()) return; // 부활한 경우
2024-12-15 01:39:39 +00:00
#if UNITY_EDITOR
if (SceneManager.GetActiveScene().name == "StatTest")
2024-12-15 01:39:39 +00:00
{
On_Regen();
transform.localPosition = Vector3.zero;
CurAnim = eAnim.Die;
Play_Idle();
MyValue.MyPC.Change_Target(false, this);
return;
}
#endif
m_animation.speed = 0f;
switch (m_Role)
{
case eRole.Mob:
case eRole.OBJ:
Off();
break;
case eRole.PC:
//InGameInfo.Ins.Defeat_byMonster();
2025-03-07 23:45:34 +00:00
// PC 부활
On_Regen();
if (!IsEnemy())
{
2025-03-07 23:45:34 +00:00
// 소환수 이동
var summ = ActorInfo.Ins.Get_Actor(eRole.Summon);
if (!DSUtil.CheckNull(summ)) summ.On_Regen();
// 펫 부활
if (!DSUtil.CheckNull(m_MyPet)) m_MyPet.On_Regen();
// 일꾼 이동
var worker = ActorInfo.Ins.Get_Actor(eRole.Worker);
if (!DSUtil.CheckNull(worker)) worker.On_Regen();
}
2024-12-15 01:39:39 +00:00
break;
}
}
protected void Reset_AttackCoolTime() { m_attackCoolTime = m_Stat.Get_Stat(eStat.AttackCoolTime); }
protected virtual void Heal_To_Target() { }
protected virtual void Set_Script() { }
protected virtual void Create_LastEffect() { }
public virtual void BossRaidCard_AddDmg(double _dmg) { }
public virtual void BossRaidCard_HP() { }
2025-04-02 23:29:27 +00:00
public virtual bool Use_Skill(SkillListTableData skilldata, bool autoskill, int index, bool testskill = false)
2024-12-15 01:39:39 +00:00
{
if (skilldata.e_SkillType == eSkillType.Passive) return false;
if (CurAnim >= eAnim.Skill)
{
if (!autoskill) MessageInfo.Ins.Add_Log(109);
return false;
}
// 내 직업이 사용할 수 있는 스킬인가?
if (skilldata.n_SkillClassID > 0 && skilldata.n_SkillClassID != m_ID)
return false;
// 침묵의 저주에 걸린 경우 스킬 사용 불가
var SilenceCurseData = Get_CCData(eCC.SilenceCurse);
if (SilenceCurseData.CCTime > 0f) return false;
2024-12-15 01:39:39 +00:00
m_Magic = dic_MagicData[index];
2025-04-02 23:29:27 +00:00
if (testskill) m_Magic.m_SkillTableData = skilldata;
2024-12-15 01:39:39 +00:00
if (IsDead() || IsCC() || CurAnim >= eAnim.Skill)
{
Del_Magic();
return false;
}
if (skilldata.e_SkillTarget == eSkillTarget.Enemy)
{
if (!isTarget) Set_Target(true);
if (!isTarget)
2024-12-15 01:39:39 +00:00
{
if (IsRole(eRole.PC)) ToastUI.Ins.Set(105);
Del_Magic();
return false;
}
2025-03-01 03:21:02 +00:00
else if (!DSUtil.WithInDistance(m_Target.Get_position(), Get_position(), skilldata.f_SkillRange))
2024-12-15 01:39:39 +00:00
{ // 마법 사용 사정거리보다 멀리 있다. 마법 쏘러 가자.
return false;
}
}
if (IsRole(eRole.PC))
{
var needMP = skilldata.n_MP - (skilldata.n_MP * m_Stat.Get_Stat(eStat.SKILL_COST));
if (needMP > m_Stat.Get_Stat(eStat.MP))
{
if (!autoskill)
{
ToastUI.Ins.Set(106);
MessageInfo.Ins.Add_Log(106);
}
Del_Magic();
return false;
}
}
2025-04-02 23:29:27 +00:00
if (!Check_MagicCoolTime(index) && !testskill) return false;
2024-12-15 01:39:39 +00:00
list_SkillData[index].m_SkillListTableData = m_Magic.m_SkillTableData;
list_SkillData[index].target = m_Target;
m_SkillData = list_SkillData[index];
m_Stat.Set_Stat(false, eStat.MP, skilldata.n_MP);
Set_MagicCoolTime(skilldata.Get_CoolTime(m_Stat.Get_Stat(eStat.COOLTIME_Multiplier)), index);
2025-04-02 23:29:27 +00:00
if (IsMainPC() && !testskill) ServerInfo.Ins.m_ServerData.Add_MissionCount(ePurpose.USE_SKILL_ALL);
2024-12-15 01:39:39 +00:00
return Play_Skill(skilldata.s_Animation);
}
public virtual void Shoot_Skill()
{
if (IsDead() || DSUtil.CheckNull(m_Magic)) return;
InGameInfo.Ins.Shoot_Effect(m_SkillData);
2024-12-28 00:20:09 +00:00
//SoundInfo.Ins.Play_OneShot(eSound.s009_CastSpell);
//if (IsRole(eRole.PC))
//NewGameUI.Ins.m_GuideQuestUI.Add_GuideQuest(ePurpose.ShootMagic);
2024-12-15 01:39:39 +00:00
Del_Magic();
}
2024-12-28 00:20:09 +00:00
public void Set_Magic(SkillListTableData skill, Actor target)
{
m_Magic = new UseMagicInfo { m_SkillTableData = skill };
m_SkillData = new ProjectileData { shooter = this, target = target, m_SkillListTableData = skill };
}
2024-12-15 01:39:39 +00:00
public void Del_Magic()
{
if (!DSUtil.CheckNull(co_casting))
{
StopCoroutine(co_casting);
co_casting = null;
}
m_Magic = null;
}
public virtual void Set_MagicCoolTime(float _time, int _index) { }
public virtual void Set_SkillCoolTime(bool add, int skillid, float rate) { }
protected virtual bool Check_MagicCoolTime(int _index) { return false; }
public virtual void Heal(float _rate, bool showhud = true)
{
2025-02-11 07:09:38 +00:00
if (IsDead() || Get_HP() >= Get_MaxHP()) return;
2024-12-15 01:39:39 +00:00
2025-02-11 07:09:38 +00:00
var heal_hp = Math.Max(m_Stat.Get_Stat(eStat.MaxHP) * _rate, 1d);
2024-12-15 01:39:39 +00:00
m_Stat.Set_Stat(true, eStat.HP, heal_hp);
if (showhud)
{
InGameInfo.Ins.Get_HUDDMGUI().Set(tf_HUD_Dmg, "<color=#00ff00>", heal_hp, eStat.None);
2025-03-05 03:47:01 +00:00
Get_HUDUI().Set_HPSlider(this);
2024-12-15 01:39:39 +00:00
}
}
public virtual void Heal(double _hp, bool showhud = true)
{
2025-02-12 00:04:43 +00:00
if (IsDead()) return;
if (_hp > 0)
{
if (Get_HP() >= Get_MaxHP()) return;
_hp = Math.Max(1, _hp);
}
2024-12-15 01:39:39 +00:00
m_Stat.Set_Stat(true, eStat.HP, _hp);
2024-12-28 00:20:09 +00:00
#if UNITY_EDITOR
2025-02-10 05:35:41 +00:00
if (SceneManager.GetActiveScene().name == "StatTest")
2024-12-28 00:20:09 +00:00
{
MainToStatTest.Ins.Set_Dmglabel($"HP : {_hp}");
return;
}
#endif
2025-03-05 03:47:01 +00:00
Get_HUDUI().Set_HPSlider(this);
if (showhud) InGameInfo.Ins.Get_HUDDMGUI().Set(tf_HUD_Dmg, "<color=#00ff00>", _hp, eStat.None);
2024-12-15 01:39:39 +00:00
}
public virtual void Heal_MP(double _mp, bool showhud = true)
{
if (IsDead()) return;
2025-02-11 23:22:40 +00:00
if (_mp < 0) // MP 감소 로직
{
double curMp = m_Stat.Get_Stat(eStat.MP);
if (curMp <= 0) return; // MP가 이미 0이면 종료
// 감소할 MP가 현재 MP보다 크면, 현재 MP만큼만 감소
if (Math.Abs(_mp) > curMp)
_mp = -curMp;
m_Stat.Set_Stat(true, eStat.MP, _mp);
}
else
m_Stat.Set_Stat(true, eStat.MP, Math.Abs(_mp));
2024-12-28 00:20:09 +00:00
#if UNITY_EDITOR
if (SceneManager.GetActiveScene().name == "StatTest")
2024-12-28 00:20:09 +00:00
{
MainToStatTest.Ins.Set_Dmglabel($"MP : {_mp}");
return;
}
#endif
2024-12-15 01:39:39 +00:00
if (showhud)
2025-02-11 23:22:40 +00:00
{
2024-12-15 01:39:39 +00:00
InGameInfo.Ins.Get_HUDDMGUI().Set(tf_HUD_Dmg, "<color=#0000ff>", _mp, eStat.None);
2025-02-11 23:22:40 +00:00
}
2024-12-15 01:39:39 +00:00
}
#region
IEnumerator Co_JumpAttack(float heightPos_y, float duration)
2024-12-15 01:39:39 +00:00
{
OptionInfo.Ins.Set_PCMove(this, false);
2024-12-15 01:39:39 +00:00
var startPos = Get_position(); // 현재 위치
2025-01-17 00:28:44 +00:00
var targetPos = Get_TeleportPostion(m_Target);
2024-12-15 01:39:39 +00:00
var elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = elapsed / duration;
// 포물선의 중간 높이를 만들기 위해 선형 보간 사용
Vector3 currentPos = Vector3.Lerp(startPos, targetPos, t);
// 높이를 포물선 형태로 변경
currentPos.y += Mathf.Sin(t * Mathf.PI) * (heightPos_y - startPos.y);
transform.position = currentPos; // 캐릭터 위치 업데이트
yield return null;
}
transform.position = targetPos; // 최종 위치 설정
}
2025-01-15 22:32:07 +00:00
public void Set_Invisible(float invisibleTime, Action actVisible) { StartCoroutine(Co_Invisible(invisibleTime, actVisible)); }
IEnumerator Co_Invisible(float invisibleTime, Action actVisible)
{
m_animation.speed = 0f;
m_bImmortal = true;
Model_OnOff(false);
2025-01-15 22:32:07 +00:00
Weapon_OnOff(false);
OptionInfo.Ins.Set_PCMove(this, false);
2025-01-15 22:32:07 +00:00
yield return new WaitForSeconds(invisibleTime);
m_animation.speed = 1f;
m_bImmortal = false;
Model_OnOff(true);
2025-01-15 22:32:07 +00:00
Weapon_OnOff(true);
OptionInfo.Ins.Set_PCMove(this, true);
2025-01-15 22:32:07 +00:00
actVisible?.Invoke();
}
protected virtual void Weapon_OnOff(bool active) { }
protected void Model_OnOff(bool active) { for (int i = 0; i < arr_Renderer.Length; i++) arr_Renderer[i].enabled = active; }
2024-12-15 01:39:39 +00:00
#endregion
public int Get_ID() { return m_ID; }
public virtual int Get_Group() { return 0; }
2025-01-11 03:20:35 +00:00
public virtual NavMeshAgent Get_Agent() { return m_NavMeshAgent; }
2024-12-15 01:39:39 +00:00
public Vector3 Get_position() { return transform.position; }
public Vector3 Get_Center_position()
{
return new Vector3(transform.position.x, transform.position.y + ObjSize.y * 0.5f, transform.position.z);
}
2025-03-03 01:55:09 +00:00
public Vector3 Get_Top_postion() { return tf_Top.position; }
2025-01-20 06:47:44 +00:00
public Vector3 Get_CenterPositionFoward(float dist = 0.3f) { return Get_Center_position() + transform.forward * dist; }
public Vector3 Get_PositionFoward(float dist = 0.3f) { return Get_position() + transform.forward * dist; }
2025-04-06 23:50:39 +00:00
public Vector3 Get_PositionFoward_OnNavMesh(float maxDist = 1f)
{
Vector3 start = Get_position();
Vector3 end = start + transform.forward * maxDist;
// NavMesh Raycast: 시작부터 목표까지 장애물이 있는지 확인
if (NavMesh.Raycast(start, end, out NavMeshHit hit, NavMesh.AllAreas))
{
// 장애물에 부딪힘 → 부딪힌 위치까지는 NavMesh
return hit.position;
}
// Raycast는 통과했지만, 목표 위치가 NavMesh 바깥일 수 있음
if (NavMesh.SamplePosition(end, out hit, 2f, NavMesh.AllAreas))
{
return hit.position;
}
// 목표 지점도 없으면, 직선상의 가장 가까운 NavMesh 위 위치 찾기
for (float d = maxDist - 1f; d >= 1f; d -= 1f)
{
Vector3 checkPos = start + transform.forward * d;
if (NavMesh.SamplePosition(checkPos, out hit, 1f, NavMesh.AllAreas))
{
return hit.position;
}
}
// 정말 없으면 제자리
return start;
}
2025-01-20 06:47:44 +00:00
public Vector3 Get_PositionBack(float dist = 0.3f) { return Get_position() + -transform.forward * dist; }
2025-01-17 00:28:44 +00:00
public Vector3 Get_TeleportPostion(Actor target, float dist = 1f)
2025-01-10 02:42:37 +00:00
{
var startPos = Get_position(); // 현재 위치
2025-01-17 00:28:44 +00:00
Vector3 direction = (target.Get_position() - Get_position()).normalized; // 목표와 현재 위치의 방향 벡터를 구함
2025-02-21 07:10:14 +00:00
var rtnPos = DSUtil.Get_RandomPos_onNavMesh(target.Get_position() - direction * dist, 0, dist);
return rtnPos;
2025-01-10 02:42:37 +00:00
}
2024-12-15 01:39:39 +00:00
public float Get_ScaleSizeDist() { return transform.localScale.x > 2f ? ObjSize.z * 0.5f : 0f; }
public ActorStatInfo Get_StatInfo() { return m_Stat; }
public double Get_HP() { return m_Stat.Get_Stat(eStat.HP); }
public double Get_MaxHP() { return m_Stat.Get_Stat(eStat.MaxHP); }
2025-03-05 03:47:01 +00:00
public float Get_HPPercent() { return (float)(Get_HP() / Get_MaxHP()); }
2024-12-15 01:39:39 +00:00
public double Get_MaxMP() { return m_Stat.Get_Stat(eStat.MaxMP); }
public Actor Get_Target() { return m_Target; }
public virtual void Del_Target(bool forcedel = false)
{
if (isTarget)
2024-12-15 01:39:39 +00:00
{
if (!forcedel && m_Target.m_IsLockTarget && !m_Target.IsDead()) return;
if (IsMainPC()) m_Target.Set_Outline(false);
2024-12-15 01:39:39 +00:00
}
m_Target = null;
}
public bool IsDead() { return DeadStatus || !gameObject.activeInHierarchy; }
public bool IsOnlyDead() { return DeadStatus; }
public bool IsMainPC() { return IsRole(eRole.PC) && !IsEnemy(); }
2024-12-15 01:39:39 +00:00
public bool IsRole(eRole _role) { return m_Role == _role; }
public bool IsSubRole(eSubRol subRol) { return m_SubRole == subRol; }
2024-12-15 01:39:39 +00:00
public bool IsEnemy() { return m_Enemy; }
public bool Get_SelectSkill(eEffect _effect)
{
if (IsMainPC())
2024-12-15 01:39:39 +00:00
return InGameInfo.Ins.Get_SelectSkillData(_effect);
return false;
}
public ServerData Get_ServerData() { return m_ServerData; }
public virtual void Change_Target(bool _ispc, Actor target, bool _ChangeTargetByHit = false)
{
if (!DSUtil.CheckNull(target) && !target.IsDead())
{
if (_ispc)
{
if (MyValue.MyPC.isTarget)
2024-12-15 01:39:39 +00:00
MyValue.MyPC.m_Target.Set_Outline(false);
}
if (_ChangeTargetByHit)
{
if (!isTarget || m_Target.IsDead())
2024-12-15 01:39:39 +00:00
{
m_Target = target;
FindOtherTargetTime = 7.5f;
}
}
else
{
m_Target = target;
FindOtherTargetTime = 7.5f;
}
if (_ispc)
{
m_Target.Set_Outline(true);
// 퀘스트 몹은 선택 사항이므로 마녀가 터치로만 타겟을 잡을 수가 있다.
// 퀘스트몹을 선택했다는 것은 퀘스트를 하겠다는 뜻이므로 모든 펫이 같이 때린다.
// 강화석도 같이 캐자.
if (m_Target.IsRole(eRole.OBJ))
2024-12-15 01:39:39 +00:00
ActorInfo.Ins.Get_Actors(eRole.Pet, 0).ForEach(f => f.Change_Target(false, m_Target));
}
}
}
public void Resurrection(float _hprate)
{
Heal(_hprate);
Play_Idle();
if (m_BoxCollider) m_BoxCollider.enabled = true;
m_NavMeshAgent.enabled = true;
}
protected virtual void On_NavMeshAgent()
{
if (!IsCC())
{ // 모든 상태이상이 해제 되었다.
m_NavMeshAgent.updatePosition = true;
if (m_NavMeshAgent.isOnNavMesh) m_NavMeshAgent.isStopped = false;
2025-02-25 06:28:10 +00:00
m_animation.speed = 1f;
2024-12-15 01:39:39 +00:00
}
}
#region
void Check_Drain_byKill(DamageInfo _dinfo)
{
if (!DSUtil.CheckNull(_dinfo) && !DSUtil.CheckNull(_dinfo.Beater) && _dinfo.Beater.IsEnemy() != IsEnemy())
{
var statinfo = _dinfo.Beater.Get_StatInfo();
if (!DSUtil.CheckNull(statinfo))
{
if (DSUtil.RandomTrue(statinfo.Get_Stat(eStat.KillToHP_Rate)))
{ // 회복
_dinfo.Beater.Heal(statinfo.Get_Stat(eStat.KillToHP));
_dinfo.Beater.Heal_MP(statinfo.Get_Stat(eStat.KillToMP));
}
if (DSUtil.RandomTrue(statinfo.Get_Stat(eStat.KillToMP_Rate)))
{ // MP 회복
_dinfo.Beater.Heal(statinfo.Get_Stat(eStat.KillToHP));
_dinfo.Beater.Heal_MP(statinfo.Get_Stat(eStat.KillToMP));
}
}
}
}
#endregion
protected bool IsCC(eCC cc) { return cc >= eCC.Freeze && cc < eCC.Max; }
2024-12-15 01:39:39 +00:00
public bool IsCC()
{
2025-02-11 00:15:02 +00:00
if (dic_ccData[eCC.Freeze].CCTime > 0f) return true;
if (dic_ccData[eCC.Attract].CCTime > 0f) return true;
if (dic_ccData[eCC.KnockedAirborne].CCTime > 0f) return true;
if (dic_ccData[eCC.KnockBack].CCTime > 0f) return true;
if (dic_ccData[eCC.Stun].CCTime > 0f) return true;
2024-12-15 01:39:39 +00:00
return false;
}
protected virtual void Check_CC_byAttack(DamageInfo _dinfo)
{
if (dic_ccData[eCC.Freeze].CCTime > 0f)
Off_Freeze();
float knockbackTime = 0f;
if (IsRole(eRole.Mob) && !IsCC())
2024-12-15 01:39:39 +00:00
knockbackTime = table_GlobalValue.Ins.Get_Float("f_KnockbackTime");
var beaterActor = _dinfo.Beater;
2025-02-10 06:47:31 +00:00
if (!DSUtil.CheckNull(beaterActor))
2024-12-15 01:39:39 +00:00
{
if (!DSUtil.CheckNull(_dinfo.Beater_pd))
{ // 서리 상태인 적을 냉기 폭격으로 때렸을 때 얼림
var pd = _dinfo.Beater_pd;
if (!DSUtil.CheckNull(pd.m_SkillListTableData) && pd.m_SkillListTableData.e_Skill == eEffect.Skill_IceArrows &&
pd.CC_AddVal2 > 0f && IsSkillExtraStatus(eSkillExtraType.Frost))
Freeze(pd.CC_AddVal2, _dinfo.act_AfterFreezing);
}
var statinfo = beaterActor.Get_StatInfo();
if (!DSUtil.CheckNull(statinfo))
{
var cc = eCC.Blooding;
if (DSUtil.RandomTrue(statinfo.Get_Stat(eStat.Blooding)))
{ // 출혈 체크
DotDamage(eCC.Blooding, _dinfo.Copy(), statinfo.Get_Stat(eStat.BloodingTime),
statinfo.Get_Stat(eStat.BloodingDelay), statinfo.Get_Stat(eStat.BloodingDmg));
}
cc = eCC.Stun;
if (dic_ccData[cc].CCTime <= 0f)
{ // 무한 스턴 방지
var addrate = Get_CCAddRate(cc, beaterActor);
Check_CCAddRate(cc, beaterActor);
dic_ccAddRate[cc][beaterActor] += statinfo.Get_Stat(eStat.StunAdd);
if (DSUtil.RandomTrue(statinfo.Get_Stat(eStat.Stun) + addrate))
{ // 스턴 체크
dic_ccAddRate[cc][beaterActor] = 0;
dic_ccData[cc].CCTime = statinfo.Get_Stat(eStat.StunTime);
_dinfo.Damage = dic_ccData[cc].CCDmg = _dinfo.Damage * statinfo.Get_Stat(eStat.StunDmg);
Cal_Damage(_dinfo);
Stun(dic_ccData[cc].CCTime);
}
}
knockbackTime += (float)statinfo.Get_Stat(eStat.AttackKnockBack);
if (DSUtil.RandomTrue(statinfo.Get_Stat(eStat.AttackSpeedRate_byAttack)))
beaterActor.Buff_or_Debuff(eCC.ATKSPD_Up,
beaterActor.Get_StatInfo().Get_Stat(eStat.AttackSpeedTime_byAttack),
beaterActor.Get_StatInfo().Get_Stat(eStat.AttackSpeedBuff_byAttack));
if (DSUtil.RandomTrue(statinfo.Get_Stat(eStat.MoveSpeedRate_byAttack)))
beaterActor.Buff_or_Debuff(eCC.MOVSPD_Up,
beaterActor.Get_StatInfo().Get_Stat(eStat.MoveSpeedTime_byAttack),
beaterActor.Get_StatInfo().Get_Stat(eStat.MoveSpeedBuff_byAttack));
if (DSUtil.RandomTrue(statinfo.Get_Stat(eStat.PiercingRate_byAttack)))
beaterActor.Buff_or_Debuff(eCC.PiercingBuff,
beaterActor.Get_StatInfo().Get_Stat(eStat.PiercingTime_byAttack),
beaterActor.Get_StatInfo().Get_Stat(eStat.PiercingRate_byAttack));
2025-02-10 06:47:31 +00:00
2024-12-15 01:39:39 +00:00
var STCdata = _dinfo.Beater_pd.m_skillTypeConfigTable;
if (!DSUtil.CheckNull(STCdata) && STCdata.e_SkillExtraTiming == eSkillExtraTiming.Hit)
Check_Extra(_dinfo);
Check_EnchantOption(_dinfo);
if (knockbackTime > 0f) KnockBack(knockbackTime);
}
}
}
2025-02-13 04:40:04 +00:00
protected virtual void Check_Extra(eSkillExtraTiming timing) { }
2024-12-15 01:39:39 +00:00
public void Check_Extra(DamageInfo _dinfo)
{
var pd = _dinfo.Beater_pd;
if (pd.e_SkillExtraType == eSkillExtraType.None) return;
float val1 = 0f, val2 = 0f, val3 = 0f, val4 = 0f;
bool bSKill, bOption;
SkillListTableData skillData = _dinfo.Beater_pd.m_SkillListTableData;
bSKill = !DSUtil.CheckNull(skillData);
if (bSKill)
{
val1 = skillData.f_ExtraValue1;
val2 = skillData.f_ExtraValue2;
val3 = skillData.f_ExtraValue3;
val4 = skillData.f_ExtraValue4;
}
else
{
OptionConfigTableData optionData = _dinfo.Beater_pd.m_OptionConfigTableData;
bOption = !DSUtil.CheckNull(optionData);
if (bOption)
{
val1 = optionData.f_ExtraValue1;
val2 = optionData.f_ExtraValue2;
val3 = optionData.f_ExtraValue3;
val4 = optionData.f_ExtraValue4;
}
}
if (!DSUtil.RandomTrue(val4)) return; // 확률 체크
SkillTypeConfigTableData skillExtraData = _dinfo.Beater_pd.m_skillTypeConfigTable;
ActorStatInfo statinfo = _dinfo.Beater.Get_StatInfo();
eCC curCC = eCC.Max;
2024-12-15 01:39:39 +00:00
float LifeTime = val1 + pd.CC_AddTime;
switch (skillExtraData.e_SkillExtraType)
{
// 적에게
case eSkillExtraType.Frost:
curCC = eCC.ATKSPD_Down;
Buff_or_Debuff(eCC.ATKSPD_Down, LifeTime, val2 + pd.CC_AddVal1);
Buff_or_Debuff(eCC.MOVSPD_Down, LifeTime, val3 + pd.CC_AddVal2);
if (_dinfo.bExtraDmg) Cal_Damage(_dinfo); // 추가 데미지
break;
2024-12-15 01:39:39 +00:00
case eSkillExtraType.Slow:
curCC = eCC.MOVSPD_Down;
2024-12-15 01:39:39 +00:00
Buff_or_Debuff(eCC.ATKSPD_Down, LifeTime, val2 + pd.CC_AddVal1);
Buff_or_Debuff(eCC.MOVSPD_Down, LifeTime, val3 + pd.CC_AddVal2);
if (_dinfo.bExtraDmg) Cal_Damage(_dinfo); // 추가 데미지
break;
case eSkillExtraType.Freezing:
Freeze(LifeTime, _dinfo.act_AfterFreezing);
if (_dinfo.bExtraDmg) Cal_Damage(_dinfo); // 추가 데미지
break;
case eSkillExtraType.Burn:
curCC = eCC.Burn;
2024-12-15 01:39:39 +00:00
DotDamage(eCC.Burn, _dinfo.Copy(), LifeTime, val2 + pd.CC_AddVal1, val3);
break;
case eSkillExtraType.Blood:
curCC = eCC.Blooding;
2024-12-15 01:39:39 +00:00
DotDamage(eCC.Blooding, _dinfo.Copy(), LifeTime, val2, val3);
break;
case eSkillExtraType.Poison:
curCC = eCC.Poison;
2024-12-15 01:39:39 +00:00
DotDamage(eCC.Poison, _dinfo.Copy(), LifeTime, val2, val3);
break;
case eSkillExtraType.Stun:
curCC = eCC.Stun;
2024-12-15 01:39:39 +00:00
Stun(LifeTime);
if (_dinfo.bExtraDmg)
{
_dinfo.Damage *= val2 + pd.CC_AddDmg;
Cal_Damage(_dinfo); // 스턴 추가 데미지
}
break;
case eSkillExtraType.DefenceDecrease:
curCC = eCC.DEF_Down;
2024-12-15 01:39:39 +00:00
Buff_or_Debuff(eCC.DEF_Down, LifeTime, val2);
Buff_or_Debuff(eCC.M_DEF_Down, LifeTime, val3);
if (_dinfo.bExtraDmg) Cal_Damage(_dinfo); // 추가 데미지
break;
// 시전자에게
case eSkillExtraType.StatUp:
{
var rate = val3;
var type = (int)val2;
var lst = MyValue.dic_StatUp[type];
for (int i = 0; i < lst.Count; i++)
Stat_BufforDebuff(statinfo, lst[i], LifeTime, rate, type, i == lst.Count - 1);
}
break;
case eSkillExtraType.ManaShield:
curCC = eCC.ManaShield;
2024-12-15 01:39:39 +00:00
LifeTime += LifeTime * pd.Get_SkillDamagePercent();
Buff_or_Debuff(curCC, LifeTime, val3, 0, val2);
2024-12-15 01:39:39 +00:00
break;
case eSkillExtraType.SwordShield:
break;
case eSkillExtraType.SpeedUp:
curCC = eCC.ATKSPD_Up;
2024-12-15 01:39:39 +00:00
Buff_or_Debuff(eCC.ATKSPD_Up, LifeTime, val2);
Buff_or_Debuff(eCC.MOVSPD_Up, LifeTime, val3);
break;
case eSkillExtraType.Aggro:
Buff_or_Debuff(eCC.ATK_Down, LifeTime, val2 + pd.CC_AddVal1);
Buff_or_Debuff(eCC.DEF_Down, LifeTime, val3 + pd.CC_AddVal1);
2024-12-15 01:39:39 +00:00
break;
case eSkillExtraType.VampirHeal:
_dinfo.Beater.Heal(val2);
_dinfo.Beater.Heal_MP(val3);
break;
case eSkillExtraType.Cure:
curCC = eCC.Cure;
2024-12-15 01:39:39 +00:00
_dinfo.Beater.DotHeal(LifeTime, val2, _dinfo.Beater.Get_MaxHP() * val3, _dinfo.Beater.Get_MaxMP() * val3);
break;
case eSkillExtraType.Knockback:
KnockBack(val1);
break;
case eSkillExtraType.Airborne:
KnockedAirborne(val1);
break;
case eSkillExtraType.Curse: // 단순 상태 확인 및 이펙트 표시 용도
break;
2025-02-11 23:22:40 +00:00
case eSkillExtraType.ManaBurn:
var manaburn = (int)(Get_MaxMP() * val1);
Heal_MP(-manaburn);
LifeTime = 1f;
break;
2025-02-12 00:04:43 +00:00
case eSkillExtraType.HPBurn:
var hpburn = (Get_MaxHP() * val1);
Heal(-hpburn);
LifeTime = 1f;
break;
case eSkillExtraType.SilenceCurse: // 스킬 사용 불가 및 최대 마나 감소
curCC = eCC.SilenceCurse;
Buff_or_Debuff(curCC, LifeTime, val2);
break;
2025-02-13 06:10:00 +00:00
case eSkillExtraType.Blind:
GlobalVolumeMgr.Ins.Set(1, LifeTime);
break;
case eSkillExtraType.KnockbackStun:
KnockBack(val1, 4f, () => { Stun(val2, true); });
break;
2024-12-15 01:39:39 +00:00
}
if (!dic_skillextra.ContainsKey(skillExtraData.e_SkillExtraType))
dic_skillextra.Add(skillExtraData.e_SkillExtraType, true);
dic_skillextra[skillExtraData.e_SkillExtraType] = true;
Set_Coroutine(() =>
{
if (dic_skillextra.ContainsKey(skillExtraData.e_SkillExtraType))
dic_skillextra[skillExtraData.e_SkillExtraType] = false;
}, LifeTime);
// 기존 이펙트가 있으면 재활용
if (curCC != eCC.Max && dic_CCEffect.ContainsKey(curCC) && dic_CCEffect[curCC].IsMyEffect(this) &&
dic_CCEffect[curCC].gameObject.activeInHierarchy)
dic_CCEffect[curCC].Reset_Time(LifeTime);
else
{
if (IsCC(curCC) && m_Stat.Get_Stat(eStat.CC_Immunity) > 0) return;
pd.m_ProjectileBase.Show_Effect(this, LifeTime, ccffect =>
{
if (curCC != eCC.Max)
{
if (!dic_CCEffect.ContainsKey(curCC))
dic_CCEffect.Add(curCC, null);
dic_CCEffect[curCC] = ccffect;
}
});
}
2025-03-05 05:32:40 +00:00
Set_IngameBuffDebuffUI(skillExtraData, LifeTime);
}
void Set_IngameBuffDebuffUI(SkillTypeConfigTableData skillExtraData, float time)
{
if (MyInfoUI.isIns && IsRole(eRole.PC))
2025-03-05 07:08:07 +00:00
MyInfoUI.Ins.m_IngameBuffDebuffBase.Add_IngameBuffDebuff(skillExtraData.s_SkillNoticeIconPath, time);
else if (IngamePetCard.isIns && IsRole(eRole.Pet))
IngamePetCard.Ins.m_IngameBuffDebuffBase.Add_IngameBuffDebuff(skillExtraData.s_SkillNoticeIconPath, time);
2025-03-05 23:16:50 +00:00
else if (IsSubRole(eSubRol.Boss) && MonsterSimpleInfo.Ins.IsMe(this))
{
switch (skillExtraData.e_SkillExtraType)
{
case eSkillExtraType.Stun:
case eSkillExtraType.Airborne:
case eSkillExtraType.Freezing:
time *= 0.5f;
break;
}
MonsterSimpleInfo.Ins.m_IngameBuffDebuffBase.Add_IngameBuffDebuff(skillExtraData.s_SkillNoticeIconPath, time);
}
2024-12-15 01:39:39 +00:00
}
public void Check_EnchantOption(DamageInfo _dinfo, bool whenhit = true)
{
if (!DSUtil.CheckNull(_dinfo.Beater))
{
var sdata = _dinfo.Beater.Get_ServerData();
if (!DSUtil.CheckNull(sdata))
for (int i = 0; i < sdata.Slot.Count; i++)
{
for (int j = 0; j < sdata.Slot[i].Enchant.Count; j++)
{
var optionid = sdata.Slot[i].Enchant[j].ID;
if (optionid > 0)
{
var statinfo = _dinfo.Beater.Get_StatInfo();
var Tdata = table_optionconfig.Ins.Get_Data(optionid);
var dcopy = _dinfo.Copy();
dcopy.Beater_pd.m_OptionConfigTableData = Tdata;
if (DSUtil.CheckNull(dcopy.Beater_pd))
dcopy.Beater_pd = new ProjectileData();
var val = Tdata.Get_Value(sdata.Slot[i].Enchant[j].Lv);
switch (Tdata.e_OptionType)
{
case eStat.STR_EXTRA_STUN:
if (whenhit)
{
dcopy.Set_Extra(eSkillExtraType.Stun);
dcopy.bExtraDmg = true;
dcopy.Damage = statinfo.Get_Stat(eStat.STR) * val;
Check_Extra(dcopy);
}
break;
case eStat.DEX_EXTRA_BLEED:
if (whenhit)
{
dcopy.Set_Extra(eSkillExtraType.Blood);
dcopy.Beater_pd.BaseDmg = statinfo.Get_Stat(eStat.DEX) * val;
Check_Extra(dcopy);
}
break;
case eStat.INT_EXTRA_SLOW:
if (whenhit)
{
dcopy.Set_Extra(eSkillExtraType.Slow);
dcopy.bExtraDmg = true;
dcopy.Damage = statinfo.Get_Stat(eStat.INT) * val;
Check_Extra(dcopy);
}
break;
case eStat.LUK_EXTRA_CURSE:
if (whenhit && DSUtil.RandomTrue(Tdata.f_ExtraValue4))
{
dcopy.Damage = statinfo.Get_Stat(eStat.LUK) * val;
Cal_Damage(dcopy);
}
break;
case eStat.STR_EXTRA_SPLASH:
if (whenhit && DSUtil.RandomTrue(Tdata.f_ExtraValue4))
{
dcopy.Damage = statinfo.Get_Stat(eStat.STR) * val;
var allies = ActorInfo.Ins.Get_AlliesActors(IsEnemy(), Get_position(), Tdata.f_ExtraValue1);
for (int k = 0; k < allies.Count; k++)
{
allies[k].Cal_Damage(dcopy);
InGameInfo.Ins.Show_Effect("Effect_STR_EXTRA_SPLASH", allies[k]);
}
}
break;
case eStat.DEX_EXTRA_DART:
if (!whenhit && DSUtil.RandomTrue(Tdata.f_ExtraValue4))
{
ProjectileData pd = new ProjectileData();
pd.CheckOptionWhenStart = false;
pd.shooter = _dinfo.Beater;
pd.eStartPos = eProjectileStartPos.Custom;
pd.v3_StartPos = _dinfo.Beater.Get_Center_position();
pd.m_OptionConfigTableData = Tdata;
pd.BaseDmg = statinfo.Get_Stat(eStat.DEX) * val;
ProjectileInfo.Ins.Shoot_Projectile("Projectile_Suriken", pd);
}
break;
case eStat.INT_EXTRA_FREEZING:
if (!whenhit && DSUtil.RandomTrue(Tdata.f_ExtraValue4))
{
ProjectileData pd = new ProjectileData();
pd.CheckOptionWhenStart = false;
pd.shooter = _dinfo.Beater;
pd.eStartPos = eProjectileStartPos.Custom;
pd.v3_StartPos = _dinfo.Beater.Get_Center_position();
pd.e_SkillExtraType = eSkillExtraType.Freezing;
pd.m_OptionConfigTableData = Tdata;
pd.BaseDmg = statinfo.Get_Stat(eStat.INT) * val;
ProjectileInfo.Ins.Shoot_Projectile("Projectile_INT_EXTRA_FREEZING", pd);
}
break;
case eStat.LUK_EXTRA_CRITICAL:
if (!whenhit)
{
_dinfo.act_CriAfterHit = cri =>
{
if (cri == eStat.CRI || cri == eStat.M_CRI)
{
dcopy.Damage = statinfo.Get_Stat(eStat.LUK) * val;
dcopy.Critical = eStat.None;
Cal_Damage(dcopy);
}
};
}
break;
}
}
}
}
}
}
public void Set_DicCCData(eCC cc, double time, double dmg, bool isUpdate = true)
{
dic_ccData[cc].TimeUpdate = isUpdate;
dic_ccData[cc].CCTime = time;
dic_ccData[cc].CCDmg = dmg;
}
#region or : , , , ,
/// <summary>
/// stat = 힘, 민, 지, 행
/// </summary>
public void Stat_BufforDebuff(ActorStatInfo statinfo, eStat stat, float LifeTime, float rate, int type = 0, bool resetStat = false)
{
if (stat == eStat.STR || stat == eStat.DEX || stat == eStat.INT || stat == eStat.LUK)
{
statinfo.Set_Buff(MyValue.dic_StatUp_from_Stat[stat], rate);
Buff_or_Debuff(MyValue.dic_StatUpCC_from_Stat[stat], LifeTime, rate, type);
if (resetStat) statinfo.Reset(true);
}
}
public void Buff_or_Debuff(eCC cc, double lifeTime, double val, int ival = 0, float fval = 0f)
{
switch (cc)
{
case eCC.ATKSPD_Down:
case eCC.MOVSPD_Down:
if (IsSubRole(eSubRol.Elite)) lifeTime -= lifeTime * 0.2f;
2025-03-05 23:16:50 +00:00
else if (IsSubRole(eSubRol.Boss))
{
lifeTime -= lifeTime * 0.5f;
MonsterSimpleInfo.Ins.m_IngameBuffDebuffBase.Add_IngameBuffDebuff("8_Slow", (float)lifeTime);
}
break;
}
2024-12-15 01:39:39 +00:00
dic_ccData[cc].TimeUpdate = true;
dic_ccData[cc].CCTime = lifeTime;
dic_ccData[cc].CCDmg = val;
dic_ccData[cc].CCVal = ival;
dic_ccData[cc].CCReduceTime = fval;
}
public CCData Get_CCData(eCC cc) { return dic_ccData[cc]; }
public bool IsSkillExtraStatus(eSkillExtraType skillExtraType)
{ return dic_skillextra.ContainsKey(skillExtraType) && dic_skillextra[skillExtraType]; }
protected void Off_StatUpBuff(eStat stat)
{
Get_StatInfo().Set_Buff(MyValue.dic_StatUp_from_Stat[stat], 0d);
Get_StatInfo().Reset(true);
}
#endregion
#region : (, )
Dictionary<eCC, Coroutine> dic_ccCoroutine = new Dictionary<eCC, Coroutine>();
public void DotDamage(eCC cc, DamageInfo dinfocopy, double lifetime, double gaptime, double dmg)
{
if (!dic_ccCoroutine.ContainsKey(cc)) dic_ccCoroutine.Add(cc, null);
dic_ccData[cc].CCTime = lifetime;
dic_ccData[cc].CCDelay = gaptime;
dic_ccData[cc].CCDmg = dmg;
if (!DSUtil.CheckNull(dic_ccCoroutine[cc])) StopCoroutine(dic_ccCoroutine[cc]);
dic_ccCoroutine[cc] = StartCoroutine(Co_DotDamage(cc, dinfocopy));
}
IEnumerator Co_DotDamage(eCC cc, DamageInfo dinfocopy)
{
var ccData = dic_ccData[cc];
var gapTime = (float)ccData.CCDelay;
2025-02-19 04:14:09 +00:00
dinfocopy.Beater_pd.AddDmgPercent = (float)ccData.CCDmg;
2024-12-15 01:39:39 +00:00
while (ccData.CCTime > 0)
{
2025-02-19 04:14:09 +00:00
var dinfo = dinfocopy.Beater.Get_DamageInfo(dinfocopy.Beater_pd);
2024-12-15 01:39:39 +00:00
dinfo.TextColor = $"<color=red>{cc} ";
Cal_Damage(dinfo);
yield return new WaitForSeconds(gapTime);
ccData.CCTime -= gapTime;
}
dic_ccCoroutine[cc] = null;
}
#endregion
#region :
Coroutine co_dotheal;
public void DotHeal(double lifetime, float gaptime, double healhp, double healmp)
{
if (healhp < 1) healhp = 1;
2025-02-24 02:24:39 +00:00
//if (healmp < 1) healmp = 1;
2024-12-15 01:39:39 +00:00
if (!DSUtil.CheckNull(co_dotheal)) StopCoroutine(co_dotheal);
co_dotheal = StartCoroutine(Co_DotHeal(lifetime, gaptime, healhp, healmp));
}
IEnumerator Co_DotHeal(double lifetime, float gaptime, double healhp, double healmp)
{
while (lifetime > 0)
{
yield return new WaitForSeconds(gaptime);
Heal(healhp);
Heal_MP(healmp);
lifetime -= gaptime;
}
co_dotheal = null;
}
#endregion
#region :
Action<Actor> act_AfterFreezing;
public virtual void Freeze(float _freezeTime, Action<Actor> act = null)
{
if (m_Stat.Get_Stat(eStat.CC_Immunity) > 0) return;
2024-12-15 01:39:39 +00:00
if (DSUtil.CheckNull(act_AfterFreezing)) act_AfterFreezing = act;
dic_ccData[eCC.Freeze].CCTime = 10f;
2025-02-25 06:28:10 +00:00
if (!IsDead()) m_animation.speed = 0f;
2024-12-15 01:39:39 +00:00
StopMove_Imm(true);
2024-12-15 01:39:39 +00:00
//Remove_Freeze();
//for (int j = 0; j < arr_Renderer.Length; j++)
//{
// var materials = arr_Renderer[j].sharedMaterials.ToList();
// materials.Add(ProjectileInfo.Ins.arr_materials[0]);
// arr_Renderer[j].materials = materials.ToArray();
//}
_freezeTime -= (float)dic_ccData[eCC.Freeze].CCReduceTime;
if (_freezeTime < 0.1f) _freezeTime = 0.1f;
dic_ccData[eCC.Freeze].CCReduceTime += 0.05f;
if (IsSubRole(eSubRol.Boss)) Cancel_Freeze(_freezeTime * 0.5f);
else if (IsSubRole(eSubRol.Elite)) Cancel_Freeze(_freezeTime * 0.2f);
2024-12-15 01:39:39 +00:00
else Cancel_Freeze(_freezeTime);
}
void Remove_Freeze()
{
for (int j = 0; j < arr_Renderer.Length; j++)
{
var materials = arr_Renderer[j].sharedMaterials.ToList();
materials.Remove(ProjectileInfo.Ins.arr_materials[0]);
arr_Renderer[j].materials = materials.ToArray();
}
}
void Off_Freeze()
{
Remove_Freeze();
dic_ccData[eCC.Freeze].CCTime = 0f;
InGameInfo.Ins.Show_Effect("Effect_Hit_IceBolt", transform.position);
act_AfterFreezing?.Invoke(this);
}
void Cancel_Freeze(float _offTime)
{
if (dic_ccData[eCC.Freeze].CCTime > 0f)
{
if (IsInvoking(nameof(Off_Freeze))) CancelInvoke(nameof(Off_Freeze));
Invoke(nameof(Off_Freeze), _offTime);
}
dic_ccData[eCC.Freeze].CCReduceTime = 0;
On_NavMeshAgent();
}
#endregion
#region :
float StunAfterKnockBackTime = 0f;
public virtual void KnockBack(double _time, float speed = 4f, Action after = null)
2024-12-15 01:39:39 +00:00
{
if (m_Stat.Get_Stat(eStat.CC_Immunity) > 0) return;
if (IsRole(eRole.OBJ) || IsSubRole(eSubRol.Boss) || DSUtil.CheckNull(m_NavMeshAgent) || IsCC()) return;
2024-12-15 01:39:39 +00:00
if (dic_ccData[eCC.KnockBack].CCTime < _time)
StartCoroutine(Co_KnockBack(_time, speed, after));
2024-12-15 01:39:39 +00:00
}
IEnumerator Co_KnockBack(double _time, float speed, Action after)
2024-12-15 01:39:39 +00:00
{
dic_ccData[eCC.KnockBack].CCTime = _time;
dic_ccData[eCC.KnockBack].CCTime -= dic_ccData[eCC.KnockBack].CCReduceTime;
if (dic_ccData[eCC.KnockBack].CCTime < 0.1f) dic_ccData[eCC.KnockBack].CCTime = 0.1f;
dic_ccData[eCC.KnockBack].CCReduceTime += 0.05f;
while (dic_ccData[eCC.KnockBack].CCTime > 0f)
{
dic_ccData[eCC.KnockBack].CCTime -= Time.deltaTime;
transform.Translate(speed * Time.deltaTime * Vector3.back);
Set_Warp(transform.position);
yield return null;
}
dic_ccData[eCC.KnockBack].CCTime = 0f;
On_NavMeshAgent();
after?.Invoke();
2024-12-15 01:39:39 +00:00
if (StunAfterKnockBackTime > 0)
{
Stun(StunAfterKnockBackTime, true);
StunAfterKnockBackTime = 0f;
}
2024-12-28 00:20:09 +00:00
#if UNITY_EDITOR
if (SceneManager.GetActiveScene().name == "StatTest")
{
transform.localPosition = Vector3.zero;
}
#endif
2024-12-15 01:39:39 +00:00
}
public void Stun_AfterKnockBack(float time) { StunAfterKnockBackTime = time; }
#endregion
#region :
public virtual void Attract(Vector3 _pos)
{
if (m_Stat.Get_Stat(eStat.CC_Immunity) > 0) return;
2024-12-15 01:39:39 +00:00
if (gameObject.activeInHierarchy && dic_ccData[eCC.Attract].CCTime <= 0f)
StartCoroutine(Co_Attract(_pos));
}
IEnumerator Co_Attract(Vector3 _pos)
{
dic_ccData[eCC.Attract].CCTime = 10f;
float t = 0.3f;
while (t > 0f)
{
m_NavMeshAgent.Warp(Vector3.MoveTowards(transform.position, _pos, Time.deltaTime * 2f));
yield return null;
t -= Time.deltaTime;
}
dic_ccData[eCC.Attract].CCTime = 0f;
On_NavMeshAgent();
}
#endregion
#region :
public virtual void KnockedAirborne(double _airborneTime = 1d)
{
if (m_Stat.Get_Stat(eStat.CC_Immunity) > 0 || dic_ccData[eCC.KnockedAirborne].CCTime > 0) return;
2024-12-15 01:39:39 +00:00
StartCoroutine(Co_KnockedAirborne((float)_airborneTime));
}
IEnumerator Co_KnockedAirborne(float _airborneTime)
{
if (IsSubRole(eSubRol.Elite)) _airborneTime -= _airborneTime * 0.2f;
else if (IsSubRole(eSubRol.Boss)) _airborneTime -= _airborneTime * 0.5f;
2024-12-15 01:39:39 +00:00
dic_ccData[eCC.KnockedAirborne].CCTime = _airborneTime;
StopMove_Imm(true);
2024-12-15 01:39:39 +00:00
m_NavMeshAgent.enabled = false;
Vector3 v3_ori = new Vector3(transform.position.x, transform.position.y, transform.position.z);
Vector3 v3_target = new Vector3(transform.position.x, transform.position.y + 1f, transform.position.z);
float t = 0f;
while (t < 1f)
{
yield return null;
t += Time.deltaTime * 2f;
transform.position = Vector3.Lerp(v3_ori, v3_target, t);
}
yield return new WaitForSeconds(_airborneTime * 0.75f);
t = 0f;
while (t < 1f)
{
yield return null;
t += Time.deltaTime * 4f;
transform.position = Vector3.Lerp(v3_target, v3_ori, t);
}
dic_ccData[eCC.KnockedAirborne].CCTime = 0f;
m_NavMeshAgent.enabled = true;
On_NavMeshAgent();
}
#endregion
#region : ()
2025-02-11 00:15:02 +00:00
Coroutine m_CoStun;
public void Stun(double time, bool showEffect = false)
{
if (m_Stat.Get_Stat(eStat.CC_Immunity) > 0) return;
2025-02-11 00:15:02 +00:00
if (!DSUtil.CheckNull(m_CoStun)) { StopCoroutine(m_CoStun); m_CoStun = null; }
m_CoStun = StartCoroutine(Co_Stun(time, showEffect));
}
2024-12-15 01:39:39 +00:00
IEnumerator Co_Stun(double _time, bool showEffect = false)
{
2025-02-11 00:15:02 +00:00
float stunTime = (float)_time;
if (IsSubRole(eSubRol.Elite)) stunTime -= stunTime * 0.2f;
else if (IsSubRole(eSubRol.Boss)) stunTime -= stunTime * 0.5f;
if (showEffect) InGameInfo.Ins.Show_Effect("Effect_Stun", this, eEffectLocation.Top, stunTime);
2024-12-15 01:39:39 +00:00
m_animation.speed = 1f;
2025-02-11 00:15:02 +00:00
AnimationPlay("stun");
2024-12-15 01:39:39 +00:00
var cc = eCC.Stun;
dic_ccData[cc].CCTime = _time;
StopMove_Imm(true);
2025-02-11 00:15:02 +00:00
yield return new WaitForSeconds(stunTime);
2024-12-15 01:39:39 +00:00
dic_ccData[cc].CCTime = 0f;
On_NavMeshAgent();
}
#endregion
#region
public void Set_MoveSpeed(bool _add, double _v)
{
if (DSUtil.CheckNull(m_NavMeshAgent)) return;
if (_add) m_NavMeshAgent.speed += (float)_v;
else m_NavMeshAgent.speed -= (float)_v;
}
public float Get_MoveSpeed()
{
var speed = m_NavSpeed;
if (dic_ccData[eCC.MOVSPD_Up].CCTime > 0)
speed += speed * (float)dic_ccData[eCC.MOVSPD_Up].CCDmg;
2025-02-13 22:49:30 +00:00
if (dic_ccValue.ContainsKey(eCC.MOVSPD_Up))
speed += speed * dic_ccValue[eCC.MOVSPD_Up];
2024-12-15 01:39:39 +00:00
if (dic_ccData[eCC.MOVSPD_Down].CCTime > 0)
speed -= speed * (float)dic_ccData[eCC.MOVSPD_Down].CCDmg;
return speed;
}
2025-01-16 06:07:21 +00:00
#endregion
#region
2025-02-20 00:40:21 +00:00
public virtual void Jump(float jumpTime, float height = 1f, float jumpspeed1 = 5f, float jumpspeed2 = 2f, Action after = null)
2025-01-16 06:07:21 +00:00
{
2025-02-20 00:40:21 +00:00
StartCoroutine(Co_Jump(jumpTime, height, jumpspeed1, jumpspeed2, after));
2025-01-16 06:07:21 +00:00
}
2025-02-20 00:40:21 +00:00
IEnumerator Co_Jump(float jumpTime, float height = 1f, float jumpspeed1 = 5f, float jumpspeed2 = 2f, Action after = null)
2025-01-16 06:07:21 +00:00
{
StopMove_Imm(false);
m_NavMeshAgent.enabled = false;
Vector3 v3_ori = new Vector3(transform.position.x, transform.position.y, transform.position.z);
2025-02-20 00:40:21 +00:00
Vector3 v3_target = new Vector3(transform.position.x, transform.position.y + height, transform.position.z);
float t = 0f, speed = jumpspeed1;
2025-01-16 06:07:21 +00:00
while (t < 1f)
{
yield return null;
t += Time.deltaTime * speed;
transform.position = Vector3.Lerp(v3_ori, v3_target, t);
}
yield return new WaitForSeconds(jumpTime);
t = 0f;
while (t < 1f)
{
yield return null;
2025-02-20 00:40:21 +00:00
t += Time.deltaTime * speed * jumpspeed2;
2025-01-16 06:07:21 +00:00
transform.position = Vector3.Lerp(v3_target, v3_ori, t);
}
m_NavMeshAgent.enabled = true;
On_NavMeshAgent();
after?.Invoke();
}
2024-12-15 01:39:39 +00:00
#endregion
#region
public virtual void Play_Idle()
{
if (IsDead() || isPlaying(eAnim.Idle)) return;
if (CurAnim != eAnim.Idle || (CurAnim == eAnim.Idle && !isPlaying()))
{
CurAnim = eAnim.Idle;
AnimationPlay(MyValue.Get_AnimName(eAnim.Idle));
}
}
public virtual void Play_Run()
{
Play_RunAnim();
}
protected void Play_RunAnim()
{
if (!IsDead() && CurAnim != eAnim.Run)
{
if (m_NavMeshAgent.isOnNavMesh)
m_NavMeshAgent.isStopped = false;
CurAnim = eAnim.Run;
m_animation.speed = 1f;
AnimationPlay(MyValue.Get_AnimName(CurAnim));
}
if (CurAnim == eAnim.Run && !Get_AnimStatus(eAnim.Run))
AnimationPlay(MyValue.Get_AnimName(CurAnim));
}
public virtual void Play_Hit()
{
HitEffect_Color();
}
public virtual void Play_Die()
{
var aniname = MyValue.Get_AnimName(eAnim.Die);
m_animation.speed = 1f;
AnimationPlay(aniname);
if (IsRole(eRole.PC) && !DSUtil.CheckNull(ActorInfo.Ins)) ActorInfo.Ins.All_DelTarget();
}
public virtual void Play_Attack(int _attack, float _as, Action actsuccess = null)
2024-12-15 01:39:39 +00:00
{
//if (IsRole(eRole.Pet) && CurAnim == eAnim.Attack) return;
if (CurAnim == eAnim.Attack || IsDead() || CurAnim >= eAnim.Skill) return;
2024-12-15 01:39:39 +00:00
StopMove_Imm(false);
2024-12-15 01:39:39 +00:00
CurAnim = eAnim.Attack + _attack;
var aniname = MyValue.Get_AnimName(eAnim.Attack + _attack);
m_animation.speed = _as <= 0f ? 1f : _as;
2025-02-26 00:19:45 +00:00
if (dic_ccData.ContainsKey(eCC.ATKSPD_Up) && dic_ccData[eCC.ATKSPD_Up].CCTime > 0f)
2024-12-15 01:39:39 +00:00
m_animation.speed += m_animation.speed * (float)dic_ccData[eCC.ATKSPD_Up].CCDmg;
2025-02-13 22:49:30 +00:00
if (dic_ccValue.ContainsKey(eCC.ATKSPD_Up))
m_animation.speed += m_animation.speed * dic_ccValue[eCC.ATKSPD_Up];
2025-02-26 00:19:45 +00:00
if (dic_ccData.ContainsKey(eCC.ATKSPD_Down) && dic_ccData[eCC.ATKSPD_Down].CCTime > 0f)
2024-12-15 01:39:39 +00:00
m_animation.speed -= m_animation.speed * (float)dic_ccData[eCC.ATKSPD_Down].CCDmg;
AnimationPlay(aniname);
actsuccess?.Invoke();
2024-12-15 01:39:39 +00:00
if (isTarget) transform.LookAt(m_Target.transform);
2024-12-15 01:39:39 +00:00
if (gos_Effect != null && gos_Effect.Length > _attack)
{
gos_Effect[_attack].SetActive(false);
gos_Effect[_attack].SetActive(true);
}
}
Coroutine co_casting;
public virtual bool Play_Skill(string motion)
{
m_animation.speed = 1f;
CurAnim = eAnim.Skill;
2025-03-01 03:21:02 +00:00
AnimationPlay(IsRole(eRole.Pet) ? "casting" : motion);
2024-12-15 01:39:39 +00:00
if (isTarget) transform.LookAt(m_Target.transform);
2024-12-15 01:39:39 +00:00
StopMove_Imm(false);
2024-12-15 01:39:39 +00:00
2024-12-15 23:37:37 +00:00
if (!DSUtil.CheckNull(m_Magic))
{
2025-03-01 03:21:02 +00:00
if (IsRole(eRole.Pet) || !string.IsNullOrEmpty(m_Magic.m_SkillTableData.s_NextAnimation))
{
co_casting = StartCoroutine(Co_Casting(m_Magic.m_SkillTableData.f_CastingTime));
2024-12-28 00:20:09 +00:00
if (m_NavMeshAgent.isOnNavMesh) m_NavMeshAgent.ResetPath();
}
switch (m_Magic.m_SkillTableData.e_Skill)
{
case eEffect.Skill_JumpAttack: StartCoroutine(Co_JumpAttack(1f, 0.8f)); break;
case eEffect.Skill_FatalBlow: StartCoroutine(Co_JumpAttack(0.8f, 0.6f)); break;
}
2024-12-15 23:37:37 +00:00
if (!string.IsNullOrEmpty(m_Magic.m_SkillTableData.s_CastingEffect))
InGameInfo.Ins.Show_Effect(m_Magic.m_SkillTableData.s_CastingEffect, Get_position());
}
2024-12-15 01:39:39 +00:00
return true;
}
IEnumerator Co_Casting(float castTime)
{
yield return new WaitForSeconds(castTime);
if (!DSUtil.CheckNull(m_Magic))
2025-03-01 03:21:02 +00:00
AnimationPlay(IsRole(eRole.Pet) ? "casting_end" : m_Magic.m_SkillTableData.s_NextAnimation);
2024-12-15 01:39:39 +00:00
else
AnimationPlay("casting_end");
}
public virtual void Play_Dodge()
{
if (IsAvoidCoolTime() || CurAnim == eAnim.Dodge || IsDead()) return;
Set_AvoidCoolTime();
Set_AutoBraking(false);
act_MoveEnd = Set_AutoBraking;
CurAnim = eAnim.Dodge;
m_animation.speed = 1f;
2024-12-15 01:39:39 +00:00
m_NavMeshAgent.speed = 6f;
m_NavMeshAgent.isStopped = false;
Del_Magic();
AnimationPlay(MyValue.Get_AnimName(CurAnim));
//Set_Path(transform.position + transform.forward * 3f);
Set_Move(transform.position + transform.forward * 3f);
//Set_Warp(transform.position + transform.forward * 2f);
}
public void AnimationPlay(string aniname)
{
m_animation.Play(aniname);
//if (IsRole(eRole.Boss)) Debug.Log(aniname);
}
protected bool Get_AnimStatus(eAnim anim) { return m_animation.GetCurrentAnimatorStateInfo(0).IsName(MyValue.Get_AnimName(anim)); }
#endregion
#region
Outline m_Outline;
public void Set_Outline(bool active)
{
if (active)
{
if (DSUtil.CheckNull(m_Outline)) m_Outline = gameObject.AddComponent<Outline>();
m_Outline.enabled = true;
m_Outline.OutlineColor = new Color32(168, 0, 0, 102);
m_Outline.OutlineWidth = 5f;
}
else if (m_Outline != null)
m_Outline.enabled = false;
Set_MobMark(active);
}
protected virtual void Set_MobMark(bool active) { }
#endregion
#region
public virtual void HitEffect_Color()
{ // 2025. 02. 09. 정인호 : GC Alloc을 2.3KB 발생으로 인해 사용 금지
//if (!ProjectileInfo.Ins || IsInvoking(nameof(Off_HitEffect_Color))) return;
2024-12-15 01:39:39 +00:00
//for (int j = 0; j < arr_Renderer.Length; j++)
//{
// var materials = arr_Renderer[j].sharedMaterials.ToList();
// materials.Add(ProjectileInfo.Ins.arr_materials[1]);
// arr_Renderer[j].materials = materials.ToArray();
//}
2024-12-15 01:39:39 +00:00
//Invoke(nameof(Off_HitEffect_Color), 0.1f);
2024-12-15 01:39:39 +00:00
}
void Off_HitEffect_Color()
{ // 2025. 02. 09. 정인호 : GC Alloc을 2.3KB 발생으로 인해 사용 금지
//for (int j = 0; j < arr_Renderer.Length; j++)
//{
// var materials = arr_Renderer[j].sharedMaterials.ToList();
// materials.Remove(ProjectileInfo.Ins.arr_materials[1]);
// arr_Renderer[j].materials = materials.ToArray();
//}
2024-12-15 01:39:39 +00:00
}
#endregion
2025-01-13 02:40:17 +00:00
#region
public void Set_ScaleControl(bool returntoOriginalScale, float targetscale = 1f, Action actComplete = null)
{
StartCoroutine(Co_ScaleControl(returntoOriginalScale, targetscale, actComplete));
}
protected virtual IEnumerator Co_ScaleControl(bool returntoOriginalScale, float targetscale, Action actComplete = null)
{
yield break;
}
#endregion
2025-01-17 00:28:44 +00:00
#region
/// <summary>
/// TelepoetPosion으로 이동
/// </summary>
2025-01-17 03:48:51 +00:00
public virtual void MoveToTarget(Actor target, float stopdist, float speed, Action _movecomplete = null, float dist = 1f)
2025-01-17 00:28:44 +00:00
{
2025-01-17 03:48:51 +00:00
StartCoroutine(Co_MoveToTarget(target, stopdist, speed, _movecomplete, dist));
2025-01-17 00:28:44 +00:00
}
2025-01-17 03:48:51 +00:00
IEnumerator Co_MoveToTarget(Actor target, float stopdist, float speed, Action _movecomplete, float dist)
2025-01-17 00:28:44 +00:00
{
m_NavMeshAgent.stoppingDistance = stopdist;
Set_Path(Get_TeleportPostion(target, dist));
2025-01-17 03:48:51 +00:00
while (!Complete_Destination())
{
m_NavMeshAgent.speed = speed;
yield return null;
}
2025-01-17 00:28:44 +00:00
_movecomplete?.Invoke();
m_NavMeshAgent.stoppingDistance = m_NavStopDistance;
2025-01-17 03:48:51 +00:00
m_NavMeshAgent.speed = Get_MoveSpeed();
2025-01-17 00:28:44 +00:00
}
public virtual void Set_JoystickStatus(int status) { }
public void Set_Warp(Vector3 _pos)
{
2025-01-26 22:48:47 +00:00
if (IsDead()) return;
2025-01-17 00:28:44 +00:00
if (m_BoxCollider) m_BoxCollider.enabled = true;
m_NavMeshAgent.enabled = true; // 사망 시 off 됨. 다시 세팅될 때 켜줌
m_NavMeshAgent.Warp(_pos);
}
public virtual void Run_byJoystick(Vector3 _v) { }
protected void StopMove_Imm(bool setIdle)
{
if (setIdle) CurAnim = eAnim.Idle;
if (m_NavMeshAgent.isOnNavMesh)
{
m_NavMeshAgent.isStopped = true;
m_NavMeshAgent.ResetPath(); // 경로를 비워서 멈춤
m_NavMeshAgent.velocity = Vector3.zero; // 이 경우도 velocity를 0으로 설정
}
}
int FindCount = 0;
protected bool Set_Path(Vector3 _pos)
{
if (m_NavMeshAgent.enabled && m_NavMeshAgent.isOnNavMesh)
{
NavMeshPath path = new NavMeshPath();
m_NavMeshAgent.CalculatePath(_pos, path);
switch (path.status)
{
case NavMeshPathStatus.PathComplete:
m_NavMeshAgent.speed = Get_MoveSpeed();
m_NavMeshAgent.SetPath(path);
FindCount = 0; // 성공 시 초기화
return true;
case NavMeshPathStatus.PathPartial:
++FindCount;
//Debug.Log($"Path Partial. Attempt: {FindCount}");
2025-01-17 00:28:44 +00:00
if (FindCount > 5)
{
FindCount = 0;
return false;
}
var newpos = DSUtil.Get_RandomPos_onNavMesh(_pos, 0f, 5f);
return Set_Path(newpos);
case NavMeshPathStatus.PathInvalid:
Debug.LogWarning("Path Invalid.");
// 적 근처로 워프넣어볼까?
//Set_Warp(DSUtil.Get_RandomPos_onNavMesh(_pos, 3f));
break;
}
}
return false;
}
protected void Set_Move(Vector3 _pos)
{
if (m_NavMeshAgent.enabled && m_NavMeshAgent.isOnNavMesh)
{
m_fAttackMoveTime = 1f;
#if UNITY_EDITOR
if (SceneManager.GetActiveScene().name == "StatTest")
m_fAttackMoveTime = 0f;
#endif
m_NavMeshAgent.stoppingDistance = 0; // 툴에서 사용 용도
m_NavMeshAgent.isStopped = false;
m_NavMeshAgent.angularSpeed = 0f;
NavMeshPath path = new NavMeshPath();
m_NavMeshAgent.CalculatePath(_pos, path);
switch (path.status)
{
case NavMeshPathStatus.PathComplete:
m_NavMeshAgent.SetPath(path);
break;
}
}
}
protected void Set_Destination(Vector3 _pos)
{
if (m_NavMeshAgent.enabled && m_NavMeshAgent.isOnNavMesh)
{
m_NavMeshAgent.ResetPath();
m_NavMeshAgent.SetDestination(_pos);
}
}
protected bool Complete_Destination()
{
if (m_NavMeshAgent.isOnNavMesh && !m_NavMeshAgent.pathPending)
if (m_NavMeshAgent.remainingDistance <= m_NavMeshAgent.stoppingDistance)
if (!m_NavMeshAgent.hasPath || m_NavMeshAgent.velocity.sqrMagnitude == 0f)
return true;
return false;
}
public void ReCal_NaveMesh()
{
//return; // TODO 정인호 : 내비메시의 이상한 위치에 있으면 주변을 검색해서 내비메시 위로 올리는데 이상한 위치로 갈 수 있어서 일단 다시 뺌
if (m_ID != 61 && m_NavMeshAgent && m_NavMeshAgent.enabled)
{
var newpos = DSUtil.Get_RandomPos_onNavMesh(Get_position(), 0f, 1f);
if (!Vector3.Equals(newpos, Get_position()))
Set_Warp(newpos);
}
}
#endregion
2024-12-15 01:39:39 +00:00
2025-02-11 00:15:02 +00:00
public bool CanMove() { return m_NavMeshAgent.isOnNavMesh && !m_NavMeshAgent.isStopped && !IsCC(); }
2024-12-15 01:39:39 +00:00
protected virtual bool IsAvoidCoolTime() { return false; }
protected virtual void Set_AvoidCoolTime() { }
public virtual MonsterAppearData Get_MonsterStatTableData() { return null; }
2025-02-16 00:14:00 +00:00
public virtual void Change_MobStatus(eMobStatus mobStatus) { }
protected virtual void Check_Battle() { }
public virtual bool isNoseeMob() { return false; }
2025-02-13 04:40:04 +00:00
public virtual void On_Regen(bool reincarnation = false, float healrate = 1f)
2024-12-15 01:39:39 +00:00
{
gameObject.SetActive(true);
DeadStatus = false;
m_Stat.Clear_BuffDebuff();
m_Stat.Set_Stat(eStat.HP, 0);
2025-02-13 04:40:04 +00:00
Heal(healrate, false);
2024-12-15 01:39:39 +00:00
Init_CC();
m_animation.speed = 1f;
2024-12-15 01:39:39 +00:00
}
public virtual void Set_AutoBraking(bool _active) { }
public void Set_Auto()
{
m_Auto = !m_Auto;
ServerInfo.Ins.m_ServerData.Set_Common(eCommon.Auto, m_Auto ? 1 : 0);
if (m_Auto)
{
IsStop = false;
//NewGameUI.Ins.m_GuideQuestUI.Add_GuideQuest(ePurpose.AutoMagic);
2024-12-15 01:39:39 +00:00
}
else
{
Del_Magic();
if (isTarget)
2024-12-15 01:39:39 +00:00
{
if (IsRole(eRole.PC))
{
m_Target.Set_Outline(false);
m_NavMeshAgent.ResetPath();
Play_Idle();
}
}
Del_Target();
}
}
public Actor Get_MyPet() { return m_MyPet; }
public void Set_MyPet(Actor actor) { m_MyPet = actor; }
#region
public virtual void Event_Idle(int a)
{
CurAnim = eAnim.Idle;
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 1, a);
#endif
}
public virtual void Move(float b)
{
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 2, 0, b);
#endif
}
public virtual void Interpolation(string s)
{
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 3, 0, 0f, s);
#endif
}
public virtual void Dodge(int a)
{
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 1, a);
#endif
}
public virtual void Immortal(int a)
{
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 1, a);
#endif
}
public virtual void Hit(float b)
{
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 2, 0, b);
#endif
m_DamageRate = b;
}
public virtual void Projectile(string s)
{
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 3, 0, 0f, s);
#endif
}
protected void Shoot_Projectile(string proj, float lifetime, Vector3 startpos)
{
if (ProjectileInfo.isIns)
{
var ccData = Get_CCData(eCC.MultiShot);
var amount = 1 + (ccData.CCTime > 0f ? ccData.CCVal : 0);
if (amount > 1)
{
float cal_angle = amount * 10f;
float angleStep = cal_angle / (amount - 1); // 전체 각도를 화살 개수로 나누기
for (int i = 0; i < amount; ++i)
{
ProjectileInfo.Ins.Shoot_Projectile(proj, this, m_Target, 1f, startpos, lifetime,
pb =>
{
float angle = -(cal_angle * 0.5f) + (angleStep * i);
pb.transform.localEulerAngles = new Vector2(0f, pb.transform.localEulerAngles.y + angle);
});
}
}
else
{
ProjectileInfo.Ins.Shoot_Projectile(proj, this, m_Target, 1f, startpos, lifetime);
}
}
}
2024-12-15 01:39:39 +00:00
public virtual void SkillEvent(int a)
{
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 1, a);
#endif
Shoot_Skill();
}
public virtual void FootR(string s)
{
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 3, 0, 0f, s);
#endif
}
public virtual void FootL(string s)
{
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 3, 0, 0f, s);
#endif
}
2025-01-15 22:32:07 +00:00
public virtual void ShowEffect(AnimationEvent s)
2024-12-15 01:39:39 +00:00
{
#if UNITY_EDITOR
2025-01-15 22:32:07 +00:00
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 3,
s.intParameter, s.floatParameter, s.stringParameter);
2024-12-15 01:39:39 +00:00
#endif
2025-01-15 22:32:07 +00:00
switch (s.intParameter)
{
case 0: InGameInfo.Ins.Show_Effect(s.stringParameter, Get_Center_position(), transform.eulerAngles); break;
case 1: InGameInfo.Ins.Show_Effect(s.stringParameter, Get_position(), transform.eulerAngles); break;
case 2: InGameInfo.Ins.Show_Effect(s.stringParameter, Get_Center_position()); break;
case 3: InGameInfo.Ins.Show_Effect(s.stringParameter, Get_position()); break;
}
2024-12-15 01:39:39 +00:00
}
public virtual void Init_CurAnim(bool resetpos)
{
CurAnim = eAnim.Idle;
if (resetpos)
Set_Warp(Vector3.zero);
}
public eAnim Get_CurAnim() { return CurAnim; }
2025-01-16 06:07:21 +00:00
public void Set_CurAnim(eAnim anim) { CurAnim = anim; }
2024-12-15 01:39:39 +00:00
public virtual bool Is_Immortal() { return m_bImmortal; }
#endregion
}