| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- using Spine.Unity;
- using Spine;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using TMPro;
- public enum AttackState
- {
- Idle = 0, //待机
- Attack = 1, //攻击
- Die = 2, //死亡
- Weak = 3, //虚弱
- }
- public enum AttackCategories
- {
- A = 0,
- B = 1,
- }
- [System.Serializable]
- public struct BossState
- {
- public int coreHp; //核心血量
- public float scale; //体型
- public StateWeakness[] weaknesses; //弱点
- public GameObject core;
- }
- [System.Serializable]
- public struct StateWeakness
- {
- public GameObject obj;
- public int Hp;
- }
- public class Boss : MoveCharacter
- {
- [Header("Boss属性")]
- public BossState[] states; //阶段
- private int maxStateId; //最高为第几阶段,0开始
- public int curStateId; //当前处于阶段n
- private BossState curState;
- private int curStateTotalHp; //当前阶段总血量
- public int restWeaknessNum; //剩余弱点数量
- private Weakness coreWeakness;
- public GameObject roarEffect;
- public float roarTime;
- public bool isChangeState;
- [Header("核心受到伤害倍率")]
- public int coreDamageRate;
- [Header("当前索敌是对塔还是对玩家")]
- public TargetType curTarget;
- [Header("Boss攻击规律")]
- public string circulate; //循环配置
- private int len;
- public AttackCategories[] categories; //循环大类
- private AttackCategories curCategory; //当前攻击大类
- public int curCategoryID;
- public float minInterval, maxInterval; //间隔时间
- private float curInterval;
- //计算当前形态总血量
- private void CalculateHp()
- {
- curStateTotalHp = curState.coreHp * coreDamageRate;
- foreach(StateWeakness w in curState.weaknesses)
- {
- curStateTotalHp += w.Hp;
- }
- totalHp = curStateTotalHp;
- hp = totalHp;
- uiHp.Show(hp, totalHp);
- }
- //切换形态
- private void ChangeBossState()
- {
- curState = states[curStateId];
- toLargeSize = curState.scale;
- beLarger = true;
- ChangeWeakness();
- CalculateHp();
- curInterval = Random.Range(minInterval, maxInterval);
- }
- //切换弱点
- private void ChangeWeakness()
- {
- StateWeakness[] ws = curState.weaknesses;
- restWeaknessNum = ws.Length;
- for (int i = 0; i < restWeaknessNum; i++)
- {
- Weakness w = ws[i].obj.GetComponent<Weakness>();
- w.totalHp = ws[i].Hp;
- w.boss = this;
- ws[i].obj.SetActive(true);
- ws[i].obj.GetComponentInChildren<ParticleSystem>().Play();
- }
- }
- public override void Init()
- {
- //确保组件不丢失
- if (!ani)
- {
- ani = GetComponentInChildren<Animator>();
- }
- //血量重置
- hp = totalHp;
- uiHp.Show(hp, totalHp);
- ChangeState(CharacterState.Idle);
- curInterval = Random.Range(minInterval, maxInterval);
- }
- private void Awake()
- {
- }
- public virtual void Start()
- {
- len = circulate.Length;
- ChangeBossState();
- Init();
- maxStateId = states.Length - 1;
- int cur = 0;
- categories = new AttackCategories[len];
- foreach(char c in circulate)
- {
- switch (c)
- {
- case 'A':
- categories[cur] = AttackCategories.A;
- break;
- case 'B':
- categories[cur] = AttackCategories.B;
- break;
- default:
- break;
- }
- cur++;
- }
- curCategory = categories[0];
- }
- public override void BeHit(int damage, Vector3 force, bool changeHurt, float repelValue)
- {
- if (restWeaknessNum == 0)
- {
- damage *= coreDamageRate;
- }
- hp -= damage;
- //伤害跳字
- if (showInjuryNum)
- {
- GameObject injuryNum = Instantiate(injuryNumText);
- injuryNum.transform.position = new Vector3(transform.position.x + Random.Range(-1f, 1f), transform.position.y + 1, transform.position.z);
- TextMeshProUGUI text = injuryNum.GetComponentInChildren<TextMeshProUGUI>();
- text.text = damage.ToString();
- if (gameObject.CompareTag("Player"))
- {
- text.color = Color.red;
- }
- }
- uiHp.Show(hp, totalHp);
- if (hp <= 0)
- {
- coreWeakness.ChangeState(CharacterState.Die);
- if (curStateId < maxStateId)
- {
- curStateId++;
- isChangeState = true;
- roarEffect.SetActive(true);
- roarEffect.GetComponentInChildren<ParticleSystem>().Play();
- ChangeState(CharacterState.Idle);
- Invoke("ChangeBossState", roarTime);
- }
- else
- {
- ChangeState(CharacterState.Die);
- }
- return;
- }
- }
- public void CheckCoreOut()
- {
- restWeaknessNum -= 1;
- if (restWeaknessNum == 0)
- {
- coreWeakness = curState.core.GetComponent<Weakness>();
- coreWeakness.boss = this;
- coreWeakness.isCore = true;
- curState.core.SetActive(true);
- curState.core.GetComponentInChildren<ParticleSystem>().Play();
- }
- }
- public override void Update()
- {
- if (beLarger)
- {
- Enlarge();
- if (toLargeSize == 0)
- {
- isChangeState = false;
- }
- }
- }
- public virtual void Attack()
- {
- }
- public override void ChangeState(CharacterState newState)
- {
- if (newState == state)
- {
- return;
- }
- switch (state)
- {
- case CharacterState.Run:
- rb.velocity = Vector3.zero;
- break;
- default:
- break;
- }
- state = newState;
- switch (newState)
- {
- case CharacterState.Idle:
- ani.Play("idle", 0, 0);
- break;
- case CharacterState.Run:
- ToMove();
- break;
- case CharacterState.Die:
- ani.Play("die", 0, 0);
- gameObject.SetActive(false);
- break;
- case CharacterState.Attack:
- Attack();
- break;
- default:
- break;
- }
- }
- public override void OnState()
- {
- switch (state)
- {
- case CharacterState.Idle:
- if (!isChangeState)
- {
- curInterval -= Time.deltaTime;
- if (curInterval <= 0)
- {
- RandomAttackState();
- }
- }
- break;
- case CharacterState.Run:
- OnMove();
- break;
- default:
- break;
- }
- }
- public virtual void ToMove()
- {
- }
- public virtual void OnMove()
- {
- }
- public void CheckTarget()
- {
- Character curTar = null;
- switch (curTarget)
- {
- case TargetType.Tower:
- float minDis = -1;
- foreach(GameObject g in TowerMap.myTowers)
- {
- float dis = Vector2.Distance(g.transform.position, transform.position);
- if (minDis == -1 || dis < minDis)
- {
- minDis = dis;
- curTar = g.GetComponent<Character>();
- }
- }
- break;
- case TargetType.Player:
- PlayerController p1 = PlayersInput.instance[0];
- PlayerController p2 = PlayersInput.instance[1];
- bool p1Alive = (p1 != null && !p1.isRevive);
- bool p2Alive = (p2 != null && !p2.isRevive);
- float dis1 = Vector2.Distance(transform.position, p1.transform.position);
- float dis2 = Vector2.Distance(transform.position, p2.transform.position);
- if (p1Alive)
- {
- if (p2Alive)
- {
- curTar = dis1 > dis2 ? p1 : p2;
- }
- else
- {
- curTar = p1;
- }
- }
- else
- {
- if(p2Alive)
- {
- curTar = p2;
- }
- }
- break;
- default:
- break;
- }
- targetCharacter = curTar;
- }
- public virtual void RandomAttackType(AttackCategories cate)
- {
- }
- public void RandomAttackState()
- {
- switch (curCategory)
- {
- case AttackCategories.A:
- RandomAttackType(AttackCategories.A);
- break;
- case AttackCategories.B:
- RandomAttackType(AttackCategories.B);
- break;
- default:
- break;
- }
- curCategoryID++;
- if (curCategoryID == len)
- {
- curCategoryID = 0;
- }
- curCategory = categories[curCategoryID];
- ChangeState(CharacterState.Attack);
- }
- public void EndCurAttackState(bool hasIntervalTime)
- {
- //和下一个动作有没有间隔
- if (hasIntervalTime)
- {
- curInterval = Random.Range(minInterval, maxInterval);
- }
- ChangeState(CharacterState.Idle);
- }
- }
|