using DG.Tweening; using IVDataFormat; using Spine.Unity; using System.Collections; using UnityEngine; using Vector3 = UnityEngine.Vector3; // 전투용 몬스터. public class IVMonster : CreatureBase { private static readonly Color CLR_DamNormal = new Color(1f, 1f, 1f); private static readonly Color CLR_DamCritical = new Color(1f, 56f / 255f, 0f); private static readonly float F_DamNormal = 24f; private static readonly float F_DamCritical = 32f; [SerializeField, AutoInjector("/ptcDie")] private ParticleSystem ptcDieEffect; [SerializeField, AutoInjector("/hit2")] private ParticleSystem ptcHit2; [SerializeField, AutoInjector("/hit3")] private ParticleSystem ptcHit3; [SerializeField] Transform damageIndicatorPos; protected override void Start() { base.Start(); bFriendly = false; } // 몬스터 애니메이션 세팅. public void SetMonsterAni(SkeletonDataAsset skdata) { if (skdata == null || (skAnim.skeletonDataAsset != null && skdata.name.Equals(skAnim.skeletonDataAsset.name))) { bLoading = false; if (bSummonNeed) { bSummonNeed = false; Summon(); } return; } if (skAnim.skeletonDataAsset != null) skAnim.skeletonDataAsset.Clear(); skAnim.ClearState(); skAnim.skeletonDataAsset = skdata; skAnim.updateWhenInvisible = UpdateMode.EverythingExceptMesh; skAnim.Initialize(true); ChangeStateForce(eState.idle); bInitNeed = true; bLoading = false; if (bSummonNeed) { bSummonNeed = false; Summon(); } skAnim.gameObject.SetActive(true); } // 사망시. protected override void OnDie() { base.OnDie(); ptcHit2.Stop(); ptcHit3.Stop(); StartCoroutine(fadeOut()); PushFrameForce(10f); alertPlayer = false; battleMgr.DieEnemy(creatureClass, iIndex); } protected void KnockBack() { int ifront = 1; float pushPower = 10f; if (IsLookRight) ifront = -1; transform.DOMoveX(transform.position.x + (ifront * pushPower), 0.3f); } private IEnumerator fadeOut() { Spine.Skeleton sk = skAnim.skeleton; yield return new WaitForSeconds(0.6f); if (eType != eMonsterType.SmallObject) { ptcDieEffect.Play(); } while (sk.A > 0) { sk.A -= 0.05f; yield return new WaitForSeconds(0.05f); } yield return null; } protected override void MoveToTarget() { if (!bCoward && moveSpeed <= 0f || target is null) return; Vector3 newPos; Vector2 to = (targetPos - (Vector2)transform.position).normalized; if (!alertPlayer) newPos = transform.position + (Vector3)to * moveSpeed * enemySlowSpeed * Time.deltaTime; else newPos = transform.position + (Vector3)to * moveSpeed * Time.deltaTime; if (bCoward) { if (newPos.x < -25) newPos.x = -25; else if (newPos.x > 25) newPos.x = 25; if (newPos.y < -25) newPos.y = -25; else if (newPos.y > 25) newPos.y = 25; } newPos.z = newPos.y * 0.1f; transform.position = newPos; ChangeLookDirection(targetTransform); } protected override void OnDamaged(Damage damage) { var indicator = battleMgr.GetDamageIndicatorText(false); if (indicator != null) { if (damage.isCritical) indicator.SetText(FormatString.BigIntString1(damage.value), F_DamCritical, CLR_DamCritical); else indicator.SetText(FormatString.BigIntString1(damage.value), F_DamNormal, CLR_DamNormal); indicator.Show(damageIndicatorPos.position); } if (eType == eMonsterType.SmalllMonster || eType == eMonsterType.MediumMonster || eType == eMonsterType.BigMonster) { ptcHit2.Play(); if(!ptcHit3.isPlaying) ptcHit3.Play(); } } // 타겟 위치 찾기. protected override void SearchTarget() { if (!IsBattleAvail()) { if (battleMgr.BattlePause) ChangeState(eState.idle); return; } fSearchTick = 0f; target = battleMgr.GetPlayer(); attackRange = 3f; if (sqrtDistToTarget <= attackRange * attackRange && maxAtk != 0) { CheckAttack(); } else if(sqrtDistToTarget <= recogRange * recogRange) { alertPlayer = true; ChangeState(eState.move); } else { ChangeState(eState.move); } } #region Ani Event public override void AttackDamage() { if (BattleMgr.Instance.BattlePause || bSummon || bDead) return; battleMgr.SendDamage(target, currentAtk, fCrtDamCalc, iCrtRateCalc); } #endregion Ani Event }