namespace DarkWynterEngine.Utilities { #region Using Statements using System; 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; #endregion using Globals; using Physics; using ObjectLib; using GameObjects; /// /// MajikWand allows the user to look at and grab both terrain and standard GameObjects. /// It is the basis of our terrainMod algorithm, and is being expanded to something like a "gravity-gun". /// public class MajikWand { /// /// Raise or lower the terrain where the player is looking. /// /// Amount to modify terrain height. /// We need the Terrain and Players. /// The Player that is terrainModing. public void TerrainMod(float modAmount, ObjectLibrary objectLibrary, Player player) { //CLEAN NOTE: REQUIRES ACCESS TO HUMAN FROM ENGINE // REDESIGN TO USE STATICS.CS.... LIST AUDIO_LISTENER; // POSITION OF ALL LISTENER PLAYERS IN THE ENVIRONMENT // PERHAPS THIS COULD BE USED BY AI TOO.. AI HEARING?! //// Play audio for each human //foreach (Human human in objectLibrary.humans) //{ // if (human.IsAlive()) // { // Vector3 soundPosition = new Vector3(); // soundPosition.X = player.lookAtPoint.X * Statics.TerrainSettings.terrainScaleFactor; // soundPosition.Y = player.lookAtPoint.Y; // soundPosition.Z = player.lookAtPoint.Z * Statics.TerrainSettings.terrainScaleFactor; // Audio.TerrainMod(player.pSounds, soundPosition, human.mass.currentPosition); // } //} int modRadius = (int)(player.attackMagnitude / 25) + 1; bool isJumping = !player.CheckPlayerOnTerrain(objectLibrary); float terrainHeightBefore = objectLibrary.terrain.GetTerrainHeight(player.mass.currentPosition.X / Statics.TerrainSettings.terrainScaleFactor, player.mass.currentPosition.Z / Statics.TerrainSettings.terrainScaleFactor); objectLibrary.terrain.ModifyTerrain(modAmount, player.lookAtPoint, modRadius); //Is the player under terrain? float terrainHeightAfter = objectLibrary.terrain.GetTerrainHeight(player.mass.currentPosition.X / Statics.TerrainSettings.terrainScaleFactor, player.mass.currentPosition.Z / Statics.TerrainSettings.terrainScaleFactor); // Lock Player to terrain... // CLEAN: implement ObjectLibrary.LockObjectToTerrain() to freeze player to current x/z position // CLEAN: add bool Mass.TerrainLocked to indicate Collision status if (terrainHeightBefore != terrainHeightAfter && isJumping == false) { player.mass.currentPosition.Y = terrainHeightAfter + Statics.PlayerSettings.DEFAULT_PLAYER_HEIGHT * 1.5f; } } /// /// Get the terrain point that the majikwand is pointing at. /// /// Object Library contains the terrain. /// Player that owns the majikwand. /// Target point on terrain public Vector3 LookAtTerrainPoint(ObjectLibrary objectLibrary, Player player) { Vector3 playerPosition = new Vector3(); Vector3 lastTempPosition = new Vector3(-1.0f); Vector3 lookDirection = new Vector3(); Vector3 finalPoint = new Vector3(-1.0f); lookDirection = player.mass.normalVector + Vector3.Zero; // Get copies of the current position and normal vector playerPosition = player.mass.currentPosition + Vector3.Zero; // Reset target object player.targetObject = Enums.ObjectType.NONE; // Increment a ray until the Y value projects beneath the surface of the terrain. Then get the closest vertex by flooring the X and Z // values for (int i = 0; i < Statics.PlayerSettings.TERRAIN_MOD_RANGE; i++) { playerPosition += lookDirection; // Bounds checking if (playerPosition.X < 0 || playerPosition.X >= Statics.TerrainSettings.collisionMapSize || playerPosition.Z >= Statics.TerrainSettings.collisionMapSize || playerPosition.Z < 0) {continue;} lastTempPosition = playerPosition; // Check if the current search Y point is below the corresponding Y in collision height data if (playerPosition.Y < objectLibrary.terrain.GetTerrainHeight((int)playerPosition.X / Statics.TerrainSettings.terrainScaleFactor, (int)playerPosition.Z / Statics.TerrainSettings.terrainScaleFactor)) { // Store the values in the vector and set targetObject player.targetObject = Enums.ObjectType.TERRAIN; finalPoint.X = (int)(playerPosition.X / Statics.TerrainSettings.terrainScaleFactor); finalPoint.Z = (int)(playerPosition.Z / Statics.TerrainSettings.terrainScaleFactor); finalPoint.Y = objectLibrary.terrain.GetTerrainHeight((int)playerPosition.X / Statics.TerrainSettings.terrainScaleFactor, (int)playerPosition.Z / Statics.TerrainSettings.terrainScaleFactor); if (player.terrainModEnabled) { if (player.terrainModTarget == Vector3.Zero) { player.terrainModTarget = finalPoint; } else { finalPoint = player.terrainModTarget; } } return finalPoint; } } // We didn't find any matching point if (finalPoint.X < 0) { // Check if the player is looking downwards if (lookDirection.Y < 0.2f) { // Ensure that the last position is non-negative if (lastTempPosition.X > 0) { // Set target object and values in the vector player.targetObject = Enums.ObjectType.TERRAIN; finalPoint.X = (int)(lastTempPosition.X / Statics.TerrainSettings.terrainScaleFactor); finalPoint.Z = (int)(lastTempPosition.Z / Statics.TerrainSettings.terrainScaleFactor); finalPoint.Y = objectLibrary.terrain.GetTerrainHeight((int)lastTempPosition.X / Statics.TerrainSettings.terrainScaleFactor, (int)lastTempPosition.Z / Statics.TerrainSettings.terrainScaleFactor); } } } if (player.terrainModEnabled) { if (player.terrainModTarget == Vector3.Zero) { player.terrainModTarget = finalPoint; } else { finalPoint = player.terrainModTarget; } } return finalPoint; } /// /// Get the terrain point that the majikwand is pointing at. /// /// Object Library contains the terrain. /// Player that owns the majikwand. /// Object currently being targeted public Vector3 LookAtObject(ObjectLibrary objectLibrary, Player player) { Vector3 tempPosition = new Vector3(); Vector3 lastTempPosition = new Vector3(-1.0f); Vector3 lookDirection = new Vector3(); Vector3 finalPoint = new Vector3(-1.0f); // Get copies of the current position and normal vector tempPosition = player.mass.currentPosition + Vector3.Zero; lookDirection = player.mass.normalVector + Vector3.Zero; // Reset target object player.targetObject = Enums.ObjectType.NONE; //Statics.lookupMapTemp.GetCollisionObjects( // Increment a ray until the Y value projects beneath the surface of the terrain. Then get the closest vertex by flooring the X and Z // values for (int i = 0; i < Statics.PlayerSettings.TERRAIN_MOD_RANGE; i++) { tempPosition += lookDirection; // Bounds checking if (tempPosition.X < 0 || tempPosition.X >= Statics.TerrainSettings.collisionMapSize || tempPosition.Z >= Statics.TerrainSettings.collisionMapSize || tempPosition.Z < 0) { continue; } lastTempPosition = tempPosition; LinkedList massList = new LinkedList(); // Statics.lookupMap.GetListXZ((int)tempPosition.X / Statics.TerrainSettings.terrainScaleFactor, // (int)tempPosition.Z / Statics.TerrainSettings.terrainScaleFactor); // Check the lookup map to see if it has any information stored for that location if (massList.Count != 0) { // We have hit something, based on the object id set the targetObject to the correct type and store the object index (in the // lookup map) in one of the three vector components int j = 0; // Parse through the particles we have found foreach (Mass testMass in massList) { if (testMass != null && testMass.gameObjectPointer != null) { // Check if the particle position and the current search position match (or are close) if (Vector3.Distance(testMass.currentPosition, tempPosition) <= testMass.boundingVolume.radius) { player.targetObject = testMass.objectType; // Store the X, Z value and the index from the lookupmap in the vector and return it finalPoint = new Vector3(tempPosition.X, (float)j, tempPosition.Z); return finalPoint; } } j++; } } //check for players foreach (Player otherPlayer in objectLibrary.humans) { if (otherPlayer.IsAlive() && otherPlayer != player) { // Check if the player's position and the current search position match (or are close) if (Vector3.Distance(otherPlayer.mass.currentPosition, tempPosition) <= otherPlayer.mass.boundingVolume.radius) { player.targetObject = otherPlayer.mass.objectType; // Store the X, Z value and the index of the player in the vector and return it finalPoint = new Vector3(tempPosition.X, (float)otherPlayer.playerIndex, tempPosition.Z); return finalPoint; } } } foreach (Player otherPlayer in objectLibrary.bots) { if (otherPlayer.IsAlive()) { // Check if the player's position and the current search position match (or are close) if (Vector3.Distance(otherPlayer.mass.currentPosition, tempPosition) <= otherPlayer.mass.boundingVolume.radius) { player.targetObject = otherPlayer.mass.objectType; // Store the X, Z value and the index of the player in the vector and return it finalPoint = new Vector3(tempPosition.X, (float)otherPlayer.playerIndex, tempPosition.Z); return finalPoint; } } } // Check if the current search Y point is below the corresponding Y in collision height data if (tempPosition.Y < objectLibrary.terrain.GetTerrainHeight((int)tempPosition.X / Statics.TerrainSettings.terrainScaleFactor, (int)tempPosition.Z / Statics.TerrainSettings.terrainScaleFactor)) { // We have hit the terrain and not found any objects, so return -1 return new Vector3(-1.0f); } } // We didn't find any objects in our range so return -1 return new Vector3(-1.0f); } } }