/// <summary> /// Scan the environment for entities, then process tracked entities /// </summary> public void CheckEnv(Npc a, BhvTree b) { if (a.TrackDict != null) { ProcessTrackDict(a, b); } }
public BhvStatus Invoke(Npc a, BhvTree b) { if (ChildHandle == null) { return(BhvStatus.FAILURE); } return(DecorateResult(ChildHandle.Invoke(a, b))); }
public override BhvStatus Invoke(Npc a, BhvTree b) { SetAnimTrigger(a, "Idle"); Debug.Log($"Npc {a.gameObject.name} has invoked an empty behavior branch"); b.SetStatus(BhvStatus.SUCCESS); return(b.Status); }
public override BhvStatus Invoke(Npc a, BhvTree b) { if (a.NavAgent.hasPath || a.MovePos != Vector3.zero) { StopMove(a); } if (a.TargetObj != null) { a.SetTargetObj(null); } if (!a.Stats.IsDead) { SetAnimBool(a, "isDead", false); b.SetStatus(BhvStatus.FAILURE); return(b.Status); } SetAnimBool(a, "isDead", true); return(b.Status); }
public override BhvStatus Invoke(Npc a, BhvTree b) { if (a.NavAgent.hasPath) { StopMove(a); } if (a.Stats.IsDead) { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (!a.Stats.IsAsleep) { SetAnimBool(a, "isAsleep", false); b.SetStatus(BhvStatus.FAILURE); return(b.Status); } SetAnimBool(a, "isAsleep", true); return(b.Status); }
public override BhvStatus Invoke(Npc a, BhvTree b) { if (a.TargetObj == null) { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (a.Stats.Wounded) { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (a.TargetEnt?.Stats.IsDead ?? false) { // We don't reset the move here because we still want to investigate what we were hunting a.ResetTargetObj(); b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } if (!b.SeeTarget) { // Set MovePos to last known TargetPos a.SetMovePos(a.TargetPos); a.ResetTargetObj(); b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (b.DistTarget > Util.GetSquare(a.Params.AwareMax)) { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (b.DistTarget <= Util.GetSquare(a.Params.AwareClose)) { a.PlaySound(SndT.HUNT); StopMove(a); b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } if (a.NavAgent.pathStatus == NavMeshPathStatus.PathPartial || a.NavAgent.pathStatus == NavMeshPathStatus.PathInvalid) { bool failure = false; if (a.NavAgent.pathStatus == NavMeshPathStatus.PathInvalid) { failure = true; } if (a.NavAgent.pathStatus == NavMeshPathStatus.PathPartial) { if (Util.CheckDistSqr(a.NavAgent.destination, a.TargetPos) > Util.GetSquare(a.Params.AtkDist)) { failure = true; } } if (failure) { StopMove(a); b.SetPathFailed(true); b.SetStatus(BhvStatus.FAILURE); return(b.Status); } } if (a.MovePos == Vector3.zero) { a.SetMovePos(a.TargetPos); } if (a.NavAgent.hasPath) { // Sometimes the calculated destination on the nav mesh isn't exactly where we wanted to move if (a.MovePos != a.NavAgent.destination) { a.SetMovePos(a.NavAgent.destination); } } float nSpd = a.Params.MoveSpd * a.Params.MoveWalk; // Set Speed accordingly if (a.NavAgent.speed != nSpd) { SetSpeed(a, nSpd); } if (!b.AnimInfo.IsName(AnimString.WALK)) { a.PlaySound(SndT.HUNT); SetAnimTrigger(a, AnimString.WALK); } if (b.TimerCheck >= a.Params.ChkAlert) { if (a.TargetPos != a.MovePos) { a.SetMovePos(a.TargetPos); } b.TimerCheck = 0.0f; CheckEnv(a, b); } if (a.NavAgent.destination != a.MovePos) { StartMove(a, a.MovePos); } return(b.Status); }
/// <summary> /// Process the entities in the TrackDict, finds closest and removes ents that are beyond MAX_DIST or dead /// </summary> public void ProcessTrackDict(Npc a, BhvTree b) { if (a.TrackDict != null && a.TrackDict.Count > 0) { float closestEntDistSqr = 0.0f; LiveEntity closestEnt = null; bool fresh = true; foreach (ulong id in a.TrackDict.Keys) { LiveEntity ent; a.TrackDict.TryGetValue(id, out ent); // If the entity dies and is cleaned up before the trackBook is processed, it will be null if (ent == null) { a.RemoveList.Add(id); continue; } // Check if the entity is invisible if (ent.Stats.Invisible) { continue; } // Check if the entity is dead if (ent.Stats.IsDead) { // If the entity is dead and the same type as this one, set behavior to aggro or hunt or something continue; } if (ent is Npc npc) { // Check if we want to make a squad with other entities of the same type // // // If we're prey if (!a.Params.Predator) { // Prey should ignore other prey if (!npc.Params.Predator) { continue; } } } float maxDist = a.Params.AwareMax; float entDist = Util.CheckDistSqr(a.transform.position, ent.transform.position); // Check if it's beyond our max awareness distance if (entDist > Util.GetSquare(maxDist)) { a.RemoveList.Add(id); continue; } // Field-of-view and Line-of-sight check if (!a.SightCheck(ent.gameObject, Util.GetSquare(maxDist))) { continue; } // If we haven't set our closest entity info yet if (fresh) { closestEntDistSqr = entDist; closestEnt = ent; fresh = false; } else { if (entDist < closestEntDistSqr) { closestEntDistSqr = maxDist; closestEnt = ent; } } } if (closestEnt != null) { // If we don't currently have a target if (a.TargetObj == null) { a.SetTargetObj(closestEnt.gameObject, closestEnt); } else { if (a.TargetObj != closestEnt.gameObject && closestEntDistSqr < (a.TargetDistSqr * a.Params.ProxPct)) { a.SetTargetObj(closestEnt.gameObject, closestEnt); } } } } else { // There's no entities within range, so reset our target if (a.TargetObj != null) { a.ResetTargetObj(); } } if (a.RemoveList != null && a.RemoveList.Count > 0) { for (int i = 0; i < a.RemoveList.Count; i++) { LiveEntity ent = null; a.TrackDict.TryGetValue(a.RemoveList[i], out ent); Untrack(a, a.RemoveList[i]); } a.RemoveList.Clear(); } }
public virtual BhvStatus Invoke(Npc a, BhvTree b) { return(b.Status); // Override in derived state }
public override BhvStatus Invoke(Npc a, BhvTree b) { if (a.TargetObj == null) { b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } if (a.Stats.Wounded) { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (b.DistTarget <= Util.GetSquare(a.Params.AwareClose)) { if (a.Params.Flighty) { a.PlaySound(SndT.ALERT); // Too close, should flee b.SetStatus(BhvStatus.FAILURE); return(b.Status); } } // Set Speed accordingly SetSpeed(a, a.Params.MoveSpd * a.Params.MoveWalk); float waryDist = ((a.Params.AwareMax - a.Params.AwareMed) / 2.0f) + a.Params.AwareMed; if (b.DistTarget <= Util.GetSquare(waryDist) && a.MovePos == Vector3.zero) { Vector3 nPos = FindFleePoint(a); if (nPos == Vector3.zero) { // Debug.Log( "Unable to find flee point" ); if (!b.AnimInfo.IsName(AnimString.IDLE)) { SetAnimTrigger(a, AnimString.IDLE); } return(BhvStatus.RUNNING); } // Debug.LogError( $"WaryFlee: {a.name} to position {nPos}" ); // Debug.Log( "Found flee point" ); b.TimerAct = 0.0f; a.SetMovePos(nPos); } if (b.TimerCheck >= a.Params.ChkAlert) { b.TimerCheck = 0.0f; CheckEnv(a, b); } if (a.NavAgent.pathPending) { return(BhvStatus.RUNNING); } if (!a.NavAgent.hasPath && a.MovePos != Vector3.zero) { StartMove(a, a.MovePos); } else { if (a.MovePos != a.NavAgent.destination) { a.SetMovePos(a.NavAgent.destination); } } if (a.MovePos != Vector3.zero) { if (a.NavAgent.hasPath) { if (!b.AnimInfo.IsName(AnimString.WALK)) { SetAnimTrigger(a, AnimString.WALK); } } else { if (a.NavAgent.velocity == Vector3.zero) { a.SetMovePos(Vector3.zero); } if (!b.AnimInfo.IsName(AnimString.IDLE)) { SetAnimTrigger(a, AnimString.IDLE); } } } if (b.DistMove <= Util.GetSquare(a.Params.StopDist + a.NavAgent.radius) && a.NavAgent.hasPath) { if (a.TargetDistSqr > Util.GetSquare(a.Params.AwareMax + 10.0f)) { a.PlaySound(SndT.ALERT); StopMove(a); // Debug.Log( "Safe distance from target, flight over" ); a.ResetTargetObj(); b.SetPathFailed(false); b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } else { StopMove(a); // Debug.Log( "Resetting move for recalculation" ); } } return(b.Status); }
public override BhvStatus Invoke(Npc a, BhvTree b) { if (a.TargetObj == null) { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (a.TargetEnt?.Stats.IsDead ?? false) { StopMove(a); a.ResetTargetObj(); b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } if (b.DistTarget > Util.GetSquare(a.Params.AtkDist)) { if (b.AnimInfo.IsName(AnimString.ATK)) { ResetAnimTrigger(a, AnimString.ATK); } StopMove(a); b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (a.NavAgent.pathStatus == NavMeshPathStatus.PathPartial || a.NavAgent.pathStatus == NavMeshPathStatus.PathInvalid) { StopMove(a); b.SetPathFailed(true); b.SetStatus(BhvStatus.FAILURE); return(b.Status); } GetFlatVectors(a, out Vector3 targetPos, out Vector3 thisPos, out Vector3 fwd); float angle = Vector3.Angle(fwd, (targetPos - thisPos)); if (angle > a.Params.RotAngle) { TurnToward(a, targetPos); } a.SetMovePos(a.TargetPos); float nSpd = a.Params.MoveSpd; if (b.AnimInfo.IsName(AnimString.ATK)) { nSpd *= a.Params.AtkSlow; } // Set Speed accordingly if (a.NavAgent.speed != nSpd) { SetSpeed(a, nSpd); } if (b.ActionReady) { if (b.TimerAct >= a.Params.AtkInit) { if (a.TargetEnt != null) { if (b.ActionReady) { a.PlaySound(SndT.ATK); if (!HubrisCore.Instance.TrySendDmg(a.TargetObj, a.TargetEnt, (int)a.Params.DamageStats.CommonType, a.Params.DamageStats.CommonAmount, false)) { Debug.LogWarning($"{a.name} could not send damage to {a.TargetObj.name}"); } } } b.SetActionReady(false); SetAnimTrigger(a, AnimString.ATK); } } else // ActionReady is false { if (a.NavAgent.velocity != Vector3.zero) { if (!b.AnimInfo.IsName(AnimString.WALK)) { SetAnimTrigger(a, AnimString.WALK); } } else { if (!b.AnimInfo.IsName(AnimString.IDLE)) { SetAnimTrigger(a, AnimString.IDLE); } } if (b.TimerAct >= a.Params.AtkEnd) { b.SetActionReady(true); b.TimerAct = 0.0f; } } if (b.TimerCheck >= a.Params.ChkAlert) { b.TimerCheck = 0.0f; CheckEnv(a, b); } if (a.NavAgent.destination != a.MovePos) { StartMove(a, a.MovePos); } b.SetPrevPos(a.transform.position); return(b.Status); }
public override BhvStatus Invoke(Npc a, BhvTree b) { if (a.TargetObj == null) { b.SetStatus(BhvStatus.FAILURE); b.SetPatient(true); return(b.Status); } if (a.Stats.Wounded) { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (!b.SeeTarget && b.DistTarget > Util.GetSquare(a.Params.AwareMed)) { // Debug.Log( "SightCheck failed" ); a.ResetTargetObj(); b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (b.DistTarget <= Util.GetSquare(a.Params.AwareMed)) { if (a.Params.Predator) { b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } else { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } } if (b.TimerAct >= a.Params.PatienceTime) { b.TimerAct = 0.0f; if (UnityEngine.Random.Range(1, 20) >= 10) { b.SetPatient(false); a.PlaySound(SndT.ALERT); b.SetStatus(a.Params.Predator ? BhvStatus.SUCCESS : BhvStatus.FAILURE); return(b.Status); } } if (b.TimerCheck >= a.Params.ChkAlert) { b.TimerCheck = 0.0f; CheckEnv(a, b); } if (a.NavAgent.hasPath) { a.NavAgent.ResetPath(); } GetFlatVectors(a, out Vector3 targetPos, out Vector3 thisPos, out Vector3 fwd); float angle = Vector3.Angle(fwd, (targetPos - thisPos)); if (angle > a.Params.RotAngle) { // Reverse walk anim to differentiate from regular walking if (!b.AnimInfo.IsName(AnimString.WALKBACK)) { SetAnimTrigger(a, AnimString.WALKBACK); } TurnToward(a, targetPos); } else { if (!b.AnimInfo.IsName(AnimString.IDLE)) { SetAnimTrigger(a, AnimString.IDLE); } } return(b.Status); }
public override BhvStatus Invoke(Npc a, BhvTree b) { if (a.TargetObj != null && b.SeeTarget) { a.PlaySound(SndT.ALERT); b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (a.Stats.Wounded) { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (a.MovePos != Vector3.zero) { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } float nSpd = a.Params.MoveSpd * a.Params.MoveWalk; // Set Speed accordingly if (a.NavAgent.speed != nSpd) { SetSpeed(a, nSpd); } if (b.TimerAct >= a.Params.RoamTime) { b.TimerAct = 0.0f; // if (Random.Range(1, 20) > 10) // RpcTriggerSound(Apex.SndT.IDLE, Random.Range(0.0f, Apex.SND_MAX_DELAY)); if (a.Params.Roam) { bool doRoam = false; // Debug.Log( "Checking if " + a.Name + " should roam..." ); if (a.TargetPos == Vector3.zero) { if (UnityEngine.Random.Range(1, 20) > 10) { // Debug.Log( a.Name + " is attempting to roam" ); a.PlaySound(SndT.IDLE); Vector3 nPos = FindRoamPoint(a); if (nPos != Vector3.zero) { a.SetMovePos(nPos); doRoam = true; } } } else // We have something that's piqued our interest { a.SetMovePos(a.TargetPos); a.SetTargetPos(Vector3.zero); doRoam = true; } if (doRoam) { // Debug.Log( a.Name + " is roaming" ); b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } } } GetFlatVectors(a, out Vector3 thisPos, out Vector3 fwd); if (a.TargetPos != Vector3.zero) { float angle = Vector3.Angle(fwd, (a.TargetPos - thisPos)); if (angle > a.Params.RotAngle) { // Reverse walk anim to differentiate from regular walking if (!b.AnimInfo.IsName(AnimString.WALKBACK)) { SetAnimTrigger(a, AnimString.WALKBACK); } TurnToward(a, a.TargetPos); } else { if (!b.AnimInfo.IsName(AnimString.IDLE)) { SetAnimTrigger(a, AnimString.IDLE); } } } else { if (!b.AnimInfo.IsName(AnimString.IDLE)) { SetAnimTrigger(a, AnimString.IDLE); } } if (b.TimerCheck >= a.Params.ChkIdle) { b.TimerCheck = 0.0f; CheckEnv(a, b); } return(b.Status); }
public override BhvStatus Invoke(Npc a, BhvTree b) { if (a.TargetObj == null) { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (a.TargetEnt?.Stats.IsDead ?? false) { StopMove(a); a.ResetTargetObj(); b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } if (b.DistTarget <= Util.GetSquare(a.Params.AtkDist)) { b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } if (a.NavAgent.pathStatus == NavMeshPathStatus.PathPartial || a.NavAgent.pathStatus == NavMeshPathStatus.PathInvalid) { bool failure = false; if (a.NavAgent.pathStatus == NavMeshPathStatus.PathInvalid) { failure = true; } if (a.NavAgent.pathStatus == NavMeshPathStatus.PathPartial) { if (Util.CheckDistSqr(a.NavAgent.destination, a.TargetPos) > Util.GetSquare(a.Params.AtkDist)) { failure = true; } } if (failure) { StopMove(a); b.SetPathFailed(true); b.SetStatus(BhvStatus.FAILURE); return(b.Status); } } a.SetMovePos(a.TargetPos); float nSpd = a.Params.MoveSpd; if (b.AnimInfo.IsName(AnimString.ATK)) { nSpd *= a.Params.AtkSlow; } else { if (!b.AnimInfo.IsName(AnimString.RUN)) { SetAnimTrigger(a, AnimString.RUN); } } // Set Speed accordingly if (a.NavAgent.speed != nSpd) { SetSpeed(a, nSpd); } if (b.TimerCheck >= a.Params.ChkAlert) { if (a.TargetPos != a.MovePos) { a.SetMovePos(a.TargetPos); } b.TimerCheck = 0.0f; CheckEnv(a, b); } if (a.NavAgent.destination != a.MovePos) { StartMove(a, a.MovePos); } return(b.Status); }
public override BhvStatus Invoke(Npc a, BhvTree b) { if (a.MovePos == Vector3.zero) { b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (a.TargetObj != null && b.SeeTarget) { StopMove(a); b.SetStatus(BhvStatus.FAILURE); return(b.Status); } if (a.TargetObj == null && a.NavAgent.hasPath) { // Sometimes the calculated destination on the nav mesh isn't exactly where we wanted to move if (a.MovePos != a.NavAgent.destination) { a.SetMovePos(a.NavAgent.destination); } // Something caught our attention midmove if (a.TargetPos != Vector3.zero) { // Debug.Log( "Something caught our attention midmove" ); StopMove(a); b.SetStatus(BhvStatus.FAILURE); return(b.Status); } } float moveDist = a.MoveDistSqr; // Need to include NavAgent.radius or else the Npc won't ever reach the MovePos if (moveDist <= Util.GetSquare(a.Params.StopDist + a.NavAgent.radius)) { StopMove(a); b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } float nSpd = a.Params.MoveSpd * a.Params.MoveWalk; // Set Speed accordingly if (a.NavAgent.speed != nSpd) { SetSpeed(a, nSpd); } if (!b.AnimInfo.IsName(AnimString.WALK)) { SetAnimTrigger(a, AnimString.WALK); } if (b.TimerCheck >= a.Params.ChkIdle) { b.TimerCheck = 0.0f; CheckEnv(a, b); } if (a.NavAgent.destination != a.MovePos) { StartMove(a, a.MovePos); } return(b.Status); }
public override BhvStatus Invoke(Npc a, BhvTree b) { if (a.TargetObj == null) { b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } if (a.TargetEnt?.Stats.IsDead ?? false) { StopMove(a); a.ResetTargetObj(); b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } if (!b.PathFailed && b.TimerCheck >= a.Params.ChkAlert) { b.TimerCheck = 0.0f; CheckEnv(a, b); } // Set Speed accordingly if (a.NavAgent.speed != a.Params.MoveSpd) { SetSpeed(a, a.Params.MoveSpd); } if (a.MovePos == Vector3.zero) { Vector3 nPos = FindFleePoint(a); if (nPos == Vector3.zero) { // Debug.Log( "Unable to find flee point" ); if (!b.AnimInfo.IsName(AnimString.IDLE)) { SetAnimTrigger(a, AnimString.IDLE); } return(BhvStatus.RUNNING); } // Debug.Log( "Found flee point" ); a.SetMovePos(nPos); } if (a.NavAgent.pathPending) { return(BhvStatus.RUNNING); } if (!a.NavAgent.hasPath) { StartMove(a, a.MovePos); } else { if (!b.AnimInfo.IsName(AnimString.RUN)) { SetAnimTrigger(a, AnimString.RUN); } if (a.MovePos != a.NavAgent.destination) { a.SetMovePos(a.NavAgent.destination); } // TurnToward( a, a.NavAgent.steeringTarget ); } // Need to include NavAgent.radius or else the Npc won't ever reach the MovePos if (b.DistMove <= Util.GetSquare(a.Params.StopDist + a.NavAgent.radius) && a.NavAgent.hasPath) { if ((a.TargetDistSqr > Util.GetSquare(a.Params.AwareMax + 10.0f))) { StopMove(a); // Debug.Log( "Safe distance from target, flight over" ); a.ResetTargetObj(); b.SetPathFailed(false); b.SetStatus(BhvStatus.SUCCESS); return(b.Status); } else { StopMove(a); // Debug.Log( "Resetting move for recalculation" ); } } return(b.Status); }