Files
valheim/Assets/_Valheim/Scripts/Actions.cs
2025-07-11 16:53:01 +08:00

1403 lines
41 KiB
C#

using System.Collections.Generic;
using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;
using BehaviorDesigner.Runtime.Tasks.Movement;
using UnityEngine;
using UnityEngine.AI;
using Valheim;
public class Actions
{
private static readonly int UserSkill = Animator.StringToHash("userSkill");
/// <summary>
/// 差值旋转到规定角度
/// </summary>
public class RotationToStipulateAngle : Action
{
public SharedVector3 angle;
public SharedGameObject Target;
public override TaskStatus OnUpdate()
{
Quaternion quaternion = new Quaternion();
quaternion.eulerAngles = angle.Value;
if (transform.rotation == quaternion)
{
return TaskStatus.Success;
}
else if (transform.eulerAngles.y < 5)
{
return TaskStatus.Success;
}
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.identity, Time.deltaTime * 15);
return TaskStatus.Failure;
}
}
public class CheckCurrentEnemyAlive : Conditional
{
public SharedGameObject Target;
public override TaskStatus OnUpdate()
{
if (Target.Value)
{
bool IsAlive = Target.Value.GetComponent<Agent>().IsAlive;
if (!IsAlive)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
return TaskStatus.Failure;
}
}
/// <summary>
/// 移动到某个位置
/// </summary>
public class MoveToPoint : NavMeshMovement
{
public SharedVector3 point;
public override void OnStart()
{
base.OnStart();
SetDestination(point.Value);
}
public override TaskStatus OnUpdate()
{
SetDestination(point.Value);
if (navMeshAgent.remainingDistance < arriveDistance.Value)
{
navMeshAgent.isStopped = true;
navMeshAgent.velocity = Vector3.zero;
return TaskStatus.Success;
}
return TaskStatus.Running;
}
}
public class MoveToPoint2 : Action
{
public SharedVector3 point;
private Pet pet;
public override void OnStart()
{
base.OnStart();
pet = transform.GetComponent<Pet>();
if (pet != null)
{
Debug.Log("TO: 开始");
SetDestination();
}
}
public override TaskStatus OnUpdate()
{
if (pet == null)
{
return TaskStatus.Failure;
}
SetDestination();
if (pet.NavAgent.remainingDistance < 0.1F)
{
pet.NavAgent.isStopped = true;
pet.NavAgent.velocity = Vector3.zero;
return TaskStatus.Success;
}
return TaskStatus.Running;
}
public void SetDestination()
{
if (pet != null )
{
pet.NavAgent.isStopped = false;
pet.NavAgent.SetDestination(point.Value);
}
}
}
public class MoveToRegeneration : Action
{
public SharedTransform Point;
private Pet pet;
public override void OnStart()
{
base.OnStart();
pet = transform.GetComponent<Pet>();
if (pet != null)
{
SetDestination();
}
}
public override TaskStatus OnUpdate()
{
if (pet == null)
{
return TaskStatus.Failure;
}
SetDestination();
if (pet.NavAgent.remainingDistance < 0.1F)
{
pet.NavAgent.isStopped = true;
pet.NavAgent.velocity = Vector3.zero;
return TaskStatus.Success;
}
return TaskStatus.Running;
}
public void SetDestination()
{
if (pet != null && Point.Value != null)
{
pet.NavAgent.isStopped = false;
int index=Random.Range(0, 11);
Vector3 point = Point.Value.gameObject.GetComponent<Regeneration>().Points[index].position;
//因为字典是从1开始 所以要减1
pet.NavAgent.SetDestination(point);
}
}
}
public class CheckArriveTargetPoint : Conditional
{
public SharedBool IsArriveTargetPoint;
public override TaskStatus OnUpdate()
{
if (IsArriveTargetPoint.Value)
{
return TaskStatus.Success;
}
else if (!IsArriveTargetPoint.Value)
{
return TaskStatus.Failure;
}
return TaskStatus.Running;
}
}
/// <summary>
/// 检测范围内是否有敌人
/// </summary>
public class CheckRangeEnemy : Conditional
{
public SharedFloat checkRange;
public SharedString enemyTag;
private bool IsEnemy;
public override TaskStatus OnUpdate()
{
if (GameManager.Ins != null)
{
List<Transform> transforms = GameManager.Ins.GetRangeEnemy(transform.position, checkRange.Value, enemyTag.Value);
Debug.Log("检测敌人数量:" + transforms.Count);
IsEnemy = transforms.Count > 0 ;
}
if (IsEnemy)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class EnemySearchTargetCon : Conditional
{
public override TaskStatus OnUpdate()
{
Enemy self = transform.GetComponent<Enemy>();
if (self == null) return TaskStatus.Failure;
bool find = false;
foreach (Pet pet in GameManager.Ins.PetList.Values)
{
// 受训练的宠物
if (pet.state == PetState.Trained)
{
// 残血的宠物
if (pet.Health <= 0)
{
continue;
}
Player player = MRNetworkManager.Ins.roomSlots[pet.teamId].transform.GetComponent<Player>();
// 所属训练师不在老巢内
if (player == null || player.InAreaId != self.areaId)
{
continue;
}
// 宠物不在老巢内
// if (!GameManager.Ins.CheckPointInArea(self.areaId, pet.transform.position))
// {
// continue;
// }
find = true;
Owner.SetVariable("Target", (SharedGameObject)pet.gameObject);
find = true;
break;
}
}
if (find == false)
{
SharedGameObject targetShared = new SharedGameObject();
targetShared.Value = null;
Owner.SetVariable("Target", targetShared);
}
return find ? TaskStatus.Success : TaskStatus.Failure;
}
}
public class EnemySearchTarget : Action
{
public override TaskStatus OnUpdate()
{
Enemy self = transform.GetComponent<Enemy>();
if (self == null) return TaskStatus.Failure;
bool find = false;
foreach (Pet pet in GameManager.Ins.PetList.Values)
{
// 受训练的宠物
if (pet.state == PetState.Trained)
{
// 残血的宠物
if (pet.Health <= 0)
{
continue;
}
if (pet.teamId != 0)
{
Debug.LogError("宠物队伍错误");
continue;
}
Player player = MRNetworkManager.Ins.roomSlots[pet.teamId].transform.GetComponent<Player>();
// 所属训练师不在老巢内
if (player == null || player.InAreaId != self.areaId)
{
continue;
}
// // 宠物不在老巢内
// if (!GameManager.Ins.CheckPointInArea(self.areaId, pet.transform.position))
// {
// continue;
// }
find = true;
Owner.SetVariable("Target", (SharedGameObject)pet.gameObject);
find = true;
break;
}
}
if (find == false)
{
SharedGameObject targetShared = new SharedGameObject();
targetShared.Value = null;
Owner.SetVariable("Target", targetShared);
}
return TaskStatus.Success;
}
}
public class BossSearchTarget : Action
{
public override TaskStatus OnUpdate()
{
EnemyBoss self = transform.GetComponent<EnemyBoss>();
if (self == null) return TaskStatus.Failure;
bool find = false;
float dis = 10000f;
GameObject preTarget = null;
foreach (Pet pet in GameManager.Ins.PetList.Values)
{
// 受训练的宠物
// if (pet.state == PetState.Trained)
// {
// // 残血的宠物
// // if (pet.Health <= 0)
// // {
// // continue;
// // }
// if (pet.state == PetState.Trained)
// {
// continue;
// }
// float space = Vector3.Distance(pet.transform.position, self.transform.position);
// if (space <= dis)
// {
// find = true;
// preTarget = pet.gameObject;
// }
// }
if (pet.state == PetState.Terminal)
{
continue;
}
float space = Vector3.Distance(pet.transform.position, self.transform.position);
if (space <= dis)
{
find = true;
preTarget = pet.gameObject;
}
}
if (find == false)
{
SharedGameObject targetShared = new SharedGameObject();
targetShared.Value = null;
Owner.SetVariable("Target", targetShared);
return TaskStatus.Failure;
}
if (find && preTarget != null)
{
Owner.SetVariable("Target", (SharedGameObject)preTarget);
}
return TaskStatus.Success;
}
}
public class CheckSelfAlive : Conditional
{
public override TaskStatus OnUpdate()
{
bool isAlive = transform.GetComponent<Agent>().IsAlive;
if (isAlive)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class CheckTargetEnemyState : Conditional
{
public SharedGameObject target;
public SharedInt state;
public override TaskStatus OnUpdate()
{
if (target.Value)
{
Enemy enemy = target.Value.GetComponent<Enemy>();
if (enemy == null) return TaskStatus.Failure;
if (enemy.state == (EnemyState)state.Value)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
return TaskStatus.Failure;
}
}
public class CheckEnemyState : Conditional
{
public SharedInt state;
public override TaskStatus OnUpdate()
{
Enemy enemy = transform.GetComponent<Enemy>();
if (enemy == null) return TaskStatus.Failure;
if (enemy.state == (EnemyState)state.Value)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class CheckBossState : Conditional
{
public SharedInt state;
public override TaskStatus OnUpdate()
{
EnemyBoss boss = transform.GetComponent<EnemyBoss>();
if (boss == null) return TaskStatus.Failure;
if (boss.bossState == (BossState)state.Value)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class SetEnemyState : Action
{
public SharedInt state;
public override TaskStatus OnUpdate()
{
Enemy enemy = transform.GetComponent<Enemy>();
if (enemy == null) return TaskStatus.Failure;
//if (GameManager.Ins.isGuide) return TaskStatus.Running;
//记录下上一次状态
Owner.SetVariable("LastState", (SharedInt)(int)enemy.state);
enemy.state = (EnemyState)state.Value;
return TaskStatus.Success;
}
}
public class SetBossState : Action
{
public SharedInt state;
public override TaskStatus OnUpdate()
{
EnemyBoss boss = transform.GetComponent<EnemyBoss>();
if (boss == null) return TaskStatus.Failure;
boss.bossState = (BossState)state.Value;
return TaskStatus.Success;
}
}
[TaskDescription("检测自身是否已受训练")]
public class CheckIsTrained : Conditional
{
public override TaskStatus OnUpdate()
{
PetState state = transform.GetComponent<Pet>().state;
if (state == PetState.Trained)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
[TaskDescription("检测宠物状态")]
public class CheckPetState : Conditional
{
public SharedInt state;
public override TaskStatus OnUpdate()
{
Pet pet = transform.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
if (pet.state == (PetState)state.Value)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
[TaskDescription("检测宠物命令")]
public class CheckPetOrder : Conditional
{
public SharedInt order;
public override TaskStatus OnUpdate()
{
Pet pet = transform.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
if (pet.order == (OrderType)order.Value)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class SetPetState : Action
{
public SharedInt state;
public override TaskStatus OnUpdate()
{
Pet pet = transform.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
pet.state = (PetState)state.Value;
return TaskStatus.Success;
}
}
public class SetPetOrder : Action
{
public SharedInt order;
public override TaskStatus OnUpdate()
{
Pet pet = transform.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
pet.order = (OrderType)order.Value;
return TaskStatus.Success;
}
}
/// <summary>
/// 检测是否在攻击范围
/// </summary>
public class CheckInAtkArea : Conditional
{
public SharedInt checkType;
public SharedGameObject target;
public override TaskStatus OnUpdate()
{
if (target.Value == null) return TaskStatus.Failure;
float atkArea = 0.0f;
if (checkType.Value == 0)
{
Pet pet = transform.GetComponent<Pet>();
if (pet != null)
{
atkArea = pet.atkArea;
}
}
else if (checkType.Value == 1)
{
Enemy enemy = transform.GetComponent<Enemy>();
if (enemy != null)
{
atkArea = enemy.atkArea;
}
}
float dis = 0.0f;
if (checkType.Value == 0)
{
Enemy enemy = target.Value.GetComponent<Enemy>();
dis = Vector3.Distance(transform.position, target.Value.transform.position) - enemy.radius;
}
else if (checkType.Value == 1)
{
Pet pet = target.Value.GetComponent<Pet>();
dis = Vector3.Distance(transform.position, target.Value.transform.position) - pet.radius;
}
if (dis <= atkArea)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class BossCheckInAtkArea : Conditional
{
public SharedGameObject target;
public override TaskStatus OnUpdate()
{
if (target.Value == null) return TaskStatus.Failure;
EnemyBoss enemyBoss = transform.GetComponent<EnemyBoss>();
if (enemyBoss == null) return TaskStatus.Failure;
Pet pet = target.Value.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
float atkArea = enemyBoss.atkArea;
float dis = Vector3.Distance(transform.position, target.Value.transform.position) - pet.radius;
if (dis <= atkArea)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class PlayerIdels : Action
{
private Animator animator;
public override TaskStatus OnUpdate()
{
if (animator == null)
{
animator = transform.GetComponent<Animator>();
}
else
{
////
}
return TaskStatus.Success;
}
}
public class SearchRevivePoint : Action
{
public override TaskStatus OnUpdate()
{
if (GameManager.Ins.RevivePointList.Count <= 0) return TaskStatus.Failure;
GameManager.Ins.RevivePointList.Sort((x, y) =>
{
if (Vector3.Distance(transform.position, x.position) > Vector3.Distance(transform.position, y.position))
{
return 1;
}
else
{
return -1;
}
});
Owner.SetVariable("TempPoints", (SharedTransform)GameManager.Ins.RevivePointList[0]);
return TaskStatus.Success;
}
}
/// <summary>
/// 检测target所属训练师是不是在老巢内
/// </summary>
public class CheckPetOwnerInArea : Conditional
{
public SharedGameObject target;
public override TaskStatus OnUpdate()
{
if (target.Value == null) return TaskStatus.Failure;
Pet pet = target.Value.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
Enemy self = transform.GetComponent<Enemy>();
if (self == null) return TaskStatus.Failure;
if (GameManager.Ins.CheckPointInArea(self.areaId, MRNetworkManager.Ins.roomSlots[pet.teamId].transform.position))
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class WaitCurrentAnimationEnd : Action
{
private Animator animator;
public override TaskStatus OnUpdate()
{
animator = transform.GetComponent<Animator>();
if (animator == null)
{
Debug.LogError("Animator is null");
return TaskStatus.Failure;
}
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
if (stateInfo.normalizedTime >= 1f)
{
// 动画已结束
return TaskStatus.Success;
}
return TaskStatus.Running;
}
}
public class WaitCurrentAnimationEnd1 : Action
{
private Animator animator;
public override void OnStart()
{
animator = transform.GetComponent<Animator>();
}
public override TaskStatus OnUpdate()
{
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
if (stateInfo.IsTag("Attack") && stateInfo.normalizedTime >= 1F)
{
return TaskStatus.Success;
}
return TaskStatus.Running;
}
}
public class WaitAnimation : Action
{
private Animator animator;
private SharedFloat waitTime = 1;
private SharedBool randomWait = false;
private SharedFloat randomWaitMin = 1;
private SharedFloat randomWaitMax = 1;
// The time to wait
private float waitDuration;
// The time that the task started to wait.
private float startTime;
// Remember the time that the task is paused so the time paused doesn't contribute to the wait time.
private float pauseTime;
public override void OnStart()
{
animator = transform.GetComponent<Animator>();
if (animator == null)
{
Debug.LogError("Animator is null");
}
// The task is done waiting if the time waitDuration has elapsed since the task was started.
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
// Remember the start time.
startTime = Time.time;
waitDuration = stateInfo.length;
Debug.Log("Animator D" + waitDuration);
}
public override TaskStatus OnUpdate()
{
if (startTime + waitDuration < Time.time)
{
return TaskStatus.Success;
}
// Otherwise we are still waiting.
return TaskStatus.Running;
}
public override void OnPause(bool paused)
{
if (paused)
{
// Remember the time that the behavior was paused.
pauseTime = Time.time;
}
else
{
// Add the difference between Time.time and pauseTime to figure out a new start time.
startTime += (Time.time - pauseTime);
}
}
public override void OnReset()
{
// Reset the public properties back to their original values
waitTime = 1;
randomWait = false;
randomWaitMin = 1;
randomWaitMax = 1;
}
}
public class PetSetOut : Action
{
public override TaskStatus OnUpdate()
{
Pet pet = transform.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
if (GameManager.Ins.SetOutTeam(pet.teamId, pet.id))
{
pet.isSetOut = true;
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class PetReturn2Team : Action
{
public override TaskStatus OnUpdate()
{
Pet pet = transform.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
if (GameManager.Ins.Return2Team(pet.teamId, pet.id))
{
pet.isSetOut = false;
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class IsPetSetOut : Conditional
{
public override TaskStatus OnUpdate()
{
Pet pet = transform.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
if (pet.isSetOut)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class Seek : NavMeshMovement2
{
public SharedInt seekType;
[BehaviorDesigner.Runtime.Tasks.Tooltip("The GameObject that the agent is seeking")]
public SharedGameObject target;
[BehaviorDesigner.Runtime.Tasks.Tooltip("If target is null then use the target position")]
public SharedVector3 targetPosition;
public float arriveDistance;
public override void OnStart()
{
base.OnStart();
if (seekType.Value == 0)
{
navMeshAgent.speed = transform.GetComponent<Pet>().seekSpeed;
}
else if (seekType.Value == 1)
{
navMeshAgent.speed = transform.GetComponent<Enemy>().speed;
}
SetDestination(Target());
}
public override TaskStatus OnUpdate()
{
if (target.Value == null) return TaskStatus.Failure;
if (seekType.Value == 0)
{
Enemy enemy = target.Value.GetComponent<Enemy>();
Pet self = transform.GetComponent<Pet>();
arriveDistance = enemy.radius + self.radius + 0.1F;
// Debug.Log("enemyRadius:" + enemy.radius);
}
else if (seekType.Value == 1)
{
Pet pet = target.Value.GetComponent<Pet>();
Enemy self = transform.GetComponent<Enemy>();
arriveDistance = pet.radius + self.radius + 0.1F;
}
SetDestination(Target());
// Debug.Log("arriveDistance:" + arriveDistance);
if (navMeshAgent.remainingDistance < arriveDistance)
{
navMeshAgent.isStopped = true;
navMeshAgent.velocity = Vector3.zero;
return TaskStatus.Success;
}
return TaskStatus.Running;
}
private Vector3 Target()
{
if (target.Value != null)
{
return target.Value.transform.position;
}
return targetPosition.Value;
}
public override void OnReset()
{
base.OnReset();
target = null;
targetPosition = Vector3.zero;
}
protected override bool HasPath()
{
return navMeshAgent.hasPath && navMeshAgent.remainingDistance > arriveDistance;
}
protected override bool HasArrived()
{
float remainingDistance;
if (navMeshAgent.pathPending)
{
remainingDistance = float.PositiveInfinity;
}
else
{
remainingDistance = navMeshAgent.remainingDistance;
}
return remainingDistance <= arriveDistance;
}
}
public class Flee : NavMeshMovement
{
public SharedFloat fleedDistance = 20;
public SharedFloat lookAheadDistance = 5;
public SharedGameObject target;
private bool hasMoved;
public override void OnStart()
{
base.OnStart();
hasMoved = false;
SetDestination(Target());
}
public override TaskStatus OnUpdate()
{
if (Vector3.Magnitude(Tareget2()) > fleedDistance.Value)
{
return TaskStatus.Success;
}
if (HasArrived())
{
if (!hasMoved)
{
return TaskStatus.Failure;
}
if (!SetDestination(Target()))
{
return TaskStatus.Failure;
}
hasMoved = false;
}
else
{
return TaskStatus.Running;
// If the agent is stuck the task shouldn't continue to return a status of running.
// var velocityMagnitude = Velocity().sqrMagnitude;
// if (hasMoved && velocityMagnitude <= 0f)
// {
// // return TaskStatus.Failure;
// return TaskStatus.Running;
// }
// hasMoved = velocityMagnitude > 0f;
}
return TaskStatus.Running;
}
// Flee in the opposite direction
private Vector3 Target()
{
if (target == null || target.Value == null)
{
// Debug.LogError("Target is null, cannot flee.");
return transform.position.normalized * lookAheadDistance.Value; ; // 或者返回其他默认行为的位置
}
return transform.position + (transform.position - target.Value.transform.position).normalized * lookAheadDistance.Value;
}
private Vector3 Tareget2()
{
if (target == null || target.Value == null)
{
// Debug.LogError("Target is null, cannot flee.");
return transform.position; // 或者返回其他默认行为的位置
}
return transform.position - target.Value.transform.position;
}
// Return false if the position isn't valid on the NavMesh.
protected override bool SetDestination(Vector3 destination)
{
if (!SamplePosition(destination))
{
return false;
}
return base.SetDestination(destination);
}
// Reset the public variables
public override void OnReset()
{
base.OnReset();
fleedDistance = 20;
lookAheadDistance = 5;
target = null;
}
}
public class RigidBodyMove2Pos : Action
{
public SharedVector3 targetPos;
public SharedFloat speed;
private Rigidbody rigidbody;
private int loopCount;
// 在行为开始时调用
public override void OnStart()
{
rigidbody = transform.GetComponent<Rigidbody>();
}
// 每次行为更新时调用
public override TaskStatus OnUpdate()
{
if (rigidbody != null)
{
// 获取目标位置
Vector3 targetPosition = targetPos.Value;
// 计算物体到目标位置的距离向量
Vector3 direction = targetPosition - transform.position;
// 设置刚体的速度
rigidbody.velocity = direction.normalized * Time.deltaTime * 50f;
}
return TaskStatus.Running;
}
}
//是否是满血
public class IsPetMaxHealth : Conditional
{
public override void OnStart()
{
base.OnStart();
}
public override TaskStatus OnUpdate()
{
Pet pet = transform.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
if (pet.Health == pet.OriginHealth)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class IsTargetPetCantAtk : Conditional
{
public SharedGameObject target;
public override void OnStart()
{
base.OnStart();
}
public override TaskStatus OnUpdate()
{
if (target.Value == null) return TaskStatus.Failure;
Pet pet = target.Value.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
Enemy self = transform.GetComponent<Enemy>();
if (self == null) return TaskStatus.Failure;
Player player = MRNetworkManager.Ins.roomSlots[pet.teamId].transform.GetComponent<Player>();
if (player == null) return TaskStatus.Failure;
if (
pet.Health <= 0 ||
// !GameManager.Ins.CheckPointInArea(self.areaId, pet.transform.position) ||
player.InAreaId != self.areaId
)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
public class IsTargetBossCantAtk : Conditional
{
public SharedGameObject target;
public override void OnStart()
{
base.OnStart();
}
public override TaskStatus OnUpdate()
{
if (target.Value == null) return TaskStatus.Failure;
Pet pet = target.Value.GetComponent<Pet>();
if (pet == null) return TaskStatus.Failure;
EnemyBoss self = transform.GetComponent<EnemyBoss>();
if (self == null) return TaskStatus.Failure;
if (pet.state == PetState.Terminal)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
/// <summary>
/// 是否使用时间技能
/// </summary>
public class IsUserTimeSkill : Conditional
{
public override TaskStatus OnUpdate()
{
var enemy = GetComponent<Agent>();
if(enemy==null) return TaskStatus.Failure;
if(!enemy.isUserSkill) return TaskStatus.Failure;
int skillId=Random.Range(0, 2);
if (GetComponent<Pet>() != null && GetComponent<Pet>().id == 2)
{
skillId = 1;
}
if(!GameManager.Ins.SkillDataList.ContainsKey(enemy.skillList[skillId]))
return TaskStatus.Failure;
if (GameManager.Ins.SkillDataList[enemy.skillList[skillId]].SkillInterval > 1)
{
enemy.GetComponent<BehaviorTree>().SetVariable("skillId", (SharedInt)enemy.skillList[skillId]);
enemy.curWaitSkillTime = enemy.waitSkillTime;
enemy.isUserSkill = false;
return TaskStatus.Success;
}
return TaskStatus.Failure;
}
}
/// <summary>
/// 是否使用血量阈值技能
/// </summary>
public class IsUserHpSkill : Conditional
{
public override TaskStatus OnUpdate()
{
var enemy = GetComponent<Agent>();
if(enemy==null) return TaskStatus.Failure;
if(!enemy.isUserHpSkill) return TaskStatus.Failure;
foreach (var id in enemy.skillList)
{
if(!GameManager.Ins.SkillDataList.ContainsKey(id))
return TaskStatus.Failure;
if (GameManager.Ins.SkillDataList[id].SkillInterval <= 1)
{
enemy.GetComponent<BehaviorTree>().SetVariable("skillId", (SharedInt)id);
enemy.isUserHpSkill = false;
enemy.userHpSkillIndex++;
return TaskStatus.Success;
}
}
return TaskStatus.Failure;
}
}
public class RotateTowards : NavMeshMovement
{
public SharedFloat rotationEpsilon = 0.5f;
public SharedFloat maxLookAtRotationDelta = 1;
public SharedBool onlyY;
public SharedGameObject target;
public SharedVector3 targetRotation;
public override TaskStatus OnUpdate()
{
// 1. 计算只绕 Y 轴的目标四元数
Quaternion targetQ = ComputeYawOnlyTarget();
// 2. 检查是否到位
if (Quaternion.Angle(transform.rotation, targetQ) < rotationEpsilon.Value)
return TaskStatus.Success;
// 3. 旋转时考虑 deltaTime
float step = maxLookAtRotationDelta.Value * Time.deltaTime;
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetQ, step);
return TaskStatus.Running;
}
private Quaternion ComputeYawOnlyTarget()
{
// 动态目标
if (target != null && target.Value != null /* && targetId.Value != 0 如果需要再加 */)
{
Vector3 dir = target.Value.transform.position - transform.position;
if (onlyY.Value) dir.y = 0;
float yaw = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;
return Quaternion.Euler(0, yaw, 0);
}
// 静态角度
return Quaternion.Euler(targetRotation.Value);
}
// Reset the public variables
public override void OnReset()
{
rotationEpsilon = 0.5f;
maxLookAtRotationDelta = 1f;
onlyY = false;
target = null;
targetRotation = Vector3.zero;
}
}
/// <summary>
/// 敌人追击宠物超过开始点距离判断 如超过需返回巢穴
/// </summary>
public class ExceedSeekDis : Conditional
{
public SharedFloat seekDistance; // 最大允许追击距离
public SharedTransform enemyTransform; // 敌人自身的位置
public SharedTransform startPoint; // 敌人开始追击的起点
public override void OnStart()
{
// 你可以在这里缓存位置,如果需要
enemyTransform.Value = transform;
startPoint = transform.GetComponent<Enemy>().startPos;
seekDistance = 5f;
}
public override TaskStatus OnUpdate()
{
if (enemyTransform.Value == null || startPoint.Value == null)
{
Debug.LogWarning("Transform 未赋值!");
return TaskStatus.Failure;
}
float distance = Vector3.Distance(enemyTransform.Value.position, startPoint.Value.position);
if (distance > seekDistance.Value)
{
Debug.LogError("满足触发条件 开始返回老巢!");
// 超出范围,返回 True 表示满足条件
return TaskStatus.Success;
}
else
{
// 未超出范围,返回 False
return TaskStatus.Failure;
}
}
/// <summary>
/// 返回老巢(起始点)
/// - 进入后不停距离检查
/// - 如果被击中则中断返回
/// - 如果到达起始点则切到警戒状态
/// </summary>
public class ReturnToNest : Action
{
public SharedGameObject agentGameObject;
public SharedTransform nestPoint;
public SharedFloat reachThreshold;
public SharedBool isHit;
public SharedBool isAlert;
// 内部缓存
private NavMeshAgent _agent;
public override void OnStart()
{
// 缓存 NavMeshAgent 组件
if (agentGameObject.Value != null)
{
_agent = agentGameObject.Value.GetComponent<NavMeshAgent>();
}
}
public override TaskStatus OnUpdate()
{
// 如果没挂 NavMeshAgent 或者没指定巢穴点,直接失败
if (_agent == null || nestPoint.Value == null)
{
Debug.LogWarning("ReturnToNest: 缺少 NavMeshAgent 或 nestPoint");
return TaskStatus.Failure;
}
// 如果在返回过程中被击中,则中断,返回 Failure
if (isHit.Value)
{
_agent.ResetPath();
return TaskStatus.Failure;
}
// 设置目的地为巢穴
_agent.SetDestination(nestPoint.Value.position);
// 如果已经到达巢穴附近
if (!_agent.pathPending && _agent.remainingDistance <= reachThreshold.Value)
{
// 到巢穴了,触发警戒
isAlert.Value = true;
isHit.Value = false;
_agent.ResetPath();
return TaskStatus.Success;
}
// 还在路上,继续返回
return TaskStatus.Running;
}
public override void OnEnd()
{
// 清理路径(可选)
if (_agent != null && _agent.hasPath)
{
_agent.ResetPath();
}
}
}
}
}