public void AimTo(float _zRotation, float _xDiff) { if (_xDiff > 0 + degreesOfDeadZone) { //We should be facing right transform.eulerAngles = new Vector3(0, 0, 0); playerSettings.FlipName(false); //Rotate gun to point at mouse weaponPivot.rotation = Quaternion.Euler(0, 0, _zRotation); } else if (_xDiff < 0 - degreesOfDeadZone) { //We should be facing left transform.eulerAngles = new Vector3(0, 180, 0); playerSettings.FlipName(true); //Rotate gun to point at mouse but gun is upside down, so flip 180 on x //And compansate fliping x by inverting z rotation weaponPivot.rotation = Quaternion.Euler(180, 0, -_zRotation); } }
/* private void FixedUpdate() { onSyncWithFixedUpdate = true; } // Update is called once per frame private void Update() { //This will sync with FixedUpdate with the intention of pausing the game and if(!onSyncWithFixedUpdate){ return; }else{ onSyncWithFixedUpdate = false; } */ // Update is called once per frame void FixedUpdate() { //Return if this player isn't an AI player if(!ps.iAmAI){ curState = AIState.WaitingForTurn;//Just in case something external ends the AI turn return; } switch (curState) { case(AIState.WaitingForTurn): //Change state when player starts turn if(ps.isMyTurn){ //Debug.Log("starting turn"); curState = AIState.Pause; StartCoroutine(ChangeStateIn(AIState.PickingTarget, 2f)); } break; case(AIState.PickingTarget): //Reset List targets.Clear(); allEnemiesHealth = 0; for(int i = 0; i < GLOBALS.numTeams; i++){ //Check if this team is alive, else skip it if(GM.teamsHealth[i] <= 0) continue; //team is dead, move on //Check if this team is the AI team if(ps.teamID == i) continue; //Don't target allies for(int j = 0; j < GLOBALS.teamSize; j++){ //Check if this Soldier is alive, else skip it if(GM.soldiersHealth[i,j] <= 0) continue; //Soldier is dead, move on //Add Soldier to possible targets to shoot if(GM.teams[i,j] != null){ targets.Add(GM.teams[i,j].transform); //And record it's health for Infinity Gauntlet Calculations allEnemiesHealth += GM.soldiersHealth[i,j]; } } } //We now have all possible targets, now we need to sort them: //sort by distance to player ascending targets = targets.OrderBy(x => Vector2.Distance(this.transform.position,x.position)).ToList(); //sort by teams health decending targets = targets.OrderBy(x => -GM.teamsHealth[x.GetComponent<PlayerSettings>().teamID]).ToList(); //sort by soldiers health decending targets = targets.OrderBy(x => -x.GetComponent<DamageHandler>().health).ToList(); curState = AIState.Pause; StartCoroutine(ChangeStateIn(AIState.tryingStraightShot, 1f)); break; case(AIState.tryingStraightShot): //Debug.Log("tryingStraightShot"); //Reset target target = null; //Loop thru all enemies and chose the first one with direct line of sight foreach (Transform tar in targets){ //Find direction vector from self to target and normalize it to length 1 dir3 = tar.position - weaponContr.weaponPivot.transform.position; dir3.Normalize(); dir3.z = 0; //Direct cast from Vector3s to Vector2s origin = weaponContr.weaponPivot.transform.position; direction = dir3; //Send a ray and store the information in hit hit = Physics2D.Raycast(origin + direction*1.5f, direction); //Check if we are hitting a player and that player is not in our team if(hit.transform.tag == "Player" && ps.teamID != hit.transform.GetComponent<PlayerSettings>().teamID){ Debug.Log("AI Player says: Found a Target!!"); target = hit.transform; break; } } if(target == null){//change state TODO Debug.Log("AI Player says: No target in sight"); //Set target to be the closest one target = targets.First(); //Change state and wait curState = AIState.Pause; StartCoroutine(ChangeStateIn(AIState.tryingParabolicShot, 1f)); //leave state break; } zRotation = CalculateStraightShotAngle(target); //Find a default weapon to fall back to if(TryWeapon(WeaponCodes.Sniper)) {/*Nothing to do*/} else if(TryWeapon(WeaponCodes.Shotgun)) {/*Nothing to do*/} else if(TryWeapon(WeaponCodes.Holy_Grenade)) {/*Nothing to do*/} else if(TryWeapon(WeaponCodes.Hadouken)) {/*Nothing to do*/} else if(TryWeapon(WeaponCodes.BFG9000)) {/*Nothing to do*/} else if(TryWeapon(WeaponCodes.Mine)) {/*Nothing to do*/} else if(TryWeapon(WeaponCodes.Grenade)) {/*Nothing to do*/} else if(TryWeapon(WeaponCodes.Bazooka)) {/*Nothing to do*/} else {TryWeapon(WeaponCodes.Bang_Pistol);} //-------Default Weapon has been set---------// //If distance between target is small, then prioritize other short range weapons if(Vector2.Distance(target.position, transform.position) < 10f){ //Try to use Shotgun, else use the Hadouken, else ThunderGun if(TryWeapon(WeaponCodes.Shotgun)) {/*Nothing to do*/} else if(TryWeapon(WeaponCodes.Hadouken)) {/*Nothing to do*/} else if(TryWeapon(WeaponCodes.ThunderGun)) {/*Nothing to do*/} else {/*Keep default weapon*/} //If the angle is good for launching, then prioritize ThunderGun if(zRotation > 30f && zRotation < 60f){ TryWeapon(WeaponCodes.ThunderGun); } //If target is in melee range, then prioritize Mjolnir if(Vector2.Distance(target.position, transform.position) < 4f){ //Close enough for Mjolnir TryWeapon(WeaponCodes.Mjolnir); } } float rotationOffset = 0f; switch (curWeapon) { case (int)WeaponCodes.Mjolnir: case (int)WeaponCodes.ThunderGun: rotationOffset = 7f; break; case (int)WeaponCodes.Hadouken: rotationOffset = 1.5f; break; case (int)WeaponCodes.Mine: case (int)WeaponCodes.Bazooka: case (int)WeaponCodes.Grenade: case (int)WeaponCodes.Holy_Grenade: case (int)WeaponCodes.Teleport_Grenade: //**************TODO******************** break; default: break; } if(Mathf.Abs(zRotation) < 90f){ zRotation += rotationOffset;//raise weapon x degrees up }else{ zRotation -= rotationOffset;//raise weapon x degrees up } //Change state and wait curState = AIState.Pause; StartCoroutine(ChangeStateIn(AIState.Aiming, 1f)); break; case(AIState.tryingParabolicShot): //Debug.Log("tryingParabolicShot"); //This is for ThunderGun and sets yDiff and xDiff zRotation = CalculateStraightShotAngle(target); angle_1 = angle_2 = 0f; if(TryWeapon(WeaponCodes.ThunderGun) && Vector2.Distance(target.position, transform.position) < 10f && zRotation > 10f && zRotation < 70f) {/*In ThunderGun range and optimal angle range*/} else if(TryWeapon(WeaponCodes.BFG9000) && targets.Last().GetComponent<DamageHandler>().health < 50) {/*The target has low health*/ zRotation = CalculateStraightShotAngle(targets.Last()); } else if(TryWeapon(WeaponCodes.Infinity_Gauntlet) && (dh.health < allEnemiesHealth/2f) && dh.health != GM.teamsHealth[ps.teamID]) {/*AI has low health and is not the last man of its team*/} else if(TryWeapon(WeaponCodes.PlaneBomber) || TryWeapon(WeaponCodes.Plane_Nuke)) { //Sort list for farthest and highest targets targets = targets.OrderBy(x => -(x.position.y * 100 + Vector2.Distance(this.transform.position,x.position))).ToList(); target = targets.First(); } else if(TryWeapon(WeaponCodes.Homing_Bazooka)) { zRotation = 90; weaponScript.fireTriggered = true; } else{ if(CalculateParabolicShotAngles(target, WeaponCodes.Bazooka) && TryWeapon(WeaponCodes.Bazooka) && rand.NextDouble() > 0.5) {/*Nothing to do*/} else if(CalculateParabolicShotAngles(target, WeaponCodes.Mine) && TryWeapon(WeaponCodes.Mine)) {/*Nothing to do*/} else if(CalculateParabolicShotAngles(target, WeaponCodes.Holy_Grenade) && TryWeapon(WeaponCodes.Holy_Grenade)) {/*Nothing to do*/} else if(CalculateParabolicShotAngles(target, WeaponCodes.Grenade) && TryWeapon(WeaponCodes.Grenade) && rand.NextDouble() > 0.5) {/*Nothing to do*/} else if(CalculateParabolicShotAngles(target, WeaponCodes.Teleport_Grenade) && TryWeapon(WeaponCodes.Teleport_Grenade)) {/*Nothing to do*/} else{TryWeapon(WeaponCodes.Bang_Pistol);} zRotation = angle_1; } //Change state and wait curState = AIState.Pause; StartCoroutine(ChangeStateIn(AIState.Aiming, 1f)); break; case(AIState.Aiming): //Check if gun is close to the correct angle if(Mathf.Abs(currentRotation - (360 + zRotation) % 360) < 5f){ //Debug.Log("Finished Aiming"); weaponContr.AimTo(zRotation, xDiff); curState = AIState.Pause; StartCoroutine(ChangeStateIn(AIState.Shooting, 1f)); break; } //Rotate Weapon currentRotation = (currentRotation + 4) % 360; if (Mathf.Cos(currentRotation * Mathf.Deg2Rad) > 0) { //We should be facing right transform.eulerAngles = new Vector3(0, 0, 0); ps.FlipName(false); //Rotate gun to point at mouse weaponContr.weaponPivot.rotation = Quaternion.Euler(0, 0, currentRotation); } else { //We should be facing left transform.eulerAngles = new Vector3(0, 180, 0); ps.FlipName(true); //Rotate gun to point at mouse but gun is upside down, so flip 180 on x //And compansate fliping x by inverting z rotation weaponContr.weaponPivot.rotation = Quaternion.Euler(180, 0, -currentRotation); } break; case(AIState.Shooting): //Debug.Log("Shooting " + curWeapon); curState = AIState.Pause; StartCoroutine(ChangeStateIn(AIState.WaitingForTurn, 1f)); weaponScript.fireTriggered = true; break; case(AIState.Moving): //***************************TODO************************** break; case(AIState.Pause): //This is a dead state meant for the AI to just wait for some time //This state should only be called along with the coroutine ChangeStateIn() break; default: Debug.LogError("Invalid State reached... but HOW??!!"); break; } }