//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// Copyright (C)2007 DarkWynter Studios. All rights reserved.
//
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {Contact : darkwynter.com for licensing information
//---------------------------------------------------------------------------------------------------------------------------------------------------
namespace DarkWynterEngine.GameObjects
{
#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;
using System.Xml;
using System.Diagnostics;
using Xclna.Xna.Animation.Content;
using Xclna.Xna.Animation;
#endregion
using Audio;
using Physics;
using Globals;
using ObjectLib;
using Utilities;
using Controllers;
///
/// Player Is Hit...
///
public struct Hit
{
///
/// Point of impact storage
///
public Vector3 POI;
///
/// Type of hit
///
public int type;
///
/// Pitch and Yaw
///
public Quaternion pitchyaw;
///
/// Steps in the animation
///
public float step;
}
///
/// Base class for Human and AI
///
public class Player : GameObject
{
#region Attributes
///
/// Player using fire
///
protected bool fireElementSelected = false;
///
/// Player using water
///
protected bool waterElementSelected = false;
///
/// Player using earth
///
protected bool earthElementSelected = false;
///
/// Player using wind
///
protected bool airElementSelected = false;
///
/// Player using terrainMod
///
public bool terrainModEnabled = false;
///
/// Type of the targeted object
///
public Enums.ObjectType targetObject;
///
/// List of where the player has been hit
///
protected List hitWhere = new List();
private Enums.AttackType activeShield = Enums.AttackType.NONE;
///
/// Last Attack mode selected
///
protected Enums.AttackType lastModeSelected = Enums.AttackType.NONE;
//protected Enums.PlayerState currentState = Enums.PlayerState.NORMAL;
private Model shieldModel;
private GameObject gameObject;
///
/// Player sounds
///
public PlayerSounds pSounds;
// Physics
///
/// Target point
///
public Vector3 lookAtPoint = new Vector3();
//public Sensor collisionSensor;
// Animation
///
/// Model animator
///
private ModelAnimator animator;
///
/// Idle animation
///
private AnimationController idle;
///
/// Walk animation
///
private AnimationController walk;
///
/// Die animation
///
private AnimationController die;
///
/// Animation currently running
///
private AnimationController currentAnimation;
///
/// Invert controller
///
public bool controlsInverted = false;
private Stopwatch mannaIncrement = new Stopwatch();
private Stopwatch RateOfFire = new Stopwatch();
private Stopwatch energyStabalizeTimer = new Stopwatch();
///
/// Timer before the player is respawned
///
public Stopwatch respawnTimer = new Stopwatch();
private Stopwatch spawnDoneTimer = new Stopwatch(); // player immortal after spawn
///
/// Player ID
///
public int playerIndex;
///
/// Player health
///
public float health;
///
/// Player manna
///
public float manna;
///
/// ID of player who killed this player
///
public int killedBy = -1;
///
/// Kill count
///
public int kills;
///
/// Mass value of attack
///
public int attackMagnitude = 30;
///
/// Thermal value of attack
///
protected int attackTemperature = 30;
///
/// Number of keys collected
///
public int numberOfKeysFound = 0;
///
/// Respawn position
///
public Vector3 spawnPosition = new Vector3();
///
/// Height above terrain to spawn player
///
public float spawnHeight = 0;
///
/// Terrain Mod target location
///
public Vector3 terrainModTarget = Vector3.Zero;
private bool firingEnergyBeam = false;
private float[] materialDiffuse = { 1.0f, 1.0f, 1.0f, 1.0f };
private Matrix initialTransform = new Matrix();
private MajikWand majikWand = new MajikWand();
#endregion
#region Methods
///
/// Default constructor
///
public Player() : base()
{
Init();
}
///
/// Constructor
///
/// Player index
public Player(int playerNumber)
{
playerIndex = playerNumber;
Init();
}
///
/// Initialize our variables
///
private void Init()
{
mass.velocity = new Vector3(0, 0, 0);
mass.mass = 10.0f;
mass.scale = new Vector3(1.0f);
mass.energy = 0.0f;
mass.staticFrictionCoefficient = 0.25f;
mass.dynamicFrictionCoefficient = 0.35f;
mass.COR = 0.6f;
mass.objectHeight = Statics.PlayerSettings.DEFAULT_PLAYER_HEIGHT;
mass.lastMaxHeight = 0;
mass.boundingVolume = new BoundingVolume(new BoundingSphere(new Vector3(10, 20, 10), 10.0f));
//All player variables need to be reset
health = 100;
manna = 100;
//collisionSensor = new Sensor();
//collisionSensor.ownerPointer = this;
}
///
/// Load information from XML
///
/// Player XML node
/// ObjectLibrary
/// True if load was successful
public override bool Load(XmlNode node, ObjectLibrary objectLibrary)
{
//base.Load( node);
// Audio
pSounds = new PlayerSounds();
// TEMP HARDCODED - REPLACE WITH XML LOADING
XML.PlayerInfo playerInfo;
playerInfo.name = "septasoul";
playerInfo.modelPath = "Content/_models/ss3";
playerInfo.texPath = "Content/_textures/septasoulTexture";
playerInfo.bumpPath = "Content/_textures/septasoulTexture_bump";
playerInfo.scale = new Vector3(10.0f);
// END HACK ===================
// Load Textures
textureList.Clear();
textureList.Add(Statics.SystemSettings.content.Load(playerInfo.texPath));
textureList.Add(Statics.SystemSettings.content.Load(playerInfo.bumpPath));
// Load Animated Model
model = Statics.SystemSettings.content.Load(playerInfo.modelPath);
mass.scale = playerInfo.scale;
foreach (ModelMesh mesh in model.Meshes)
{
for (int i = 0; i < mesh.MeshParts.Count; i++)
{
ModelMeshPart part = mesh.MeshParts[i];
part.Effect = ShaderParameters.effect_draw.Clone(Statics.SystemSettings.graphics.GraphicsDevice);
}
}
// Create Animators
animator = new ModelAnimator(model);
idle = new AnimationController(animator.Animations["idle"]);
walk = new AnimationController(animator.Animations["walk"]);
die = new AnimationController(animator.Animations["die"]);
RunController(animator, idle);
// Create Animation Transforms
if (playerInfo.name == "dojoboy" || playerInfo.name == "dojogirl")
{
initialTransform = Matrix.CreateRotationY((float)(-Math.PI / 2.0f)) * Matrix.CreateTranslation(new Vector3(0, -Statics.PlayerSettings.DEFAULT_PLAYER_HEIGHT / 2.0f, 0));
}
else if (playerInfo.name == "bunny")
{
initialTransform = Matrix.CreateTranslation(new Vector3(0, Statics.PlayerSettings.DEFAULT_PLAYER_HEIGHT, 0));
}
else if (playerInfo.name == "fish")
{
initialTransform = Matrix.CreateRotationY((float)(-Math.PI)) * Matrix.CreateTranslation(new Vector3(0, -Statics.PlayerSettings.DEFAULT_PLAYER_HEIGHT / 2.0f + 5, 0));
}
else
{
initialTransform = Matrix.Identity;
}
// Load non-animated Model
shieldModel = Statics.SystemSettings.content.Load("Content/_models/Shield");
foreach (ModelMesh mesh in shieldModel.Meshes)
{
for (int i = 0; i < mesh.MeshParts.Count; i++)
{
// Add effect to mesh
mesh.MeshParts[i].Effect = ShaderParameters.effect_draw;
}
}
textureList.Add(Statics.SystemSettings.content.Load("Content/_textures/RockQuartz"));
textureList.Add(Statics.SystemSettings.content.Load("Content/_textures/EarthParticleLava"));
textureList.Add(Statics.SystemSettings.content.Load("Content/_textures/Water"));
textureList.Add(Statics.SystemSettings.content.Load("Content/_textures/AirParticleCold"));
// Reset the Rate of Fire limiter
RateOfFire = new Stopwatch();
RateOfFire.Start();
energyStabalizeTimer = new Stopwatch();
energyStabalizeTimer.Start();
mannaIncrement = new Stopwatch();
mannaIncrement.Start();
kills = 0;
killedBy = -1;
terrainModEnabled = false;
earthElementSelected = true;
fireElementSelected = false;
waterElementSelected = false;
airElementSelected = false;
lastModeSelected = Enums.AttackType.EARTH;
//relies on the x,z being set somewhere else..
try
{
int x = (int)(Statics.TerrainSettings.collisionMapSize * float.Parse(node.Attributes["startx"].Value));
int z = (int)(Statics.TerrainSettings.collisionMapSize * float.Parse(node.Attributes["startz"].Value));
spawnHeight = objectLibrary.terrain.GetTerrainHeight(x / Statics.TerrainSettings.terrainScaleFactor, z / Statics.TerrainSettings.terrainScaleFactor);
SetSpawnPoint(new Vector3(x, spawnHeight + Statics.PlayerSettings.DEFAULT_PLAYER_HEIGHT, z));
}
catch { System.Diagnostics.Debug.WriteLine("Error reading player attributes"); return false; }
mass.boundingVolume.UpdateSphere(mass.currentPosition);
return true;
}
#region UpdateCalls
private void RunController(ModelAnimator animator, AnimationController controller)
{
foreach (BonePose p in animator.BonePoses)
{
p.CurrentController = (IAnimationController)controller;
p.CurrentBlendController = null;
}
currentAnimation = controller;
}
private void UpdateController(ObjectLibrary objectLibrary)
{
lookAtPoint = new Vector3();
currentAnimation.Update(Statics.SystemSettings.elementalGameTime);
if (currentAnimation != idle)
{
RunController(animator, idle);
}
// Rotation Controls
if (DarkWynterGame.playerController.gameInput.playerRotation != Vector2.Zero)
{
if (controlsInverted)
{
mass.Rotate(-DarkWynterGame.playerController.gameInput.playerRotation.Y, DarkWynterGame.playerController.gameInput.playerRotation.X);
}
else
{
mass.Rotate(DarkWynterGame.playerController.gameInput.playerRotation.Y, DarkWynterGame.playerController.gameInput.playerRotation.X);
}
if (terrainModEnabled)
{
terrainModTarget = Vector3.Zero;
}
}
// Translation Controls
if (DarkWynterGame.playerController.gameInput.playerMotion != Vector2.Zero)
{
mass.MovePlayer(DarkWynterGame.playerController.gameInput.playerMotion.Y, DarkWynterGame.playerController.gameInput.playerMotion.X);
if (terrainModEnabled)
{
terrainModTarget = Vector3.Zero;
}
RunController(animator, walk);
}
// Zoom Control
if (DarkWynterGame.playerController.gameInput.zoomAmount != 0.0f)
{
Statics.RenderSettings.zoomFactor += DarkWynterGame.playerController.gameInput.zoomAmount;
if (Statics.RenderSettings.zoomFactor < 1.0f)
Statics.RenderSettings.zoomFactor = 1.0f;
else if (Statics.RenderSettings.zoomFactor > 5.0f)
Statics.RenderSettings.zoomFactor = 5.0f;
}
// Cutoff point for what the player can do while dead.......
if (IsAlive() == false)
{
RunController(animator, die);
return;
}
// Incrementaly regenerate players manna
if (mannaIncrement.ElapsedMilliseconds >= Statics.PlayerSettings.MANNA_INCREMENT_RATE)
{
mannaIncrement.Reset();
mannaIncrement.Start();
ChangeManna(+2);
}
// Player fall damage applied
if (mass.fallingDamageMultiplier != 0.0f)
{
ChangeHealth(-mass.fallingDamageMultiplier * Statics.PlayerSettings.FALLING_HEALTH_LOSS, objectLibrary);
mass.fallingDamageMultiplier = 0.0f;
if (IsAlive() == false)
{
Kill(playerIndex, objectLibrary);
// Killed himself
if (playerIndex < 4)
{
((Human)this).SetKilledByInfo("SPLAT!!!");
}
}
}
// Toggle movement type
if (DarkWynterGame.playerController.gameInput.movementTypeToggle)
{
if (mass.movementType == Enums.MovementType.WALK)
{
mass.movementType = Enums.MovementType.HOVER;
}
else
{
mass.movementType = Enums.MovementType.WALK;
mass.totalForce = Vector3.Zero;
mass.velocity = Vector3.Zero;
}
}
// Set Mass and Energy of Attack
attackMagnitude += DarkWynterGame.playerController.gameInput.massChangeDelta;
attackTemperature += DarkWynterGame.playerController.gameInput.thermalChangeDelta;
if (attackMagnitude < 1) { attackMagnitude = 1; }
else if (attackMagnitude > 100) { attackMagnitude = 100; }
if (attackTemperature < 0) { attackTemperature = 0; }
else if (attackTemperature > 100) { attackTemperature = 100; }
// Check for Attack request from user
if (DarkWynterGame.playerController.gameInput.terrainModToggle)
{
terrainModEnabled = !terrainModEnabled;
}
if (terrainModEnabled && DarkWynterGame.playerController.gameInput.attack != 0)
{
DarkWynterGame.playerController.gameInput.attackMode = Enums.AttackMode.TERRAIN_MOD;
}
else if (DarkWynterGame.playerController.gameInput.attackAmount > 0)
{
DarkWynterGame.playerController.gameInput.attackMode = Enums.AttackMode.ATTACK;
}
else
{
DarkWynterGame.playerController.gameInput.attackMode = Enums.AttackMode.NONE;
}
// Set the LookAt point
if (terrainModEnabled)
{
lookAtPoint = majikWand.LookAtTerrainPoint(objectLibrary,this);
if (lookAtPoint.X < 0.0f)
{
lookAtPoint = new Vector3(0.0f, 500.0f, 0.0f);
}
}
// Player Attack
if (DarkWynterGame.playerController.gameInput.attack != 0)
{
// Does player have enough manna?
if (manna > Statics.PlayerSettings.ATTACK_MANNA_COST)
{
// Is terrainMod switch on
if (DarkWynterGame.playerController.gameInput.attackMode == Enums.AttackMode.TERRAIN_MOD)
{
if (ChangeManna(-Math.Abs(DarkWynterGame.playerController.gameInput.attack) * 0.1f))
{
if (targetObject == Enums.ObjectType.TERRAIN)
{
majikWand.TerrainMod(DarkWynterGame.playerController.gameInput.attack, objectLibrary, this);
}
}
}
// must be an attack or defend
else
{
// Check if fire button was used
if (manna > DarkWynterGame.playerController.gameInput.attack / 2.0f)
{
if (fireElementSelected)
{
if (ChangeManna(-Statics.PlayerSettings.ENERGY_BEAM_MANNA_COST))
{
// Play audio for each human
foreach (Human human in objectLibrary.humans)
{
if (human.IsAlive())
{
Audio.FireAttack(pSounds, mass.currentPosition, human.mass.currentPosition);
}
}
// Fire Attack
//UseEnergyBeam(objectLibrary, DarkWynterGame.playerController.gameInput.attack);
Attack_Bullet(Enums.BulletType.Water, objectLibrary);
firingEnergyBeam = true;
}
}
}
else
{
firingEnergyBeam = false;
}
// Check if particle Attack was initiated
if (DarkWynterGame.playerController.gameInput.attackAmount > 0.0f && manna > Statics.PlayerSettings.ATTACK_MANNA_COST)
{
// AND make sure they are not shielding at the same time
if (DarkWynterGame.playerController.gameInput.defendAmount == 0.0f)
{
// Attack
if (earthElementSelected)
{
//Attack_Grenade(Particle.ParticleType.Earth, objectLibrary);
Attack_Swarm(objectLibrary);
}
else if (waterElementSelected)
{
Attack_Grenade(Enums.ParticleType.Water, objectLibrary);
}
else if (airElementSelected)
{
Attack_Grenade(Enums.ParticleType.Air, objectLibrary);
}
}
}
// Player uses shield
if (DarkWynterGame.playerController.gameInput.defendAmount > 0.0f && manna > Statics.PlayerSettings.SHIELD_MANNA_COST)
{
//Set player's shield to last element selected
switch (lastModeSelected)
{
case Enums.AttackType.WIND:
activeShield = Enums.AttackType.WIND;
break;
case Enums.AttackType.EARTH:
activeShield = Enums.AttackType.EARTH;
break;
case Enums.AttackType.WATER:
activeShield = Enums.AttackType.WATER;
break;
case Enums.AttackType.FIRE:
case Enums.AttackType.NONE:
activeShield = Enums.AttackType.NONE;
break;
}
}
else
{
activeShield = Enums.AttackType.NONE;
}
}
}
}
// If triggers not pressed at all
else
{
activeShield = Enums.AttackType.NONE;
}
// See if player is jumping
if (DarkWynterGame.playerController.gameInput.jump)
{
if (CheckPlayerOnTerrain(objectLibrary) == false)
{
mass.AddForce(new Vector3(0, Statics.PlayerSettings.IN_AIR_JUMP_CONSTANT, 0));
}
else
{
mass.AddForce(new Vector3(0, Statics.PlayerSettings.JUMP_CONSTANT, 0));
}
RunController(animator, die);
}
// See if player changed the Element mode
if (DarkWynterGame.playerController.gameInput.modeSwitch != Enums.AttackType.NONE)
{
switch (DarkWynterGame.playerController.gameInput.modeSwitch)
{
case Enums.AttackType.WIND:
{
airElementSelected = true;// !airElementSelected;
if (airElementSelected)
{
// Disable earth and water
earthElementSelected = false;
waterElementSelected = false;
fireElementSelected = false;
lastModeSelected = Enums.AttackType.WIND;
}
else
{
lastModeSelected = Enums.AttackType.NONE;
}
}
break;
case Enums.AttackType.EARTH:
{
earthElementSelected = true;// !earthElementSelected;
if (earthElementSelected)
{
// Disable air and water
airElementSelected = false;
waterElementSelected = false;
fireElementSelected = false;
lastModeSelected = Enums.AttackType.EARTH;
}
else
{
lastModeSelected = Enums.AttackType.NONE;
}
}
break;
case Enums.AttackType.FIRE:
{
fireElementSelected = true;// !fireElementSelected;
airElementSelected = false;
waterElementSelected = false;
earthElementSelected = false;
if (fireElementSelected)
{
lastModeSelected = Enums.AttackType.FIRE;
}
else
{
lastModeSelected = Enums.AttackType.NONE;
}
}
break;
case Enums.AttackType.WATER:
{
waterElementSelected = true;// !waterElementSelected;
if (waterElementSelected)
{
// Disable earth and air
earthElementSelected = false;
airElementSelected = false;
fireElementSelected = false;
lastModeSelected = Enums.AttackType.WATER;
}
else
{
lastModeSelected = Enums.AttackType.NONE;
}
}
break;
case Enums.AttackType.TERRAIN:
{
lastModeSelected = Enums.AttackType.TERRAIN;
}
break;
}
}
// Check the player's overall velocity
if (mass.velocity.Length() > Statics.PlayerSettings.MAX_VELOCITY)
{
// If NOT falling
//if (Math.Abs(mass.velocity.Y) < Math.Abs(mass.velocity.X) || Math.Abs(mass.velocity.Y) < Math.Abs(mass.velocity.Z))
//{
mass.velocity.Normalize();
mass.velocity *= Statics.PlayerSettings.MAX_VELOCITY;
//}
}
}
///
/// Update player
///
/// ObjectLibrary
public override void Update(ref ObjectLibrary objectLibrary)
{
if (energyStabalizeTimer.ElapsedMilliseconds > 3000)
{
//update player's energy value
if (mass.energy < 0.0f)
{
mass.ChangeEnergy(0.01f);
}
else if (mass.energy > 0.0f)
{
mass.ChangeEnergy(-0.01f);
}
energyStabalizeTimer.Reset();
energyStabalizeTimer.Start();
}
if (currentAnimation != null)
{
currentAnimation.Update(Statics.SystemSettings.elementalGameTime);
}
animator.Update();
UpdateController(objectLibrary);
mass.UpdatePosition();
mass.isMoving = true;
//if (mass.isMoving && !Statics.dynamicList.Contains(mass))
//{
// Statics.dynamicList.Add(mass);
//}
mass.boundingVolume.UpdateSphere(mass.currentPosition);
Vector3 sensorDistance;
if (mass.movementType == Enums.MovementType.WALK)
{
sensorDistance = mass.sensorDirection + Vector3.Zero;
}
else
{
sensorDistance = mass.velocity + Vector3.Zero;
}
if (sensorDistance.Length() > Statics.PlayerSettings.MAX_SENSOR_DISTANCE)
{
sensorDistance.Normalize();
sensorDistance = sensorDistance * Statics.PlayerSettings.MAX_SENSOR_DISTANCE;
}
//collisionSensor.mass.SetPosition(mass.currentPosition + sensorDistance,
// mass.currentPosition + sensorDistance * 1.5f);
if (spawnDoneTimer.IsRunning)
{
if (spawnDoneTimer.ElapsedMilliseconds >= Statics.PlayerSettings.SPAWN_DONE_DELAY)
{
spawnDoneTimer.Stop();
spawnDoneTimer.Reset();
}
}
// Play audio for each human
foreach (Human human in objectLibrary.humans)
{
if (human.IsAlive())
{
if (DarkWynterGame.playerController.gameInput.playerMotion.Length() > 0)
{
Audio.Walking(pSounds, mass.currentPosition, human.mass.currentPosition);
}
if (DarkWynterGame.playerController.gameInput.jump)
{
Audio.Jump(pSounds, mass.currentPosition, human.mass.currentPosition);
}
}
}
}
#endregion
#region Draw Calls
///
/// General case draw function
///
/// Model Manager
/// Draw technique to use
public override void Draw(ModelManager modelManager, string technique)
{
// Did we die??
if (IsAlive() == false)
{
return;
}
//check spawn done delay
if (spawnDoneTimer.IsRunning)
{
float ratio = (float)spawnDoneTimer.ElapsedMilliseconds / (float)Statics.PlayerSettings.SPAWN_DONE_DELAY;
SetDiffuseAlpha(ratio);
}
else
{
SetDiffuseAlpha(255);
}
// Calculate ObjectSpace(Rotation) and WorldSpace(Translation) Transformation Matrix
matrix = initialTransform * Matrix.CreateScale(mass.scale) *
Matrix.CreateFromQuaternion(mass.currentRotation) *
Matrix.CreateTranslation(mass.currentPosition);
DrawAnimation();
}
///
/// Draw the energy beam
///
/// ObjectLibrary
public void DrawEnergyBeam(ObjectLibrary objectLibrary)
{
if (fireElementSelected == true && DarkWynterGame.playerController.gameInput.attack != 0.0f && manna > -DarkWynterGame.playerController.gameInput.attack / 2.0f)
{
Vector3 startPosition = mass.currentPosition + mass.perpVector + mass.normalVector - mass.upVector * 3;
Vector3 targetPosition;
float[] diffuse = { 1, 1, 1, 1 };
// Get the particles information from LookAtPoint and store it in the local vector3 lookAtPoint
Vector3 lookPoint = majikWand.LookAtObject(objectLibrary, this);
// Check if the target object was Earth
if (targetObject == Enums.ObjectType.PARTICLE)
{
targetPosition = mass.currentPosition + mass.normalVector * lookPoint.Length();
}
else
{
targetPosition = mass.currentPosition + mass.normalVector * Statics.PlayerSettings.TERRAIN_MOD_RANGE;
}
matrix = Matrix.Identity;
ShaderParameters.World.SetValue(matrix);
ShaderParameters.materialDiffuse.SetValue(diffuse);
//fire texture
ShaderParameters.modelTexture1.SetValue(textureList[4]);
//water texture
ShaderParameters.modelTexture2.SetValue(textureList[3]);
//should interpolate
ShaderParameters.particleEnergyValue.SetValue((DarkWynterGame.playerController.gameInput.attack / 2.0f) + 0.5f);
VertexPositionTexture[] list = new VertexPositionTexture[6];
float size = 1.0f;
list[0].Position = startPosition - mass.perpVector * size;// new Vector3(-size, 0, 0);
//list[0].Color = new Color(0, 0, 0);
list[0].TextureCoordinate = new Vector2(0, 1);
list[1].Position = targetPosition - mass.perpVector * size + mass.normalVector * size;// new Vector3(-size, 0, size);
//list[1].Color = new Color(0, 255, 0);
list[1].TextureCoordinate = new Vector2(0, 0);
list[2].Position = targetPosition + mass.perpVector * size + mass.normalVector * size;//new Vector3(size, 0, size);
//list[2].Color = new Color(0, 0, 255);
list[2].TextureCoordinate = new Vector2(1, 0);
list[3].Position = list[0].Position;//new Vector3(-size, 0, 0);
//list[3].Color = new Color(255, 255, 255);
list[3].TextureCoordinate = list[0].TextureCoordinate;
list[4].Position = list[2].Position;//new Vector3(size, 0, size);
//list[4].Color = new Color(0, 0, 0);
list[4].TextureCoordinate = list[2].TextureCoordinate;
list[5].Position = startPosition + mass.normalVector * size;//new Vector3(0, 0, size);
//list[5].Color = new Color(0, 100, 0);
list[5].TextureCoordinate = new Vector2(1, 1);
// Technique
ShaderParameters.effect_draw.CurrentTechnique = ShaderParameters.effect_draw.Techniques["EnergyBeamShaderMain"];
ShaderParameters.effect_draw.Begin();
foreach (EffectPass pass in ShaderParameters.effect_draw.CurrentTechnique.Passes)
{
pass.Begin();
Statics.SystemSettings.graphics.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, list, 0, 2);
pass.End();
}
ShaderParameters.effect_draw.End();
}
}
///
/// Draw player's shield around the player when it is enabled
///
public void DrawShield()
{
//if (activeShield != Enums.ShieldType.NO_SHIELD)
// HACK: THIS IS TO SEE THE PLAYER AT ALL TIMES
if (true)
{
matrix = Matrix.CreateScale(mass.boundingVolume.radius * 5) *
Matrix.CreateTranslation(mass.currentPosition);
ShaderParameters.World.SetValue(matrix);
ShaderParameters.modelTexture1.SetValue(textureList[4]);
switch (activeShield)
{
case Enums.AttackType.EARTH:
{
ShaderParameters.modelTexture1.SetValue(textureList[2]);
break;
}
case Enums.AttackType.FIRE:
{
ShaderParameters.modelTexture1.SetValue(textureList[3]);
break;
}
case Enums.AttackType.WATER:
{
ShaderParameters.modelTexture1.SetValue(textureList[4]);
break;
}
case Enums.AttackType.WIND:
{
ShaderParameters.modelTexture1.SetValue(textureList[5]);
break;
}
}
// Draw the shield model
base.DrawTriStrips(shieldModel, "ShieldShaderMain");
}
}
///
/// Draw the animated player model
///
public void DrawAnimation()
{
try
{
animator.world = matrix;
animator.Update();
currentAnimation.Update(Statics.SystemSettings.elementalGameTime);
int index = 0;
// Update all the effects with the palette and world and draw the meshes
for (int i = 0; i < animator.numMeshes; i++)
{
// Get the mesh
ModelMesh mesh = model.Meshes[i];
// The starting index for the modelEffects array
int effectStartIndex = index;
if (animator.palette[i] != null && animator.matrixPaletteParams[index] != null)
{
foreach (Effect effect in mesh.Effects)
{
animator.worldParams[index].SetValue(matrix);
animator.matrixPaletteParams[index].SetValue(animator.palette[i]);
index++;
}
}
else
{
foreach (Effect effect in mesh.Effects)
{
animator.worldParams[index].SetValue(animator.pose[mesh.ParentBone.Index] * matrix);
index++;
}
}
int numParts = mesh.MeshParts.Count;
GraphicsDevice device = mesh.VertexBuffer.GraphicsDevice;
device.Indices = mesh.IndexBuffer;
for (int j = 0; j < numParts; j++)
{
ModelMeshPart currentPart = mesh.MeshParts[j];
if (currentPart.NumVertices == 0 || currentPart.PrimitiveCount == 0)
continue;
Effect currentEffect = animator.modelEffects[effectStartIndex + j];
if (animator.palette[i] != null && animator.matrixPaletteParams[i] != null)
{
currentEffect.CurrentTechnique = currentEffect.Techniques["SkinnedPlayerShaderMain"];
}
else
{
currentEffect.CurrentTechnique = currentEffect.Techniques["PlayerShaderMain"];
}
currentEffect.Parameters["modelTexture1"].SetValue(textureList[0]);
currentEffect.Parameters["bumpTexture1"].SetValue(textureList[1]);
// Lighting
currentEffect.Parameters["shininess"].SetValue(7000.0f);
currentEffect.Parameters["particleEnergyValue"].SetValue((mass.energy / 2.0f) + 0.5f);
currentEffect.Parameters["playerIsDead"].SetValue(!IsAlive());
currentEffect.Parameters["ViewProj"].SetValue(Statics.RenderSettings.matrixView * Statics.RenderSettings.matrixProjection);
currentEffect.Parameters["EyePostion"].SetValue(Matrix.Invert(Statics.RenderSettings.matrixView));
currentEffect.Parameters["lightPosition0"].SetValue(Statics.LevelSettings.lightPosition1);
currentEffect.Parameters["lightAmbient0"].SetValue(Statics.LevelSettings.lightAmbient1);
currentEffect.Parameters["lightDiffuse0"].SetValue(Statics.LevelSettings.lightDiffuse1);
currentEffect.Parameters["lightSpecular0"].SetValue(Statics.LevelSettings.lightSpecular1);
if (Statics.SystemSettings.singleLightSource)
{
currentEffect.Parameters["lightPosition1"].SetValue(Statics.LevelSettings.lightPosition1);
currentEffect.Parameters["lightAmbient1"].SetValue(Statics.LevelSettings.lightAmbient1);
currentEffect.Parameters["lightDiffuse1"].SetValue(Statics.LevelSettings.lightDiffuse1);
currentEffect.Parameters["lightSpecular1"].SetValue(Statics.LevelSettings.lightSpecular1);
}
else
{
currentEffect.Parameters["lightPosition1"].SetValue(Statics.LevelSettings.lightPosition2);
currentEffect.Parameters["lightAmbient1"].SetValue(Statics.LevelSettings.lightAmbient2);
currentEffect.Parameters["lightDiffuse1"].SetValue(Statics.LevelSettings.lightDiffuse2);
currentEffect.Parameters["lightSpecular1"].SetValue(Statics.LevelSettings.lightSpecular2);
}
currentEffect.Parameters["materialDiffuse"].SetValue(materialDiffuse);
device.VertexDeclaration = currentPart.VertexDeclaration;
device.Vertices[0].SetSource(mesh.VertexBuffer, currentPart.StreamOffset, currentPart.VertexStride);
currentEffect.Begin();
EffectPassCollection passes = currentEffect.CurrentTechnique.Passes;
int numPasses = passes.Count;
for (int k = 0; k < numPasses; k++)
{
EffectPass pass = passes[k];
pass.Begin();
device.DrawIndexedPrimitives(PrimitiveType.TriangleList, currentPart.BaseVertex,
0, currentPart.NumVertices, currentPart.StartIndex, currentPart.PrimitiveCount);
pass.End();
}
currentEffect.End();
}
}
}
catch (NullReferenceException)
{
throw new InvalidOperationException("The effects on the model for a " +
"ModelAnimator were changed without calling ModelAnimator.InitializeEffectParams().");
}
catch (InvalidCastException)
{
throw new InvalidCastException("ModelAnimator has thrown an InvalidCastException. This is " +
"likely because the model uses too many bones for the matrix palette. The default palette size "
+ "is 56 for windows and 40 for Xbox.");
}
}
///
/// Draw the player model for AI-Vision pass
///
/// View matrix
/// Projection matrix
/// Player index
public void DrawAIVision(Matrix view, Matrix proj, float playerIndex)
{
//return;
try
{
matrix = initialTransform *
Matrix.CreateScale(mass.scale) *
Matrix.CreateFromQuaternion(mass.currentRotation) *
Matrix.CreateTranslation(mass.currentPosition);
animator.world = matrix;
int index = 0;
// Update all the effects with the palette and world and draw the meshes
for (int i = 0; i < animator.numMeshes; i++)
{
ModelMesh mesh = model.Meshes[i];
// The starting index for the modelEffects array
int effectStartIndex = index;
if (animator.palette[i] != null && animator.matrixPaletteParams[index] != null)
{
foreach (Effect effect in mesh.Effects)
{
animator.worldParams[index].SetValue(matrix);
animator.matrixPaletteParams[index].SetValue(animator.palette[i]);
index++;
}
}
else
{
foreach (Effect effect in mesh.Effects)
{
animator.worldParams[index].SetValue(animator.pose[mesh.ParentBone.Index] * matrix);
index++;
}
}
int numParts = mesh.MeshParts.Count;
GraphicsDevice device = mesh.VertexBuffer.GraphicsDevice;
device.Indices = mesh.IndexBuffer;
for (int j = 0; j < numParts; j++)
{
ModelMeshPart currentPart = mesh.MeshParts[j];
if (currentPart.NumVertices == 0 || currentPart.PrimitiveCount == 0)
continue;
Effect currentEffect = animator.modelEffects[effectStartIndex + j];
currentEffect.CurrentTechnique = currentEffect.Techniques["AI_Vision_PlayerShaderMain"];
currentEffect.Parameters["ViewProj"].SetValue(view * proj);
currentEffect.Parameters["playerIndex"].SetValue(playerIndex);
device.VertexDeclaration = currentPart.VertexDeclaration;
device.Vertices[0].SetSource(mesh.VertexBuffer, currentPart.StreamOffset, currentPart.VertexStride);
currentEffect.Begin();
EffectPassCollection passes = currentEffect.CurrentTechnique.Passes;
int numPasses = passes.Count;
for (int k = 0; k < numPasses; k++)
{
EffectPass pass = passes[k];
pass.Begin();
device.DrawIndexedPrimitives(PrimitiveType.TriangleList,
currentPart.BaseVertex,
0,
currentPart.NumVertices,
currentPart.StartIndex,
currentPart.PrimitiveCount);
pass.End();
}
currentEffect.End();
}
}
}
catch (NullReferenceException)
{
throw new InvalidOperationException("The effects on the model for a " +
"ModelAnimator were changed without calling ModelAnimator.InitializeEffectParams().");
}
catch (InvalidCastException)
{
throw new InvalidCastException("ModelAnimator has thrown an InvalidCastException. This is " +
"likely because the model uses too many bones for the matrix palette. The default palette size "
+ "is 56 for windows and 40 for Xbox.");
}
}
#endregion
#region Set the Player's color.
///
/// Set player's red component
///
/// Red component (0-255)
public void SetDiffuseRed(float red)
{
materialDiffuse[0] = (1.0f * red) / 255.0f;
}
///
/// Set player's green component
///
/// Green component (0-255)
public void SetDiffuseGreen(float green)
{
materialDiffuse[1] = (1.0f * green) / 255.0f;
}
///
/// Set player's blue component
///
/// Blue component (0-255)
public void SetDiffuseBlue(float blue)
{
materialDiffuse[2] = (1.0f * blue) / 255.0f;
}
///
/// Set player's alpha component
///
/// Alpha component (0-255)
public void SetDiffuseAlpha(float alpha)
{
materialDiffuse[3] = alpha;
}
private float[] GetDiffuseColor()
{
return materialDiffuse;
}
#endregion
#region Life, death, and taxes
///
/// Check if this player is a human
///
/// True if human
public bool IsHuman()
{
if (playerIndex < 4)
{
return true;
}
return false;
}
///
/// Check if player is alive
///
/// True if alive
public bool IsAlive()
{
return (health > 0);
}
private bool ChangeManna(float diff)
{
if (manna + diff < 0)
{
//don't have enough
return false;
}
manna += diff;
if (manna < 0)
{
manna = 0;
}
else if (manna > 100)
{
manna = 100;
}
return true;
}
///
/// Change the player's health
///
/// Change in health
/// ObjectLibrary
public void ChangeHealth(float diff, ObjectLibrary objectLibrary)
{
if (spawnDoneTimer.IsRunning)
{
return;
}
if (diff < 0)
{
// Play audio for each human
foreach (Human human in objectLibrary.humans)
{
if (human.IsAlive())
{
Audio.Hit(pSounds, mass.currentPosition, human.mass.currentPosition);
}
}
}
health += diff;
if (health < 0)
{
health = 0;
}
else if (health > 100)
{
health = 100;
}
}
private void Kill(int killerID)
{
killedBy = killerID;
//Begin their respawn timer
respawnTimer.Reset();
respawnTimer.Start();
}
private void Kill(int killerID, ObjectLibrary objectLibrary)
{
Kill(killerID);
AssignKillCredit( objectLibrary);
}
///
/// Assign kill credit to responsible player
///
/// ObjectLibrary
public void AssignKillCredit(ObjectLibrary objectLibrary)
{
// They were alive going into this method if they come out dead then
// We know someone killed them and can assign credit
// If the player did not suicide find out who killed them
if (killedBy != playerIndex)
{
if (killedBy < 4)
{
// Find the killer who is human
for (int i = 0; i < objectLibrary.humans.Count; i++)
{
// Assign credit to the killer
if (killedBy == objectLibrary.humans[i].playerIndex)
{
objectLibrary.humans[i].kills++;
}
}
}
else
{
// Find the bot that killed
for (int i = 0; i < objectLibrary.bots.Count; i++)
{
// Assign credit to the killer
if (killedBy == objectLibrary.bots[i].playerIndex)
{
objectLibrary.bots[i].kills++;
}
}
}
}
else
{
kills--;
}
}
///
/// Set the player's spawn point
///
/// Spawn point
public void SetSpawnPoint(Vector3 spawn)
{
spawnPosition = Vector3.Zero + spawn;
mass.SetPosition(spawnPosition, new Vector3(Statics.TerrainSettings.collisionMapSize / 2, 0, Statics.TerrainSettings.collisionMapSize / 2));
}
///
/// Respawn our player
///
public void SpawnPlayer()
{
// Remove from map
//Statics.lookupMap.RemoveLast(this.mass);
//Statics.lookupMap.RemoveCurrent(this.mass);
mass.velocity = Vector3.Zero;
mass.totalForce = Vector3.Zero;
spawnPosition.Y = spawnHeight + Statics.PlayerSettings.DEFAULT_PLAYER_HEIGHT;
mass.SetPosition(spawnPosition, new Vector3(Statics.TerrainSettings.collisionMapSize / 2, 0, Statics.TerrainSettings.collisionMapSize / 2));
mass.boundingVolume = new BoundingVolume(new BoundingSphere(
new Vector3(spawnPosition.X, Statics.PlayerSettings.DEFAULT_PLAYER_HEIGHT / 2.0f, spawnPosition.Z), mass.scale.Y/2));
health = 100;
manna = 100;
killedBy = -1;
activeShield = Enums.AttackType.NONE;
// Reset the Rate of Fire limiter
RateOfFire.Reset();
RateOfFire.Start();
energyStabalizeTimer.Reset();
energyStabalizeTimer.Start();
mannaIncrement = new Stopwatch();
mannaIncrement.Start();
//stop the respawn timer
respawnTimer.Stop();
respawnTimer.Reset();
//start the invincibility timer
spawnDoneTimer.Reset();
spawnDoneTimer.Start();
//Statics.lookupMap.SetPosition(this.mass);
}
///
/// Check if the player was hit by a particle
///
/// Particle
/// ObjectLibrary
/// Indicates if the particle needs to be recycled (True)
public bool PlayerHitByParticle(Particle particle, ObjectLibrary objectLibrary)
{
if ((particle.hasCollided != playerIndex && particle.ownerID != playerIndex) ||
(particle.hurtOwner == true && particle.ownerID == playerIndex))
{
// We know player is hit... determine which direction
Vector3 toParticle = new Vector3(particle.mass.currentPosition.X - mass.currentPosition.X,
particle.mass.currentPosition.Y - mass.currentPosition.Y,
particle.mass.currentPosition.Z - mass.currentPosition.Z);
Vector3 playerLook = new Vector3(mass.normalVector.X, 0, mass.normalVector.Z);
playerLook.Normalize();
Vector3 cross = Vector3.Cross(toParticle, playerLook);
if (cross.Y < 0)
{
hitWhere.Add(Enums.HitWhere.LEFT);
}
else
{
hitWhere.Add(Enums.HitWhere.RIGHT);
}
// Player shielded properly.. no damage and absorbs the particle
if ((activeShield == Enums.AttackType.EARTH && particle.particleType == Enums.ParticleType.Earth) ||
(activeShield == Enums.AttackType.WATER && particle.particleType == Enums.ParticleType.Water) ||
(activeShield == Enums.AttackType.WIND && particle.particleType == Enums.ParticleType.Air))
{
// Correct shield -> player absorbs manna
ChangeManna(Statics.PlayerSettings.SHIELD_MANNA_GAIN * particle.mass.mass);
if (IsHuman())
{
((Human)this).ShowMannaIndicator();
}
//Get rid of it altogether
//Statics.lookupMap.RemoveLast(particle.mass);
//Statics.lookupMap.RemoveCurrent(particle.mass);
//if (Statics.lookupMap.DynamicContains(particle.mass))
//{
// Statics.lookupMap.RemoveDynamic(particle.mass);
//}
particle.mass.ClearValues();
particle.mass.deadObject = true;
return true;
}
else
{
// Wrong shield -> player loses health
ChangeHealth(DamageCalculations(particle.mass, mass), objectLibrary);
// If tornado.. apply random force!
if (particle.particleType == Enums.ParticleType.Air)
{
mass.AddForce(new Vector3(0, particle.mass.mass * 100000, 0));
}
// If the player is dead and they haven't been assigned who killed them then do so
if (!IsAlive() && killedBy == -1)
{
Kill(particle.ownerID);
if (playerIndex < 4)
{
//Its a human.. set its killedby HUD info
((Human)this).SetKilledByInfo(particle);
}
}
}
particle.hasCollided = playerIndex;
particle.hasCollidedTimer = Stopwatch.StartNew();
}
return false;
}
private float DamageCalculations(Mass particleMass, Mass playerMass)
{
float damage = 0.0f;
Particle particle = ((Particle)particleMass.gameObjectPointer);
// ~ about between 0 and 1 for slow to fast
float particleVelocityRatio = particleMass.velocity.Length() / 2000.0f;
// Velocity.Length() range~
// Earth: 200-1600
// Water: 400-1700
// Air: 500-1700
// Particle type based damage modifier
if (particle.particleType == Enums.ParticleType.Earth)
{
if (particleMass.energy > 0.3f)
{
//lava hurts more
if (particleMass.velocity.Length() < 50)
{
//its slower.. it hurts more?
damage = 25.0f;
}
else
{
damage = 10.0f;
}
}
else
{
//frozen rock and rock are the same
damage = 5.0f + particleVelocityRatio;
}
}
else if (particle.particleType == Enums.ParticleType.Water)
{
if (particleMass.energy > 0.5f)
{
//boiling water hurts alot
if (particleMass.velocity.Length() < 50)
{
damage = 25.0f;
}
else
{
damage = 20.0f;
}
}
else if (particleMass.energy < 0.0f)
{
//frozen ice hurts a bit more
damage = 3.0f + particleVelocityRatio;
}
else
{
//regular water doesn't hurt that much
if (particleMass.velocity.Length() < 50)
{
//slow water doesn't hurt
damage = 0.0f;
}
else
{
damage = 10.0f;
}
}
}
else //air particle is all the same
{
damage = 0.1f + particleVelocityRatio;
}
float totalDamage = -damage * (1 + (particleMass.mass / 5.0f)) * Statics.PlayerSettings.DIRECT_HEALTH_LOSS;
Debug.WriteLine("Particle type=" + particle.particleType.ToString() + ",mass=" + particleMass.mass + ", vRatio=" + particleVelocityRatio
+ ", v=" + particleMass.velocity.Length() + " damage=" + damage + "...total= " + totalDamage + ".... energy=" + particleMass.energy);
return totalDamage;
}
#endregion
#region Player Abilities
private void UseEnergyBeam(ObjectLibrary objectLibrary, float elementUse)
{
Vector3 lookAtPoint = new Vector3(-1.0f);
// Get the particles information from LookAtPoint and store it in the local vector3 lookAtPoint
lookAtPoint = majikWand.LookAtObject(objectLibrary, this);
// Check if the target object was a particle or a player
if (targetObject == Enums.ObjectType.PARTICLE || targetObject == Enums.ObjectType.PLAYER)
{
if (targetObject == Enums.ObjectType.PARTICLE)
{
// Reference the particle from lookupMap
LinkedList linkedList = new LinkedList(); //Statics.lookupMap.GetListXZ((int)lookAtPoint.X / Statics.TerrainSettings.terrainScaleFactor,
//(int)lookAtPoint.Z / Statics.TerrainSettings.terrainScaleFactor);
int j = 0;
foreach (Mass massObj in linkedList)
{
if (j == (int)lookAtPoint.Y)
{
gameObject = massObj.gameObjectPointer;
break;
}
j++;
}
}
else //its a player
{
if ((int)lookAtPoint.Y < 4)
{
//its a human
gameObject = objectLibrary.humans[(int)lookAtPoint.Y];
}
else
{
//its a bot
gameObject = objectLibrary.bots[(int)lookAtPoint.Y - 4];
}
}
if (gameObject == null)
{
//didn't find it.. probably won't happen but just in case
return;
}
// Expel or absorb energy
float cost = 0;
/*
if (elementUse < 0)
{
if (targetObject == Enums.ObjectType.PARTICLE)
{
//absorb manna from particle
cost = -Statics.PlayerSettings.PARTICLE_ABSORB_MANNA_COST * -elementUse;
}
else
{
//absorb health from player
cost = -Statics.PlayerSettings.PLAYER_ABSORB_MANNA_COST * -elementUse;
}
}
else
{
//expel
cost = -Statics.PlayerSettings.EXPEL_MANNA_COST * elementUse;
}
*/
if (targetObject == Enums.ObjectType.PARTICLE)
{
if (Math.Abs(gameObject.mass.energy) <= 1.0f && ChangeManna(cost))
{
float dEnergy = elementUse;
//If we use dpad: float dEnergy = (particleThermalValue - 37) / 40.0f;
gameObject.mass.ChangeEnergy(dEnergy * 0.01f);
if (gameObject.mass.objectType == Enums.ObjectType.PARTICLE)
{
((Particle)gameObject).ownerID = playerIndex;
}
gameObject.mass.isChanging = true;
if (elementUse < 0)
{
//add manna
ChangeManna(Statics.PlayerSettings.PARTICLE_ABSORB_MANNA_GAIN * -elementUse);
if (IsHuman())
{
((Human)this).ShowMannaIndicator();
}
}
}
}
else
{
if (Math.Abs(gameObject.mass.energy) <= 1.0f && ChangeManna(cost))
{
float dEnergy = elementUse;
//If we use dpad: float dEnergy = (particleThermalValue - 37) / 40.0f;
gameObject.mass.ChangeEnergy(dEnergy * 0.01f);
if (elementUse < 0)
{
//add health from player
ChangeHealth(Statics.PlayerSettings.PLAYER_ABSORB_HEALTH_GAIN * -elementUse, objectLibrary);
((Player)gameObject).ChangeHealth(-Statics.PlayerSettings.PLAYER_ABSORB_HEALTH_GAIN * -elementUse, objectLibrary);
}
else
{
//hurt player
((Player)gameObject).ChangeHealth(-Statics.PlayerSettings.EXPEL_HEALTH_LOSS * elementUse, objectLibrary);
}
//check if we killed the player
if (((Player)gameObject).IsAlive() == false)
{
((Player)gameObject).Kill(playerIndex, objectLibrary);
if (((Player)gameObject).IsHuman())
{
//set killed info on screen for human
string s;
if (IsHuman())
{
s = "Player " + (playerIndex + 1);
}
else
{
s = "Bot " + (playerIndex + 1);
}
((Human)gameObject).SetKilledByInfo("ZAPPED by " + s);
}
}
}
}
}
}
private void Attack_Grenade(Enums.ParticleType type, ObjectLibrary objectLibrary)
{
// Enable shooting again if Rate Of Fire timer returns greater than the static fire rate
if (RateOfFire.Elapsed.TotalMilliseconds > Statics.PlayerSettings.RATE_OF_FIRE + ((float)attackMagnitude * 10.0f))
{
// Reset the rate of fire counter
RateOfFire.Reset();
RateOfFire.Start();
// Charge Manna
if (ChangeManna(-Statics.PlayerSettings.ATTACK_MANNA_COST * ((attackMagnitude + attackTemperature) / 10.0f)))
{
// Start the attack
objectLibrary.Attack_Grenade(playerIndex, type, mass.currentPosition + 5 * mass.normalVector, mass.normalVector, attackMagnitude, attackTemperature);
}
}
}
private void Attack_Bullet(Enums.BulletType type, ObjectLibrary objectLibrary)
{
// Enable shooting again if Rate Of Fire timer returns greater than the static fire rate
if (RateOfFire.Elapsed.TotalMilliseconds > Statics.PlayerSettings.RATE_OF_FIRE + ((float)attackMagnitude * 10.0f))
{
// Reset the rate of fire counter
RateOfFire.Reset();
RateOfFire.Start();
// Charge Manna
if (ChangeManna(-Statics.PlayerSettings.ATTACK_MANNA_COST * ((attackMagnitude + attackTemperature) / 10.0f)))
{
// Start the attack
objectLibrary.Attack_Bullet(playerIndex, type, mass.currentPosition + 5 * mass.normalVector, mass.normalVector, attackMagnitude, attackTemperature);
}
}
}
private void Attack_Swarm(ObjectLibrary objectLibrary)
{
// Enable shooting again if Rate Of Fire timer returns greater than the static fire rate
//if (RateOfFire.Elapsed.TotalMilliseconds > Statics.PlayerSettings.RATE_OF_FIRE + ((float)attackMagnitude * 10.0f))
//{
// Reset the rate of fire counter
// RateOfFire.Reset();
//RateOfFire.Start();
// Charge Manna
//if (ChangeManna(-Statics.PlayerSettings.ATTACK_MANNA_COST * ((attackMagnitude + attackTemperature) / 10.0f)))
//{
// Start the attack
objectLibrary.Attack_Swarm(playerIndex, mass.currentPosition + 5 * mass.normalVector, mass.normalVector, attackMagnitude, attackTemperature);
//}
//}
}
///
/// Check to see if the player is flying or on the ground
///
/// ObjectLibrary
/// On ground = True
public bool CheckPlayerOnTerrain(ObjectLibrary objectLibrary)
{
base.GetObjectHeight(objectLibrary.terrain);
// Get difference between average and player
if (heightDifference < 0.0f)
{
// In the Air
return false;
}
else
{
// On the Ground
return true;
}
}
#endregion
#region Collision Responses
///
/// Add Player specific responses to an object to object collision involving this and collidedObject.
/// Uses collidedObject.collisionWithPlayerResponse to determine health and manna bonuses and damage.
///
/// Object that collided with this Player.
/// Resultant force of collision
/// ObjectLibrary
/// True = this object has to be recycled
public override bool ObjectCollisionResponse(GameObject collidedObject, Vector3 resultantForce, ObjectLibrary objectLibrary)
{
// collidedObject will be absorbed by the player so we don't need to calculate collision forces
switch (collidedObject.collisionWithPlayerResponse)
{
case Enums.CollisionResponses.HEALTHBONUS:
ChangeHealth((collidedObject.collisionMultiplier * resultantForce.Length()) * 1.0f, objectLibrary);
break;
case Enums.CollisionResponses.HEALTHLOSS:
mass.AddForce(resultantForce);
ChangeHealth((collidedObject.collisionMultiplier * resultantForce.Length()) * -1.0f, objectLibrary);
break;
case Enums.CollisionResponses.MANNABONUS:
ChangeManna(collidedObject.collisionMultiplier * 1.0f);
break;
case Enums.CollisionResponses.MANNALOSS:
mass.AddForce(resultantForce);
ChangeManna(collidedObject.collisionMultiplier * -1.0f);
break;
case Enums.CollisionResponses.NONE:
mass.AddForce(resultantForce);
break;
}
// Player did not absorb the colliding object
return false;
}
///
/// Add Player specific responses to an object to terrain collision involving this
///
/// Terrain
public override void TerrainCollisionResponse(Terrain terrain)
{
base.GetObjectHeight(terrain);
// Add Gravity if terrain and player are touching
if (heightDifference < 0.0f)
{
mass.AddForce(mass.mass * Statics.GameSettings.accelDueToGravity);
}
else if (heightDifference > 0.0f)
{
#region Walk
// Ground pushing up to negate gravity
if (mass.movementType == Enums.MovementType.WALK)
{
//only if its NOT a wall
if (heightDifference < Statics.PlayerSettings.DEFAULT_PLAYER_HEIGHT)
{
//just set their height!
mass.currentPosition.Y = localTerrainHeight + (mass.objectHeight / 2);
}
else
{
mass.KickBack(5.0f);
}
}
#endregion
#region Hover
else if (mass.movementType == Enums.MovementType.HOVER)
{
// Call base first
base.TerrainCollisionResponse(terrain);
//if (mass.totalForce.Y < 0.0f)
//{
// mass.totalForce.Y = 0.0f;
//}
//if (mass.velocity.Y < 0.0f)
//{
// mass.velocity.Y = 0.0f;
//}
mass.totalForce.Y = 0.0f;
mass.velocity.Y = 0.0f;
if (velocityTangentialComponent.Length() < 5.5f)
{
mass.totalForce = Vector3.Zero;
mass.acceleration = Vector3.Zero;
mass.velocity = Vector3.Zero;
}
else
{
// Add terrain rebound force to object
mass.AddForce((heightDifference * terrain.playerSurfaceTension * surfaceNormal));// +
//(totalForceNormalComponent + (velocityNormalComponent * mass.mass / Statics.SystemSettings.dt)));
// Pass everything to friction (friction coefficients, the normal force on the body and the direction of friction)
mass.AddFriction(mass.dynamicFrictionCoefficient + terrain.mass.dynamicFrictionCoefficient,
gravityNormalComponent.Length() * mass.mass,
-velocityTangentialComponent);
}
}
#endregion
mass.lastMaxHeight = 0;
}
}
#endregion
#endregion
}
}