2025-02-20 00:40:21 +00:00
using System ;
2024-12-15 01:39:39 +00:00
using System.Collections ;
2025-02-22 01:03:12 +00:00
using System.Collections.Generic ;
2024-12-15 01:39:39 +00:00
using UnityEngine ;
2025-02-20 04:55:36 +00:00
using Random = UnityEngine . Random ;
2024-12-15 01:39:39 +00:00
public class BossMobActor : MobActor
{
2025-02-25 00:53:33 +00:00
protected Dictionary < int , GameObject > dic_indicator = new Dictionary < int , GameObject > ( ) ;
2025-02-19 00:06:35 +00:00
protected bool CanUseSkill1 , CanUseSkill2 ;
2025-02-21 07:10:14 +00:00
protected float CoolTime_PassiveSkill , CoolTime_Skill1 , CoolTime_Skill2 ;
2025-02-20 04:55:36 +00:00
protected int UseSkillIndex = 0 ;
2025-02-19 00:06:35 +00:00
2025-02-21 04:45:42 +00:00
public override void On_Regen ( bool reincarnation = false , float healrate = 1 )
{
base . On_Regen ( reincarnation , healrate ) ;
CanUseSkill1 = CanUseSkill2 = false ;
2025-02-21 07:10:14 +00:00
CoolTime_PassiveSkill = 0 ;
2026-09-08 15:19:49 +00:00
WL . Combat . Boss . BossPatternTable . Apply ( this , m_MonsterTableData ) ; // #813h 패턴 데이터 적용 + 페이즈 1 통지 (행 없으면 무동작 = 프리팹 값 · C8)
2025-02-21 04:45:42 +00:00
}
2025-02-20 01:30:24 +00:00
protected override void Update ( )
2024-12-15 01:39:39 +00:00
{
2025-02-20 01:30:24 +00:00
base . Update ( ) ;
2025-02-20 04:55:36 +00:00
if ( IsDead ( ) ) return ;
2025-02-21 07:10:14 +00:00
Check_PassiveSkill ( ) ;
2025-02-20 04:55:36 +00:00
if ( UseSkillIndex ! = 1 & & CoolTime_Skill1 > 0f ) CoolTime_Skill1 - = Time . deltaTime ;
if ( UseSkillIndex ! = 2 & & CoolTime_Skill2 > 0f ) CoolTime_Skill2 - = Time . deltaTime ;
// 스킬 사용 결정
2025-02-24 02:24:39 +00:00
if ( isTarget & & UseSkillIndex = = 0 & & MobStatus ! = eMobStatus . Skill & & ! IsCC ( ) )
2025-02-20 04:55:36 +00:00
{
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 ;
2024-12-15 01:39:39 +00:00
}
2025-02-20 04:55:36 +00:00
protected virtual void Init ( bool initSkill1CoolTime , bool initSkill2CoolTime )
2024-12-15 01:39:39 +00:00
{
2025-02-20 06:04:31 +00:00
Change_MobStatus ( isTarget ? eMobStatus . Attack : eMobStatus . PatrolWait ) ;
UseSkillIndex = 0 ;
2025-05-22 20:37:51 +00:00
// 다음 스킬 바로 못 쓰게
if ( initSkill1CoolTime & & CanUseSkill2 )
{
CanUseSkill2 = false ;
2025-05-24 00:03:13 +00:00
if ( CoolTime_Skill2 < 0.5f )
CoolTime_Skill2 = 0.5f ;
2025-05-22 20:37:51 +00:00
}
else if ( initSkill2CoolTime & & CanUseSkill1 )
{
CanUseSkill1 = false ;
2025-05-24 00:03:13 +00:00
if ( CoolTime_Skill1 < 0.5f )
CoolTime_Skill1 = 0.5f ;
2025-05-22 20:37:51 +00:00
}
2025-02-20 06:04:31 +00:00
}
void InActiveAllIndicator ( )
{
2025-06-10 00:45:38 +00:00
foreach ( var item in dic_indicator )
item . Value . SetActive ( false ) ;
2024-12-15 01:39:39 +00:00
}
2025-02-19 00:06:35 +00:00
public override void Del_Target ( bool forcedel = false )
2024-12-15 01:39:39 +00:00
{
2025-02-19 00:06:35 +00:00
base . Del_Target ( forcedel ) ;
2025-02-20 06:04:31 +00:00
InActiveAllIndicator ( ) ;
2024-12-15 01:39:39 +00:00
}
2025-02-19 00:06:35 +00:00
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 ;
2026-09-08 15:19:49 +00:00
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 통지
2025-02-19 00:06:35 +00:00
}
2024-12-15 01:39:39 +00:00
protected override void Set_Die ( )
{
2025-02-20 04:55:36 +00:00
Init ( true , true ) ;
2025-03-10 07:15:28 +00:00
if ( n_Reincarnation < = 0 )
{
StopAllCoroutines ( ) ; // 모든 스킬 멈춤
foreach ( var item in dic_indicator ) // 모든 인디케이터 끄기
item . Value . SetActive ( false ) ;
}
2025-08-01 07:09:46 +00:00
base . Set_Die ( ) ;
2024-12-15 01:39:39 +00:00
}
protected override void On_NavMeshAgent ( )
{
base . On_NavMeshAgent ( ) ;
2025-02-20 04:55:36 +00:00
Init ( false , false ) ;
2024-12-15 01:39:39 +00:00
}
2025-02-20 00:40:21 +00:00
2025-02-21 07:10:14 +00:00
protected virtual void Check_PassiveSkill ( )
{
if ( CoolTime_PassiveSkill > 0f ) CoolTime_PassiveSkill - = Time . deltaTime ;
if ( CoolTime_PassiveSkill < = 0f )
{
2025-05-31 00:02:24 +00:00
if ( isTarget & & m_Stat . Get_Stat ( eStat . StartleBehind ) > 0 & & MobStatus ! = eMobStatus . Skill )
2025-02-21 07:10:14 +00:00
{
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 ) ;
2025-05-31 00:02:24 +00:00
if ( isTarget )
{
m_Target . Stun ( skillData . f_ExtraValue2 , true ) ;
Set_Warp ( Get_TeleportPostion ( m_Target , - skillData . f_ExtraValue3 ) ) ;
Change_MobStatus ( eMobStatus . Attack ) ;
}
2025-02-21 07:10:14 +00:00
}
2025-02-20 00:40:21 +00:00
protected virtual float Get_Skill1Dmg ( ) { return 1f ; }
protected virtual Vector3 Get_Skill1Pos ( ) { return Get_CenterPositionFoward ( ) ; }
2025-02-20 01:00:59 +00:00
protected virtual void Set_Skill1Projectile ( ProjectileBase pb ) { }
2025-02-20 00:40:21 +00:00
protected virtual void BossProjectile2 ( string s )
{
2025-03-04 23:42:24 +00:00
if ( ProjectileInfo . isIns )
2025-02-20 00:40:21 +00:00
ProjectileInfo . Ins . Shoot_Projectile ( m_MonsterTableData . s_Porjectile2 , this , m_Target , Get_Skill1Dmg ( ) , Get_Skill1Pos ( ) ,
2025-02-20 01:00:59 +00:00
m_MonsterTableData . f_ProjectileLifeTime2 , pb = > { Set_Skill1Projectile ( pb ) ; } ) ;
2025-02-20 00:40:21 +00:00
}
2025-02-22 23:13:50 +00:00
2025-02-20 00:40:21 +00:00
protected virtual float Get_Skill2Dmg ( ) { return 1f ; }
protected virtual Vector3 Get_Skill2Pos ( ) { return Get_CenterPositionFoward ( ) ; }
2025-02-20 01:00:59 +00:00
protected virtual void Set_Skill2Projectile ( ProjectileBase pb ) { }
2025-02-20 00:40:21 +00:00
protected virtual void BossProjectile3 ( string s )
{
2025-03-04 23:42:24 +00:00
if ( ProjectileInfo . isIns )
2025-02-20 00:40:21 +00:00
ProjectileInfo . Ins . Shoot_Projectile ( m_MonsterTableData . s_Porjectile3 , this , m_Target , Get_Skill2Dmg ( ) , Get_Skill2Pos ( ) ,
2025-02-20 01:00:59 +00:00
m_MonsterTableData . f_ProjectileLifeTime3 , pb = > { Set_Skill2Projectile ( pb ) ; } ) ;
2025-02-20 00:40:21 +00:00
}
2025-02-22 01:03:12 +00:00
protected void Load_Indicator ( string prefab , int index )
{
2025-02-25 00:53:33 +00:00
if ( dic_indicator . ContainsKey ( index ) )
dic_indicator [ index ] . SetActive ( false ) ;
2025-02-22 01:03:12 +00:00
else
2025-05-23 22:18:32 +00:00
IndicatorInfo . Ins . Make_Indicator ( prefab , go = > { dic_indicator . Add ( index , go ) ; } ) ;
2025-02-22 01:03:12 +00:00
}
protected void Load_Projectile ( string prefab , float skilldmg , Vector3 pos , float lifetime , ProjectileBase _pb , Action < ProjectileBase > 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 ) ;
}
2025-02-20 00:40:21 +00:00
protected void Run_byUseSkill ( float range , float speed , Action < bool > moveend )
{
StartCoroutine ( Co_Run_byUseSkill ( range , speed , moveend ) ) ;
}
IEnumerator Co_Run_byUseSkill ( float range , float speed , Action < bool > 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 ) ;
}
2025-06-10 08:31:49 +00:00
2025-06-10 23:02:22 +00:00
protected IEnumerator Co_LookTarget ( float looktime , GameObject goindicator = null )
2025-06-10 08:31:49 +00:00
{
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 ) ;
}
}
2024-12-15 01:39:39 +00:00
}