481 lines
19 KiB
C#
481 lines
19 KiB
C#
|
|
using System;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.SceneManagement;
|
||
|
|
|
||
|
|
public enum eMobStatus { PatrolWait, PatrolRot, Patroling, Battle, BattleStop, Attack, Chase, }
|
||
|
|
|
||
|
|
public class MobActor : Actor
|
||
|
|
{
|
||
|
|
public int MagicID, HealCount;
|
||
|
|
public float HealRate = 0.1f;
|
||
|
|
|
||
|
|
protected int m_SpawnerId;
|
||
|
|
protected eMobStatus MobStatus;
|
||
|
|
Vector3 OriginalPos, TargetPatrolPos;
|
||
|
|
float m_PatrolDelay, m_DieTime;
|
||
|
|
bool b_IsFirstAttack, NoUpdate_byTool;
|
||
|
|
protected MonsterAppearData m_MonsterAppearData;
|
||
|
|
protected MonsterTableData m_MonsterTableData;
|
||
|
|
Action<int> m_actDie;
|
||
|
|
protected MobMark m_MobMark;
|
||
|
|
|
||
|
|
protected override void Start()
|
||
|
|
{
|
||
|
|
base.Start();
|
||
|
|
GetComponent<Rigidbody>().isKinematic = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
public override void Set(bool isEnemy, Actor owner, ServerData sdata, int _id, bool _stop, bool _ui = false)
|
||
|
|
{
|
||
|
|
base.Set(isEnemy, owner, sdata, _id, _stop);
|
||
|
|
|
||
|
|
if (MagicID > 0) m_Magic = new UseMagicInfo { m_SkillTableData = table_skilllist.Ins.Get_Data_orNull(MagicID), m_uiIndex = -1 };
|
||
|
|
m_SpawnerId = _id;
|
||
|
|
m_MonsterAppearData = table_monsterappear.Ins.Get_Data_orNull(m_SpawnerId);
|
||
|
|
|
||
|
|
//var chapter = InGameInfo.Ins.Get_CurStageData().Chapter;
|
||
|
|
if (transform.localScale.x > 1f)
|
||
|
|
{
|
||
|
|
m_NavMeshAgent.stoppingDistance = m_NavStopDistance * transform.localScale.x;
|
||
|
|
if (m_AttackType == eAttackType.Physics && m_NavMeshAgent.stoppingDistance > 7f) m_NavMeshAgent.stoppingDistance = 7f;
|
||
|
|
//else m_AttackType == eAttackType.Range && m_NavMeshAgent.stoppingDistance > 20f) m_NavMeshAgent.stoppingDistance = 20f;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (m_SubRole == eSubRol.Dummy) IsStop = true;
|
||
|
|
|
||
|
|
#if UNITY_EDITOR
|
||
|
|
if (SceneManager.GetActiveScene().name == "StatTest") return;
|
||
|
|
#endif
|
||
|
|
Set_RunSmoke(false);
|
||
|
|
Set_Warp(Get_position());
|
||
|
|
InGameInfo.Ins.Show_Effect("Effect_MonsterSpawn", Get_position());
|
||
|
|
}
|
||
|
|
public void Set(eRole role, MonsterTableData mobtable, Vector3 pos, Action<int> actDie, int order)
|
||
|
|
{
|
||
|
|
m_Role = role;
|
||
|
|
m_actDie = actDie;
|
||
|
|
bool IsBoss = IsRole(eRole.Boss);
|
||
|
|
m_MonsterTableData = mobtable;
|
||
|
|
var scale = m_MonsterTableData.f_DefaultScale;
|
||
|
|
if (!DSUtil.CheckNull(m_MonsterTableData)) transform.localScale = (IsBoss ? 1.3f : 1f) * scale * Vector3.one;
|
||
|
|
if (!IsBoss) IsBoss = scale > 2f;
|
||
|
|
|
||
|
|
m_AttackType = m_MonsterTableData.e_AttackType;
|
||
|
|
b_IsFirstAttack = m_MonsterTableData.b_IsFirstAttack;
|
||
|
|
|
||
|
|
//var chapter = InGameInfo.Ins.Get_CurStageData().Chapter;
|
||
|
|
//if (IsBoss && chapter < 101) { GameUI.Ins.IngameUI.m_BossInfoUI.Set(m_MonsterTableData.Get_Name()); }
|
||
|
|
|
||
|
|
// 순찰 모드로 전환
|
||
|
|
transform.SetPositionAndRotation(pos, Quaternion.identity);
|
||
|
|
OriginalPos = pos;
|
||
|
|
Change_MobStatus(eMobStatus.PatrolWait);
|
||
|
|
|
||
|
|
// 몹 스탯 설정
|
||
|
|
m_Stat = new ActorStatInfo(m_Role, m_MonsterTableData, m_MonsterAppearData);
|
||
|
|
Reset_AttackCoolTime();
|
||
|
|
m_NavMeshAgent.speed = (float)m_Stat.Get_Stat(eStat.FinalMoveSpeed);
|
||
|
|
m_NavMeshAgent.avoidancePriority = 51 + order;
|
||
|
|
|
||
|
|
#if UNITY_EDITOR
|
||
|
|
if (SceneManager.GetActiveScene().name == "StatTest")
|
||
|
|
{
|
||
|
|
transform.localPosition = Vector3.zero;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
//GameUI.Ins.IngameUI.m_ChapterQuest.Add_PurposeCount(new ChapterQuestAddData { purpose = ePurpose.MeetMob, mobid = m_MonsterTableData.n_MonsterID });
|
||
|
|
}
|
||
|
|
public override void On_Regen()
|
||
|
|
{
|
||
|
|
base.On_Regen();
|
||
|
|
Set_Warp(OriginalPos);
|
||
|
|
Change_MobStatus(eMobStatus.PatrolWait);
|
||
|
|
InGameInfo.Ins.Show_Effect("Effect_MonsterSpawn", Get_position());
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void Awake()
|
||
|
|
{
|
||
|
|
base.Awake();
|
||
|
|
m_NavMeshAgent.avoidancePriority = 51;
|
||
|
|
tag = "Mob";
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void Update()
|
||
|
|
{
|
||
|
|
if (NoUpdate_byTool || IsStop || IsDead() || IsCC()) return;
|
||
|
|
Update_ETC();
|
||
|
|
|
||
|
|
// 순찰 중
|
||
|
|
switch (MobStatus)
|
||
|
|
{
|
||
|
|
case eMobStatus.PatrolWait:
|
||
|
|
if (m_PatrolDelay > 0f)
|
||
|
|
m_PatrolDelay -= Time.deltaTime;
|
||
|
|
else
|
||
|
|
Change_MobStatus(eMobStatus.PatrolRot);
|
||
|
|
Check_Battle();
|
||
|
|
break;
|
||
|
|
case eMobStatus.PatrolRot:
|
||
|
|
// TargetPatrolPos 위치를 바라봄
|
||
|
|
Vector3 directionToTarget = (TargetPatrolPos - transform.position).normalized;
|
||
|
|
Quaternion lookRotation = Quaternion.LookRotation(new Vector3(directionToTarget.x, 0, directionToTarget.z));
|
||
|
|
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 5f);
|
||
|
|
if (Quaternion.Angle(transform.rotation, lookRotation) < 5f)
|
||
|
|
Change_MobStatus(eMobStatus.Patroling);
|
||
|
|
//Check_Battle();
|
||
|
|
break;
|
||
|
|
case eMobStatus.Patroling:
|
||
|
|
// TargetPatrolPos 위치로 이동함
|
||
|
|
if (Complete_Destination())
|
||
|
|
Change_MobStatus(eMobStatus.PatrolWait);
|
||
|
|
//Check_Battle();
|
||
|
|
break;
|
||
|
|
case eMobStatus.BattleStop:
|
||
|
|
Change_MobStatus(eMobStatus.PatrolRot);
|
||
|
|
Heal(1f);
|
||
|
|
break;
|
||
|
|
case eMobStatus.Battle:
|
||
|
|
if (!DSUtil.CheckNull(m_Target))
|
||
|
|
{
|
||
|
|
if (CurAnim < eAnim.Attack && Vector3.Distance(Get_position(), m_Target.Get_position()) > m_NavMeshAgent.stoppingDistance)
|
||
|
|
{
|
||
|
|
if (!isPlaying(eAnim.Attack, eAnim.Attack2, eAnim.Attack3))
|
||
|
|
Change_MobStatus(eMobStatus.Chase);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
Change_MobStatus(eMobStatus.Attack);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
Change_MobStatus(eMobStatus.BattleStop);
|
||
|
|
Check_Patrol();
|
||
|
|
break;
|
||
|
|
case eMobStatus.Attack:
|
||
|
|
if (!DSUtil.CheckNull(m_Target))
|
||
|
|
{
|
||
|
|
if (m_Target.IsDead())
|
||
|
|
{
|
||
|
|
Check_Battle();
|
||
|
|
if (MobStatus == eMobStatus.Attack) // 다음 타겟 못 찾았음
|
||
|
|
Change_MobStatus(eMobStatus.PatrolWait);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!isPlaying(eAnim.Attack, eAnim.Attack2, eAnim.Attack3) && Vector3.Distance(m_Target.Get_position(), Get_position()) > m_MonsterTableData.f_BaseATKRange + 0.5f)
|
||
|
|
Change_MobStatus(eMobStatus.Chase);
|
||
|
|
else if (m_attackCoolTime <= 0f)
|
||
|
|
{
|
||
|
|
m_attackCoolTime = 1f;
|
||
|
|
Play_Attack(0, m_MonsterTableData.f_BaseATKSpeed);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
Change_MobStatus(eMobStatus.BattleStop);
|
||
|
|
break;
|
||
|
|
case eMobStatus.Chase:
|
||
|
|
if (!DSUtil.CheckNull(m_Target))
|
||
|
|
{
|
||
|
|
Set_Path(m_Target.Get_position());
|
||
|
|
if (Vector3.Distance(Get_position(), m_Target.Get_position()) <= m_NavMeshAgent.stoppingDistance)
|
||
|
|
Change_MobStatus(eMobStatus.Attack);
|
||
|
|
}
|
||
|
|
Check_Patrol();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
if (m_attackCoolTime > 0f) m_attackCoolTime -= Time.deltaTime;
|
||
|
|
if (m_HitTime > 0f) { m_HitTime -= Time.deltaTime; if (m_attackCoolTime > 0f) return; }
|
||
|
|
if (GoToTargetTime > 0f && IsAutoAIMob()) GoToTargetTime -= Time.deltaTime;
|
||
|
|
|
||
|
|
//// 일정 시간이 지나면 가장 가까운 적을 다시 찾아봄
|
||
|
|
//if (FindOtherTargetTime > 0f)
|
||
|
|
//{
|
||
|
|
// FindOtherTargetTime -= Time.deltaTime;
|
||
|
|
// if (FindOtherTargetTime <= 0f)
|
||
|
|
// {
|
||
|
|
// FindOtherTargetTime = 7.5f;
|
||
|
|
// FindNextTarget(m_FindDist);
|
||
|
|
// }
|
||
|
|
//}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
protected void Change_MobStatus(eMobStatus mobStatus)
|
||
|
|
{
|
||
|
|
#if UNITY_EDITOR
|
||
|
|
if (SceneManager.GetActiveScene().name == "StatTest") return;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
MobStatus = mobStatus;
|
||
|
|
|
||
|
|
switch (mobStatus)
|
||
|
|
{
|
||
|
|
case eMobStatus.PatrolWait:
|
||
|
|
Del_Target();
|
||
|
|
Play_Idle();
|
||
|
|
m_PatrolDelay = m_MonsterTableData.f_PatrolWaitTime;
|
||
|
|
if (m_NavMeshAgent.isOnNavMesh && !IsCC()) m_NavMeshAgent.isStopped = false;
|
||
|
|
m_NavMeshAgent.stoppingDistance = 0.1f;
|
||
|
|
break;
|
||
|
|
case eMobStatus.PatrolRot:
|
||
|
|
Del_Target();
|
||
|
|
if (m_NavMeshAgent.isOnNavMesh && !IsCC()) m_NavMeshAgent.isStopped = false;
|
||
|
|
TargetPatrolPos = DSUtil.Get_RandomPos_onNavMesh(OriginalPos, m_MonsterAppearData.f_PatrolRange - 1f, m_MonsterAppearData.f_PatrolRange);
|
||
|
|
break;
|
||
|
|
case eMobStatus.Patroling:
|
||
|
|
Del_Target();
|
||
|
|
Play_Run();
|
||
|
|
Set_Path(TargetPatrolPos);
|
||
|
|
m_NavMeshAgent.stoppingDistance = 0.1f;
|
||
|
|
break;
|
||
|
|
case eMobStatus.Battle:
|
||
|
|
m_NavMeshAgent.stoppingDistance = m_MonsterTableData.f_BaseATKRange;
|
||
|
|
FindNextTarget(10000f);
|
||
|
|
break;
|
||
|
|
case eMobStatus.BattleStop:
|
||
|
|
Del_Target();
|
||
|
|
Play_Idle();
|
||
|
|
StopMove_Imm();
|
||
|
|
break;
|
||
|
|
case eMobStatus.Attack:
|
||
|
|
break;
|
||
|
|
case eMobStatus.Chase:
|
||
|
|
Play_Run();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void Check_Battle()
|
||
|
|
{
|
||
|
|
if (b_IsFirstAttack)
|
||
|
|
{ // 선공이고, 플레이어가 추적 범위 안에 들어오면 전투 상태로 전환
|
||
|
|
var enemies = ActorInfo.Ins.Get_EnemyActors(IsEnemy(), Get_position(), m_MonsterTableData.f_BaseChaseRange);
|
||
|
|
if (enemies.Count > 0)
|
||
|
|
Change_MobStatus(eMobStatus.Battle);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void Check_Patrol()
|
||
|
|
{
|
||
|
|
// 플레이어가 추적 범위 밖으로 나가면 순찰 상태로 전환
|
||
|
|
if (!isPlaying(eAnim.Attack, eAnim.Attack2, eAnim.Attack3) && m_Target == null || Vector3.Distance(OriginalPos, Get_position()) > m_MonsterTableData.f_BaseChaseRange)
|
||
|
|
Change_MobStatus(eMobStatus.BattleStop);
|
||
|
|
}
|
||
|
|
|
||
|
|
//protected override void Check_Attack()
|
||
|
|
//{
|
||
|
|
// // 현재 애니메이션 상태 정보를 가져옴
|
||
|
|
// AnimatorStateInfo stateInfo = m_animation.GetCurrentAnimatorStateInfo(0);
|
||
|
|
|
||
|
|
// // 애니메이션의 특정 구간 (예: 30%에서 40% 사이) 확인
|
||
|
|
// if (stateInfo.normalizedTime >= 0.3f && stateInfo.normalizedTime <= 0.4f && stateInfo.IsName("attack"))
|
||
|
|
// {
|
||
|
|
// // 데미지를 한 번만 적용
|
||
|
|
// if (!hasAppliedDamage)
|
||
|
|
// {
|
||
|
|
// switch (CurAnim)
|
||
|
|
// {
|
||
|
|
// case eAnim.Attack:
|
||
|
|
// case eAnim.Attack2:
|
||
|
|
// case eAnim.Attack3:
|
||
|
|
// case eAnim.Attack4:
|
||
|
|
// switch (m_AttackType)
|
||
|
|
// {
|
||
|
|
// // 근접
|
||
|
|
// case eAttackType.MeleePhysics:
|
||
|
|
// case eAttackType.MeleeMagic:
|
||
|
|
// case eAttackType.MeleePure:
|
||
|
|
// m_Target.Get_Damage(Get_DamageInfo());
|
||
|
|
// break;
|
||
|
|
// // 원거리
|
||
|
|
// case eAttackType.RangePhysics:
|
||
|
|
// case eAttackType.RangeMagic:
|
||
|
|
// case eAttackType.RangePure:
|
||
|
|
// ProjectileInfo.Ins.Shoot_Projectile(m_MonsterTableData.s_Porjectile, this, m_Target, 1f, tfs_ProjectileStart[0].position);
|
||
|
|
// break;
|
||
|
|
// }
|
||
|
|
// break;
|
||
|
|
// case eAnim.Skill1:
|
||
|
|
// case eAnim.Skill2:
|
||
|
|
// break;
|
||
|
|
// }
|
||
|
|
|
||
|
|
// hasAppliedDamage = true; // 데미지가 적용되었음을 표시
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
// else
|
||
|
|
// {
|
||
|
|
// // 구간을 벗어나면 다시 데미지 적용 가능하도록 설정
|
||
|
|
// hasAppliedDamage = false;
|
||
|
|
// }
|
||
|
|
//}
|
||
|
|
|
||
|
|
bool IsAutoAIMob() { return IsRole(eRole.Mob) || IsRole(eRole.Boss); }
|
||
|
|
|
||
|
|
public void Set_Target(Actor _target) { m_Target = _target; }
|
||
|
|
void FindNextTarget(float _dist)
|
||
|
|
{
|
||
|
|
switch (m_SubRole)
|
||
|
|
{
|
||
|
|
case eSubRol.Healer:
|
||
|
|
var allies = ActorInfo.Ins.Get_AlliesActors(IsEnemy(), Get_position());
|
||
|
|
var hurts = allies.FindAll(f => f.Get_HP() < f.Get_MaxHP());
|
||
|
|
m_Target = hurts.Count > 0 ? hurts[0] : null;
|
||
|
|
break;
|
||
|
|
case eSubRol.Dummy:
|
||
|
|
break;
|
||
|
|
case eSubRol.None:
|
||
|
|
case eSubRol.Ore:
|
||
|
|
case eSubRol.Witch:
|
||
|
|
m_Target = ActorInfo.Ins.Get_Nearest_EnemyActor_orNull(IsEnemy(), Get_position());
|
||
|
|
// 내가 타게팅했으니 너도 날 타게팅 할 수 있어야 한다.
|
||
|
|
if (m_Target != null)
|
||
|
|
{
|
||
|
|
//ActorInfo.Ins.Add_FindTarget_AllPC(m_Target.IsEnemy(), m_Role, m_SpawnerId);
|
||
|
|
if (IsRole(eRole.QuestMob))
|
||
|
|
GoToTargetTime = 0f;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void Kill_OnePunch(DamageInfo dinfo)
|
||
|
|
{
|
||
|
|
base.Kill_OnePunch(dinfo);
|
||
|
|
if (!DSUtil.CheckNull(dinfo.Beater_pd) &&
|
||
|
|
!DSUtil.CheckNull(dinfo.Beater_pd.m_SkillListTableData) &&
|
||
|
|
dinfo.Beater_pd.m_SkillListTableData.e_Skill == eEffect.Skill_FireBolt)
|
||
|
|
ServerInfo.Ins.m_ServerData.Add_TitleCondition(59); // 칭호 : 두방은 사치
|
||
|
|
}
|
||
|
|
protected override void VeryStrongDamage(double dmg)
|
||
|
|
{
|
||
|
|
base.VeryStrongDamage(dmg);
|
||
|
|
if (dmg > 1000000000000d) ServerInfo.Ins.m_ServerData.Add_Item(new ItemData(eItem.Title, 68, 1)); // 칭호 : 한방있는
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void Set_Die()
|
||
|
|
{
|
||
|
|
var sdata = ServerInfo.Ins.m_ServerData;
|
||
|
|
m_actDie?.Invoke(m_MonsterTableData.n_MonsterID);
|
||
|
|
sdata.Add_CollectionMobKill(m_MonsterTableData.n_MonsterID);
|
||
|
|
base.Set_Die();
|
||
|
|
if (IsRole(eRole.QuestMob))
|
||
|
|
GameUI.Ins.IngameUI.m_ChapterQuest.Add_PurposeCount(new ChapterQuestAddData { purpose = ePurpose.SaveNPC });
|
||
|
|
else
|
||
|
|
{
|
||
|
|
m_DieTime = m_MonsterAppearData.f_SpawnerDelay;
|
||
|
|
//m_MonsterAppearData.Cal_DropItems(this);
|
||
|
|
|
||
|
|
if (IsRole(eRole.Boss))
|
||
|
|
{
|
||
|
|
Time.timeScale = 0.3f;
|
||
|
|
Set_Coroutine(() =>
|
||
|
|
{
|
||
|
|
Time.timeScale = MyValue.Get_GameSpeed();
|
||
|
|
}, 0.4f);
|
||
|
|
sdata.Add_MissionCount(MyValue.arr_Mission[0], 3);
|
||
|
|
sdata.Add_MissionCount(MyValue.arr_Mission[1], 2);
|
||
|
|
|
||
|
|
if (dic_ccData[eCC.Freeze].CCTime > 0) sdata.Add_TitleCondition(57); // 칭호 : 얼음땡
|
||
|
|
if (dic_ccData[eCC.KnockedAirborne].CCTime > 0) sdata.Add_TitleCondition(58); // 칭호 : 비행기 태우는
|
||
|
|
|
||
|
|
//GameUI.Ins.IngameUI.m_ChapterQuest.Add_PurposeCount(new ChapterQuestAddData { purpose = ePurpose.BossKill, mobid = m_MonsterTableData.n_MonsterID });
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
#if UNITY_EDITOR
|
||
|
|
if (SceneManager.GetActiveScene().name == "StatTest") return;
|
||
|
|
#endif
|
||
|
|
sdata.Add_MissionCount(MyValue.arr_Mission[0], 2);
|
||
|
|
sdata.Add_MissionCount(MyValue.arr_Mission[1], 1);
|
||
|
|
|
||
|
|
//GameUI.Ins.IngameUI.m_ChapterQuest.Add_PurposeCount(new ChapterQuestAddData { purpose = ePurpose.MobKill, mobid = m_MonsterTableData.n_MonsterID });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public override void Shoot_Skill()
|
||
|
|
{
|
||
|
|
base.Shoot_Skill();
|
||
|
|
if (IsRole(eRole.MemoryMob) && m_SubRole == eSubRol.Witch) { }
|
||
|
|
else Reset_AttackCoolTime();
|
||
|
|
}
|
||
|
|
public override void Get_Damage(DamageInfo _dinfo)
|
||
|
|
{
|
||
|
|
//_dinfo.Damage = 1f; // 테스트 : 몹 안 죽게
|
||
|
|
base.Get_Damage(_dinfo);
|
||
|
|
|
||
|
|
switch (m_Role)
|
||
|
|
{
|
||
|
|
case eRole.QuestMob:
|
||
|
|
case eRole.MemoryMob:
|
||
|
|
if (m_SubRole == eSubRol.Dummy)
|
||
|
|
{
|
||
|
|
if (!GameUI.Ins.IngameUI.m_StageTimeUI.Get_Start()) GameUI.Ins.IngameUI.m_StageTimeUI.Set_Start();
|
||
|
|
// 젬 드랍
|
||
|
|
if (DSUtil.RandomTrue(0.1f))
|
||
|
|
InGameInfo.Ins.Shoot_Effect(new ProjectileData { shooter = this, m_Skill = eEffect.DropItem_Gem });
|
||
|
|
return; // 더미는 타겟 안 잡음
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 멀리서 맞았으면 맞은 몹을 타겟으로 잡고 주변 몹들도 같이 간다.
|
||
|
|
if (m_Target == null || IsRole(eRole.QuestMob))
|
||
|
|
{
|
||
|
|
if (m_Target == null)
|
||
|
|
Change_Target(false, _dinfo.Beater, true);
|
||
|
|
|
||
|
|
// TODO 정인호 : 몬스터 주변 몬스터 부르기
|
||
|
|
//var allies = ActorInfo.Ins.Get_EnemyActors(m_Role, transform, m_byHitDist);
|
||
|
|
//for (int i = 0; i < allies.Count; i++)
|
||
|
|
// if (allies[i].Get_Target() == null)
|
||
|
|
// allies[i].Change_Target(false, m_Target, true);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public override void Change_Target(bool _ispc, Actor target, bool _ChangeTargetByHit = false)
|
||
|
|
{
|
||
|
|
base.Change_Target(_ispc, target, _ChangeTargetByHit);
|
||
|
|
if (m_Target != null) b_IsFirstAttack = true;
|
||
|
|
if (b_IsFirstAttack) Change_MobStatus(eMobStatus.Battle);
|
||
|
|
}
|
||
|
|
protected override void Heal_To_Target()
|
||
|
|
{
|
||
|
|
base.Heal_To_Target();
|
||
|
|
if (m_Target != null) m_Target.Heal(HealRate);
|
||
|
|
if (HealCount > 0)
|
||
|
|
{
|
||
|
|
var allies = ActorInfo.Ins.Get_AlliesActors(IsEnemy(), Get_position());
|
||
|
|
var hurts = allies.FindAll(f => f != m_Target && f.Get_HP() < f.Get_MaxHP());
|
||
|
|
for (int i = 0; i < hurts.Count; i++)
|
||
|
|
{
|
||
|
|
hurts[i].Heal(HealRate);
|
||
|
|
if (i + 1 == HealCount - 1) break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
public override MonsterAppearData Get_MonsterStatTableData() { return m_MonsterAppearData; }
|
||
|
|
public override int Get_Group() { return m_SpawnerId; }
|
||
|
|
protected override void Set_MobMark(bool active)
|
||
|
|
{
|
||
|
|
if (m_MobMark == null)
|
||
|
|
{
|
||
|
|
m_MobMark = InGameInfo.Ins.Get_Obj(eObj.MobMark).GetComponent<MobMark>();
|
||
|
|
m_MobMark.transform.localScale = Vector3.one * 0.2f;
|
||
|
|
}
|
||
|
|
m_MobMark.Set(active, tf_HUD_Dmg);
|
||
|
|
}
|
||
|
|
|
||
|
|
public override void Projectile(string s)
|
||
|
|
{
|
||
|
|
base.Projectile(s);
|
||
|
|
if (ProjectileInfo.Ins)
|
||
|
|
ProjectileInfo.Ins.Shoot_Projectile(m_MonsterTableData.s_Porjectile1, this, m_Target, 1f, Get_ProjectileStartPos(),
|
||
|
|
m_MonsterTableData.f_ProjectileLifeTime1);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Set_NoUpdate_byTool(MonsterTableData mobdata)
|
||
|
|
{
|
||
|
|
NoUpdate_byTool = true;
|
||
|
|
m_MonsterTableData = mobdata;
|
||
|
|
}
|
||
|
|
}
|