using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using Random = UnityEngine.Random; public class BossMobActor : MobActor { protected Dictionary dic_indicator = new Dictionary(); protected bool CanUseSkill1, CanUseSkill2; protected float CoolTime_PassiveSkill, CoolTime_Skill1, CoolTime_Skill2; protected int UseSkillIndex = 0; public override void On_Regen(bool reincarnation = false, float healrate = 1) { base.On_Regen(reincarnation, healrate); CanUseSkill1 = CanUseSkill2 = false; CoolTime_PassiveSkill = 0; WL.Combat.Boss.BossPatternTable.Apply(this, m_MonsterTableData); // #813h 패턴 데이터 적용 + 페이즈 1 통지 (행 없으면 무동작 = 프리팹 값 · C8) } protected override void Update() { base.Update(); if (IsDead()) return; Check_PassiveSkill(); if (UseSkillIndex != 1 && CoolTime_Skill1 > 0f) CoolTime_Skill1 -= Time.deltaTime; if (UseSkillIndex != 2 && CoolTime_Skill2 > 0f) CoolTime_Skill2 -= Time.deltaTime; // 스킬 사용 결정 if (isTarget && UseSkillIndex == 0 && MobStatus != eMobStatus.Skill && !IsCC()) { bool skill1Ready = CanUseSkill1 && CoolTime_Skill1 <= 0f; bool skill2Ready = CanUseSkill2 && CoolTime_Skill2 <= 0f; if (skill1Ready && skill2Ready) UseSkillIndex = Random.Range(1, 3); // 1 또는 2 랜덤 선택 else if (skill1Ready) UseSkillIndex = 1; else if (skill2Ready) UseSkillIndex = 2; } else UseSkillIndex = 0; if (IsStop) return; } protected virtual void Init(bool initSkill1CoolTime, bool initSkill2CoolTime) { Change_MobStatus(isTarget ? eMobStatus.Attack : eMobStatus.PatrolWait); UseSkillIndex = 0; // 다음 스킬 바로 못 쓰게 if (initSkill1CoolTime && CanUseSkill2) { CanUseSkill2 = false; if (CoolTime_Skill2 < 0.5f) CoolTime_Skill2 = 0.5f; } else if (initSkill2CoolTime && CanUseSkill1) { CanUseSkill1 = false; if (CoolTime_Skill1 < 0.5f) CoolTime_Skill1 = 0.5f; } } void InActiveAllIndicator() { foreach (var item in dic_indicator) item.Value.SetActive(false); } public override void Del_Target(bool forcedel = false) { base.Del_Target(forcedel); InActiveAllIndicator(); } public override void Get_Damage(DamageInfo _dinfo) { base.Get_Damage(_dinfo); if (!CanUseSkill1) CanUseSkill1 = (Get_HP() / Get_MaxHP()) <= 0.9; if (!CanUseSkill2) CanUseSkill2 = (Get_HP() / Get_MaxHP()) <= 0.7; WL.Combat.Boss.BossPatternTable.ApplySkillGates(this, m_MonsterTableData, Get_HPPercent(), ref CanUseSkill1, ref CanUseSkill2); // #813h 임계 조회 (행 없으면 위 두 줄 결과 유지 · C8) WL.Combat.Boss.BossPatternTable.UpdatePhase(this, m_MonsterTableData, Get_HPPercent()); // #813h 페이즈 임계 통과 시 BossPhase 통지 } protected override void Set_Die() { Init(true, true); if (n_Reincarnation <= 0) { StopAllCoroutines(); // 모든 스킬 멈춤 foreach (var item in dic_indicator) // 모든 인디케이터 끄기 item.Value.SetActive(false); } base.Set_Die(); } protected override void On_NavMeshAgent() { base.On_NavMeshAgent(); Init(false, false); } protected virtual void Check_PassiveSkill() { if (CoolTime_PassiveSkill > 0f) CoolTime_PassiveSkill -= Time.deltaTime; if (CoolTime_PassiveSkill <= 0f) { if (isTarget && m_Stat.Get_Stat(eStat.StartleBehind) > 0 && MobStatus != eMobStatus.Skill) { var skillData = table_skilllist.Ins.Get_Data_orNull(m_MonsterTableData.n_PassiveSkillID); if (Vector3.Distance(Get_position(), m_Target.Get_position()) > skillData.f_ExtraValue1) StartCoroutine(Co_StartleBehind(skillData)); } } } IEnumerator Co_StartleBehind(SkillListTableData skillData) { CoolTime_PassiveSkill = skillData.f_ExtraValue4; InGameInfo.Ins.Show_Effect("Effect_Teleport", Get_position()); AnimationPlay("startlebehind"); yield return new WaitForSeconds(0.5f); if (isTarget) { m_Target.Stun(skillData.f_ExtraValue2, true); Set_Warp(Get_TeleportPostion(m_Target, -skillData.f_ExtraValue3)); Change_MobStatus(eMobStatus.Attack); } } protected virtual float Get_Skill1Dmg() { return 1f; } protected virtual Vector3 Get_Skill1Pos() { return Get_CenterPositionFoward(); } protected virtual void Set_Skill1Projectile(ProjectileBase pb) { } protected virtual void BossProjectile2(string s) { if (ProjectileInfo.isIns) ProjectileInfo.Ins.Shoot_Projectile(m_MonsterTableData.s_Porjectile2, this, m_Target, Get_Skill1Dmg(), Get_Skill1Pos(), m_MonsterTableData.f_ProjectileLifeTime2, pb => { Set_Skill1Projectile(pb); }); } protected virtual float Get_Skill2Dmg() { return 1f; } protected virtual Vector3 Get_Skill2Pos() { return Get_CenterPositionFoward(); } protected virtual void Set_Skill2Projectile(ProjectileBase pb) { } protected virtual void BossProjectile3(string s) { if (ProjectileInfo.isIns) ProjectileInfo.Ins.Shoot_Projectile(m_MonsterTableData.s_Porjectile3, this, m_Target, Get_Skill2Dmg(), Get_Skill2Pos(), m_MonsterTableData.f_ProjectileLifeTime3, pb => { Set_Skill2Projectile(pb); }); } protected void Load_Indicator(string prefab, int index) { if (dic_indicator.ContainsKey(index)) dic_indicator[index].SetActive(false); else IndicatorInfo.Ins.Make_Indicator(prefab, go => { dic_indicator.Add(index, go); }); } protected void Load_Projectile(string prefab, float skilldmg, Vector3 pos, float lifetime, ProjectileBase _pb, Action act_pb) { if (DSUtil.CheckNull(_pb)) ProjectileInfo.Ins.Shoot_Projectile(prefab, this, m_Target, skilldmg, pos, lifetime, pb => { act_pb(pb); pb.gameObject.SetActive(false); }); else _pb.gameObject.SetActive(false); } protected void Run_byUseSkill(float range, float speed, Action moveend) { StartCoroutine(Co_Run_byUseSkill(range, speed, moveend)); } IEnumerator Co_Run_byUseSkill(float range, float speed, Action moveend) { if (!DSUtil.CheckNull(m_Target)) { Change_MobStatus(eMobStatus.Skill); transform.LookAt(m_Target.transform); AnimationPlay(MyValue.Get_AnimName(eAnim.Run)); m_NavMeshAgent.stoppingDistance = 0.1f; var direction = (Get_position() - m_Target.Get_position()).normalized; var targetPos = m_Target.Get_position() + direction * range; Set_Path(Get_TeleportPostion(m_Target, range)); while (!Complete_Destination()) { m_NavMeshAgent.speed = speed; yield return null; } m_NavMeshAgent.stoppingDistance = m_NavStopDistance; m_NavMeshAgent.speed = Get_MoveSpeed(); moveend(true); } else moveend(false); } protected IEnumerator Co_LookTarget(float looktime, GameObject goindicator = null) { float t = 0f; bool isindicator = goindicator; while (t < looktime) { yield return null; t += Time.deltaTime; if (isTarget) transform.LookAt(m_Target.Get_position()); if (isindicator) goindicator.transform.eulerAngles = new Vector3(0f, transform.eulerAngles.y); } } }