Files
FutureMen2/Assets/_FutureMen2/Scripts/Enemy/FrogBoss/FrogBoss.cs
2026-01-29 17:34:43 +08:00

274 lines
6.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using DragonLi.Core;
using UnityEngine;
using Random = UnityEngine.Random;
public class FrogBoss : Enemy
{
[Header("Base")]
public GameObject clipQuadObj;
public Animator bossAnim;
[Header("Skill Prefabs")]
public Transform mouthPoint;
public GameObject poisonBallPrefab;
public GameObject eggPrefab;
public Transform eggFirePoint;
public EnemyBoneHit mouthBoneHit;
public List<FrogBugEnemy> frogBugs = new List<FrogBugEnemy>();
public GameObject[] bossCrystals;
private float rotateSpeed = 180f; // 越大转得越快(插值系数)
public List<FrogBugEnemy> GetAliveTentacles()
{
List<FrogBugEnemy> list = new();
foreach (var t in frogBugs)
if (t != null && !t.isDead)
list.Add(t);
return list;
}
private void Start()
{
clipQuadObj.transform.localPosition = new Vector3(0, -5f, 0);
mouthBoneHit.SetDamage(Data.Atk_1P);
bloodSlider.gameObject.SetActive(false);
foreach (var item in bossCrystals)
{
item.SetActive(false);
}
transform.LookAt(GameManager.Ins.player.transform.position.ReflectVectorXOZ());
}
public override void Update()
{
base.Update();
if (enemyState != EnemyState.Show && enemyState != EnemyState.Dead)
{
skill1Timer += Time.deltaTime;
skill2Timer += Time.deltaTime;
Transform player = GameManager.Ins.player.transform;
if (!player) return;
Vector3 dir = player.position - transform.position;
dir.y = 0;
if (dir.sqrMagnitude < 0.0001f)
return;
Quaternion targetRot = Quaternion.LookRotation(dir);
transform.transform.rotation = Quaternion.RotateTowards(
transform.transform.rotation,
targetRot,
rotateSpeed * Time.deltaTime
);
}
}
#region Show
public override void Show()
{
base.Show();
clipQuadObj.transform.DOLocalMoveY(10, 5).OnComplete(() =>
{
isShowEnd = true;
Roar();
});
}
public override void EndShow()
{
base.EndShow();
bloodSlider.gameObject.SetActive(true);
foreach (var item in bossCrystals)
{
item.SetActive(true);
}
}
#endregion
#region Skill Reset
public bool HasAnySkillReady()
{
return skill1Timer >= skill1Cooldown ||
skill2Timer >= skill2Cooldown ||
IsUserSkill3();
}
public bool IsUserSkill3()
{
float hpPercent =health / maxHealth;
int index = Mathf.FloorToInt(hpPercent / 0.2f);
if (index < spikeTriggerIndex)
{
spikeTriggerIndex = index;
return true;
}
return false;
}
public void ResetSkill1() => skill1Timer = 0;
public void ResetSkill2() => skill2Timer = 0;
#endregion
#region Animation Wrappers
public void Roar()
{
bossAnim.SetInteger("State", 0);
GameManager.Ins.PlaySound3D("1.2", transform);
}
public void Run()
{
bossAnim.SetInteger("State", 2);
GameManager.Ins.PlaySound3D("1.19", transform);
}
public void Idle()
{
bossAnim.SetInteger("State", 1);
if(isDead)
return;
GameManager.Ins.PlaySound3D("1.20", transform, true);
}
public override void Hit()
{
if(enemyState!= EnemyState.Idle)
return;
base.Hit();
int hitIndex = Random.Range(0, 100);
string hitStr=hitIndex>=50 ?"isHit1":"isHit2";
bossAnim.SetTrigger(hitStr);
}
public void TongueAttack()
{
bossAnim.SetInteger("State", 3);
GameManager.Ins.PlaySound3D("1.31", transform, true);
}
public void Spit()
{
bossAnim.SetInteger("State", 4);
GameManager.Ins.PlaySound3D("1.20", transform, true);
}
public void EggAttack()
{
bossAnim.SetInteger("State", 5);
}
[NonSerialized]
public float tongueRange = 10f;
public float moveSpeed = 3.5f;
public bool IsPlayerInTongueRange()
{
return Vector3.Distance(
transform.position,
GameManager.Ins.player.transform.position
) <= tongueRange;
}
public IEnumerator MoveToTongueRange()
{
Run();
while (!IsPlayerInTongueRange())
{
Vector3 playerPos = GameManager.Ins.player.transform.position;
Vector3 dir = (playerPos - transform.position).normalized;
// 只在 XZ 平面移动
transform.position += new Vector3(
dir.x, 0, dir.z
) * moveSpeed * Time.deltaTime;
// 面向玩家
transform.forward = Vector3.Lerp(
transform.forward,
new Vector3(dir.x, 0, dir.z),
Time.deltaTime * 8f
);
yield return null;
}
Idle();
}
#endregion
public override void ChangeHp(float value, object info, Transform _sender)
{
if(enemyState== EnemyState.Show)
return;
base.ChangeHp(value, info, _sender);
}
#region Die
public override void Dead()
{
if (isDead)
{
return;
}
GameManager.Ins.curLevel++;
isDead = true;
health = 0;
if (bloodSlider != null)
bloodSlider.gameObject.SetActive(false);
if(ColliderComponent!=null)
ColliderComponent.enabled = false;
if(behaviourTree != null)
behaviourTree.enabled = false;
GameManager.Ins.PlaySound3D("1.46",transform,true);
foreach (var item in bossCrystals)
{
if(item==null)
continue;
item.SetActive(false);
}
foreach (var item in GetAliveTentacles())
{
item.Dead();
}
StartCoroutine(DeathDissolve());
}
IEnumerator DeathDissolve()
{
clipQuadObj.SetActive(true);
bloodSlider.gameObject.SetActive(false);
clipQuadObj.transform.localPosition = new Vector3(0, 5f, 0);
bossAnim.SetBool("isDie",true);
yield return new WaitForSeconds(3f);
clipQuadObj.transform.DOLocalMoveY(-5f, 5);
yield return new WaitForSeconds(8f);
GameManager.Ins.CreateBoss(transform.position.ReflectVectorXOZ());
Destroy(gameObject);
}
#endregion
}