Files
FutureMen2/Assets/_FutureMen2/Scripts/Actions/TortoiseActions.cs

314 lines
7.7 KiB
C#
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections;
using System.Collections.Generic;
using BehaviorDesigner.Runtime.Tasks;
using DragonLi.Core;
using UnityEngine;
public class TortoiseSprintAttack : Action
{
private TortoiseBoss boss;
private bool isFinished;
[Header("Sprint")]
public float sprintDistance = 3f;
public float sprintSpeed = 6f;
[Header("Angry Trample")]
public float angryDuration = 3f;
public float rotateSpeed = 90f;
public override void OnStart()
{
boss = GetComponent<TortoiseBoss>();
isFinished = false;
boss.ResetSkill1();
StartCoroutine(SkillFlow());
}
public override TaskStatus OnUpdate()
{
return isFinished ? TaskStatus.Success : TaskStatus.Running;
}
IEnumerator SkillFlow()
{
// ===== Phase 1冲刺 =====
yield return SprintThroughPlayer();
// ===== Phase 2愤怒践踏旋转 =====
yield return AngryTrample();
// ===== Phase 3转向玩家 → Idle =====
yield return RotateToPlayer();
boss.Idle();
isFinished = true;
}
#region Phase 1 - Sprint
IEnumerator SprintThroughPlayer()
{
// boss.Roar();
// yield return new WaitForSeconds(0.6f);
boss.BeginAttack();
boss.Run();
GameManager.Ins.PlaySound3D("1.19",transform);
Transform player = GameManager.Ins.player.transform;
Vector3 dir = (player.position - boss.transform.position).normalized;
dir.y = 0;
// 🎯 贯穿目标点
Vector3 targetPos = player.position + dir * sprintDistance;
// A* 移动
boss.ai.maxSpeed = sprintSpeed;
boss.ai.isStopped = false;
boss.ai.destination = targetPos;
// 面向移动方向
boss.transform.rotation = Quaternion.LookRotation(dir);
// 等待到达
while (!boss.ai.reachedEndOfPath)
{
if (boss.isDead)
{
StopAllCoroutines();
isFinished = true;
}
yield return null;
}
boss.ai.isStopped = true;
boss.EndAttack();
}
#endregion
#region Phase 2 - Angry Trample
IEnumerator AngryTrample()
{
Transform player = GameManager.Ins.player.transform;
// 1⃣ 计算玩家方向(基准方向)
Vector3 dir = player.position - boss.transform.position;
dir.y = 0;
if (dir.sqrMagnitude < 0.01f)
yield break;
Quaternion baseRot = Quaternion.LookRotation(dir);
// 2⃣ 左侧 30°
Quaternion leftRot = baseRot * Quaternion.Euler(0, -15f, 0);
yield return RotateAndTrample(leftRot);
// 3⃣ 右侧 30°
Quaternion rightRot = baseRot * Quaternion.Euler(0, 15f, 0);
yield return RotateAndTrample(rightRot);
}
IEnumerator RotateAndTrample(Quaternion targetRot)
{
// 先转向
while (Quaternion.Angle(boss.transform.rotation, targetRot) > 1f)
{
if (boss.isDead)
{
StopAllCoroutines();
isFinished = true;
}
boss.transform.rotation = Quaternion.RotateTowards(
boss.transform.rotation,
targetRot,
rotateSpeed * Time.deltaTime
);
yield return null;
}
// 播放践踏动画
boss.Trample();
// 在该方向持续践踏
float timer = 0f;
while (timer < angryDuration)
{
timer += Time.deltaTime;
yield return null;
}
}
#endregion
#region Phase 3 - Rotate To Player
IEnumerator RotateToPlayer()
{
Transform player = GameManager.Ins.player.transform;
Vector3 dir = player.position - boss.transform.position;
dir.y = 0;
if (dir.sqrMagnitude < 0.01f)
yield break;
Quaternion targetRot = Quaternion.LookRotation(dir);
while (Quaternion.Angle(boss.transform.rotation, targetRot) > 1f)
{
if (boss.isDead)
{
StopAllCoroutines();
isFinished = true;
}
boss.transform.rotation = Quaternion.RotateTowards(
boss.transform.rotation,
targetRot,
rotateSpeed * Time.deltaTime
);
yield return null;
}
}
#endregion
}
public class TortoiseFireballAttack : Action
{
private TortoiseBoss boss;
private bool isFinished;
[Header("Fireball")]
public float shootInterval = 0.2f;
public float launchHeight = 4f;
public float flightTime = 1.2f;
public override void OnStart()
{
boss = GetComponent<TortoiseBoss>();
isFinished = false;
boss.ResetSkill2();
StartCoroutine(Fire());
}
public override TaskStatus OnUpdate()
{
return isFinished ? TaskStatus.Success : TaskStatus.Running;
}
IEnumerator Fire()
{
boss.Roar();
yield return new WaitForSeconds(0.5f);
foreach (var point in boss.firePoints)
{
SpawnFireBall(point);
yield return new WaitForSeconds(shootInterval);
}
yield return new WaitForSeconds(1f);
isFinished = true;
}
void SpawnFireBall(Transform firePoint)
{
Vector3 playerPos = GameManager.Ins.player.transform.position;
// 在玩家周围随机半径1米落点
Vector2 rand = Random.insideUnitCircle * 1f;
Vector3 targetPos = playerPos + new Vector3(rand.x, 0, rand.y);
GameObject ball = Object.Instantiate(boss.fireBallPre, firePoint.position, Quaternion.identity);
FireBallProjectile proj = ball.GetComponent<FireBallProjectile>();
proj.LaunchToTarget(firePoint.position, targetPos, flightTime);
proj.SetDamage(boss.Data.Atk_2);
}
}
public class TortoiseDrillingAttack : Action
{
private TortoiseBoss boss;
private bool isFinished;
public float moveDuration = 20f;
public override void OnStart()
{
boss = GetComponent<TortoiseBoss>();
isFinished = false;
boss.ResetSkill2();
boss.ResetSkill1();
StartCoroutine(Drilling());
}
public override TaskStatus OnUpdate()
{
return isFinished ? TaskStatus.Success : TaskStatus.Running;
}
IEnumerator Drilling()
{
// 1⃣ 钻地
yield return StartCoroutine(boss.Drilling());
// 2⃣ 弹球移动
yield return StartCoroutine(DrillBounceMove(moveDuration));
// 3⃣ 钻出
yield return StartCoroutine(boss.EndDrilling());
isFinished = true;
}
public IEnumerator DrillBounceMove(float duration)
{
float timer = 0f;
Vector3 moveDir = Random.insideUnitSphere;
moveDir.y = 0;
moveDir.Normalize();
// ⚠️ 只开一次
boss.skill3Effect.SetActive(true);
boss.skill3Collider.enabled = true;
while (timer < duration)
{
timer += Time.deltaTime;
if (boss.isDead)
yield break;
Vector3 nextPos =
transform.position + moveDir * boss.drillMoveSpeed * Time.deltaTime;
if (Physics.Raycast(
transform.position,
moveDir,
out RaycastHit hit,
1.2f,
boss.drillHitMask))
{
moveDir = Vector3.Reflect(moveDir, hit.normal);
moveDir.y = 0;
moveDir.Normalize();
}
else
{
transform.position = nextPos;
}
yield return null;
}
}
}