339 lines
8.3 KiB
C#
339 lines
8.3 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using BehaviorDesigner.Runtime.Tasks;
|
||
using DragonLi.Core;
|
||
using UnityEngine;
|
||
|
||
public class OctopusTentacleAtk : Action
|
||
{
|
||
public int attackCount;
|
||
|
||
private OctopusBoss boss;
|
||
private bool isFinished;
|
||
|
||
public override void OnStart()
|
||
{
|
||
boss = GetComponent<OctopusBoss>();
|
||
isFinished = false;
|
||
|
||
boss.ResetSkill1();
|
||
StartCoroutine(Attack());
|
||
}
|
||
|
||
public override TaskStatus OnUpdate()
|
||
{
|
||
return isFinished ? TaskStatus.Success : TaskStatus.Running;
|
||
}
|
||
|
||
IEnumerator Attack()
|
||
{
|
||
var list = boss.GetAliveTentacles();
|
||
list.Shuffle();
|
||
if (list.Count == 0)
|
||
{
|
||
isFinished = true;
|
||
yield break;
|
||
}
|
||
// 🔥 狂暴:4 条一起
|
||
if (attackCount == 4)
|
||
{
|
||
int index = 0;
|
||
|
||
while (index < list.Count)
|
||
{
|
||
int count = Mathf.Min(4, list.Count - index);
|
||
yield return AttackGroup(list, index, count, true);
|
||
if (boss.isDead)
|
||
yield break;
|
||
index += count;
|
||
}
|
||
}
|
||
// 🔹 普通:2 条一组
|
||
else
|
||
{
|
||
int index = 0;
|
||
|
||
while (index < list.Count)
|
||
{
|
||
int count = Mathf.Min(2, list.Count - index);
|
||
yield return AttackGroup(list, index, count, false);
|
||
if (boss.isDead)
|
||
yield break;
|
||
index += count;
|
||
}
|
||
}
|
||
|
||
isFinished = true;
|
||
}
|
||
|
||
IEnumerator AttackGroup(
|
||
List<Tentacle> list,
|
||
int startIndex,
|
||
int count,
|
||
bool isFurious
|
||
)
|
||
{
|
||
List<Coroutine> coroutines = new();
|
||
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
coroutines.Add(
|
||
StartCoroutine(list[startIndex + i].Attack(isFurious))
|
||
);
|
||
}
|
||
|
||
// ⏳ 等这一组全部攻击完成
|
||
foreach (var c in coroutines)
|
||
{
|
||
if (boss.isDead)
|
||
yield break;
|
||
yield return c;
|
||
}
|
||
|
||
|
||
// 组与组之间稍微停顿(可调)
|
||
yield return new WaitForSeconds(0.5f);
|
||
}
|
||
|
||
}
|
||
|
||
//技能2 吐墨水
|
||
public class OctopusSprayAttack : Action
|
||
{
|
||
private OctopusBoss boss;
|
||
private bool isFinished;
|
||
|
||
private float rotateSpeed = 360f; // 每秒旋转角度
|
||
public override void OnStart()
|
||
{
|
||
boss = GetComponent<OctopusBoss>();
|
||
isFinished = false;
|
||
|
||
boss.ResetSkill2();
|
||
StartCoroutine(Spray());
|
||
}
|
||
|
||
public override TaskStatus OnUpdate()
|
||
{
|
||
return isFinished ? TaskStatus.Success : TaskStatus.Running;
|
||
}
|
||
|
||
IEnumerator Spray()
|
||
{
|
||
// 1️⃣ 显示特效
|
||
boss.sprayEx.SetActive(true);
|
||
GameManager.Ins.PlaySound3D("1.14",transform,true);
|
||
Transform player = GameManager.Ins.player.transform;
|
||
|
||
// 2️⃣ 锁定玩家方向(只转 Y)
|
||
Vector3 dir = player.position - boss.sprayRoot.position;
|
||
dir.y = 0;
|
||
|
||
Quaternion startRot = Quaternion.LookRotation(dir);
|
||
|
||
// 3️⃣ 决定扫射方向
|
||
float sign = Random.value > 0.5f ? 1f : -1f;
|
||
Quaternion endRot = startRot * Quaternion.Euler(0, boss.sprayAngle * sign, 0);
|
||
|
||
boss.sprayRoot.rotation = startRot;
|
||
|
||
// 4️⃣ 扫射
|
||
float timer = 0f;
|
||
while (timer < boss.sprayDuration&& !boss.isDead)
|
||
{
|
||
float t = timer / boss.sprayDuration;
|
||
boss.sprayRoot.rotation = Quaternion.Slerp(startRot, endRot, t);
|
||
|
||
timer += Time.deltaTime;
|
||
yield return null;
|
||
}
|
||
|
||
// 5️⃣ 关闭特效
|
||
boss.sprayEx.SetActive(false);
|
||
yield return RotateToPlayer();
|
||
isFinished = true;
|
||
}
|
||
IEnumerator RotateToPlayer()
|
||
{
|
||
Transform player = GameManager.Ins.player.transform;
|
||
|
||
Vector3 dir = player.position - transform.position;
|
||
dir.y = 0;
|
||
|
||
if (dir.sqrMagnitude < 0.01f)
|
||
yield break;
|
||
|
||
Quaternion targetRot = Quaternion.LookRotation(dir);
|
||
|
||
while (Quaternion.Angle(transform.rotation, targetRot) > 1f)
|
||
{
|
||
transform.rotation = Quaternion.RotateTowards(
|
||
transform.rotation,
|
||
targetRot,
|
||
rotateSpeed * Time.deltaTime
|
||
);
|
||
yield return null;
|
||
}
|
||
}
|
||
}
|
||
|
||
//技能3 触手突刺
|
||
public class OctopusSpikeAttack : Action
|
||
{
|
||
private OctopusBoss boss;
|
||
private bool isFinished;
|
||
|
||
public override void OnStart()
|
||
{
|
||
boss = GetComponent<OctopusBoss>();
|
||
isFinished = false;
|
||
|
||
boss.ResetSkill2();
|
||
boss.ResetSkill1();
|
||
StartCoroutine(Spike());
|
||
}
|
||
|
||
public override TaskStatus OnUpdate()
|
||
{
|
||
return isFinished ? TaskStatus.Success : TaskStatus.Running;
|
||
}
|
||
|
||
IEnumerator Spike()
|
||
{
|
||
var list = boss.GetAliveTentacles();
|
||
if (list.Count == 0)
|
||
{
|
||
isFinished = true;
|
||
yield break;
|
||
}
|
||
|
||
foreach (var t in list)
|
||
t.Hide();
|
||
|
||
yield return new WaitForSeconds(2f);
|
||
float playerDiameter = 0.5f * 2f;
|
||
float redCircleDiameter = playerDiameter * 3f;
|
||
|
||
var points = SpikeAreaGenerator.Generate(
|
||
GameManager.Ins.player.transform.position,
|
||
list.Count,
|
||
2.5f,
|
||
5f,
|
||
redCircleDiameter
|
||
);
|
||
for (int i = 0; i < list.Count; i++)
|
||
{
|
||
GameManager.Ins.CreateEnemySkillTip(points[i].ReflectVectorXOZ()+new Vector3(0,0.01f,0),2.5f);
|
||
}
|
||
// TODO:生成红圈提示
|
||
yield return new WaitForSeconds(3f);
|
||
GameInit.Ins.PlayAudio("1.16",transform,true);
|
||
for (int i = 0; i < list.Count; i++)
|
||
{
|
||
list[i].Spike(points[i]);
|
||
}
|
||
yield return new WaitForSeconds(6f);
|
||
isFinished = true;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
public class OctopusTeleport : Action
|
||
{
|
||
private OctopusBoss boss;
|
||
private bool isFinished;
|
||
|
||
[Header("Move Config")]
|
||
public float moveDuration = 2f;
|
||
public float hideDuration = 0.5f;
|
||
private float rotateSpeed = 360f; // 每秒旋转角度
|
||
public override void OnStart()
|
||
{
|
||
boss = GetComponent<OctopusBoss>();
|
||
isFinished = false;
|
||
|
||
boss.ResetTeleport();
|
||
StartCoroutine(TeleportMove());
|
||
}
|
||
|
||
public override TaskStatus OnUpdate()
|
||
{
|
||
return isFinished ? TaskStatus.Success : TaskStatus.Running;
|
||
}
|
||
|
||
IEnumerator TeleportMove()
|
||
{
|
||
// 1️⃣ 触手下沉
|
||
var tentacles = boss.GetAliveTentacles();
|
||
foreach (var t in tentacles)
|
||
t.Hide();
|
||
|
||
yield return new WaitForSeconds(hideDuration);
|
||
|
||
// 2️⃣ 选目标点
|
||
Transform target = boss.teleportPoints[
|
||
Random.Range(0, boss.teleportPoints.Length)
|
||
];
|
||
|
||
Vector3 startPos = boss.transform.position;
|
||
Vector3 endPos = target.position;
|
||
|
||
// 3️⃣ 朝向目标
|
||
Vector3 lookDir = endPos - startPos;
|
||
lookDir.y = 0;
|
||
if (lookDir.sqrMagnitude > 0.01f)
|
||
boss.transform.rotation = Quaternion.LookRotation(lookDir);
|
||
|
||
// 4️⃣ 平滑移动
|
||
float timer = 0f;
|
||
while (timer < moveDuration)
|
||
{
|
||
timer += Time.deltaTime;
|
||
float t = timer / moveDuration;
|
||
boss.transform.position = Vector3.Lerp(startPos, endPos, t);
|
||
yield return null;
|
||
}
|
||
|
||
boss.transform.position = endPos;
|
||
|
||
yield return RotateToPlayer();
|
||
|
||
// 5️⃣ 触手刷新 / 再出现
|
||
foreach (var t in tentacles)
|
||
t.RefreshToBoss();
|
||
|
||
isFinished = true;
|
||
}
|
||
|
||
IEnumerator RotateToPlayer()
|
||
{
|
||
Transform player = GameManager.Ins.player.transform;
|
||
|
||
Vector3 dir = player.position - transform.position;
|
||
dir.y = 0;
|
||
|
||
if (dir.sqrMagnitude < 0.01f)
|
||
yield break;
|
||
|
||
Quaternion targetRot = Quaternion.LookRotation(dir);
|
||
|
||
while (Quaternion.Angle(transform.rotation, targetRot) > 1f)
|
||
{
|
||
transform.rotation = Quaternion.RotateTowards(
|
||
transform.rotation,
|
||
targetRot,
|
||
rotateSpeed * Time.deltaTime
|
||
);
|
||
yield return null;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|