/// <summary> /// TargetCoords is used when a ship has been hit and it will try and destroy /// this ship /// </summary> /// <param name="row">row generated around the hit tile</param> /// <param name="column">column generated around the hit tile</param> private void TargetCoords(ref int row, ref int column) { Location l = _Targets.Pop(); if ((_Targets.Count == 0)) _CurrentState = AIStates.Searching; row = l.Row; column = l.Column; }
/// <summary> /// ProcessShot will be called uppon when a ship is found. /// It will create a stack with targets it will try to hit. These targets /// will be around the tile that has been hit. /// </summary> /// <param name="row">the row it needs to process</param> /// <param name="col">the column it needs to process</param> /// <param name="result">the result og the last shot (should be hit)</param> protected override void ProcessShot(int row, int col, AttackResult result) { if (result.Value == ResultOfAttack.Hit) { _CurrentState = AIStates.Searching; } else if (result.Value == ResultOfAttack.ShotAlready) { throw new ApplicationException("Error in AI"); } }
public override AIStates OnGetHit( Mobile by, AIStates AIState, int dmg ) { if ( AIState != AIStates.Attack && AIState != AIStates.Fighting ) { OnBeginFight( by ); return AIStates.BeingAttacked; } return AIState; }
/// <summary> /// ProcessShot will be called uppon when a ship is found. /// It will create a stack with targets it will try to hit. These targets /// will be around the tile that has been hit. /// </summary> /// <param name="row">the row it needs to process</param> /// <param name="col">the column it needs to process</param> /// <param name="result">the result og the last shot (should be hit)</param> protected override void ProcessShot(int row, int col, AttackResult result) { if (result.Value == ResultOfAttack.Hit) { _CurrentState = AIStates.TargetingShip; AddTarget(row - 1, col); AddTarget(row, col - 1); AddTarget(row + 1, col); AddTarget(row, col + 1); } else if (result.Value == ResultOfAttack.ShotAlready) { throw new ApplicationException("Error in AI"); } }
public override AIStates OnGetHit( Mobile by, AIStates AIState, int dmg ) { if ( AIState != AIStates.Attack && AIState != AIStates.Fighting ) { OnBeginFight( by ); if ( by == From ) From.AttackTarget = From.LastOffender; else From.AttackTarget = by; return AIStates.BeingAttacked; } return AIState; }
/// <summary> /// ProcessShot will be called uppon when a ship is found. /// It will create a stack with targets it will try to hit. These targets /// will be randomly assigned. /// </summary> /// <param name="row">the row it needs to process</param> /// <param name="rowOld">the row it contained before hit</param> /// <param name="col">the column it needs to process</param> /// <param name="colOld">the column it contained before hit</param> /// <param name="result">the result of the last shot (should be hit)</param> protected override void ProcessShot(int row, int col, AttackResult result) { if (result.Value == ResultOfAttack.Hit) { _CurrentState = AIStates.Searching; int rowOld = row; int colOld = col; SearchCoords(ref row, ref col); AddTarget(row, colOld); AddTarget(rowOld, col); } else if (result.Value == ResultOfAttack.ShotAlready) { throw new ApplicationException("Error in AI"); } }
/// <summary> /// ProcessShot will be called uppon when a ship is found. /// It will create a stack with targets it will try to hit. These targets /// will be around the tile that has been hit. /// </summary> /// <param name="row">the row it needs to process</param> /// <param name="col">the column it needs to process</param> /// <param name="result">the result og the last shot (should be hit)</param> protected override void ProcessShot(int row, int col, AttackResult result) { /// no next targets will be added if AI hits a target /// everytime AI hits the target, next target will be set randomly Console.WriteLine(row + " " + col); if (result.Value == ResultOfAttack.Hit) { _CurrentState = AIStates.TargetingShip; AddTarget(_Random.Next(0, EnemyGrid.Width), _Random.Next(0, EnemyGrid.Height)); } else if (result.Value == ResultOfAttack.ShotAlready) { throw new ApplicationException("Error in AI"); } }
public void MoveTo(Vector3 start, Vector3 target) { if (Active) { if (start.x >= target.x) { transform.position = transform.position; } CurrentState = AIStates.MOVING; DrawLine(start, target, new Color(255, 0, 0), 0.5f); float step = speed * Time.deltaTime; transform.position = Vector3.MoveTowards(start, target, step); } }
private void Start() { movement = GetComponent <CarMovement>(); driftLine = GetComponent <CarDriftLine>(); carDriftDust = GetComponent <CarDriftDust>(); carColliderCommon = GetComponent <ColliderCommon>(); ballColliderCommon = ball.GetComponent <ColliderCommon>(); carPowerUpControl = GetComponent <CarPowerUpControl>(); InitializeTempDistance(); aIState = AIStates.None; FindAllCarsExceptThis(); }
protected override void ProcessShot(int row, int col, AttackResult result) { if (result.Value == ResultOfAttack.Hit) { _CurrentState = AIStates.RandomTarget; AddTarget(row - _Random.Next(0, EnemyGrid.Height), col); AddTarget(row, col - _Random.Next(0, EnemyGrid.Width)); AddTarget(row + _Random.Next(0, EnemyGrid.Height), col); AddTarget(row, col + _Random.Next(0, EnemyGrid.Width)); } else if (result.Value == ResultOfAttack.ShotAlready) { throw new ApplicationException("Error in AI"); } }
/// <summary> /// TargetCoords is used when a ship has been hit and it will try and destroy /// this ship /// </summary> /// <param name="row">row generated around the hit tile</param> /// <param name="column">column generated around the hit tile</param> private void TargetCoords(ref int row, ref int column) { Location l = _Targets.Pop(); if ((_Targets.Count == 0)) { _CurrentState = AIStates.Searching; } else if ((_Targets.Count == 1)) { _CurrentState = AIStates.Searching; } row = l.Row; column = l.Column; }
private void OnStateExit(AIStates state, AIStates toState) { switch (state) { case AIStates.Idling: { break; } case AIStates.Chasing: { break; } } }
//Patrol method for rotating void Patrol(Text text, AISense sense) { isSpotted = false; // Do Patrol transform.Rotate(0, 0, -Time.deltaTime * rotationSpeed); // Check for Transitions if (sense.CanSee(GameManager.instance.player) || sense.CanHear(GameManager.instance.player, GameManager.instance.noiseMaker.volume)) { //Since spotted, increase the counter text.text = "Times Spotted: " + ++timesSpotted; //currentstate is now Chasing currentState = AIStates.ChaseAndFire; } }
public void OnAction(Entity entity) { if (entity.Name == "Player") { //Delete(entity); } if ((entity.Mask & MASK) == MASK) { List <IComponent> components = entity.Components; IComponent healthComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_HEALTH); }); IComponent ammoComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_AMMO); }); ComponentAI aiComponent = (ComponentAI)components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_AI); }); AIStates state = aiComponent.CurrentState; IComponent pickupComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_PICK_UP); }); IComponent aliveComponent = components.Find(delegate(IComponent component) { return(component.ComponentType == ComponentTypes.COMPONENT_ALIVE); }); PowerUp((ComponentHealth)healthComponent, (ComponentAmmo)ammoComponent, (ComponentPickUp)pickupComponent, (ComponentAlive)(aliveComponent)); if (pickupComponent == null && aliveComponent == null) { Delete(entity); } } }
private void IdentifyDriftTimeAndRotation() { int direction = Random.Range(0, 2); if (direction == 0) { carDirection = CarDirection.Right; } else { carDirection = CarDirection.Left; } StartCoroutine(Drifting(RandomDriftingTime())); aIState = AIStates.Drift; }
protected void checkStateBehaviour() { switch (currentState) { case AIStates.Patrol: if (agent.remainingDistance < 0.3f && !nextPathCalculated) { nextPathCalculated = true; setAgentParameters(0, 0); setAnimatorParameters("Speed", 0); co = StartCoroutine(loadAnimationSeek()); } break; case AIStates.Peace: if (agent.remainingDistance < 0.3f && !nextPathCalculated) { nextPathCalculated = true; setAgentParameters(0, 0); setAnimatorParameters("Speed", 0); co = StartCoroutine(loadAnimationSeek()); } break; case AIStates.Feeding: if (!seeking_food) { setFoodPoint(); } break; case AIStates.Alerted: //nada setAnimatorParameters("Speed", 3); break; case AIStates.Attack: //nada break; default: currentState = AIStates.Patrol; setNextRandomPoint(); break; } }
/// <summary> /// ProcessShot will be called uppon when a ship is found. /// It will create a stack with targets it will try to hit. These targets /// will be around the tile that has been hit. /// </summary> /// <param name="row">The row it needs to process.</param> /// <param name="col">The column it needs to process.</param> /// <param name="result">The result og the last shot (should be hit).</param> protected override void ProcessShot(int row, int col, AttackResult result) { // If the attack hits. if (result.Value == ResultOfAttack.Hit) { _CurrentState = AIStates.TargetingShip; AddTarget(row - 1, col); AddTarget(row, col - 1); AddTarget(row + 1, col); AddTarget(row, col + 1); } // If the attack is at a place that is already attacked. else if (result.Value == ResultOfAttack.ShotAlready) { throw (new ApplicationException("Error in AI")); } }
/// <summary> /// TargetCoords is used when a ship has been hit and it will try to avoid /// the ship /// </summary> /// <param name="row">row generated around the hit tile</param> /// <param name="column">column generated around the hit tile</param> private void FindTargetCoords(ref int row, ref int column) { Location l = _Targets.Pop(); if ((_Targets.Count == 0)) { _CurrentState = AIStates.Searching; } row = l.Row; column = l.Column; while (row == l.Row && column == l.Column) { SearchCoords(ref row, ref column); } }
public override AIStates OnGetHit(Mobile by, AIStates AIState, int dmg) { if (AIState != AIStates.Attack && AIState != AIStates.Fighting) { OnBeginFight(by); if (by == From) { From.AttackTarget = From.LastOffender; } else { From.AttackTarget = by; } return(AIStates.BeingAttacked); } return(AIState); }
// Update is called once per frame public void FixedUpdate() { if (currentState == AIStates.Dead) { return; } //Si no está en alerta o attaque accede aquí así restamos si tiene hambre if (!currentState.Equals(AIStates.Alerted) && !currentState.Equals(AIStates.Attack) && !currentState.Equals(AIStates.Peace)) { //coroutinePatrolEnded indica si las coroutines han terminado así no mezclamos animaciones ni estados durante las animaciones if (!currentState.Equals(AIStates.Feeding) && !feeding && coroutinePatrolEnded) { hungry -= hungry_time; if (hungry < 0) { hungry = 0; } if (hungry < min_hungry) { currentState = AIStates.Feeding; } } //si está comiendo restauramos el hambre a 100 y volvemos al estado Patrol else if (feeding && coroutinePatrolEnded) { hungry += hungry_time * 50; if (hungry >= 90f && !currentState.Equals(AIStates.Alerted) && !currentState.Equals(AIStates.Attack)) { Debug.Log("ENTRO IF FEEDING UPDATE"); setAnimatorParameters("Feeding_bool", false); hungry = 100; currentState = AIStates.Patrol; seeking_food = false; feeding = false; StartCoroutine(wait()); } } } //chequeamos los estados aunque en realidad solo dos estados aquí los demás estados se activan por eventos // de los colliders VISION Y ATTACK_COLLIDER checkStateBehaviour(); }
/// <summary> /// ProcessShot will be called uppon when a ship is found. /// It will create a stack with targets it will try to hit. These targets /// will be around the tile that has been hit. /// </summary> /// <param name="row">the row it needs to process</param> /// <param name="col">the column it needs to process</param> /// <param name="result">the result og the last shot (should be hit)</param> protected override void ProcessShot(int row, int col, AttackResult result) { if (result.Value == ResultOfAttack.Hit) { _CurrentState = AIStates.TargetingShip; Random rnd = new Random(); int row_rand = rnd.Next(-1, 1); int column_rand = rnd.Next(-1, 1); AddTarget(row - 1 + row_rand, col + column_rand); AddTarget(row + row_rand, col - 1 + column_rand); AddTarget(row + 1 + row_rand, col + column_rand); AddTarget(row + row_rand, col + 1 + column_rand); } else if (result.Value == ResultOfAttack.ShotAlready) { throw new ApplicationException("Error in AI"); } }
// '' <summary> // '' ProcessHit gets the last hit location coordinates and will ask AddTarget to // '' create targets around that location by calling the method four times each time with // '' a new location around the last hit location. // '' It will then set the state of the AI and if it's not Searching or targetingShip then // '' start ReOrderTargets. // '' </summary> // '' <param name="row"></param> // '' <param name="col"></param> public void ProcessHit(int row, int col) { _LastHit.Add(_CurrentTarget); AddTarget((row - 1), col); AddTarget(row, (col - 1)); AddTarget((row + 1), col); AddTarget(row, (col + 1)); if ((_CurrentState == AIStates.Searching)) { _CurrentState = AIStates.TargetingShip; } else { // either targetting or hitting ... both are the same here _CurrentState = AIStates.HittingShip; ReOrderTargets(); } }
// Use this for initialization void Start() { if (patrolPoints.Length == 0 || patrolPoints[0] == null) { state = AIStates.Idle; } else { state = AIStates.Patroling; } if (patrolPoints.Length > 0 && patrolPoints[0] != null) { agent.SetDestination(patrolPoints[Random.Range(0, patrolPoints.Length)].position); } animation = GetComponentInChildren <Animator>(); player = GameObject.FindGameObjectWithTag("Player"); alarm = GameObject.FindGameObjectWithTag("alertbar").GetComponent <Alarm>(); }
private void AIDecisions() { if (null == currentTarget) { state = AIStates.patrol; } else if (null != currentTarget && previouslyAttackedTarget != currentTarget) { if (navMeshAgent.remainingDistance > navMeshAgent.stoppingDistance) { state = AIStates.chase; } else //if (navMeshAgent.remainingDistance < navMeshAgent.stoppingDistance) { state = AIStates.attack; } } }
void PlayStateTransitionVoice(AIStates overrideVoice = AIStates.None) { overrideVoice = (overrideVoice == AIStates.None) ? currentState : overrideVoice; switch (overrideVoice) { case AIStates.Hostile: break; case AIStates.Suspicious: break; case AIStates.Calm: break; default: break; } }
private void OnStateEnter(AIStates state, AIStates fromState) { switch (state) { case AIStates.Idling: { MaxStableMoveSpeed = 0f; break; } case AIStates.Chasing: { MaxStableMoveSpeed = settings.MaxStableMoveSpeed; break; } } }
protected IEnumerator Patrol() { while (this.enabled && currentState == AIStates.Patrol) { agent.speed = Mathf.Lerp(agent.speed, walkSpeed, 2f * Time.deltaTime); Transform waypoint = null; this.UpdatePath(waypoint); // check transitions if (!HasTarget()) { currentState = AIStates.Patrol; break; } yield return(null); } }
// Use this for initialization void Start() { // Get Starting Position InitialPoint = this.transform.position; // Set Dying to false Dying = false; // Set Manipulated to false Manipulated = false; // Set Default state to IDLE ThisAIState = AIStates.IDLE; // Get NavMeshAgent component ThisNavAgent = this.GetComponent <NavMeshAgent>(); // Get reference to Player PlayerReference = GameObject.FindGameObjectWithTag("Player"); // First Random Position ThisNavAgent.destination = NewRandomPosition(); anim = GetComponentInChildren <Animator>(); }
private void PlayerDetection(ComponentPosition pos, ComponentVelocity vel, AIStates state) { if (state == AIStates.Wandering) { Vector2 AIpos = new Vector2(pos.Position.X, pos.Position.Z); Vector2 v = MyGame.NewCameraPosition - AIpos; float dot = MyGame.DotProduct(v.Normalized(), AIpos.Normalized()); if (dot > 0.7) { droneSpeed = 0.8f; } else { droneSpeed = 0.5f; } } }
private void MoveTo() { //If the target is in position we switch tto the attack state if (Position.DistanceTo(target.Position) < 300) { //Change the state to the attack state myState = AIStates.Attack; } else { //Get the direction to move in Vector2 dir = target.Position - Position; //Normalizing direction for movement dir = dir.Normalized(); //Move and slide has the phsics delta already worked in and using it helps the objects slide past each other MoveAndSlide(dir * speed); //Rotate to target Rotation = Mathf.LerpAngle(Rotation, dir.Angle(), 0.2f); } }
/// <summary> /// ProcessHit gets the last hit location coordinates and will ask AddTarget to /// create targets around that location by calling the method four times each time with /// a new location around the last hit location. /// It will then set the state of the AI and if it's not Searching or targetingShip then /// start ReOrderTargets. /// </summary> /// <param name="row"></param> /// <param name="col"></param> private void ProcessHit(int row, int col) { _LastHit.Add(_CurrentTarget); // Uses _CurrentTarget as the source AddTarget(row - 1, col); AddTarget(row, col - 1); AddTarget(row + 1, col); AddTarget(row, col + 1); if (_CurrentState == AIStates.Searching) { _CurrentState = AIStates.TargetingShip; } else { // either targetting or hitting... both are the same here _CurrentState = AIStates.HittingShip; ReOrderTargets(); } }
public void SetAnimVars(AIStates state) { switch (state) { case AIStates.Calm: animator.anim.SetBool(animator.hostile, false); animator.anim.SetBool(animator.suspicious, false); break; case AIStates.Suspicious: animator.anim.SetBool(animator.hostile, false); animator.anim.SetBool(animator.suspicious, true); break; case AIStates.Hostile: animator.anim.SetBool(animator.hostile, true); animator.anim.SetBool(animator.suspicious, true); break; } }
private void HandleMelee() { if (AIState == AIStates.Melee) { if (currentAttackLoadTime <= 0) { character.Attack(); currentTimeBetweenAttacks = timeBetweenAttacks; AIState = AIStates.Wait; targetPosition = target.targetObject.transform.position; movementController.lastInputMove = (targetPosition - this.transform.position).normalized; SetToIdleAfter(attackLoadTime); character.immune = false; } else { currentAttackLoadTime -= Time.deltaTime; } } }
// <summary> // ProcessShot will be called uppon when a ship is found. // It will create a stack with targets it will try to hit. These targets // will be around the tile that has been hit. // </summary> // <param name="row">the row it needs to process</param> // <param name="col">the column it needs to process</param> // <param name="result">the result og the last shot (should be hit)</param> protected override void ProcessShot(int row, int col, AttackResult result) { Random random = new Random(); if (result.Value == ResultOfAttack.Hit) { _CurrentState = AIStates.TargetingShip; AddTarget(row - 1, col); int num = random.Next(5); if (num == 1) { AddTarget(row - 1, col - 1); } AddTarget(row, col - 1); num = random.Next(5); if (num == 1) { AddTarget(row + 1, col - 1); } AddTarget(row + 1, col); num = random.Next(5); if (num == 1) { AddTarget(row + 1, col + 1); } AddTarget(row, col + 1); num = random.Next(5); if (num == 1) { AddTarget(row - 1, col + 1); } } else if (result.Value == ResultOfAttack.ShotAlready) { throw new ApplicationException("Error in AI"); } }
// Find our nearest target, whether it be a player, enemy, or item, based // on what state we are currently in and what is available. Transform FindNearestTarget() { Transform nearestTarget = null; if( (aiState != AIStates.Pursue_Item && ( (!IsEnemy && Manager_Targeting.instance.enemyTargets.Count == 0) || (IsEnemy && Manager_Targeting.instance.playerTargets.Count == 0) ) ) || (aiState == AIStates.Pursue_Item && (detectionRadius == null || detectionRadius.inRangeItems.Count == 0 && detectionRadius.itemStorersInRange.Count == 0))) { if(aiState == AIStates.Pursue_Item) aiState = AIStates.Pursue; // If we were pursuing an item, there were none nearby so pursue again. return null; } // Setup our correct target list to check from. float shortestSoFar = 100; List<Transform> targets = Manager_Targeting.instance.playerTargets; if(aiState == AIStates.Pursue_Item) { // Put the names of all of your healing items in that Any() and All() parts I have // since that checks for healing items. You can just put a part of // their name. They will only attempt to go after those if their // health isn't maxed. If any are not healing, they will go after any of the // ones that aren't healing then using All to make sure the item's name is not in _healingItemNames. // You can check below in the foreach loop where we check for dist < shortestSoFar if(detectionRadius.inRangeItems.Count > 0 && ( (_charStatus.Stats[0] < _charStatus.Stats[1] && detectionRadius.inRangeItems.Any(item => item != null && _healingItemNames.Any(itemName => item.name.Contains(itemName)) ) ) || (detectionRadius.inRangeItems.Any(item => item != null && _healingItemNames.All(itemName => !item.name.Contains(itemName)) ) )) ) targets = detectionRadius.inRangeItems; else if(detectionRadius.itemStorersInRange.Count > 0) targets = detectionRadius.itemStorersInRange; else { // No need to pursue item then. This stuff is here just in case we // reach here. aiState = AIStates.Wander; targetForNavMesh = null; return null; } } else // Not pursuing an item. { // For players to target enemies. if(!IsEnemy) targets = Manager_Targeting.instance.enemyTargets; } foreach(Transform curTarget in targets) { if(curTarget != null) { // Just another check seeing if an item checking doesn't have a parent. // Detection radius already does this but double checks can be good. // If a character is what we are looking at, we make sure they are // alive. if(((curTarget.tag == "Player" || curTarget.tag == "Enemy") && curTarget.GetComponent<CharacterStatus>().Stats[0] > 0) || (curTarget.tag == "ItemStorer" || (curTarget.tag == "Item" && curTarget.parent == null))) { if(curTarget.tag == "Item" && curTarget.GetComponent<Base_Item>().ItemType == Base_Item.ItemTypes.Collectable) { // If we are checking an item and we have less than // 90% health left and the item is a collectable, we will // go for that right away. if(_charStatus.Stats[0] < _charStatus.Stats[1] * 0.9f) { nearestTarget = curTarget; break; } } float dist = Vector3.Distance(transform.position, curTarget.position); // Here we check to see that the distance checking is less than the shortest so far. // Then we see if the curTarget is not an item, or if it is, we see that we have less than // max health and the curTarget is a healing item, otherwise, we simply check that it is not // a healing item. if(dist < shortestSoFar && (curTarget.tag != "Item" || ( (_charStatus.Stats[0] < _charStatus.Stats[1] && _healingItemNames.Any(itemName => curTarget.name.Contains(itemName) ) ) || (_healingItemNames.All(itemName => !curTarget.name.Contains(itemName) ) ) ) ) ) { shortestSoFar = dist; nearestTarget = curTarget; } } } } if(nearestTarget != null) { if(nearestTarget.tag == "Player" || nearestTarget.tag == "Enemy") { // We now have a targeted character. _charAttacking.TargetedCharacter = nearestTarget; // AI players also retarget the same way human players do. if(gameObject.tag == "Player") Manager_Targeting.instance.TargetACharacter(_charStatus.PlayerNumber, _charAttacking); // Get references from them. targetCharStatus = nearestTarget.GetComponent<CharacterStatus>(); targetDetRadius = targetCharStatus.detectionRadius; } this.targetForNavMesh = nearestTarget; } return nearestTarget; }
/** Initializes reference variables. * If you override this function you should in most cases call base.Awake () at the start of it. * */ protected virtual void Awake() { seeker = GetComponent<Seeker>(); AnimControl = GetComponent<AIStates>(); //This is a simple optimization, cache the transform component lookup tr = transform; //Make sure we receive callbacks when paths complete seeker.pathCallback += OnPathComplete; //Cache some other components (not all are necessarily there) controller = GetComponent<CharacterController>(); navController = GetComponent<NavmeshController>(); rigid = rigidbody; }
void UpdateState() { if (health < 1) curstate = AIStates.Dead; }
// Update is called once per frame void Update() { switch(currentState) { case AIStates.MOVING_RIGHT: transform.Translate(new Vector3(moveSpeed * Time.deltaTime, 0, 0), Space.World); if(transform.position.x - player.position.x > 5) currentState = AIStates.MOVING_LEFT; break; case AIStates.MOVING_LEFT: transform.Translate(new Vector3(-moveSpeed * Time.deltaTime, 0, 0), Space.World); if(transform.position.x - player.position.x < -5) { // Set up the swoop info startPosition = transform.position; endPosition = player.transform.position; swoopCenter = player.transform.position; swoopCenter.y = transform.position.y; // above the player at the bee's level startSwoop = startPosition - swoopCenter; endSwoop = endPosition - swoopCenter; currentState = AIStates.SWOOPING_DOWN; } break; case AIStates.SWOOPING_DOWN: swoopTime += Time.deltaTime; transform.position = Vector3.Slerp(startSwoop, endSwoop, swoopTime * 2); transform.position += swoopCenter; if(swoopTime > 0.5f) { swoopTime = 0.0f; // Calculate second half of swoop Vector3 temp = startPosition; startPosition = endPosition; endPosition = temp + new Vector3(10, 0, 0); startSwoop = startPosition - swoopCenter; endSwoop = endPosition - swoopCenter; currentState = AIStates.SWOOPING_UP; } break; case AIStates.SWOOPING_UP: swoopTime += Time.deltaTime; transform.position = Vector3.Slerp(startSwoop, endSwoop, swoopTime * 2); transform.position += swoopCenter; if(swoopTime > 0.5f) { swoopTime = 0.0f; currentState = AIStates.MOVING_LEFT; } break; default: break; } switch(currentHealth) { case 3: transform.Find("MeanBee").renderer.material.mainTexture = beeTextures[0]; break; case 2: transform.Find("MeanBee").renderer.material.mainTexture = beeTextures[1]; break; case 1: transform.Find("MeanBee").renderer.material.mainTexture = beeTextures[2]; break; default: // Empty the bar, then destroy the Bee object Destroy(beeHealthBarFill); Destroy(gameObject); break; } }
/// <summary> /// ProcessHit gets the last hit location coordinates and will ask AddTarget to /// create targets around that location by calling the method four times each time with /// a new location around the last hit location. /// It will then set the state of the AI and if it's not Searching or targetingShip then /// start ReOrderTargets. /// </summary> /// <param name="row"></param> /// <param name="col"></param> private void ProcessHit(int row, int col) { _LastHit.Add(_CurrentTarget); //Uses _CurrentTarget as the source AddTarget(row - 1, col); AddTarget(row, col - 1); AddTarget(row + 1, col); AddTarget(row, col + 1); if (_CurrentState == AIStates.Searching) { _CurrentState = AIStates.TargetingShip; } else { //either targetting or hitting... both are the same here _CurrentState = AIStates.HittingShip; ReOrderTargets(); } }
// Here we check to see if we can attack and what distance away we are. // If we are holding a throwable, the distance will be increased so that // we can throw it at a further range. void AttemptAttack(float distFromTarget) { if(targetCharStatus == null || (detectionRadius.inCloseRangeChar.Count == 0 && anim.GetInteger("HoldStage") != 1)) // HoldStage 1 means we are holding a throwable. return; float minDistUsing = minAttackDist; float maxDistUsing = maxAttackDist; bool holdingThrowable = false; if(anim.GetInteger("HoldStage") == 1) { maxDistUsing = maxAttackDist + 3; holdingThrowable = true; } // This part determines if we are in range to attack. if(distFromTarget > minDistUsing && distFromTarget < maxDistUsing) { // Face our target when within range and in idle. Otherwise just get the angle from us // facing our target currently. float angle = FaceCharacterTarget(); // If facing our target by a good amount and making sure // they are vulnerable and are not guarding. If they are, they will // have a small chance of attacking. if(targetCharStatus.Vulnerable) // Make sure they are Vulnerable. { if(angle < 55 && (!targetCharStatus.BaseStateInfo.IsTag("Guard") || (targetCharStatus.BaseStateInfo.IsTag("Guard") && Random.value > 0.95f))) { if(Random.Range(0, 100) < attackRatio) { if(!holdingThrowable) { // Attempt a grab. Grabs are done by moving slightly. if(canUseGrabs && _charItem.ItemHolding == null && anim.GetFloat("Move") > 0.2f && Random.value > 0.7f) _charAttacking.AttackSetup(3, 0); // Attempt grab. else { int attackUsed = 1; if(anim.GetFloat("Move") > 0.94f) attackUsed = 2; // If moving too fast, go for the slide attack. float vDir = 0; // If we are next to an itemStorer, we will use our // low attack and kick it. if(detectionRadius.NextToItemStorer && detectionRadius.inCloseRangeChar.Count == 0) vDir = -1; _charAttacking.AttackSetup(attackUsed, vDir); } } // If we are holding a throwable, then throw it! else _charItem.Throw(); } } } else // They aren't vulnerable so a random chance to retreat below. // if they aren't simply dodging. { if(!targetCharStatus.BaseStateInfo.IsTag("Dodging")) if(Random.Range(0f, 20f) > 19f) aiState = AIStates.Retreat; } } }
public override void Update(GameTime gameTime) { Player player = GetNeareastPlayer(); switch (AIState) { case AIStates.DODGE: break; case AIStates.ATTACK: break; case AIStates.ROAM: if (!(Vector2.Distance(DestinationPos, Position) < 5)) { var dir = DestinationPos - Position; dir.Normalize(); Position += dir * 5f; } else { destPos = new Vector2(rand.Next(width / 2 + 5, Game1.GAME_WIDTH - width / 2), rand.Next(height / 2 + 5, Game1.GAME_HEIGHT - height / 2)); } break; default: AIState = AIStates.DODGE; break; } foreach (Player p in GameplayState.Players) { // Why would I check if my bullets hit me? Well... there's probably many // resons but for now, keep it my way. if (p == this) continue; // Laser guns are an exception to bullet checks... instead, they're just a // giant rectangle. The laser isn't removed if it's hitting me if (p.equippedWeapon.GetType() == typeof(LaserGun)) { var weapon = (LaserGun)p.equippedWeapon; if (weapon.Laser.Bounds.Intersects(Bounds) && weapon.Laser.IsActive) Damage(p.equippedWeapon.Damage); } else { // Here's the bullet foreach loop, it just uses a fancy lambda expression p.equippedWeapon.Bullets.ForEach((b) => { // If there's no forcefield then KILL ME if (!forceField) { if (b.Bounds.Intersects(Bounds)) { Damage(p.equippedWeapon.Damage); b.DestroyMe = true; } } // If there is a force field then don't kill me else { if (b.Bounds.Intersects(ForceFieldBounds)) { b.DestroyMe = true; } } }); } } equippedWeapon.Update(gameTime); }
// Use this for initialization void Start() { textPanel.SetActive(false); updateLocation(); if(board == null) { board = GameObject.Find("Board"); } if(goalPoint == null) { // Debug.Log("goal being set"); chooseNewGoal(); // Debug.Log(string.Format("the goalpoint name is {0}", goalPoint)); findPath(); state = AIStates.IDLE; // state = (AIStates)Random.Range(0, 3); } Player.turn += StateMachine; // this flags all the squares as hot foreach(GameObject square in persueRoom) { square.GetComponent<ClickObject>().personalSquare(); } }
void OnEnable() { // Reenable our Agent if it isn't active. if(Agent) { if(!Agent.gameObject.activeSelf) Agent.gameObject.SetActive(true); Agent.Resume(); } if(!IsEnemy) aiState = AIStates.Wander; // Default state upon enable for players. }
//Pet bobs around a point. void Idle() { switch (_currentIdleState) { case IdleState.NONE: break; case IdleState.RECORDING_POSITON: lastLocation = transform.position; _currentIdleState = IdleState.DOIN_MY_THANG; break; case IdleState.DOIN_MY_THANG: transform.position = new Vector3(transform.position.x,lastLocation.y + ((float)Math.Sin(Time.time) / floatingStrength),transform.position.z); idleTimeLeft -= Time.deltaTime; if (idleTimeLeft < 0f) _currentAIState = AIStates.DECIDING; break; } //Currently Only Moves Up and Down. }
void CheckParalyze() { if (rb.velocity != Vector3.zero && rb.angularVelocity != Vector3.zero) { if (_currentAIState == AIStates.PLAYING) _currentPlayingState = PlayingState.STUNNED; else _currentAIState = AIStates.PARALYZED; } //_currentAIState = AIStates.IDLING; }
public override AIStates OnGetHit( Mobile by, AIStates AIState, int dmg ) { if ( by != summonedFrom && AIState != AIStates.Attack && AIState != AIStates.Fighting ) return AIStates.BeingAttacked; return AIState; }
void Stabalize() { if (_currentAIState == AIStates.PARALYZED) { if (Time.time > stablizeTime + stablizeCooldown) { stablizeTime = Time.time; rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; _currentAIState = AIStates.DECIDING; } } else if (_currentPlayingState == PlayingState.STUNNED) { if (Time.time > playStablizeTime + playStablizeCooldown) { playStablizeTime = Time.time; rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; _currentPlayingState = PlayingState.SETTING_UP; } } }
// Use this for initialization void Start() { myState = AIStates.Roaming; }
public void Play() { _currentAIState = AIStates.PLAYING; if (_currentPlayingState == PlayingState.NONE) _currentPlayingState = PlayingState.SETTING_UP; }
// This is only called for enemies. public IEnumerator SpawnIn(EnemySpawnType spawnType) { // Make sure the enemies are spawned with the rotation of the spawn point // so make it face the direction facing the trigger area for the current // battle zone. aiState = AIStates.Spawn; Vector3 moveDir = myTransform.forward; // Entered area becomes true after exiting our spawn spot trigger bounds // for the current area. while(!_enteredArea) { if(spawnType == EnemySpawnType.Normal) _charMotor.Move(moveDir, false, false); else if (spawnType == EnemySpawnType.Find_Way && !targetForNavMesh) targetForNavMesh = FindNearestTarget(); yield return new WaitForSeconds(0.0001f); } // We can now target a character. // I just change the character's name to the name given in the // corresponding enum. Just a personal preference. gameObject.name = _charStatus.myCharacterEnemy.ToString (); aiState = AIStates.Wander; _charStatus.Vulnerable = true; // We can now be hit. // We are now added to the enemyTargets list so players can target us. Manager_Targeting.instance.enemyTargets.Add (myTransform); StopCoroutine ("SpawnIn"); yield break; }
void Deciding() { ResetAIStates(); if (IsOutOfPlayerLimits()) { _currentAIState = AIStates.RETURNING; if (_currentReturningState == ReturningState.NONE) _currentReturningState = ReturningState.LOOKING_FOR_TARGET; } else { if (Random.value < 0.5f) { _currentAIState = AIStates.IDLING; if (_currentIdleState == IdleState.NONE) _currentIdleState = IdleState.DOIN_MY_THANG; } else { _currentAIState = AIStates.ROAMING; if (_currentRoamingState == RoamingState.NONE) _currentRoamingState = RoamingState.LOOKING_FOR_TARGET; } } }
void Update() { if(Manager_Cutscene.instance.inCutscene || Manager_Game.instance.IsPaused) return; if(_charStatus.Busy) { // If we are in an attack state... if(_charStatus.BaseStateInfo.IsTag("Attack") && !_charStatus.BaseStateInfo.IsName("Atk_Slide")) { // If we landed an attack and are no longer in attack hit delay... if(Manager_BattleZone.instance.InBattle && anim.GetBool("AttackHit") && _charAttacking.HitDelayTime == 0) { // Atk_HeavyHigh is the launch attack state that sends the // hit character into the air setting them up for air combos. if(!_charStatus.BaseStateInfo.IsName("Atk_HeavyHigh")) { if(!_charStatus.BaseStateInfo.IsName("Atk_Heavy_N")) // Only bother if we are not in our finisher. { // Choose a combo if we haven't achieved a long enough one // past our max given only if there is only one character in close range, // or we are an enemy and are not in hard. Otherwise we will attempt to // dodge since you can dodge after an attack hits. AI players act more // like hard AI enemies. bool chooseToCombo = (!IsEnemy && detectionRadius.inCloseRangeChar.Count < 2) || (IsEnemy && (_difficulty != GameDifficulty.Hard || detectionRadius.inCloseRangeChar.Count < 2)); if(chooseToCombo && _charAttacking.Combo < maxCombo) ComboSetup(); else if(!chooseToCombo && detectionRadius.inCloseRangeChar.Any(enemy => enemy.GetComponent<CharacterAttacking>().IsAttacking)) _charAttacking.DodgeSetup(Random.Range(-1, 2), Random.Range(-1, 2)); } } else // We launched the target up into the air, so we get ready to jump to pursue them. { if(canUseAirAttacks && (_charAttacking.TargetedCharacter && _charAttacking.TargetedCharacter.position.y > myTransform.position.y + 1.2f)) { if(Random.value > 0.6f) { _charAttacking.AnimEventActivateHitbox(0); // True here is for jumping, no need to move (Vector3.zero) // Just jump. _charMotor.Move (Vector3.zero, true, false); } } } } } else if(_charStatus.BaseStateInfo.IsName("Guard_Hit")) { // Counter after being hit when guarding. Can only be done // before 80% of the animation has finished. Can be lowered if // desired. if(!anim.IsInTransition(0) && _charStatus.BaseStateInfo.normalizedTime < 0.8f && Random.Range(0, 100) < attackRatio) _charAttacking.AttackSetup(1, 0); } // Next is where we attack or throw a grabbed character. else if(_charStatus.BaseStateInfo.IsTag("Grab")) { if(!anim.IsInTransition(0)) { // Grab_Idle is the base grabbing state where we can // choose to throw or hit a grabbed character. if(_charStatus.BaseStateInfo.IsName("Grab_Idle")) { // I only make the AI hit a grabbed character no more // than 4 times (> 3). If they have, then they will // throw them. if(Random.value > 0.9f || _hitsWhileGrabbing > 3) _charAttacking.GrabAttackSetup(2); // Throw em' else { if(Random.Range (0, 100) < attackRatio) { _hitsWhileGrabbing++; _charAttacking.GrabAttackSetup(1); // Hit em' } } } } } else { // If we are guarding. if(anim.GetBool("IsGuarding")) { // If there are no more opposing characters nearby or // our targetedCharacter is no longer attacking. if(detectionRadius.inCloseRangeChar.Count == 0 || (targetCharStatus && !targetCharStatus.AmIAttacking)) { if(anim.GetBool("IsGuarding") && Random.value > 0.5f) { // Stop guarding. anim.SetBool("IsGuarding", false); } } } } return; } // Checks to see if any items are present and nearby. bool itemsCloseNearby = detectionRadius.inGrabRangeItems.Count > 0; bool itemsNearby = detectionRadius.inRangeItems.Count > 0 || detectionRadius.itemStorersInRange.Count > 0; // See if player 1's health is less than ours - healthBelowForHealthItem (random amount), only applies to players of course. // Since there is only one other player, we check all players by using Any and see if the status we are checking // is not our own and if its health Stats[0] is less than our by our chosen amount. I use // this bool anytime we check for healing items below. bool letTeamMateGet = !IsEnemy && (Manager_Game.instance.allPlayerStatus.Any(status => status != _charStatus && status.Stats[0] < _charStatus.Stats[0] - healthBelowForHealthItem) ); // Here is where I make the AI get rid of an item they are holding if they // find a healing item/collectable nearby if they have less than 90% health. if(_charItem.ItemHolding != null && (_charStatus.Stats[0] < _charStatus.Stats[1] * 0.9f)) { // If there is a healing item nearby we seek it out by getting // rid of an item we are holding so we can grab that one and heal // ourselves, unless we are a player and player 1's health is less than ours. if(itemsNearby && detectionRadius.inRangeItems.Count > 0 && detectionRadius.inRangeItems.Any(item => item != null && _healingItemNames.Any(itemName => item.name.Contains(itemName)))) { if(!letTeamMateGet && Random.value > 0.96f) { // Holding a weapon if(anim.GetInteger("HoldStage") == 3) _charItem.DropItem (); // Holding a throwable else if(anim.GetInteger("HoldStage") == 1) _charItem.Throw(); // Target that item. targetForNavMesh = detectionRadius.inRangeItems.Find(item => item != null && _healingItemNames.Any(itemName => item.name.Contains(itemName))); aiState = AIStates.Pursue_Item; } } } // This next part is only for players when you aren't in battle. The AI // will follow the leader player, when they aren't going after an item that // is. Same goes for if there are no enemy targets present. if(!IsEnemy && (!Manager_BattleZone.instance.InBattle || Manager_Targeting.instance.enemyTargets.Count == 0)) { if(_strafeDir != 0) _strafeDir = 0; if(!leadPlayer) return; if(itemsNearby) { if(Random.Range(0f, 20f) > 19.5f) { // First check to see if there are any item containers nearby. If not, next // check to see if there are items nearby, and if so, we look through them all and // see if any of their names contain one from our _healingItemNames array, otherwise, // we simply check to see that none of any of them are not a healing item by using All() // on the _healingItemNames array. if( detectionRadius.itemStorersInRange.Count > 0 || (detectionRadius.inRangeItems.Count > 0 && (!letTeamMateGet && detectionRadius.inRangeItems.Any(item => item != null && _healingItemNames.Any(itemName => item.name.Contains(itemName))) ) || (detectionRadius.inRangeItems.Any(item => item != null && _healingItemNames.All(itemName => !item.name.Contains(itemName))) )) || (!letTeamMateGet && _charStatus.Stats[0] < _charStatus.Stats[1])) // Do not have full health. { aiState = AIStates.Pursue_Item; targetForNavMesh = FindNearestTarget(); } } } // If we aren't pursuing an item, lets follow the leader player. if(aiState != AIStates.Pursue_Item && targetForNavMesh != leadPlayer) { if(Agent.stoppingDistance != _charStatus.PlayerNumber - 1) Agent.stoppingDistance = _charStatus.PlayerNumber - 1; targetForNavMesh = leadPlayer; } // Otherwise we want to get an item nearby first. else if(aiState == AIStates.Pursue_Item) { if(targetForNavMesh && (targetForNavMesh.tag == "Item" || targetForNavMesh.tag == "ItemStorer")) { if(Agent.stoppingDistance != 0.3f) Agent.stoppingDistance = 0.3f; if(itemsCloseNearby) { if(_charStatus.BaseStateInfo.IsTag("NotBusy") && _charMotor.onGround) { if(Random.value > 0.98f) { _charItem.Pickup(); } } } if(detectionRadius.NextToItemStorer) { FaceCharacterTarget(); // Face the item container. if(Random.value > 0.97f) { // Use low attack (-1 second parameter) _charAttacking.AttackSetup(1, -1); } } } if (!itemsNearby || _charItem.ItemHolding != null || targetForNavMesh == null) aiState = AIStates.Wander; } if(targetForNavMesh) { this.targetPos = targetForNavMesh.position; Agent.SetDestination(targetPos); // update the agent's position Agent.transform.position = myTransform.position; Vector3 moveDir = Agent.desiredVelocity.normalized; distFromTarget = Vector3.Distance(myTransform.position, targetForNavMesh.position); float distToSlowDown = (aiState != AIStates.Pursue_Item) ? 3 : 1.2f; if(distFromTarget < distToSlowDown) moveDir *= (aiState != AIStates.Pursue_Item ? 0.5f : 0.2f); // Walk or move very slow if pursuing an item and near it. // If the desired velocity is that small, just zero it out. // A personal preference of mine to aid in preventing the // character from doing unnecessary small movements. if(moveDir.magnitude < 0.2f) moveDir = Vector3.zero; _charMotor.Move(moveDir, false, _charAttacking.TargetedCharacter && distFromTarget < 3 && aiState != AIStates.Retreat); // AI will go into targeting and strafing mode if less than 3 units away from their targeted character and not retreating. } return; } // Have enemies just wander if there are no players around to target. // That would be in the case of a Game Over. If we don't have a // targetForNavMesh, we will simply choose random spots to move to around // our current location. if(IsEnemy && Manager_Targeting.instance.playerTargets.Count == 0) { aiState = AIStates.Wander; Wander (); } // Reset any hits given while grabbing a character after leaving // grabbing by either throwing or our grab being broken out of. if(_hitsWhileGrabbing > 0) { if(_charStatus.BaseStateInfo.IsName("Grab_Throw") || _charStatus.BaseStateInfo.IsName("Grab_Break")) _hitsWhileGrabbing = 0; } // Players who have chosen a new path have a different stopping distance, the end boundary in the // current battle area's x and z position with their own y position. if(Agent.stoppingDistance != 0.1f && (IsEnemy || (!IsEnemy && !_choseNewPath))) Agent.stoppingDistance = 0.1f; distFromTarget = 10; float enemiesNearPlayer = 0; // This is the only place where a new targetForNavMesh is found for sake of // convenience. When you want to find a new one at some point, I make the // current one null, so during the next frame it will find a new one here // depending on what our current AI state is. if(aiState != AIStates.Spawn) { // I don't want players (!IsEnemy) to have another player targeted when // reaching this point since we are in battle. if(targetForNavMesh == null || (!IsEnemy && targetForNavMesh.tag == "Player")) targetForNavMesh = FindNearestTarget(); else { if(targetForNavMesh.tag == "Item") distFromTarget = Vector3.Distance(myTransform.position, targetForNavMesh.position); else { if(_charAttacking.TargetedCharacter) distFromTarget = Vector3.Distance(new Vector3(myTransform.position.x, 0, myTransform.position.z), new Vector3(_charAttacking.TargetedCharacter.position.x, 0, _charAttacking.TargetedCharacter.position.z)); } } // An easy way to find out how many enemies are close to our // targeted character. if(targetDetRadius != null) enemiesNearPlayer = targetDetRadius.inCloseRangeChar.Count; } if(aiState != AIStates.Pursue) if(_strafeDir != 0) _strafeDir = 0; // Reset strafing if not pursuing. if (targetForNavMesh) { Vector3 move = Agent.desiredVelocity; float maxDistForRetreat = 5; // update the progress if the character has made it to the previous target if(aiState != AIStates.Retreat) targetPos = targetForNavMesh.position + _randomOffset; else // Retreating { // I found this part here works well for retreating from a target. if(targetForNavMesh && !_choseNewPath) { if(distFromTarget < maxDistForRetreat) { targetPos = myTransform.position + ( (myTransform.position - (targetForNavMesh.position) ) * maxDistForRetreat); // Go out at least as far as the distance you are checking against (maxDistForRetreat) so that the enemy stays away nicely } else move = Vector3.zero; // Far enough away, don't need to move so we can face our target, done below with MinMovement on EnemyMotor. } } // If our retreat position has gone outside of the bounds of the navmesh... if (!Agent.hasPath && !_choseNewPath && _enteredArea && aiState == AIStates.Retreat) { // We will use the position of the end boundary for the current battle area, and use our // y position instead. Vector3 newPos = Manager_BattleZone.instance.zonesEnd[Manager_BattleZone.instance.currentAreaNumber].transform.position; newPos.y = myTransform.position.y + 0.05f; targetPos = newPos; if (!IsEnemy) Agent.stoppingDistance = 3; // The players can't get close enough to the end boundary since they can't go through its collider like the enemies so I increase this. _choseNewPath = true; // Now we can't change our new position until we get out of retreat since it would interfere. } Agent.SetDestination(targetPos); // update the agent's position Agent.nextPosition = myTransform.position; if(move.magnitude < 0.1f) move = Vector3.zero; // This bool refers to if we should rotate and face our target, whether we are close enough and not retreating, // or far away enough when retreating. bool faceTarget = _charAttacking.TargetedCharacter && ((distFromTarget < 3 && aiState != AIStates.Retreat) || (aiState == AIStates.Retreat && distFromTarget > maxDistForRetreat)); // use the values to move the character _charMotor.Move(move, jump, faceTarget); } else // If no target for nav mesh { // We still need to call the character's move method, but we send zeroed input as the move param. _charMotor.Move(Vector3.zero, jump, false); } if(jump) // Reset this in case we jumped above. jump = false; // This will be true if there are any opposing characters close by us. bool charCloseNearby = detectionRadius.inCloseRangeChar.Count > 0; if(targetForNavMesh == null) return; // A random chance of choosing a closer target if there is more // than one available. if(_charAttacking.TargetedCharacter) { // Choose appropriate list based on if we are an enemy or a player. List<Transform> charChecking = Manager_Targeting.instance.playerTargets; if(!IsEnemy) charChecking = Manager_Targeting.instance.enemyTargets; _changeNewTargetTimer += Time.deltaTime; if(_changeNewTargetTimer > Random.Range(4, 8)) { _changeNewTargetTimer = 0; foreach(Transform character in charChecking) { if(character != null && character != _charAttacking.TargetedCharacter) { if(Vector3.Distance(myTransform.position, character.position) < distFromTarget) { if(Random.value > 0.5f) { // Reset so that we will find a new target on the // next frame which will be closer since // FindNearestTarget() does just that. ResetPlayerTarget(); return; } } } } } } // I put these here so that an enemy will always be able to attack or guard // when nearby a targeted character. If their target is dead, they will // reset it. If there are any nearby characters will be ready to guard or // dodge if possible. if(targetCharStatus) { if(charCloseNearby) AttemptGuardOrDodge (); AttemptAttack (distFromTarget); if(targetCharStatus.Stats[0] < 0) { ResetPlayerTarget(); return; } } // Here, in each state, I specify specific unique things the character // will do in each state. Pursuing for example, they will choose a spot // around their targeted character to move to and attack when close. // Going into other states from the current state are done here as // well. switch(aiState) { case AIStates.Wander: // Choose random spots around a target to move to. Wander (); if(targetForNavMesh.tag == "Player" && targetCharStatus && targetCharStatus.Vulnerable && enemiesNearPlayer < Manager_Targeting.instance.playerTargets.Count + 1) { if(Random.Range(-10f, 10f) > 9f) aiState = AIStates.Pursue; } // If we are able to get items and there are some nearby, have a // chance at going after them if no opposing characters are close by. if(canGetItems && itemsNearby && !charCloseNearby) { if(Random.Range(0f, 20f) > 18f) aiState = AIStates.Pursue_Item; } break; case AIStates.Pursue: if(targetForNavMesh.tag == "Player" || targetForNavMesh.tag == "Enemy") { if(!IsEnemy || (enemiesNearPlayer < Manager_Targeting.instance.playerTargets.Count + 1)) { // Stop any strafing if too far away from our target. if (distFromTarget > 3 && _strafeDir != 0) _strafeDir = 0; if(targetCharStatus.Vulnerable) { // Choose a random spot to go to near a target and make sure // there isn't already an opposing character there. if(!_chosenRandomOffset && targetDetRadius) { if(!targetDetRadius.FoeNearBack && Random.Range(-20f, 20f) > 19f) { _chosenRandomOffset = true; _randomOffset = -targetForNavMesh.forward * 0.95f; } else if(!targetDetRadius.FoeNearRight && Random.Range(-20f, 20f) > 19f) { _chosenRandomOffset = true; _randomOffset = targetForNavMesh.right * 0.95f; } else if(!targetDetRadius.FoeNearLeft && Random.Range(-20f, 20f) > 18.8f) { _chosenRandomOffset = true; _randomOffset = -targetForNavMesh.right * 0.95f; } } else { // A random chance to choose a strafe direction only if // our targeted character is close by. if(charCloseNearby && detectionRadius.inCloseRangeChar.Contains(targetCharStatus.transform) && _canChooseStrafeDir) { if(Random.value > 0.5f) _strafeDir = -1; else _strafeDir = 1; _canChooseStrafeDir = false; } // If they aren't nearby... stop strafing. else if(!charCloseNearby || !detectionRadius.inCloseRangeChar.Contains(targetCharStatus.transform)) { if(_strafeDir != 0 && Random.value > 0.98f) { _strafeDir = 0; _canChooseStrafeDir = true; } } // Reset our current strafe direction after a set time // so we can choose a new one. _choseRandomOffsetTimer += Time.deltaTime; if(_choseRandomOffsetTimer > Random.Range(4, 6)) { if(!_canChooseStrafeDir && Random.value > 0.99f) _canChooseStrafeDir = true; if(_choseRandomOffsetTimer > Random.Range(8f, 14f)) { _chosenRandomOffset = false; _choseRandomOffsetTimer = 0; _canChooseStrafeDir = true; } } } } else { // Make sure our target is alive (health > 0) if(targetCharStatus.Stats[0] > 0) { if(!targetCharStatus.BaseStateInfo.IsTag("Dodging") && distFromTarget < 3 && Random.Range(0f, 10f) > 9f) aiState = AIStates.Retreat; } else // They are dead. { // Reset our target and we will choose another on the // next frame from the same location way above. FindNearestTarget(); return; } } } else // A go back to wander chance if they are too many opposing characters already around our target. { if(Random.Range(0f, 10f) > 9.8f) aiState = AIStates.Wander; } } else if(targetForNavMesh.tag == "Item") { // Go after that item we have targeted if no opposing characters // are close by. if(canGetItems && !charCloseNearby) aiState = AIStates.Pursue_Item; // Reset this regardless so we can choose a new targetForNavMesh. targetForNavMesh = null; return; } // If all of these are true, we will have a chance of going at a // nearby item. if(canGetItems && !charCloseNearby && itemsCloseNearby) { if(Random.Range(0f, 20f) > 19.2f) { aiState = AIStates.Pursue_Item; targetForNavMesh = null; return; } } break; // When retreating, we wait until our targeted player is vulnerable // again. There is a chance that targetCharacterStatus could become // null if the player were to die, so if that were to happen, we // would reset our player target and return to wandering. A new target // will be chosen again if one is available. case AIStates.Retreat: if(targetCharStatus != null) { if (targetCharStatus.Stats[0] > 0) { if (!targetCharStatus.Vulnerable) { // If far enough away, I make the character face their target // while they are in retreat and in idle. if (distFromTarget > 5) FaceCharacterTarget(); } else { // Try to pursue again after they are vulnerable. if (Random.Range(0f, 10f) > 9.7f) { if (_choseNewPath) _choseNewPath = false; aiState = AIStates.Pursue; } } } else { FindNearestTarget(); return; } } else { if(Random.value > 0.97f) { if (_choseNewPath) _choseNewPath = false; ResetPlayerTarget(); aiState = AIStates.Wander; return; } } break; case AIStates.Pursue_Item: if(!canGetItems) aiState = AIStates.Wander; // Get rid of any random offset when going after items since we // don't want it. We just want the item's position. if(_randomOffset.magnitude > 0) _randomOffset = Vector3.zero; // If we are currently holding an item. if(_charItem.ItemHolding != null) { targetForNavMesh = null; aiState = AIStates.Pursue; return; } else // Not holding an item. { if(!itemsNearby) { targetForNavMesh = null; aiState = AIStates.Pursue; return; } // Make sure there are no players nearby before going after an item. if(!charCloseNearby) { if(targetForNavMesh.tag == "Item") { if(itemsCloseNearby) { // Attempt to pick up an item in grab range. if(Random.value > 0.98f) _charItem.Pickup(); } } // We reset this so at the top we will begin searching for // a new target, an item this time which is done in the // FindNearestTarget() method. else { targetForNavMesh = null; return; } } else // There are opposing characters nearby. { // We will attempt to go after them. if(Random.Range(0f, 20f) > 19.4f) aiState = AIStates.Pursue; } } break; } }
void Roaming() { switch (_currentRoamingState) { case RoamingState.NONE: break; case RoamingState.LOOKING_FOR_TARGET: targetLocation = RandomPointInPlayerSphere(); _currentRoamingState = RoamingState.MOVING; break; case RoamingState.MOVING: transform.position = Vector3.MoveTowards(transform.position, targetLocation,Time.deltaTime / movementRate); if (ReachedTarget()) _currentRoamingState = RoamingState.REACHED_TARGET; break; case RoamingState.REACHED_TARGET: _currentAIState = AIStates.DECIDING; break; default: throw new ArgumentOutOfRangeException(); } }
// States: Wander, Persue, Idle void StateMachine() { // Debug.Log("statemachine being called at time " + Time.time); //Debug.Log(string.Format("at time {0} the state is {1}", Time.time, state)); checkRoomInvasion(); switch(state) { case AIStates.WANDER: if(goalPoint == null) { selectRandomState(); chooseNewGoal(); return; } if(currentSquare.Equals(goalPoint)) { // you done! // choose a new state and return // Debug.Log("we have moved into the goal square so we are calculating a new square to wander to"); selectRandomState(); chooseNewGoal(); cleanPathNodes(); findPath(); // Debug.Log(goalPoint); return; } // sets the current square to not holding this character anymore in anticipation for the move // then choose a square that advances the ai towards the target square currentSquare = findNextMove(); updateLocation(); break; case AIStates.PERSUE: // Debug.Log("You GETTIN CHASED"); foreach(GameObject square in persueRoom) { if(squareContainsPlayer(square)) { // we do a persuit goalPoint = square; cleanPathNodes(); findPath(); currentSquare = findNextMove(); updateLocation(); return; } } selectRandomState(); // this is not in use for now // selectRandomState(); break; case AIStates.IDLE: state = AIStates.WANDER; goalPoint = null; break; default: break; } }
/// <summary> /// ProcessShot is able to process each shot that is made and call the right methods belonging /// to that shot. For example, if its a miss = do nothing, if it's a hit = process that hit location /// </summary> /// <param name="row">the row that was shot at</param> /// <param name="col">the column that was shot at</param> /// <param name="result">the result from that hit</param> protected override void ProcessShot(int row, int col, AttackResult result) { switch (result.Value) { case ResultOfAttack.Miss: _CurrentTarget = null; break; case ResultOfAttack.Hit: ProcessHit(row, col); break; case ResultOfAttack.Destroyed: ProcessDestroy(row, col, result.Ship); break; case ResultOfAttack.ShotAlready: throw new ApplicationException("Error in AI"); } if (_Targets.Count == 0) _CurrentState = AIStates.Searching; }
using Microsoft.VisualBasic;
/// <summary> /// RemoveShotsAround will remove targets that belong to the destroyed ship by checking if /// the source of the targets belong to the destroyed ship. If they don't put them on a new stack. /// Then clear the targets stack and move all the targets that still need to be shot at back /// onto the targets stack /// </summary> /// <param name="toRemove"></param> private void RemoveShotsAround(Location toRemove) { Stack<Target> newStack = new Stack<Target>(); //create a new stack //check all targets in the _Targets stack foreach (Target t in _Targets) { //if the source of the target does not belong to the destroyed ship put them on the newStack if (!object.ReferenceEquals(t.Source, toRemove)) newStack.Push(t); } _Targets.Clear(); //clear the _Targets stack //for all the targets in the newStack, move them back onto the _Targets stack foreach (Target t in newStack) { _Targets.Push(t); } //if the _Targets stack is 0 then change the AI's state back to searching if (_Targets.Count == 0) _CurrentState = AIStates.Searching; }
// Use this for initialization void Start() { currentHealth = MAX_HEALTH; _pixelInset = beeHealthBarFill.pixelInset; currentState = AIStates.MOVING_RIGHT; }