Project_WL/Assets/Script/Character/Actor.cs

1878 lines
73 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
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; // 내가 받은 피해, 내가 준 피해, 공격 쿨타임
protected Transform tf_HUD_HP, tf_HUD_Dmg;
protected Vector3 ObjSize, Original_Scale;
[SerializeField]
protected Actor m_Target, m_MyPet;
protected Dictionary<int, UseMagicInfo> dic_MagicData = new Dictionary<int, UseMagicInfo>();
protected UseMagicInfo m_Magic;
protected float m_NavSpeed, m_NavStopDistance, m_HitTime, FindOtherTargetTime = 7.5f, GoToTargetTime = 10f, OriginalAnimSpeed, m_fAttackMoveTime, m_DamageRate = 1f;
protected bool m_Enemy, IsPlaySkill, IsChargeAttack, m_Auto, DeadStatus, hasAppliedDamage;
protected bool _isstop;
protected bool IsStop
{
get { return _isstop; }
set
{
_isstop = value;
//Debug.Log("IsStop 변경 " + value);
}
}
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>();
protected Dictionary<eCC, CCData> dic_ccData = new Dictionary<eCC, CCData>();
protected Dictionary<eCC, Dictionary<Actor, double>> dic_ccAddRate = new Dictionary<eCC, Dictionary<Actor, double>>();
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();
dic_ccAddRate.Clear();
foreach (var key in dic_skillextra.Keys.ToList())
dic_skillextra[key] = false;
}
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;
public HUDUI m_HUDUI { get; set; }
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;
}
}
var hud_hp = new GameObject("HUD_HP");
tf_HUD_HP = hud_hp.transform;
tf_HUD_HP.parent = transform;
tf_HUD_HP.position = Get_position() + Vector3.down * 0.1f;
// maxY를 기준으로 HUD 위치 조정
Vector3 headPosition = new Vector3(transform.position.x, maxY, transform.position.z);
var hud_dmg = new GameObject("HUD_Dmg");
tf_HUD_Dmg = hud_dmg.transform;
tf_HUD_Dmg.parent = transform;
tf_HUD_Dmg.position = headPosition;
}
protected virtual void Start()
{
}
protected virtual void OnEnable()
{
if (gos_Effect != null) DSUtil.InActivateGameObjects(gos_Effect);
}
protected virtual void OnDestroy()
{
if (m_HUDUI) Destroy(m_HUDUI.gameObject);
}
protected override void Update()
{
if (IsChargeAttack)
{
if (IsStop || IsDead() || IsCC()) return;
if (DSUtil.CheckNull(m_Target) || m_Target.IsDead())
Set_Target();
if (DSUtil.CheckNull(m_Target))
{
Play_Idle();
return;
}
if (Vector3.Distance(Get_position(), m_Target.Get_position()) > m_NavMeshAgent.stoppingDistance)
Play_Run();
else if (CurAnim != eAnim.Attack)
Play_Attack(0, (float)m_Stat.Get_Stat(eStat.FinalAttackSpeed));
}
Update_ETC();
}
protected virtual void FixedUpdate() { }
protected void Update_ETC()
{
foreach (var item in dic_ccData)
{
if (item.Value.CCReduceTime > 0f)
item.Value.CCReduceTime -= 0.0001f;
if (item.Value.CCReduceTime < 0f)
item.Value.CCReduceTime = 0f;
}
foreach (var item in dic_ccData)
{
if (item.Value.TimeUpdate && item.Value.CCTime > 0)
{
item.Value.CCTime -= Time.deltaTime;
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;
}
}
}
}
}
protected bool isPlaying()
{
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;
}
protected virtual void Set_Target(bool _usemagic = false) { }
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;
Make_HUDUI();
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()
{
if (!DSUtil.CheckNull(m_HUDUI)) m_HUDUI.Off();
gameObject.SetActive(false);
}
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)
{
IsStop = _stop;
if (IsStop)
{
if (m_NavMeshAgent && m_NavMeshAgent.isOnNavMesh) m_NavMeshAgent.ResetPath();
Play_Idle();
}
}
public void Set_Warp(Vector3 _pos)
{
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()
{
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}");
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);
}
}
public void Set_AttackCoolTime(float _rate)
{
var cooltime = m_Stat.Get_Stat(eStat.AttackCoolTime) * _rate;
if (m_attackCoolTime > cooltime)
m_attackCoolTime = cooltime;
}
protected void Make_HUDUI(Action act = null)
{
#if UNITY_EDITOR
if (SceneManager.GetActiveScene().name == "StatTest" ||
SceneManager.GetActiveScene().name == "Settings") return;
#endif
InGameInfo.Ins.Get_HUDUI(hudui =>
{
m_HUDUI = hudui;
m_HUDUI.name = name;
m_HUDUI.Init(this, tf_HUD_HP);
act?.Invoke();
});
}
public virtual DamageInfo Get_DamageInfo(ProjectileData _pd, double _attackrate = 1d, bool forceCri = false)
{
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));
dinfo.Damage = dinfo.BaseDmg * _attackrate;
dinfo.PiercingDmg = dinfo.BaseDmg *
(m_Stat.Get_Stat(eStat.PIERCING_Multiplier) +
dinfo.Get_AddValue(eAddExtraType.Add_Piercing_Multiplier_bySpiriBless));
dinfo.TextColor = HUDBase.Get_TextColor(m_AttackType);
if (dic_ccData[eCC.PiercingBuff].CCTime > 0)
dinfo.PiercingDmg += dinfo.BaseDmg * m_Stat.Get_Stat(eStat.PiercingBuff_byAttack);
dinfo.Cal_Cri(m_AttackType, m_Stat, forceCri); // 크리티컬 판정
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);
//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);
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);
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);
var cal2 = cal1 * 1000000;
var cal3 = cal2 * _dinfo.Damage;
_dinfo.Damage = Math.Round(cal3 * 0.000001); // /1000000을 *0.000001로 변경
}
// 몬스터 데미지 추가
if (IsRole(eRole.Mob))
{
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 (IsRole(eRole.Boss))
{
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);
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);
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_ccData[eCC.ManaShield].Off_Effect();
}
}
Cal_Damage(_dinfo);
Check_CC_byAttack(_dinfo);
#if UNITY_EDITOR
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name == "StatTest")
{
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;
m_Stat.Set_Stat(false, eStat.HP, _dinfo.Damage);
_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;
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); // 칭호 : 승차감 좋은 버스, 택시
if (!DSUtil.CheckNull(pd) && pd.IsSkill(eEffect.Skill_Ignited) && pd.CC_AddVal2 > 0)
{ // 버닝효과 체크, 버닝 효과 발동
var ccData = Get_CCData(eCC.Burn);
if (ccData.CCTime > 0f)
{
var other = ActorInfo.Ins.Get_NearstAllyActor(IsEnemy(), Get_position(), 5f);
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, ccData);
}
}
}
}
else
{
if (DSUtil.CheckNull(pd) ||
!DSUtil.CheckNull(pd) && !pd.IsSkill(eEffect.Skill_Ignited) && !pd.IsSkill(eEffect.Select_BodyonFire))
Play_Hit();
}
#if UNITY_EDITOR
if (SceneManager.GetActiveScene().name == "StatTest")
return;
#endif
// UI 설정
m_HUDUI.Set_HPSlider(m_Stat.Get_Stat(eStat.HP), m_Stat.Get_Stat(eStat.MaxHP));
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()
{
#if UNITY_EDITOR
if (SceneManager.GetActiveScene().name == "StatTest")
{
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.Boss:
case eRole.OBJ:
//MobInfo.Ins.Add_Dead();
Off();
break;
case eRole.PC:
//InGameInfo.Ins.Defeat_byMonster();
// 소환수 이동
var summ = ActorInfo.Ins.Get_Actor(eRole.Summon);
if (!DSUtil.CheckNull(summ)) summ.On_Regen();
// 펫 부활
var pet = ActorInfo.Ins.Get_Actor(eRole.Pet);
if (!DSUtil.CheckNull(pet)) pet.On_Regen();
// PC 부활
On_Regen();
break;
}
}
protected void Reset_AttackCoolTime() { m_attackCoolTime = m_Stat.Get_Stat(eStat.AttackCoolTime); }
protected virtual void Projectile_To_Target(string _proj)
{
Reset_AttackCoolTime();
ProjectileInfo.Ins.Shoot_Projectile(_proj, this, m_Target, 1f, Get_CenterPositionFoward() );
}
protected virtual void Projectile_To_Target2(string _proj)
{
Reset_AttackCoolTime();
ProjectileInfo.Ins.Shoot_Projectile(_proj, this, m_Target, 1f, Get_CenterPositionFoward());
}
protected virtual void Projectile_To_Target3(string _proj)
{
Reset_AttackCoolTime();
ProjectileInfo.Ins.Shoot_Projectile(_proj, this, m_Target, 1f, Get_CenterPositionFoward());
}
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() { }
public virtual bool Use_Skill(SkillListTableData skilldata, bool autoskill, int index)
{
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;
m_Magic = dic_MagicData[index];
if (IsDead() || IsCC() || CurAnim >= eAnim.Skill)
{
Del_Magic();
return false;
}
if (skilldata.e_SkillTarget == eSkillTarget.Enemy)
{
if (DSUtil.CheckNull(m_Target)) Set_Target(true);
if (DSUtil.CheckNull(m_Target))
{
if (IsRole(eRole.PC)) ToastUI.Ins.Set(105);
Del_Magic();
return false;
}
else if (Vector3.Distance(m_Target.Get_position(), Get_position()) > skilldata.f_SkillRange)
{ // 마법 사용 사정거리보다 멀리 있다. 마법 쏘러 가자.
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;
}
}
if (!Check_MagicCoolTime(index)) return false;
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);
return Play_Skill(skilldata.s_Animation);
}
public virtual void Shoot_Skill()
{
if (IsDead() || DSUtil.CheckNull(m_Magic)) return;
InGameInfo.Ins.Shoot_Effect(m_SkillData);
//SoundInfo.Ins.Play_OneShot(eSound.s009_CastSpell);
//if (IsRole(eRole.PC))
//NewGameUI.Ins.m_GuideQuestUI.Add_GuideQuest(ePurpose.ShootMagic);
Del_Magic();
}
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 };
}
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)
{
if (IsDead()) return;
var heal_hp = m_Stat.Get_Stat(eStat.MaxHP) * _rate;
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);
if (m_HUDUI != null)
m_HUDUI.Set_HPSlider(m_Stat.Get_Stat(eStat.HP), m_Stat.Get_Stat(eStat.MaxHP));
}
}
public virtual void Heal(double _hp, bool showhud = true)
{
if (IsDead()) return;
m_Stat.Set_Stat(true, eStat.HP, _hp);
#if UNITY_EDITOR
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name == "StatTest")
{
MainToStatTest.Ins.Set_Dmglabel($"HP : {_hp}");
return;
}
#endif
if (!DSUtil.CheckNull(m_HUDUI)) m_HUDUI.Set_HPSlider(m_Stat.Get_Stat(eStat.HP), m_Stat.Get_Stat(eStat.MaxHP));
if (showhud)
InGameInfo.Ins.Get_HUDDMGUI().Set(tf_HUD_Dmg, "<color=#00ff00>", _hp, eStat.None);
}
public virtual void Heal_MP(double _mp, bool showhud = true)
{
if (IsDead()) return;
m_Stat.Set_Stat(true, eStat.MP, _mp);
#if UNITY_EDITOR
if (SceneManager.GetActiveScene().name == "StatTest")
{
MainToStatTest.Ins.Set_Dmglabel($"MP : {_mp}");
return;
}
#endif
if (showhud)
InGameInfo.Ins.Get_HUDDMGUI().Set(tf_HUD_Dmg, "<color=#0000ff>", _mp, eStat.None);
}
#region
IEnumerator Co_JumpAttack(float heightPos_y, float duration)
{
var startPos = Get_position(); // 현재 위치
var targetPos = Get_TeleportPostion();
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; // 최종 위치 설정
}
#endregion
public int Get_ID() { return m_ID; }
public virtual int Get_Group() { return 0; }
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);
}
public Vector3 Get_Top_postion() { return tf_HUD_Dmg.position; }
public Vector3 Get_CenterPositionFoward(float dist = 1f) { return Get_Center_position() + transform.forward * dist; }
public Vector3 Get_PositionFoward(float dist = 1f) { return Get_position() + transform.forward * dist; }
public Vector3 Get_TeleportPostion(float dist = 1f)
{
var startPos = Get_position(); // 현재 위치
Vector3 direction = (m_Target.Get_position() - Get_position()).normalized; // 목표와 현재 위치의 방향 벡터를 구함
return m_Target.Get_position() - direction * 1f; // 목표 위치에서 -1f 앞 지점 계산
}
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); }
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 (m_Target)
{
if (!forcedel && m_Target.m_IsLockTarget && !m_Target.IsDead()) return;
if (IsRole(eRole.PC) && !IsEnemy()) m_Target.Set_Outline(false);
}
m_Target = null;
}
public bool IsDead() { return DeadStatus || !gameObject.activeInHierarchy; }
public bool IsOnlyDead() { return DeadStatus; }
public bool IsRole(eRole _role) { return m_Role == _role; }
public bool IsEnemy() { return m_Enemy; }
public virtual bool IsBerserkPet() { return false; }
public virtual bool Get_IsMainPC() { return false; }
public bool Get_SelectSkill(eEffect _effect)
{
if (IsRole(eRole.PC) && !IsEnemy())
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 (!DSUtil.CheckNull(MyValue.MyPC.m_Target))
MyValue.MyPC.m_Target.Set_Outline(false);
}
if (_ChangeTargetByHit)
{
if (DSUtil.CheckNull(m_Target) || m_Target.IsDead())
{
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.QuestMob) || (m_Target.IsRole(eRole.OBJ) && m_Target.m_SubRole == eSubRol.Ore))
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;
m_animation.speed = OriginalAnimSpeed;
}
}
#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
public bool IsCC()
{
foreach (var item in dic_ccData)
{
if (item.Key >= eCC.Freeze && item.Value.CCTime > 0) return true;
}
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) || IsRole(eRole.Boss)) && !IsCC())
knockbackTime = table_GlobalValue.Ins.Get_Float("f_KnockbackTime");
var beaterActor = _dinfo.Beater;
if (!DSUtil.CheckNull(_dinfo) && !DSUtil.CheckNull(beaterActor))
{
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));
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);
}
}
}
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();
CCData ccdata = null;
float LifeTime = val1 + pd.CC_AddTime;
switch (skillExtraData.e_SkillExtraType)
{
// 적에게
case eSkillExtraType.Frost:
case eSkillExtraType.Slow:
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:
DotDamage(eCC.Burn, _dinfo.Copy(), LifeTime, val2 + pd.CC_AddVal1, val3);
break;
case eSkillExtraType.Blood:
DotDamage(eCC.Blooding, _dinfo.Copy(), LifeTime, val2, val3);
break;
case eSkillExtraType.Poison:
DotDamage(eCC.Poison, _dinfo.Copy(), LifeTime, val2, val3);
break;
case eSkillExtraType.Stun:
Stun(LifeTime);
if (_dinfo.bExtraDmg)
{
_dinfo.Damage *= val2 + pd.CC_AddDmg;
Cal_Damage(_dinfo); // 스턴 추가 데미지
}
break;
case eSkillExtraType.DefenceDecrease:
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:
LifeTime += LifeTime * pd.Get_SkillDamagePercent();
Buff_or_Debuff(eCC.ManaShield, LifeTime, val3, 0, val2);
ccdata = dic_ccData[eCC.ManaShield];
break;
case eSkillExtraType.SwordShield:
break;
case eSkillExtraType.SpeedUp:
Buff_or_Debuff(eCC.ATKSPD_Up, LifeTime, val2);
Buff_or_Debuff(eCC.MOVSPD_Up, LifeTime, val3);
break;
case eSkillExtraType.Aggro:
break;
case eSkillExtraType.VampirHeal:
_dinfo.Beater.Heal(val2);
_dinfo.Beater.Heal_MP(val3);
break;
case eSkillExtraType.Cure:
_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;
}
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);
pd.m_ProjectileBase.Show_Effect(this, LifeTime, ccdata);
}
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)
{
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;
while (ccData.CCTime > 0)
{
var dinfo = dinfocopy.Beater.Get_DamageInfo(dinfocopy.Beater_pd, ccData.CCDmg);
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;
if (healmp < 1) healmp = 1;
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 (DSUtil.CheckNull(m_NavMeshAgent) || DSUtil.CheckNull(m_animation)) return;
if (DSUtil.CheckNull(act_AfterFreezing)) act_AfterFreezing = act;
dic_ccData[eCC.Freeze].CCTime = 10f;
if (!IsDead())
{
OriginalAnimSpeed = m_animation.speed;
m_animation.speed = 0f;
}
StopMove_Imm();
//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 (IsRole(eRole.Boss) || transform.localScale.x > 2f) Cancel_Freeze(_freezeTime * 0.4f);
else if (IsRole(eRole.PC)) Cancel_Freeze(_freezeTime * 0.5f);
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)
{
if (IsRole(eRole.OBJ) || IsRole(eRole.Boss) || DSUtil.CheckNull(m_NavMeshAgent) || IsCC()) return;
if (dic_ccData[eCC.KnockBack].CCTime < _time)
StartCoroutine(Co_KnockBack(_time, speed));
}
IEnumerator Co_KnockBack(double _time, float speed)
{
dic_ccData[eCC.KnockBack].CCTime = _time;
//if (IsRole(eRole.Boss)) _time *= 0.7f;
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;
OriginalAnimSpeed = 1f;
On_NavMeshAgent();
if (StunAfterKnockBackTime > 0)
{
Stun(StunAfterKnockBackTime, true);
StunAfterKnockBackTime = 0f;
}
#if UNITY_EDITOR
if (SceneManager.GetActiveScene().name == "StatTest")
{
transform.localPosition = Vector3.zero;
}
#endif
}
public void Stun_AfterKnockBack(float time) { StunAfterKnockBackTime = time; }
#endregion
#region :
public virtual void Attract(Vector3 _pos)
{
if (DSUtil.CheckNull(m_NavMeshAgent)) return;
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 (dic_ccData[eCC.KnockedAirborne].CCTime > 0) return;
StartCoroutine(Co_KnockedAirborne((float)_airborneTime));
}
IEnumerator Co_KnockedAirborne(float _airborneTime)
{
dic_ccData[eCC.KnockedAirborne].CCTime = _airborneTime;
StopMove_Imm();
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 : ()
public void Stun(double time, bool showEffect = false) { StartCoroutine(Co_Stun(time, showEffect)); }
IEnumerator Co_Stun(double _time, bool showEffect = false)
{
m_animation.speed = 1f;
//AnimationPlay("stun");
var cc = eCC.Stun;
dic_ccData[cc].CCTime = _time;
StopMove_Imm();
yield return new WaitForSeconds((float)_time);
dic_ccData[cc].CCTime = 0f;
On_NavMeshAgent();
if (showEffect) InGameInfo.Ins.Show_Effect("Effect_Stun", this, eEffectLocation.Top, (float)_time);
}
#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;
if (dic_ccData[eCC.MOVSPD_Down].CCTime > 0)
speed -= speed * (float)dic_ccData[eCC.MOVSPD_Down].CCDmg;
return speed;
}
#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();
if (IsDead() || IsCC() || CurAnim >= eAnim.Attack) return; // 공격, 스킬 쓸 때는 피격 애님 무시
if (CurAnim == eAnim.Run) return; // 달릴 때도 무시
if (IsRole(eRole.Mob)) m_HitTime = 0.5f;
var aniname = MyValue.Get_AnimName(eAnim.Hit);
m_animation.speed = 1f;
AnimationPlay(aniname);
}
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)
{
if (IsRole(eRole.Pet) && CurAnim == eAnim.Attack) return;
//if (IsDead() || CurAnim == eAnim.Attack + _attack || CurAnim >= eAnim.Skill1) return;
if (IsDead() || CurAnim >= eAnim.Skill) return;
//if (m_NavMeshAgent.enabled && m_NavMeshAgent.isOnNavMesh)
// m_NavMeshAgent.isStopped = true;
StopMove_Imm();
CurAnim = eAnim.Attack + _attack;
var aniname = MyValue.Get_AnimName(eAnim.Attack + _attack);
m_animation.speed = _as <= 0f ? 1f : _as;
if (dic_ccData.ContainsKey(eCC.ATKSPD_Up) && dic_ccData[eCC.ATKSPD_Up].CCTime > 0)
m_animation.speed += m_animation.speed * (float)dic_ccData[eCC.ATKSPD_Up].CCDmg;
if (dic_ccData.ContainsKey(eCC.ATKSPD_Down) && dic_ccData[eCC.ATKSPD_Down].CCTime > 0f)
m_animation.speed -= m_animation.speed * (float)dic_ccData[eCC.ATKSPD_Down].CCDmg;
AnimationPlay(aniname);
if (m_Target != null) transform.LookAt(m_Target.transform);
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;
AnimationPlay(motion);
if (!DSUtil.CheckNull(m_Target)) transform.LookAt(m_Target.transform);
if (m_NavMeshAgent.isOnNavMesh)
m_NavMeshAgent.isStopped = true;
if (!DSUtil.CheckNull(m_Magic))
{
if (!string.IsNullOrEmpty(m_Magic.m_SkillTableData.s_NextAnimation))
{
co_casting = StartCoroutine(Co_Casting(m_Magic.m_SkillTableData.f_CastingTime));
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;
case eEffect.Skill_DashSlash: Set_Warp(Get_TeleportPostion()); break;
}
if (!string.IsNullOrEmpty(m_Magic.m_SkillTableData.s_CastingEffect))
InGameInfo.Ins.Show_Effect(m_Magic.m_SkillTableData.s_CastingEffect, Get_position());
}
return true;
}
IEnumerator Co_Casting(float castTime)
{
yield return new WaitForSeconds(castTime);
if (!DSUtil.CheckNull(m_Magic))
AnimationPlay(m_Magic.m_SkillTableData.s_NextAnimation);
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;
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()
{
if (!ProjectileInfo.Ins || IsInvoking(nameof(Off_HitEffect_Color))) return;
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();
}
Invoke(nameof(Off_HitEffect_Color), 0.1f);
}
void Off_HitEffect_Color()
{
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();
}
}
#endregion
public bool CanMove() { return !IsCC() && m_NavMeshAgent.isOnNavMesh && !m_NavMeshAgent.isStopped; }
protected virtual bool IsAvoidCoolTime() { return false; }
protected virtual void Set_AvoidCoolTime() { }
public virtual void On_Is10_4() { }
public virtual void Check_10_4() { }
public virtual MonsterAppearData Get_MonsterStatTableData() { return null; }
public virtual void On_Regen()
{
gameObject.SetActive(true);
DeadStatus = false;
m_Stat.Clear_BuffDebuff();
m_Stat.Set_Stat(eStat.HP, 0);
Heal(1f, false);
Init_CC();
m_animation.speed = 1f;
}
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);
}
else
{
Del_Magic();
if (m_Target != null)
{
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
}
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();
if (m_NavMeshAgent.isOnNavMesh)
m_NavMeshAgent.isStopped = false;
}
public virtual void Indicator(int a)
{
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 1, a);
#endif
}
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
}
public virtual void ShowEffect(string s)
{
#if UNITY_EDITOR
if (SettingsMain.Ins) SettingsMain.Ins.Add_Event(System.Reflection.MethodBase.GetCurrentMethod().Name, 3, 0, 0f, s);
#endif
InGameInfo.Ins.Show_Effect(s, Get_Center_position(), transform.eulerAngles);
}
public virtual void Init_CurAnim(bool resetpos)
{
CurAnim = eAnim.Idle;
if (resetpos)
Set_Warp(Vector3.zero);
}
public eAnim Get_CurAnim() { return CurAnim; }
public virtual bool Is_Immortal() { return m_bImmortal; }
#endregion
}