using System.Collections;
using System.Collections.Generic;
using BehaviorDesigner.Runtime.Tasks;
using DragonLi.Behaviour;
using UnityEngine;
using Action = BehaviorDesigner.Runtime.Tasks.Action;
using System.Collections;
using BehaviorDesigner.Runtime.Tasks;
using DG.Tweening;
using Pathfinding;
using UnityEngine;
///
/// 吐舌攻击
///
public class FrogBleepAttack : Action
{
private FrogBoss boss;
private bool isFinished;
public float tongueSpeed = 25f;
public float damage = 30f;
private float rotateSpeed = 360f; // 每秒旋转角度
public override void OnStart()
{
boss = GetComponent();
isFinished = false;
boss.ResetSkill1();
boss.StartCoroutine(SkillRoutine());
}
public override TaskStatus OnUpdate()
{
return isFinished ? TaskStatus.Success : TaskStatus.Running;
}
IEnumerator SkillRoutine()
{
// 1️⃣ 不在攻击范围 → 先移动
if (!boss.IsPlayerInTongueRange())
{
yield return boss.StartCoroutine(
boss.MoveToTongueRange()
);
}
// 2️⃣ 锁定玩家位置(关键)
Vector3 lockPos = GameManager.Ins.player.transform.position;
// 面向玩家
yield return RotateToPlayer();
// 3️⃣ 吐舌头
boss.TongueAttack();
yield return new WaitForSeconds(0.4f);
float dis = Vector3.Distance(boss.mouthPoint.position, lockPos);
float time = dis / tongueSpeed;
yield return new WaitForSeconds(time);
boss.Idle();
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;
}
}
}
///
/// 毒液弹攻击
///
public class FrogPoisonAttack : Action
{
private FrogBoss boss;
private bool isFinished;
private float rotateSpeed = 360f; // 每秒旋转角度
public override void OnStart()
{
boss = GetComponent();
isFinished = false;
boss.ResetSkill2();
boss.StartCoroutine(Attack());
}
public override TaskStatus OnUpdate()
{
return isFinished ? TaskStatus.Success : TaskStatus.Running;
}
IEnumerator Attack()
{
yield return RotateToPlayer();
boss.Spit();
yield return new WaitForSeconds(0.5f);
for (int i = 0; i < 3; i++)
{
Vector2 rand = Random.insideUnitCircle * 1.2f;
Vector3 target = GameManager.Ins.player.transform.position
+ new Vector3(rand.x, 0, rand.y);
GameObject ball = Object.Instantiate(
boss.poisonBallPrefab,
boss.mouthPoint.position,
Quaternion.identity
);
ball.GetComponent().Launch(
boss.mouthPoint.position,
target,
boss.Data.Atk_2dot,
boss.Data.Atk_2Time
);
yield return new WaitForSeconds(0.5f);
}
boss.Idle();
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;
}
}
}
///
/// 吐卵 召唤小虫怪
///
public class FrogEggAttack : Action
{
private FrogBoss boss;
private bool isFinished;
[Header("Egg Config")]
public int eggCount = 12;
public float shootInterval = 0.15f;
public float fanAngle = 60f;
public float launchHeight = 3f;
public float flightTime = 1.1f;
public override void OnStart()
{
boss = GetComponent();
isFinished = false;
boss.StartCoroutine(Attack());
}
public override TaskStatus OnUpdate()
{
return isFinished ? TaskStatus.Success : TaskStatus.Running;
}
IEnumerator Attack()
{
boss.EggAttack();
yield return new WaitForSeconds(0.5f);
boss.aiPath.isStopped = true;
Transform firePoint = boss.eggFirePoint; // 嘴巴
float step = fanAngle / (eggCount - 1);
float startAngle = -fanAngle * 0.5f;
int eggBugCount = boss.GetAliveTentacles().Count;
int insCount;
if (eggBugCount >= 12)
{
boss.Idle();
isFinished = true;
yield break;
}
insCount=12-eggBugCount;
for (int i = 0; i < insCount; i++)
{
float angle = startAngle + step * i;
// 🔥 轻微左右转头
boss.transform
.DORotate(
boss.transform.eulerAngles + new Vector3(0, angle * 0.15f, 0),
0.1f
);
SpawnEgg(firePoint, angle);
yield return new WaitForSeconds(shootInterval);
}
yield return new WaitForSeconds(0.5f);
// 吐完跑向左右
Vector3 side = Random.value > 0.5f ? -boss.transform.right : boss.transform.right;
boss.transform.DOMove(boss.transform.position + side * 5f, 1.5f);
boss.Idle();
isFinished = true;
}
void SpawnEgg(Transform firePoint, float angle)
{
GameObject egg = Object.Instantiate(
boss.eggPrefab,
firePoint.position,
Quaternion.identity
);
FrogBugEnemy bug = egg.GetComponent();
bug.SetAtk(boss.Data.Atk_2,boss.Data.Hp_CS2);
// 扇形方向
Vector3 dir = Quaternion.Euler(0, angle, 0) * boss.transform.forward;
// 落点
Vector3 targetPos =
firePoint.position +
dir * Random.Range(3.5f, 5.5f);
bug.LaunchEgg(
firePoint.position,
targetPos,
launchHeight,
flightTime,
boss.Data.Atk_3,
boss.Data.Hp_CS2
);
}
}
public class FrogIdleMove : Action
{
public float moveRadius = 4f; // 扇形半径
public float moveAngle = 90f; // 扇形角度
public float stayTime = 3f; // 到点后停留时间
public float rotateSpeed = 360f;
private FrogBoss boss;
private Transform player;
private float stayTimer;
private Vector3 curTarget;
[Header("Distance To Player")]
public float minPlayerDistance = 10f; // 最近不能小于
public float maxPlayerDistance = 20f; // 最远不能超过
public override void OnStart()
{
boss = GetComponent();
player = GameManager.Ins.player.transform;
PickNewTarget();
}
public override TaskStatus OnUpdate()
{
if (player == null)
return TaskStatus.Running;
if (boss.HasAnySkillReady())
{
boss.aiPath.isStopped = true;
boss.Idle();
return TaskStatus.Failure;
}
FaceToPlayer();
Move();
return TaskStatus.Running; // 永远不结束
}
#region Core
void FaceToPlayer()
{
Vector3 dir = player.position - transform.position;
dir.y = 0;
if (dir.sqrMagnitude < 0.01f)
return;
Quaternion targetRot = Quaternion.LookRotation(dir);
transform.rotation = Quaternion.RotateTowards(
transform.rotation,
targetRot,
rotateSpeed * Time.deltaTime
);
}
void Move()
{
if (Vector3.Distance(transform.position, curTarget) < 0.3f)
{
stayTimer += Time.deltaTime;
boss.Idle();
if (stayTimer >= stayTime)
PickNewTarget();
return;
}
boss.Run();
boss.aiPath.isStopped = false;
boss.aiPath.destination = curTarget;
}
void PickNewTarget()
{
stayTimer = 0f;
Vector3 bossPos = transform.position;
Vector3 toPlayer = player.position - bossPos;
toPlayer.y = 0;
// 玩家正前方扇形
Vector3 forward = toPlayer.normalized;
const int MAX_TRY = 10;
for (int i = 0; i < MAX_TRY; i++)
{
float angle = Random.Range(-moveAngle * 0.5f, moveAngle * 0.5f);
Vector3 dir = Quaternion.Euler(0, angle, 0) * forward;
float dist = Random.Range(moveRadius * 0.4f, moveRadius);
Vector3 candidate = bossPos + dir * dist;
// 👉 与玩家距离校验
float playerDist = Vector3.Distance(candidate, player.position);
if (playerDist < minPlayerDistance || playerDist > maxPlayerDistance)
continue;
// A* 校正
NNInfo nn = AstarPath.active.GetNearest(candidate);
if (nn.node != null && nn.node.Walkable)
{
curTarget = nn.position;
return;
}
}
// 🔥 兜底:保持原地
curTarget = bossPos;
}
#endregion
}