public static BTStatus SleepNearLeader(Animal agent) { var leader = GetLeader(agent); if (leader == null || leader == agent) { return(BTStatus.Failure); } if (leader.AnimationState == AnimalAnimationState.Sleeping) { // sleep near alpha if (Vector3.WrappedDistance(agent.Position, leader.Position) < agent.Species.HeadDistance * 3) { agent.SetState(AnimalAnimationState.LyingDown, 10f); agent.Hunger = Math.Min(agent.Hunger, 50); return(BTStatus.Success); } // TODO: avoid overlapping with other herd members, make the leader pick a spot to sleep that can accomidate the herd var route = AIUtilities.GetRouteFacingTarget(agent.Position, leader.Position, agent.Species.WanderingSpeed, agent.Species.HeadDistance * 2); agent.Target.SetPath(route); agent.NextTick = agent.Target.TargetTime; agent.AnimationState = AnimalAnimationState.Wander; return(BTStatus.Success); } return(BTStatus.Failure); }
void Update() { if (projectile != null && !LevelManager.instance.paused && sr.isVisible) { shootTimer += Time.deltaTime; if (shootTimer >= SHOOT_COOLDOWN) { // Find closest player and shoot at them. GameObject player = AIUtilities.getClosestPlayer(transform.position); // only shoot if player is approximately on our y-level if (Mathf.Abs(player.transform.position.y - transform.position.y) < 2f) { // shoot float direction = Mathf.Sign(player.transform.position.x - transform.position.x); GameObject newProjectile = LevelManager.instance.placeSpawnedObject((Vector2)gameObject.transform.position + new Vector2(direction, 0f), projectile, transform.parent); Rigidbody2D rb = newProjectile.GetComponent <Rigidbody2D>(); if (rb != null) { rb.velocity = new Vector2(projectileSpeed * direction, rb.velocity.y); } Vector3 scale = newProjectile.transform.localScale; scale.x = Mathf.Abs(scale.x) * direction; newProjectile.transform.localScale = scale; shootTimer = 0f; } } } }
public static IEnumerator <BTStatus> Hunt(Animal agent, Func <Animal, BTStatus> noNearbyFoodBehavior) { while (agent.Hunger > Brain.HungerSatiated) { var agentRegion = RouteRegions.GetRegion(agent.Position.WorldPosition3i); var nearPrey = NetObjectManager.GetObjectsWithin(agent.Position.XZ, agent.DetectionRange).OfType <Animal>() .Where(x => agent.ShouldFleeUs(x) && RouteRegions.GetRegion(x.Position.WorldPosition3i) == agentRegion) .OrderBy(x => Vector3.WrappedDistanceSq(x.Position, agent.Position) + (x.AnimationState == AnimalAnimationState.Sleeping ? -200 : 0)); foreach (var prey in nearPrey) { var i = 0; while (prey.Active) { Eco.Simulation.ExternalInputs.PredatorTracker.AddPredator(agent); var route = AIUtilities.GetRoute(agent.Position, prey.Position, prey.Alertness < 50 ? agent.Species.WanderingSpeed : agent.Species.Speed); agent.Target.SetPath(route); agent.Target.Set(prey); agent.NextTick = Math.Min(agent.Target.TargetTime, WorldTime.Seconds + 3); i++; yield return(BTStatus.Running); if (Vector3.WrappedDistance(agent.Position, prey.Position) < 2f || i > 4) { // making this look good will require a lot of work, for now just let it go agent.Hunger = 0; Eco.Simulation.ExternalInputs.PredatorTracker.RemovePredator(agent); yield break; } } } yield return(noNearbyFoodBehavior(agent)); } }
// Update is called once per frame void Update() { if (sr == null) { sr = GetComponent <SpriteRenderer>(); } if (!sr.isVisible) { return; } if (rb == null) { rb = GetComponent <Rigidbody2D>(); } // Find closest player and move toward it GameObject player = AIUtilities.getClosestPlayer(transform.position); if (player != null && rb != null) { float direction = Mathf.Sign(player.transform.position.x - transform.position.x); Vector2 position = transform.position; position.x += (direction * moveSpeed) * Time.deltaTime; transform.position = position; Vector3 scale = transform.localScale; scale.x = Mathf.Abs(scale.x) * -direction; transform.localScale = scale; } }
// Update is called once per frame void Update() { // If we dont have a target do nothing if (target == null) { return; } AIUtilities.LookAtTarget(transform, target.position, maxRotation); AIUtilities.ClampTurretRotation(transform, minRotationAngle, maxRotationAngle); float angleToPosition = AIUtilities.GetAngleToTarget(transform, target.position); if (Vector3.Distance(transform.position, target.position) < 600) { if (Mathf.Abs(angleToPosition) < 1) { if ((_shotCounter += Time.deltaTime) > fireRate) { _shotCounter = 0.0f; Shoot(); } } } }
private void Update() { if (Placed) { GameObject enemy = AIUtilities.GetNearestGameObject(VisionCheck, EnemyTag, Range); if (enemy != null) { Barrel.transform.LookAt(enemy.transform.position + Vector3.up); if (WaitTime <= 0) { GameObject shot = Instantiate(Projectile, Barrel.transform.position + Barrel.transform.forward, Barrel.transform.rotation); Projectile projectile = shot.GetComponent <Projectile>(); projectile.WeaponDamage = Damage; projectile.EnemyTag = EnemyTag; Rigidbody rb = shot.GetComponent <Rigidbody>(); rb.AddForce(Barrel.transform.forward * (ShotSpeed * 10)); rb.useGravity = false; WaitTime = Rate; } else { WaitTime -= Time.deltaTime; } } } }
// Update is called once per frame void Update() { if (_target == null) { GameObject target = targetArea.GetObstacle(); if (target) { _target = target.transform; } } else { AIUtilities.LookAtTarget(transform, _target.position, maxRotation); AIUtilities.ClampTurretRotation(transform, minRotationAngle, maxRotationAngle); float angleToPosition = AIUtilities.GetAngleToTarget(transform, _target.position); if (Mathf.Abs(angleToPosition) < 1) { if (coRunning == false) { StartCoroutine(coShoot()); } } } }
private void Update() { GameObject go = AIUtilities.GetNearestGameObject(gameObject, "Monster", Range, xray: true); target = go; if (target != null && Placed) { if (projectile.GetComponent <TowerProjectile>()) { projectile.GetComponent <TowerProjectile>().target = target; } else if (projectile.GetComponent <TowerRapidProjectile>()) { projectile.GetComponent <TowerRapidProjectile>().target = target; } //Debug.Log(target.name); AimBarrel(target); Fire(target); //Debug.Log((target.transform.position - rangeFinder.transform.position).magnitude); if (!CheckEnemyRange(target)) { target = null; } } }
bool CanPieceMove(int piece) { Vector2Int pieceLocation = AIUtilities.FindTargetLocation(piece); bool canMove = false; if (piece == 20 || piece == 21) { return(true); } else { for (int y = Mathf.Max(0, pieceLocation.y - 1); y <= Mathf.Min(7, pieceLocation.y + 1); y++) { for (int x = Mathf.Max(0, pieceLocation.x - 1); x <= Mathf.Min(7, pieceLocation.x + 1); x++) { if (!(x == pieceLocation.x && y == pieceLocation.y)) { ChessPiece p = Utilities.chessBoard[pieceLocation.x, pieceLocation.y].GetComponent <ChessPiece>(); if (p.IsMovePossible(x, y, Utilities.chessBoard[x, y])) { canMove = true; } } } } } return(canMove); }
public override void Act(StateController controller) { AIUtilities.AIMove = Vector2.zero; List <Vector2Int> possibleMoves = controller.bm.redSelectedPiece.PossibleMoves(); if (possibleMoves.Count == 0) { return; } Vector2Int bestMove = possibleMoves[0]; Vector2Int targetLocation = AIUtilities.FindTargetLocation(controller.shortTermTarget); foreach (Vector2Int move in possibleMoves) { if ((targetLocation - move).magnitude <= (targetLocation - bestMove).magnitude) { bestMove = move; } } Vector2 direction = bestMove - controller.bm.redSelection; direction.Normalize(); AIUtilities.AIMove = direction; }
public static BTStatus TryEatNearbyCorpses(Animal agent) { Animal targetCorpse = null; if (agent.TryGetMemory <Animal>("targetCorpse", out targetCorpse) && !targetCorpse.Active) { targetCorpse = null; agent.Brain.Memory.Remove("targetCorpse"); } if (targetCorpse == null) { foreach (var corpse in Animal.Corpses.Shuffle()) { if (!corpse.Active) { Animal.Corpses.Remove(corpse); } else if (Vector3.WrappedDistance(corpse.Position, agent.Position) < 40 && agent.Species.Eats(corpse.Species)) { targetCorpse = corpse; agent.Brain.Memory["targetCorpse"] = targetCorpse; break; } } } if (targetCorpse != null) { if (agent.AnimationState == AnimalAnimationState.Eating) { // finished eating, go do something else agent.Hunger = 0; agent.Brain.Memory.Remove("targetCorpse"); return(BTStatus.Failure); } // eat or walk then eat agent.AnimationState = AnimalAnimationState.Eating; if (Vector3.WrappedDistance(targetCorpse.Position, agent.Position) < 3) { agent.NextTick = WorldTime.Seconds + 10f; agent.Target.Set(targetCorpse); return(BTStatus.Success); } else { var route = AIUtilities.GetRouteFacingTarget(agent.Position, targetCorpse.Position, agent.Species.WanderingSpeed, agent.Species.HeadDistance); agent.Target.SetPath(route); agent.Target.Set(targetCorpse); agent.NextTick = agent.Target.TargetTime + 20f; return(BTStatus.Success); } } return(BTStatus.Failure); }
private void Update() { if (attack != null) { GameObject target = AIUtilities.GetNearestGameObject(spawner.gameObject, attack.Target, xray: true); if (target != null) { spawner.gameObject.transform.LookAt(target.transform); } } }
public static BTStatus Swim(Animal agent, Vector2 direction, float speed, AnimalAnimationState state, bool surface, int tries = 10) { var targetPos = AIUtilities.FindTargetSwimPosition(agent.Position, 5.0f, 20.0f, direction, 90, 360, tries, surface); if (targetPos == agent.Position) return BTStatus.Failure; agent.AnimationState = state; agent.Target.Set(agent.Position, targetPos, speed); agent.NextTick = agent.Target.TargetTime; return BTStatus.Success; }
public override bool Decide(StateController controller) { Vector2Int targetLocation = AIUtilities.FindTargetLocation(controller.shortTermPieceToControl); if (targetLocation == controller.bm.redSelection) { AIUtilities.AIPressed = false; return(true); } return(false); }
public override void Act(StateController controller) { AIUtilities.AIMove = new Vector2(0, 0); Vector2Int targetLocation = AIUtilities.FindTargetLocation(controller.shortTermPieceToControl); Vector2 move = targetLocation - controller.bm.redSelection; move.Normalize(); AIUtilities.AIPressed = true; AIUtilities.AIMove = move; }
void Update() { GameObject[] gameObjects = AIUtilities.GetGameObjects(gameObject, monster, range); if (gameObjects.Length > 0) { foreach (GameObject monster in gameObjects) { TravelNav tn = monster.GetComponent <TravelNav>(); Game.game.CoreHealth -= tn.Value; Destroy(monster); } } }
public static BTStatus LandMovement(Animal agent, Vector2 direction, float speed, AnimalAnimationState state, float minDistance = 2f, float maxDistance = 20f, float minDirectionOffsetDegrees = 0, float maxDirectionOffsetDegrees = 360, int tryCount = 10) { var search = AIUtilities.FindRoute(agent.Position, 2f, 20f, direction); if (search != null) { var smoothed = search.LineOfSightSmooth(agent.Position); PiecewiseLinearFunction route = AIUtilities.ProjectRoute(smoothed, speed); agent.NextTick = WorldTime.Seconds + route.EndTime; agent.Target.SetPath(route); agent.AnimationState = state; return BTStatus.Success; } else return LandAnimalUnStuckOrDie(agent, speed, state); }
public static BTStatus AmphibiousMovement(Animal agent, Vector2 generalDirection, float speed, AnimalAnimationState state, float minDistance = 2f, float maxDistance = 20f) { var start = agent.Position.WorldPosition3i; if (!World.World.IsUnderwater(start)) start = RouteManager.NearestWalkableY(agent.Position.WorldPosition3i); if (!start.IsValid) return LandMovement(agent, generalDirection, speed, state, minDistance, maxDistance); if (generalDirection == Vector2.zero) generalDirection = Vector2.right.Rotate(RandomUtil.Range(0f, 360)); else generalDirection = generalDirection.Normalized; var target = (agent.Position + (generalDirection * RandomUtil.Range(minDistance, maxDistance)).X_Z()).WorldPosition3i; if (World.World.IsUnderwater(target)) target.y = World.World.MaxWaterHeight[target]; else target = RouteManager.NearestWalkableXYZ(target, 5); // This is a low-effort search that includes water surface and should occasionally fail, just pick a semi-random node that was visited when it fails var allowWaterSearch = new AStarSearch(RouteCacheData.NeighborsIncludeWater, start, target, 30); if (allowWaterSearch.Status != SearchStatus.PathFound) { target = allowWaterSearch.Nodes.Last().Key; allowWaterSearch.GetPath(target); } if (allowWaterSearch.Path.Count < 2) return BTStatus.Failure; else if (allowWaterSearch.Status == SearchStatus.Unpathable && allowWaterSearch.Nodes.Count < RouteRegions.MinimumRegionSize && !World.World.IsUnderwater(agent.Position.WorldPosition3i)) { // Search region was unexpectedly small and agent is on land, might be trapped by player construction. // Try regular land movement so region checks can apply & the agent can get unstuck (or die) return LandMovement(agent, generalDirection, speed, state, minDistance, maxDistance); } var smoothed = allowWaterSearch.LineOfSightSmooth(agent.Position); PiecewiseLinearFunction route = AIUtilities.ProjectRoute(smoothed, speed); agent.AnimationState = state; agent.NextTick = WorldTime.Seconds + route.EndTime; agent.Target.SetPath(route); return BTStatus.Success; }
void Update() { if (ResetTime <= 0) { GameObject enemy = AIUtilities.GetNearestGameObject(gameObject, EnemyTag, TriggerRange, xray: true); if (enemy != null) { ResetTime = Rate; Particles.Play(); GameObject[] monsters = AIUtilities.GetGameObjects(gameObject, EnemyTag, Range); monsters.ToList().ForEach(m => m.GetComponent <Damagable>().ApplyDamage(Damage)); } } else { ResetTime -= Time.deltaTime; } }
private void Update() { GameObject go = AIUtilities.GetNearestGameObject(gameObject, attack.Target, 0, attack.Nc.Fov, attack.Nc.SeeThroughWalls); if (go != null && !hit) { hit = true; Damagable health = go.GetComponent <Damagable>(); if (health != null) { health.ApplyDamage(Damage); } if (DestroyOnHit) { Destroy(gameObject); } } }
void Update() { bool hasLOSToPlayer = AIUtilities.HasLineOfSight(transform.position, player.transform.position, player); if (hasLOSToPlayer) { lastKnownPlayerLocation = player.transform.position; lastKnownVisual.transform.position = lastKnownPlayerLocation; } var aimPos = lastKnownPlayerLocation; aimPos.y = 0; aiming.LookAt(aimPos); if (!hasLOSToPlayer) { confidence += confidenceRegen * Time.deltaTime; } // DEBUG INPUTS if (Input.GetKeyDown(KeyCode.Alpha1)) { AffectConfidence(100f); movement.StopMoving(); } if (Input.GetKeyDown(KeyCode.Alpha2)) { AffectConfidence(-100f); movement.StopMoving(); } Vector3 moveToPoint = Vector3.down; // Getting in cover if (confidence < 50f) { if (hasLOSToPlayer /*&& lastPlayerPos != player.transform.position*/) { moveToPoint = AIUtilities.GetClosestLOSPoint(this, transform.position, player.transform.position, false, player); } // Attacking player } else { if (hasLOSToPlayer) { shooting.Shoot(transform.forward); } else { if (AIUtilities.HasLineOfSight(transform.position, lastKnownPlayerLocation)) { print("has los"); moveToPoint = lastKnownPlayerLocation; } else { print("no los"); moveToPoint = AIUtilities.GetClosestLOSPoint(this, transform.position, lastKnownPlayerLocation, true); } } } if (moveToPoint != Vector3.down && moveToPoint != lastMoveToPoint) { print("<color=red>Moving</color>"); movement.MoveToPoint(moveToPoint); moveToVisual.transform.position = moveToPoint; lastMoveToPoint = moveToPoint; movingToNode = Grid.GetNodeWorldPoint(moveToPoint); } }
// Start is called before the first frame update private void Start() { Waypoints = AIUtilities.GenerateWaypoints(transform.position, 1000, 25); }
void FindShortTermTarget(int longTermTarget) { Vector2Int longTermTargetLocation = AIUtilities.FindTargetLocation(longTermTarget); bool targetFound = false; if (longTermTargetLocation.x < 0 || longTermTargetLocation.y < 0) { // target not found on board } for (int distance = 1; distance < 6; distance++) { for (int y = Mathf.Max(0, longTermTargetLocation.y - distance); y <= Mathf.Min(7, longTermTargetLocation.y + distance); y++) { for (int x = Mathf.Max(0, longTermTargetLocation.x - distance); x <= Mathf.Min(7, longTermTargetLocation.x + distance); x++) { if (Mathf.Abs(longTermTargetLocation.x - x) == distance || Mathf.Abs(longTermTargetLocation.y - y) == distance) { if (Utilities.chessBoard[x, y] == null) { openingTarget = new Vector2Int(x, y); Vector2Int checkShortTerm = Vector2Int.zero; if (openingTarget.x > longTermTargetLocation.x) { checkShortTerm.x = -1; } else if (openingTarget.x < longTermTargetLocation.x) { checkShortTerm.x = 1; } else { checkShortTerm.x = 0; } if (openingTarget.y > longTermTargetLocation.y) { checkShortTerm.y = -1; } else if (openingTarget.y < longTermTargetLocation.y) { checkShortTerm.y = 1; } else { checkShortTerm.y = 0; } shortTermTarget = Utilities.chessBoard[openingTarget.x + checkShortTerm.x, openingTarget.y + checkShortTerm.y] .GetComponent <ChessPiece>().id; targetFound = true; } } } } if (targetFound) { break; } } if (!targetFound) { shortTermTarget = longTermTarget; } }
void Update() { if (m_navAgent.isOnNavMesh) { var player = AIUtilities.GetNearestGameObject(gameObject, target, range, fov, SeeThroughWalls); //Debug.Log($"Player: {player}"); if (player != null) { Attacking = ((transform.position - player.transform.position).magnitude <= attackRange && AttackTime <= 0); //Debug.Log($"Attacking: {Attacking}"); if (Attacking) { transform.LookAt(player.transform); if (animator != null) { animator.SetTrigger("Attack"); } AttackTime = attackCD; m_navAgent.isStopped = true; } else if ((transform.position - player.transform.position).magnitude <= attackRange) { m_navAgent.isStopped = true; } else { m_navAgent.SetDestination(player.transform.position); m_navAgent.isStopped = false; } } else if (MoveTime <= 0) { if (m_navAgent.isStopped && m_navAgent != null && m_navAgent.isOnNavMesh) { m_navAgent.isStopped = false; } //Debug.Log("Moving"); if (animator != null) { animator.SetTrigger("StopAttack"); } MoveTime = MoveCd; Vector3 target = Vector3.up; if (m_x && m_z) { target = new Vector3(gameObject.transform.position.x + Random.Range(-searchDistance, searchDistance + 1), 0, gameObject.transform.position.z + Random.Range(-searchDistance, searchDistance + 1)); } else if (!m_x && m_z) { target = new Vector3(transform.position.x, 0, gameObject.transform.position.z + Random.Range(-searchDistance, searchDistance + 1)); } else if (m_x && !m_z) { target = new Vector3(gameObject.transform.position.x + Random.Range(-searchDistance, searchDistance + 1), 0, transform.position.z); } if (target != null && m_navAgent != null && m_navAgent.isOnNavMesh) { m_navAgent.SetDestination(target); if (m_weapon != null && !m_weapon.gameObject.activeSelf) { m_weapon.SetActive(true); } } } if (MoveTime > 0 && m_navAgent.destination == transform.position) { MoveTime -= Time.deltaTime; } if (AttackTime > 0) { AttackTime -= Time.deltaTime; } if (animator != null) { animator.SetFloat("Speed", m_navAgent.velocity.magnitude); } } }
public static IEnumerator <BTStatus> FoodFinder(Animal agent, Func <Animal, BTStatus> noNearbyFoodBehavior, float hungerRestored) { var lastPos = Vector3.Zero; Queue <Vector3> foodSources = new Queue <Vector3>(); while (agent.Hunger > Brain.HungerSatiated) { foodSources.Clear(); while (foodSources.Count == 0) { if (Vector3.WrappedDistanceSq(lastPos, agent.Position) > 100) { var agentRegion = RouteRegions.GetRegion(agent.Position.WorldPosition3i); foodSources.AddRange(EcoSim.PlantSim.PlantsWithinRange(agent.Position, 10, plant => agent.Species.Eats(plant.Species) && RouteRegions.GetRegion(plant.Position.WorldPosition3i.Down()) == agentRegion).Shuffle().Select(plant => plant.Position + Vector3.Down)); lastPos = agent.Position; } else { yield return(noNearbyFoodBehavior(agent)); } } while (foodSources.Count > 0 && agent.Hunger > Brain.HungerSatiated && Vector3.WrappedDistanceSq(lastPos, agent.Position) < 100) { // low-effort search for the first option or any other option visited while trying to hit the first Vector3 targetPlantPosition; PiecewiseLinearFunction route = AIUtilities.GetRouteToAny(agent.Position, foodSources, agent.Species.WanderingSpeed, out targetPlantPosition, 100, 20, agent.Species.HeadDistance); if (route == null) { break; } agent.Target.SetPath(route); agent.Target.LookPos = targetPlantPosition; agent.AnimationState = AnimalAnimationState.LookingForFood; var target = route.EndPosition; // just in case something interrupts the path while (agent.Target.TargetTime > WorldTime.Seconds && agent.Target.TargetPosition == target) { agent.NextTick = agent.Target.TargetTime; yield return(BTStatus.Running); } if (Vector3.WrappedDistanceSq(target, agent.Position) < 4) { agent.AnimationState = AnimalAnimationState.Eating; agent.NextTick = WorldTime.Seconds + 10; agent.Hunger -= hungerRestored; agent.Target.LookPos = targetPlantPosition; yield return(BTStatus.Running); } // something interrupted eating, probably need to find new food if (agent.Target.TargetPosition != target) { break; } } } }
public void Die() { AIUtilities.EnemyDied(this); }