//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {License Information: Creative Commons} //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynter.Engine.GameObjects { #region Using Statements using System; using System.Collections; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; using System.Xml; using System.Diagnostics; using DarkWynter.Engine; using DarkWynter.Engine.Globals; using DarkWynter.Engine.ObjectLib; using DarkWynter.Engine.GameObjects; using DarkWynter.Stream; using Globals; using DarkWynter.Engine.Init; using Xclna.Xna.Animation; #endregion /// /// Bots /// public class AI : Player { private Enums_Engine.TurnDirection turnDirection = Enums_Engine.TurnDirection.NOT_SET; private Vector3 Destination = new Vector3(0, 0, 0); private enum State { Goto, Stop, Exit } private State aiState = State.Goto; /// /// Constructor /// public AI(Load gameObjectLoader) : base(gameObjectLoader) { mass.objectType = Enums_Engine.ObjectType.PLAYER; mass.gameObjectPointer = this; } public void SpawnPlayer(ObjectLibrary objectLibrary) { _spawnPosition.Y = objectLibrary.terrain.GetTerrainHeight( spawnPosition.X / Statics_Engine.TerrainSettings.terrainScaleFactor, spawnPosition.Z / Statics_Engine.TerrainSettings.terrainScaleFactor); base.SpawnPlayer(); health = Statics_Engine.AISettings.AI_MAX_HEALTH; } public Vector3 goToDestination(Vector3 destination) { Vector3 Orientation = destination - mass.currentPosition; Orientation.Normalize(); MoveTowardDirection(Orientation); mass.MoveObject((float)Math.Abs(Orientation.Z), 0.0f); return destination - this.mass.currentPosition; } /// /// Load stuff from XML /// /// The Bot node /// ObjectLibrary /// True if load was successful public override bool Load(ObjectLibrary objectLibrary) { if (!base.Load(objectLibrary)) { return false; } health = Statics_Engine.AISettings.AI_MAX_HEALTH; manna = 100; aiState = State.Goto; return true; } /// /// General update function /// /// ObjectLibrary public override void Update(ref ObjectLibrary objectLibrary) { // cap the y at zero so they can't get above the H2O plane //mass.currentPosition.Y = 0.0f; // If dead they can't update if (IsAlive() == false) { return; } if ((aiState == State.Goto) || (Destination != Vector3.Zero)) { gotoLogic(); } else if (aiState == State.Stop) { stopLogic(); } else if (aiState == State.Exit) { exitLogic(); } base.Update(ref objectLibrary); } public void SetDestination(Vector3 Location) { Destination = Location; } private bool fuzzyDestination(Vector3 Position, Vector3 TargetPosition) { if ((Position.X - TargetPosition.X < 20 || TargetPosition.X - Position.X < 20) && (Position.Z - TargetPosition.Z < 20 || TargetPosition.Z - Position.Z < 20)) return true; else return false; } public void gotoLogic() { goToDestination(Destination); if (fuzzyDestination(mass.currentPosition, Destination)) { mass.currentPosition = Destination; Destination = Vector3.Zero; aiState = State.Stop; } } public void stopLogic() { } public void exitLogic() { } public void UpdateState(ObjectLibrary objectLibrary) { if (aiState == State.Stop) { idleLogic(); } } private void idleLogic() { } private float AngleToDirection(Vector3 direction) { Vector2 diff2 = new Vector2(direction.X, direction.Z); diff2.Normalize(); Vector2 N = new Vector2(mass.normalVector.X, mass.normalVector.Z); N.Normalize(); return (float)Math.Acos((double)(Vector2.Dot(diff2, N))); } private Enums_Engine.TurnDirection DirectionToOrientation(Vector3 direction) { // Determine which direction to turn Vector3 toDirection = new Vector3(direction.X, 0, direction.Z); toDirection.Normalize(); Vector3 lookAt = new Vector3(mass.normalVector.X, 0, mass.normalVector.Z); lookAt.Normalize(); Vector3 cross = Vector3.Cross(toDirection, lookAt); if (cross.Y < 0.01) { return Enums_Engine.TurnDirection.LEFT; } else { return Enums_Engine.TurnDirection.RIGHT; } } public virtual void MoveTowardDirection(Vector3 direction) { float angle = AngleToDirection(direction); if (float.IsNaN(angle) || angle < 0.1) { // this was set to 10.0 f which completely turned the character around in the wrong direction ALWAYS // we twitched it to something much smaller and the character walks in a straight line //Rotate(new Vector2(0.0f, 0.0f)); //DarkWynterGame.playerController.gameInput.playerRotation.X = 0.0f; //DarkWynterGame.playerController.gameInput.playerMotion.Y = 10.0f; // weird math //ACTUALLY //If the angle is this small or not a number the idea would be NOT to rotate and just to move. } else { if (turnDirection == Enums_Engine.TurnDirection.NOT_SET) { // Determine which direction to turn turnDirection = DirectionToOrientation(direction); } if (turnDirection == Enums_Engine.TurnDirection.LEFT) { Rotate(new Vector2(0.05f, 0.0f)); //DarkWynterGame.playerController.gameInput.playerRotation.X = 0.05f; } else { Rotate(new Vector2(-0.05f, 0.0f)); //DarkWynterGame.playerController.gameInput.playerRotation.X = -0.05f; } } } } }