| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using Sirenix.OdinInspector;
- public class WaterSprite : Boss
- {
- public enum AttackMethods
- {
- Move, //移动,浮空+点水,动画控制高度,代码控制位移x;点水处生化
- Umbrella, //黑伞回旋镖
- Lotus, //召唤莲花
- Hair, //辫子攻击
- Rush, //水面冲刺
- Shoot, //苦无射击
- }
- public enum BossStage
- {
- waterSprite, //水诡形态
- polliwog, //蝌蚪形态
- }
- [System.Serializable]
- public struct AttackAssignment
- {
- public AttackMethods attack;
- public int weight; //权重
- }
- [System.Serializable]
- public struct BossAttackType
- {
- public AttackCategories category;
- public AttackAssignment[] attacks;
- }
- [Space(30)]
- [Header("水诡白家娘娘")]
- [Header("攻击配置")]
- public BossAttackType[] attackConfigurations;
- public AttackMethods curAttackType;
- private WaterSpriteAttackController attack;
- public GameObject smokeFx;
- public int attackNum;
- public int attackCount = 0;
- public float comboInterval;
- [Header("瞬身")]
- public float bodyFlickerTime;
- [HideInInspector]public float bodyFlickerTimer;
- public bool isDisappear = false;
- [Header("移动")]
- private WaterSpriteJumpMove jumpMoveCS;
- [Header("变化形态")]
- [LabelText("召唤蝌蚪的数量")]
- public int polliNum; //召唤蝌蚪的数量
- [LabelText("召唤蝌蚪的脚本")]
- public PolliwogShot pws;
- private BossStage curBossStage;
- [Range(1,100)]
- [LabelText("血量到达多少百分比后切换蝌蚪形态")]
- public int[] changeStateHPPer; //每次转化形态的血量百分比预设
- private int nextAimHP; //下一个血量预设值
- private int changeHPID; //下一个是预设数组里的第几个
- [LabelText("过多久从蝌蚪形态切回水诡形态")]
- public float polliTime;
- private float pastPoliTime; //已经过去的蝌蚪时间
- [Header("变化阶段")]
- [LabelText("愤怒状态攻击间隔")] public float angryAttackInterval;
- [LabelText("愤怒状态持续时间")] public float angryDuration;
- private float angryTimer;
- [FoldoutGroup("状态提示")] public bool isAngry = false;
- [FoldoutGroup("状态提示")] public bool isTakingUmbre = false;
- [FoldoutGroup("状态提示")] public bool isHoldingUmbre = true;
- [FoldoutGroup("状态提示")] public bool isReadyChangStage = false;
- [FoldoutGroup("状态提示")] public bool isAppearing = false;
- private Coroutine shootCoroutine;
- private float hairAttackTimer;
- public GameObject smokeShell;
- public GameObject summonStart;
- public override void Init()
- {
- base.Init();
- attack = GetComponent<WaterSpriteAttackController>();
- jumpMoveCS = GetComponent<WaterSpriteJumpMove>();
- jumpMoveCS.ws = this;
- nextAimHP = (int)(changeStateHPPer[changeHPID] / 100f * totalHp);
- changeHPID++;
- curInterval = statOfPhase[bossPhase].maxInterval;
- StartCoroutine(Appear());
- GameObject[] injuryNums = new GameObject[100];
- for (int i = 0; i < 100; i++)
- {
- injuryNums[i] = PoolManager.Instantiate(injuryNumTextSummon);
- }
- foreach(GameObject injuryNum in injuryNums)
- {
- injuryNum.SetActive(false);
- }
- }
- public override void Update()
- {
- base.Update();
- OnStage();
- if (bossPhase < statOfPhase.Length - 1)
- {
- if ((float)hp / (float)totalHp < statOfPhase[bossPhase + 1].hpRadioThreshold)
- {
- ChangePhase();
- }
- }
- if (isAngry)
- {
- if (angryTimer >= 0) angryTimer -= Time.deltaTime;
- else
- {
- Debug.Log("退出愤怒状态");
- isAngry = false;
- StartCoroutine(Appear());
- ChangeCirculate(3);
- }
- }
- if(!isHoldingUmbre) attack.OnBlackUmbrella();
- }
- //步步生花
- public override void ToMove()
- {
- jumpMoveCS.ToJump();
- }
- public override void OnMove()
- {
- jumpMoveCS.OnJumpMove();
- }
- public override void BeHit(AttackController.AttackMethod attackMethod, Character attackFrom, int damage = -1)
- {
- base.BeHit(attackMethod, attackFrom, damage);
- if (hp <= nextAimHP)
- {
- isReadyChangStage = true;
- }
- }
- public override void RandomAttackType(AttackCategories cate)
- {
- AttackAssignment[] attacks = attackConfigurations[(int)cate].attacks;
- int[] powers = new int[attacks.Length];
- for (int i = 0; i < attacks.Length; i++)
- {
- if (!isHoldingUmbre && attacks[i].attack == AttackMethods.Umbrella)
- {
- continue;
- }
- if(curAttackType == AttackMethods.Hair && attacks[i].attack == AttackMethods.Hair && !isAngry) continue;
- powers[i] = attacks[i].weight;
- }
- int a = RandomWithWeight(powers);
- curAttackType = attacks[a].attack;
- attackCount = 1;
- switch (curAttackType)
- {
- case AttackMethods.Hair:
- if (bossPhase == 2) attackCount = Random.Range(1, 3);
- break;
- case AttackMethods.Shoot:
- if (bossPhase == 2) attackCount = Random.Range(1, 3);
- if (bossPhase == 2) attackCount = Random.Range(2, 4);
- break;
- }
- }
- public override void ChangePhase()
- {
- base.ChangePhase();
- switch (bossPhase)
- {
- case 1:
- ChangeCirculate(2);
- break;
- case 2:
- ChangeCirculate(1);
- bodyTrans.gameObject.SetActive(false);
- isAngry = true;
- angryTimer = angryDuration;
- RandomAttackState();
- ClearAllSkills();
- isTakingUmbre = false;
- break;
- }
- }
- public override void ClearAllSkills()
- {
- if (attack.blackUmbrella)
- {
- if(attack.blackUmbrella.gameObject.activeSelf)
- attack.blackUmbrella.BeCleared();
- isHoldingUmbre = true;
- }
- if(shootCoroutine != null) StopCoroutine(shootCoroutine);
- }
- public override void ChangeBossState(BossState bs)
- {
- base.ChangeBossState(bs);
- if(bs == BossState.rise && oldState != BossState.weak && !isHoldingUmbre) ani.Play("idle_no3", 0, 0);
- }
- #region 状态相关
- public override void ChangeState(CharacterState newState)
- {
- if (state == newState || newState == CharacterState.FramePause || isAppearing)
- {
- return;
- }
- Debug.Log("从" + state + "切换到" + newState);
- switch (state)
- {
- case CharacterState.Run:
- rb.velocity = Vector3.zero;
- break;
- case CharacterState.Attack:
- spineEvent.isAttackOn = false;
- break;
- default:
- break;
- }
- state = newState;
- switch (newState)
- {
- case CharacterState.Idle:
- if (bossState != BossState.weak)
- {
- if (isHoldingUmbre)
- {
- //Debug.Log(222);
- int randomAni = RandomWithWeight(weight);
- ani.Play(idleAniNames[randomAni], 0, 0);
- }
- else
- {
- ani.Play("idle_no3", 0, 0);
- }
- }
- break;
- case CharacterState.Run:
- ToMove();
- break;
- case CharacterState.Die:
- ani.Play("die", 0, 0);
- rb.constraints &= ~RigidbodyConstraints.FreezePositionY;
- ChangeBossState(BossState.invincible);
- StartCoroutine(DieEnd(13.067f));
- ClearAllSkills();
- isDie = true;
- break;
- case CharacterState.Attack:
- if (!isToBossRoom)
- {
- //hitResistance = 300;
- Attack();
- }
- break;
- default:
- break;
- }
- spineEvent.isAttackOn = false;
- spineEvent.isAttackOff = false;
- }
- public override void OnState()
- {
- if (curBossStage == BossStage.polliwog) return;
- switch (state)
- {
- case CharacterState.Idle:
- if (isReadyChangStage)
- {
- ChangeBossState(BossState.invincible);
- ani.Play("fall");
- if (spineEvent.isAttackOn) ChangeStage(BossStage.polliwog);
- return;
- }
- else if (isTakingUmbre)
- {
- return;
- }
- if (isToBossRoom)
- {
- OnChangeBG();
- }
- else if(attackCount > 0)
- {
- curInterval -= Time.deltaTime;
- if (curInterval <= 0)
- {
- //Debug.Log("触发连招");
- ChangeState(CharacterState.Attack);
- }
- }
- else if (bossState != BossState.weak)
- {
- //Debug.Log(curInterval);
- curInterval -= Time.deltaTime;
- if (curInterval <= 0)
- {
- RandomAttackState();
- }
- }
- break;
- case CharacterState.Run:
- OnMove();
- if (isReadyChangStage) ChangeState(CharacterState.Idle);
- break;
- case CharacterState.Attack:
- OnAttack();
- break;
- case CharacterState.HitStun:
- hitFeedbackSystem.HitStunUpdate();
- break;
- case CharacterState.SpecialStatus_Float:
- attributeStatus.SpecialStateEffect(SpecialState.FloatState);
- break;
- case CharacterState.SpecialStatus_BlowUp:
- attributeStatus.SpecialStateEffect(SpecialState.BlownUp);
- break;
- case CharacterState.SpecialStatus_ShotDown:
- attributeStatus.SpecialStateEffect(SpecialState.ShotDown);
- break;
- case CharacterState.SpecialStatus_Weak:
- attributeStatus.SpecialStateEffect(SpecialState.Weak);
- break;
- default:
- break;
- }
- if (isInBossRoom)
- {
- changeBackTime += Time.deltaTime;
- if (changeBackTime >= toOrigNeedTime)
- {
- ChangeBG(false);
- changeBackTime = 0;
- }
- }
- OnBossState();
- if (stage < hpRadio.Length)
- {
- if ((float)hp / (float)totalHp < hpRadio[stage])
- {
- stage++;
- DropSouls();
- }
- }
- }
- #endregion
- IEnumerator DieEnd(float time)
- {
- yield return new WaitForSeconds(time);
- gameObject.SetActive(false);
- }
- IEnumerator Appear()
- {
- ChangeBossState(BossState.invincible);
- PoolManager.Instantiate(smokeShell, transform.position);
- bodyTrans.gameObject.SetActive(false);
- isAppearing = true;
- yield return new WaitForSeconds(1.5f);
- bodyTrans.gameObject.SetActive(true);
- ani.Play("smoke");
- yield return new WaitForSeconds(1.7f);
- spineEvent.isAttackOn = false;
- ChangeBossState(BossState.normal);
- ani.Play("idle");
- isAppearing = false;
- }
- #region 形态相关
- public void ChangeStage(BossStage bs)
- {
- if (bs == curBossStage)
- {
- return;
- }
- isReadyChangStage = false;
- curBossStage = bs;
- switch (bs)
- {
- case BossStage.waterSprite:
- curInterval = Random.Range(statOfPhase[bossPhase].minInterval, statOfPhase[bossPhase].maxInterval);
- if (changeHPID < changeStateHPPer.Length - 1)
- {
- nextAimHP = (int)(changeStateHPPer[changeHPID] / 100f * totalHp);
- changeHPID++;
- }
- else
- {
- nextAimHP = -1000;
- }
- StartCoroutine(Appear());
- //所有蝌蚪消失
- pws.AllPoliDie();
- break;
- case BossStage.polliwog:
- PoolManager.Instantiate(summonStart, transform.position);
- pastPoliTime = 0;
- bodyTrans.gameObject.SetActive(false);
- //在原地召唤一堆蝌蚪
- pws.Shoot(polliNum, bodyTrans.position);
- ChangeState(CharacterState.Idle);
- break;
- default:
- break;
- }
- ClearAllSkills();
- isTakingUmbre = false;
- attackCount = 0;
- }
- private void OnStage()
- {
- switch (curBossStage)
- {
- case BossStage.polliwog:
- pastPoliTime += Time.deltaTime;
- if (pastPoliTime >= polliTime)
- {
- ChangeStage(BossStage.waterSprite);
- pastPoliTime = 0;
- }
- break;
- }
- }
- #endregion
- #region 攻击相关
- public override void Attack()
- {
- attackCount--;
- switch (curAttackType)
- {
- case AttackMethods.Move:
- jumpMoveCS.CountJumpTime();
- ChangeState(CharacterState.Run);
- break;
- case AttackMethods.Umbrella:
- isHoldingUmbre = false;
- ani.Play("shoot");
- attack.SkillBlackUmbrella();
- break;
- case AttackMethods.Hair:
- if (isHoldingUmbre) ani.Play("roar");
- else ani.Play("roar_no3");
- int attackTimes = 0;
- switch (bossPhase)
- {
- case 0:
- attackTimes = 6;
- break;
- case 1:
- attackTimes = 6;
- break;
- case 2:
- attackTimes = 10;
- break;
- }
- if (isAngry) attackTimes = 10;
- attack.SkillHairSprint(attackTimes);
- ChangeBossState(BossState.invincible);
- hairAttackTimer = Time.time;
- break;
- case AttackMethods.Shoot:
- if (isHoldingUmbre) ani.Play("smoke", 0, 0);
- else ani.Play("smoke_no3", 0, 0);
- bodyFlickerTimer = Time.time + 2;
- break;
- default:
- break;
- }
- }
- public override void OnAttack()
- {
- switch (curAttackType)
- {
- case AttackMethods.Umbrella:
- if (spineEvent.isAttackOn)
- {
- spineEvent.isAttackOn = false;
- attack.BlackUmbrellaRelease();
- EndCurAttackState(true);
- }
- break;
- case AttackMethods.Hair:
- if (Time.time - hairAttackTimer > 1.67f)
- {
- EndCurAttackState(true);
- }
- break;
- case AttackMethods.Shoot:
- if (Time.time - bodyFlickerTimer > bodyFlickerTime)
- {
- if (isDisappear)
- {
- if(pc == null) pc = PlayersInput.instance[0];
- int faceDir = pc.bodyTrans.transform.localScale.x > 0 ? 1 : -1;
- transform.position = pc.transform.position + Vector3.right * faceDir * 5;
- BodyFlickerAppear();
- if (isHoldingUmbre) ani.Play("attack", 0, 0);
- else ani.Play("attack_no3", 0, 0);
- }
- if (spineEvent.isAttackOn)
- {
- spineEvent.isAttackOn = false;
- int randomInt = Random.Range(0, 2);
- int num = 0;
- switch (randomInt)
- {
- case 0:
- switch (bossPhase)
- {
- case 0:
- num = 11;
- break;
- case 1:
- num = 15;
- break;
- case 2:
- num = 19;
- break;
- }
- attack.KunaiAttack((pc.transform.position - pws.transform.position).normalized, num,8);
- break;
- case 1:
- shootCoroutine = StartCoroutine(TestAttack(bossPhase));
- break;
- }
- EndCurAttackState(true);
- }
- }
- else
- {
- if (spineEvent.isAttackOn)
- {
- spineEvent.isAttackOn = false;
- BodyFlickerDisappear();
- }
- }
- break;
- default:
- break;
- }
- IEnumerator TestAttack(int bossPhase)
- {
- float shortInterval = 0.08f;
- for(int i = 0;i < 3; i++)
- {
- for (int j = 0; j < bossPhase+2; j++)
- {
- attack.KunaiAttack((pc.transform.position - pws.transform.position).normalized, 1);
- yield return new WaitForSeconds(shortInterval);
- }
- yield return new WaitForSeconds(0.2f);
- }
- yield return new WaitForSeconds(0.2f);
- for (int i = 0; i < 7 + bossPhase * 2; i++)
- {
- attack.KunaiAttack((pc.transform.position - pws.transform.position).normalized, 1);
- yield return new WaitForSeconds(shortInterval);
- }
- yield return new WaitForSeconds(0.2f);
- }
- }
- #endregion
- #region 瞬身相关
- public void BodyFlickerDisappear()
- {
- if (isDisappear || curBossStage == BossStage.polliwog) return;
- //Debug.Log("瞬身开始");
- bodyTrans.gameObject.SetActive(false);
- PoolManager.Instantiate(smokeFx, transform.position);
- ChangeBossState(BossState.invincible);
- bodyFlickerTimer = Time.time;
- isDisappear = true;
- }
- public void BodyFlickerAppear()
- {
- if (!isDisappear || curBossStage == BossStage.polliwog) return;
- //Debug.Log("瞬身结束");
- bodyTrans.gameObject.SetActive(true);
- PoolManager.Instantiate(smokeFx, transform.position);
- ChangeBossState(BossState.normal);
- isDisappear = false;
- }
- public override void EndCurAttackState(bool hasIntervalTime)
- {
- //和下一个动作有没有间隔
- if (hasIntervalTime)
- {
- if (attackCount <= 0)
- {
- if (bossPhase < statOfPhase.Length) curInterval = Random.Range(statOfPhase[bossPhase].minInterval, statOfPhase[bossPhase].maxInterval);
- else Debug.LogError("没有配置该阶段属性");
- }
- else curInterval = comboInterval;
- }
- ChangeState(CharacterState.Idle);
- ChangeBossState(BossState.rise);
- }
- #endregion
- }
|