using IVDataFormat; using System.Collections.Generic; using UnityEngine; using System.Numerics; using Spine; using Spine.Unity; using static CreatureBase; using AnimationState = Spine.AnimationState; using Vector2 = UnityEngine.Vector2; using Vector3 = UnityEngine.Vector3; public class IVSummon : MonoBehaviour { private const string ECheckAttack = "AttackDamage"; private const string ECheckAttackState = "CheckAttackState"; private const string ECheckSkillState = "CheckSkillState"; private const string ECheckDamageState = "CheckDamageState"; private const string ECheckCeremonyState = "CheckCeremonyState"; private const string ECheckWarp_outState = "CheckPOutState"; private const string ECheckWarp_inState = "CheckPInState"; [SerializeField] private AudioSource asNormalAttack; [SerializeField] protected eState animState = eState.idle; protected ParticleSystem ptcMuzzle; protected BattleMgr battleMgr; protected AnimationState anState; protected SkeletonAnimation skAnim; protected IBattleEntity target; protected Transform targetTransform => target != null ? (target as Entity).transform : null; protected Vector2 targetPos => target != null ? (target as Entity).transform.position : Vector2.zero; protected float sqrtDistToTarget => target != null ? ((Vector2)transform.position - targetPos).sqrMagnitude : 9999f; public bool IsInit { get; private set; } private Transform trfslefParent; protected const float F_SearchTime = 0.1f; protected bool bAttackable = false; protected bool bFrontRight = true; protected bool isSummon = false; protected int iCrtRate = 0; protected int idnumber; protected float fCrtDam = dConst.RateMaxFloat; protected float fMov = dConst.RateMaxFloat; protected float fSpd = dConst.RateMaxFloat; protected float fSearchTick = 0f; protected float fAttackTick = 0f; protected float fAttackTime = 0.3f; protected float attackRange = 8f; protected float fMovCalc = 10f; protected float summonTime = 0f; protected float fCrtDamCalc = dConst.RateMaxFloat; protected int iCrtRateCalc = 0; protected BigInteger biAtk = 0L; Bitset32.Mask targetTags; private void OnEnable() { ChangeState(eState.warp_in); } public void SetInit(BattleMgr btmgr) { battleMgr = btmgr; if (!IsInit) { trfslefParent = transform.parent; skAnim = GetComponent(); anState = skAnim.AnimationState; anState.Event += HandleAnimEvent; if(transform.childCount > 0) ptcMuzzle = transform.Find("Muzzle").GetComponent(); targetTags = Bitset32.GetMask(EntityTag.Enemy); IsInit = true; } } public void SetStatus(BigInteger biatk, float fcrtdam, int crtrate , float smtime, Vector3 summonPos, int idnum, float attckInterval = 0.3f) { transform.position = summonPos + (Vector3)Random.insideUnitCircle.normalized * 3f; trfslefParent.localScale = Global.V3_1XRev; isSummon = true; skAnim.enabled = true; biAtk = biatk; fCrtDam = fcrtdam; iCrtRateCalc = crtrate; summonTime = smtime; gameObject.SetActive(true); anState.Event += HandleAnimEvent; idnumber = idnum; fAttackTime = attckInterval; } public void SearchTarget() { fSearchTick = 0f; if (!TargetFinder.TryFindNearest(transform.position, targetTags, out target)) { ChangeState(eState.idle); } else { if (sqrtDistToTarget <= attackRange * attackRange) { skAnim.timeScale = 2.0f; CheckAttack(); } else { ChangeState(eState.move); } } } protected virtual void MoveToTarget() { Vector3 v3framepos; ChangeFront(); v3framepos = Vector3.MoveTowards(transform.position, targetPos, fMovCalc * Time.deltaTime); v3framepos.z = v3framepos.y * 0.1f; transform.position = v3framepos; } public virtual void CheckAttack() { if (bAttackable) { if(ptcMuzzle != null) ptcMuzzle.Play(); ChangeFront(); ChangeState(eState.attack); } else { ChangeState(eState.idle); } } protected void HandleAnimEvent(TrackEntry trackEntry, Spine.Event e) { if (e.Data.Name.Equals(ECheckAttack)) AttackDamage(); else if (e.Data.Name.Equals(ECheckAttackState)) CheckAttackState(); else if (e.Data.Name.Equals(ECheckDamageState)) CheckDamageState(); else if (e.Data.Name.Equals(ECheckSkillState)) CheckSkillState(); else if (e.Data.Name.Equals(ECheckCeremonyState)) CheckCeremonyState(); else if (e.Data.Name.Equals(ECheckWarp_outState)) CheckWarp_outState(); else if (e.Data.Name.Equals(ECheckWarp_inState)) CheckWarp_inState(); } public void ChangeState(eState changestate) { if (changestate == animState && changestate != eState.attack && changestate != eState.skill) return; animState = changestate; switch (animState) { case eState.idle: anState.SetAnimation(0, "idle", true); break; case eState.move: anState.SetAnimation(0, "move", true); break; case eState.attack: bAttackable = false; fAttackTick = 0f; anState.SetAnimation(0, "attack", false); break; case eState.attack2: bAttackable = false; fAttackTick = 0f; anState.SetAnimation(0, "attack2", false); break; case eState.die: anState.SetAnimation(0, "die", false); break; case eState.skill: bAttackable = false; fAttackTick = 0f; anState.SetAnimation(0, "attack", false); break; case eState.ceremony: anState.SetAnimation(0, "ceremony", false); break; case eState.warp_in: anState.SetAnimation(0, "warp_in", false); break; case eState.warp_out: anState.SetAnimation(0, "warp_out", false); break; case eState.rush: anState.SetAnimation(0, "rush", false); break; case eState.damage: anState.SetAnimation(0, "damage", false); break; } } public void ChangeStateForce(eState changestate) { if (anState == null) return; animState = changestate; switch (animState) { case eState.idle: anState.SetAnimation(0, "idle", true); break; case eState.move: anState.SetAnimation(0, "move", true); break; case eState.attack: bAttackable = false; fAttackTick = 0f; anState.SetAnimation(0, "attack", false); break; case eState.attack2: bAttackable = false; fAttackTick = 0f; anState.SetAnimation(0, "attack2", false); break; case eState.die: anState.SetAnimation(0, "die", false); break; case eState.skill: bAttackable = false; fAttackTick = 0f; anState.SetAnimation(0, "attack", false); break; case eState.ceremony: anState.SetAnimation(0, "ceremony", false); break; case eState.warp_in: anState.SetAnimation(0, "warp_in", false); break; case eState.warp_out: skAnim.timeScale = 1.0f; anState.SetAnimation(0, "warp_out", false); break; case eState.rush: anState.SetAnimation(0, "rush", false); break; case eState.damage: anState.SetAnimation(0, "damage", false); break; } } protected virtual void ChangeFront() { if (bFrontRight) { if (transform.position.x > targetPos.x) { bFrontRight = false; transform.localScale = Vector3.one; } } else { if (transform.position.x < targetPos.x) { bFrontRight = true; transform.localScale = Global.oneRev; } } } public void ForceUnSummon() { summonTime = -1f; } private void Update() { if (summonTime > 0) summonTime -= Time.deltaTime; if (summonTime < 0) { isSummon = false; summonTime = 0f; if (!isSummon) ChangeStateForce(eState.warp_out); } if (isSummon) { switch (animState) { case eState.idle: // attack time. if (fAttackTick < fAttackTime) { fAttackTick += Time.deltaTime; if (fAttackTick >= fAttackTime) bAttackable = true; } // re-search target time. if (fSearchTick < F_SearchTime) { fSearchTick += Time.deltaTime; if (fSearchTick >= F_SearchTime) SearchTarget(); } // move. if (animState == eState.idle && sqrtDistToTarget <= attackRange * attackRange && biAtk != 0) CheckAttack(); break; case eState.move: // attack time. if (fAttackTick < fAttackTime) { fAttackTick += Time.deltaTime; if (fAttackTick >= fAttackTime) bAttackable = true; } // re-search target time. if (fSearchTick < F_SearchTime) { fSearchTick += Time.deltaTime; if (fSearchTick >= F_SearchTime) SearchTarget(); } // move. if (animState == eState.move) { MoveToTarget(); if(sqrtDistToTarget <= attackRange * attackRange && biAtk != 0) { CheckAttack(); } } break; } } } public void AttackDamage() { if (SoundMgr.Instance.EfcOn && asNormalAttack != null) asNormalAttack.Play(); target.GetDamage(biAtk, fCrtDamCalc, iCrtRateCalc, idnumber); } public void CheckAttackState() { skAnim.timeScale = 1.0f; SearchTarget(); } public void CheckSkillState() { SearchTarget(); } public void CheckDamageState() { ChangeState(eState.idle); } public void CheckDieState() { } public void CheckCeremonyState() { ChangeState(eState.idle); } public void CheckWarp_outState() { gameObject.SetActive(false); } public void CheckWarp_inState() { ChangeState(eState.idle); SearchTarget(); } }