1403 lines
41 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|