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);
}
}
}