/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of Penumbra Overture.
*
* Penumbra Overture is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Penumbra Overture is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Penumbra Overture. If not, see .
*/
#include "Player.h"
#include "PlayerHelper.h"
#include "Init.h"
#include "GameEntity.h"
#include "MapHandler.h"
#include "PlayerMoveStates.h"
#include "PlayerState_InteractHaptX.h"
#include "PlayerState_MiscHaptX.h"
#include "PlayerState_WeaponHaptX.h"
#include "PlayerState_Interact.h"
#include "PlayerState_Misc.h"
#include "PlayerState_Weapon.h"
#include "ButtonHandler.h"
#include "Inventory.h"
#include "Notebook.h"
#include "SaveHandler.h"
#include "EffectHandler.h"
#include "HapticGameCamera.h"
#include "TriggerHandler.h"
#include "Triggers.h"
#include "GlobalInit.h"
//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayer::cPlayer(cInit *apInit) : iUpdateable("Player")
{
mpInit = apInit;
mpScene = apInit->mpGame->GetScene();
mpGraphics = apInit->mpGame->GetGraphics();
mpGfxDrawer = mpGraphics->GetDrawer();
mpResources = apInit->mpGame->GetResources();
//Create and setup camera
mpCamera = mpScene->CreateCamera3D(eCameraMoveMode_Walk);
mpScene->SetCamera(mpCamera);
//Get Debug variables
mbShowHealth = mpInit->mpConfig->GetBool("Debug","ShowHealth",false);
mbShowSoundsPlaying = mpInit->mpConfig->GetBool("Debug","ShowSoundsPlaying",false);
mvSize.x = mpInit->mpGameConfig->GetFloat("Player","Width",1);
mvSize.y = mpInit->mpGameConfig->GetFloat("Player","Height",1);
mvSize.z = mvSize.x;
mfCameraHeightAdd = mpInit->mpGameConfig->GetFloat("Player","CameraHeightAdd",0);
mfDefaultMass = mpInit->mpGameConfig->GetFloat("Player","Mass",1);
mfMass = mfDefaultMass;
mfCrouchHeight = mpInit->mpGameConfig->GetFloat("Player","CrouchHeight",1);;
mfSpeedMul = 1.0f;
mfHeadMoveSizeMul = 1.0f;
mfHeadMoveSpeedMul = 1.0f;
mItemFlash.SetUp(0.3f,1,0,1,1);
//jump properties
mbJumpButtonDown = false;
mfJumpCount = 0;
mfMaxJumpCount = mpInit->mpGameConfig->GetFloat("Player","MaxJumpCount",1);
//Create and init player states
mState = ePlayerState_Normal;
mvStates.resize(ePlayerState_LastEnum);
if(mpInit->mbHasHaptics)
{
mvStates[ePlayerState_Normal] = hplNew( cPlayerState_NormalHaptX, (mpInit,this) );
mvStates[ePlayerState_Push] = hplNew( cPlayerState_PushHaptX, (mpInit,this) );
mvStates[ePlayerState_Move] = hplNew( cPlayerState_MoveHaptX, (mpInit,this) );
mvStates[ePlayerState_InteractMode] = hplNew( cPlayerState_InteractModeHaptX, (mpInit,this) );
mvStates[ePlayerState_Grab] = hplNew( cPlayerState_GrabHaptX, (mpInit,this) );
mvStates[ePlayerState_WeaponMelee] = hplNew( cPlayerState_WeaponMeleeHaptX, (mpInit,this) );
mvStates[ePlayerState_UseItem] = hplNew( cPlayerState_UseItemHaptX, (mpInit,this) );
mvStates[ePlayerState_Message] = hplNew( cPlayerState_MessageHaptX, (mpInit,this) );
mvStates[ePlayerState_Throw] = hplNew( cPlayerState_ThrowHaptX, (mpInit,this) );
mvStates[ePlayerState_Climb] = hplNew( cPlayerState_ClimbHaptX, (mpInit,this) );
}
else
{
mvStates[ePlayerState_Normal] = hplNew( cPlayerState_Normal, (mpInit,this) );
mvStates[ePlayerState_Push] = hplNew( cPlayerState_Push, (mpInit,this) );
mvStates[ePlayerState_Move] = hplNew( cPlayerState_Move, (mpInit,this) );
mvStates[ePlayerState_InteractMode] = hplNew( cPlayerState_InteractMode, (mpInit,this) );
mvStates[ePlayerState_Grab] = hplNew( cPlayerState_Grab, (mpInit,this) );
mvStates[ePlayerState_WeaponMelee] = hplNew( cPlayerState_WeaponMelee, (mpInit,this) );
mvStates[ePlayerState_UseItem] = hplNew( cPlayerState_UseItem, (mpInit,this) );
mvStates[ePlayerState_Message] = hplNew( cPlayerState_Message, (mpInit,this) );
mvStates[ePlayerState_Throw] = hplNew( cPlayerState_Throw, (mpInit,this) );
mvStates[ePlayerState_Climb] = hplNew( cPlayerState_Climb, (mpInit,this) );
}
//The max distance you can be from something to grab it.
mfMaxGrabDist = mpInit->mpGameConfig->GetFloat("Player","MaxGrabDist",0);
//The max distance you can be from something to move it.
mfMaxMoveDist = mpInit->mpGameConfig->GetFloat("Player","MaxMoveDist",0);
//The max distance you can be from something to push it.
mfMaxPushDist = mpInit->mpGameConfig->GetFloat("Player","MaxPushDist",0);
//The maximum speed you can push something with
mfMaxPushSpeed = mpInit->mpGameConfig->GetFloat("Player","MaxPushSpeed",0);
mvMaxPushHeadMovement = cVector2f(cMath::ToRad(5),cMath::ToRad(15));
mvMinPushHeadMovement = cVector2f(cMath::ToRad(-5),cMath::ToRad(-10));
//This is the maximum distance on which an item can be used.
mfMaxUseItemDist = mpInit->mpGameConfig->GetFloat("Player","MaxUseItemDist",0);
//Set the maximum time the jumpbutton can be held and make the jump longer.
mfJumpCount = 0;
mfMaxJumpCount = mpInit->mpGameConfig->GetFloat("Player","MaxJumpCount",1);
//The border that decides when the mouse moves the screen in interact mode.
mvInteractMoveBorder = cVector2f(130,95);
//Create head movement
mpHeadMove = hplNew( cPlayerHeadMove,(this) );
//create damage effect
mpDamage = hplNew( cPlayerDamage,(mpInit) );
//Create death effect
mpDeath = hplNew( cPlayerDeath,(mpInit) );
//Create flashlight
mpFlashLight = hplNew( cPlayerFlashLight,(mpInit) );
//Create Glowstick
mpGlowStick = hplNew( cPlayerGlowStick,(mpInit) );
//Create Flare
mpFlare = hplNew( cPlayerFlare,(mpInit) );
//Create leaner
mpLean = hplNew( cPlayerLean,(mpInit,this) );
//Create ear ringer
mpEarRing = hplNew( cPlayerEarRing,(mpInit,this) );
//Health
mpHealth = hplNew( cPlayerHealth,(mpInit) );
//NOise Filter
mpNoiseFilter = hplNew( cPlayerNoiseFilter,(mpInit) );
//Fear Filter
mpFearFilter = hplNew( cPlayerFearFilter,(mpInit) );
//Look at
mpLookAt = hplNew( cPlayerLookAt,(this) );
//Hidden
mpHidden = hplNew( cPlayerHidden,(mpInit) );
//Create ray callbacks
mpGroundRayCallback = hplNew( cPlayerGroundRayCallback,() );
mpPickRayCallback = hplNew( cPlayerPickRayCallback,() );
//Create body callback
mpBodyCallback = hplNew( cPlayerBodyCallback,(this) );
//Load font
mpFont = mpResources->GetFontManager()->CreateFontData("verdana.fnt");
//Create and init move states
//This must be called after head move is created!
mMoveState = ePlayerMoveState_Walk;
mvMoveStates.resize(ePlayerMoveState_LastEnum);
mvMoveStates[ePlayerMoveState_Walk] = hplNew( cPlayerMoveState_Walk,(this,mpInit) );
mvMoveStates[ePlayerMoveState_Run] = hplNew( cPlayerMoveState_Run,(this,mpInit) );
mvMoveStates[ePlayerMoveState_Still] = hplNew( cPlayerMoveState_Still,(this,mpInit) );
mvMoveStates[ePlayerMoveState_Jump] = hplNew( cPlayerMoveState_Jump,(this,mpInit) );
mvMoveStates[ePlayerMoveState_Crouch] = hplNew( cPlayerMoveState_Crouch,(this,mpInit) );
/////////////////////////
//Create player gui stuff
//Cross hair
mCrossHairState = eCrossHairState_None;
mvCrossHairPos = cVector2f(400, 300);
mvCrossHairs.resize(eCrossHairState_LastEnum);
for(size_t i=0; i < mvCrossHairs.size(); i++) mvCrossHairs[i] = NULL;
mvCrossHairs[eCrossHairState_Inactive] = mpGfxDrawer->CreateGfxObject("player_crosshair_inactive","diffalpha2d");
mvCrossHairs[eCrossHairState_Active] = mpGfxDrawer->CreateGfxObject("player_crosshair_active","diffalpha2d");
mvCrossHairs[eCrossHairState_Invalid] = mpGfxDrawer->CreateGfxObject("player_crosshair_invalid","diffalpha2d");
mvCrossHairs[eCrossHairState_Grab] = mpGfxDrawer->CreateGfxObject("player_crosshair_grab","diffalpha2d");
mvCrossHairs[eCrossHairState_Examine] = mpGfxDrawer->CreateGfxObject("player_crosshair_examine","diffalpha2d");
mvCrossHairs[eCrossHairState_Pointer] = mpGfxDrawer->CreateGfxObject("player_crosshair_pointer","diffalpha2d");
mvCrossHairs[eCrossHairState_DoorLink] = mpGfxDrawer->CreateGfxObject("player_crosshair_doorlink","diffalpha2d");
mvCrossHairs[eCrossHairState_PickUp] = mpGfxDrawer->CreateGfxObject("player_crosshair_pickup","diffalpha2d");
mvCrossHairs[eCrossHairState_Ladder] = mpGfxDrawer->CreateGfxObject("player_crosshair_ladder","diffalpha2d");
mvCrossHairs[eCrossHairState_Cross] = mpGfxDrawer->CreateGfxObject("player_crosshair_cross","diffalpha2d");
///////////////////////////////
//Haptic Init
if(mpInit->mbHasHaptics)
{
mpLowLevelHaptic = mpInit->mpGame->GetHaptic()->GetLowLevel();
mpLowLevelHaptic->SetCamera(mpCamera);
mpLowLevelHaptic->SetCameraOffset(cVector3f(0,0.7f,mpInit->mfHapticOffsetZ));
mpHapticCamera = hplNew( cHapticGameCamera, (mpInit,this) );
mpDamageForce = mpInit->mpGame->GetHaptic()->GetLowLevel()->CreateSinusWaveForce(
cVector3f(0,1,0),0.1f,3);
mpDamageDirForce = mpLowLevelHaptic->CreateImpulseForce(0);
mpDamageDirForce->SetActive(false);
mpHapticCamera->SetInteractModeCameraSpeed(mpInit->mpConfig->GetFloat("Haptics","InteractModeCameraSpeed",0.5f));
mpHapticCamera->SetActionModeCameraSpeed(mpInit->mpConfig->GetFloat("Haptics","ActionModeCameraSpeed",1.0f));
}
//Set up variable values
Reset();
}
//-----------------------------------------------------------------------
cPlayer::~cPlayer(void)
{
if(mpInit->mbHasHaptics) hplDelete( mpHapticCamera );
hplDelete( mpGroundRayCallback);
hplDelete( mpPickRayCallback);
hplDelete( mpHeadMove);
hplDelete( mpBodyCallback);
hplDelete( mpDamage);
hplDelete( mpDeath);
hplDelete( mpFlashLight);
hplDelete( mpLean);
hplDelete( mpEarRing);
hplDelete( mpGlowStick);
hplDelete( mpFlare);
hplDelete( mpHealth);
hplDelete( mpNoiseFilter);
hplDelete( mpFearFilter);
hplDelete( mpLookAt);
hplDelete( mpHidden);
/*mpInit->mpConfig->SetFloat("Game","PlayerWidth",mvSize.x);
mpInit->mpConfig->SetFloat("Game","PlayerHeight",mvSize.y);
mpInit->mpConfig->SetFloat("Game","PlayerCrouchHeight",mfCrouchHeight);*/
mpInit->mpConfig->SetBool("Debug","ShowHealth",mbShowHealth);
mpInit->mpConfig->SetBool("Debug","ShowSoundsPlaying",mbShowSoundsPlaying);
STLDeleteAll(mvMoveStates);
STLDeleteAll(mvStates);
for(size_t i=0; i < mvCrossHairs.size(); i++)
if(mvCrossHairs[i]) mpGfxDrawer->DestroyGfxObject(mvCrossHairs[i]);
STLMapDeleteAll(m_mapCollideCallbacks);
}
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS - PROPERTIES
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cPlayer::SetMass(float afX)
{
mfMass = afX;
if(mpCharBody)mpCharBody->SetMass(afX);
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS - ACTION
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cPlayer::SetActive(bool abActive)
{
mbActive = abActive;
if(mbActive==false)
{
ChangeState(ePlayerState_Normal);
}
}
//-----------------------------------------------------------------------
void cPlayer::SetPower(float afX)
{
mfPower = afX;
}
void cPlayer::AddPower(float afX)
{
mfPower += afX;
if(mfPower > 100) mfPower =100;
if(mfPower < 0) mfPower =0;
}
//-----------------------------------------------------------------------
void cPlayer::SetPrevMoveState(ePlayerMoveState aState)
{
mvMoveStates[mMoveState]->mPrevMoveState = aState;
}
//-----------------------------------------------------------------------
void cPlayer::SetStartPos(const tString& asName)
{
ChangeState(ePlayerState_Normal);
cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D();
if(pWorld)
{
cStartPosEntity *pStart = pWorld->GetStartPosEntity(asName);
if(pStart==NULL)
{
Warning("Couldn't find start position '%s'\n",asName.c_str());
pStart = pWorld->GetFirstStartPosEntity();
}
cVector3f vPosition(0,0,0), vCamRotation(0,0,0),vBodyRotation(0,0,0);
if(pStart)
{
vPosition = pStart->GetWorldMatrix().GetTranslation();
cMatrixf mtxInv = cMath::MatrixInverse(pStart->GetWorldMatrix());
vCamRotation = cMath::GetAngleFromPoints3D(cVector3f(0,0,0), mtxInv.GetForward()*-1);
vBodyRotation = cMath::GetAngleFromPoints3D(cVector3f(0,0,0), mtxInv.GetForward());
}
//Set position of the player, this should include body and stuff:
//mpCamera->SetPosition(vPosition + cVector3f(0,mvSize.y/2.0f,0));
mpCharBody->SetPosition(vPosition + cVector3f(0,mpCharBody->GetSize().y/2.0f,0));
//mpCharBody->SetPosition(cVector3f(0,0.43f,0));
mpCamera->SetYaw(vCamRotation.y);
mpCamera->SetPitch(vCamRotation.x);
}
}
//-----------------------------------------------------------------------
void cPlayer::ChangeMoveState(ePlayerMoveState aState, bool abSetHeadHeightDirectly)
{
if(mMoveState == aState) return;
//Log("Change movestate from %d to: %d\n",(int)mMoveState,(int)aState);
ePlayerMoveState PrevState = mMoveState;
mMoveState = aState;
mvMoveStates[aState]->InitState(mvMoveStates[PrevState]);
if(abSetHeadHeightDirectly)
{
SetHeightAdd(mvMoveStates[aState]->mfHeightAdd);
}
}
//-----------------------------------------------------------------------
void cPlayer::FootStep(float afMul, const tString &asType, bool abSkipCount)
{
if(mlGroundCount<=0 && abSkipCount==false) return;
iPhysicsMaterial *pMaterial = mpGroundRayCallback->mpMaterial;
if(pMaterial==NULL) return;
cSurfaceData *pData = pMaterial->GetSurfaceData();
if(pData==NULL) {
Error("No surface data in material '%s'!\n",pMaterial->GetName().c_str());
return;
}
tString sMatStepType = pMaterial->GetSurfaceData()->GetStepType();
if(sMatStepType == "")return;
const tString& sType = asType!="" ? asType : mvMoveStates[mMoveState]->msStepType;
tString sSoundName = "player_step_" + sType + "_" + sMatStepType;
cResources *pResources = gpInit->mpGame->GetResources();
cSoundEntityData *pSoundData = pResources->GetSoundEntityManager()->CreateSoundEntity(sSoundName);
if(pSoundData)
{
cSoundHandler *pSoundHandler = gpInit->mpGame->GetSound()->GetSoundHandler();
pSoundHandler->PlayGui( pSoundData->GetMainSoundName(),false,
afMul * pSoundData->GetVolume());
cGameTrigger_Sound *pSound = hplNew( cGameTrigger_Sound, () );
pSound->mpSound = pSoundData;
mpInit->mpTriggerHandler->Add(pSound, eGameTriggerType_Sound,
mpCharBody->GetFeetPosition() + cVector3f(0,0.2f,0),
10, 1.0f/60.0f, pSoundData->GetMaxDistance());
}
/*cWorld3D *pWorld = mpScene->GetWorld3D();
cSoundEntity *pSound = pWorld->CreateSoundEntity("Step",sSoundName,true);
if(pSound)
{
pSound->SetVolume(afMul * pSound->GetVolume());
pSound->SetPosition(cVector3f(0,0.2f,0.4f));
mFeetNode.AddEntity(pSound);
mFeetNode.SetPosition(mFeetNode.GetLocalPosition());
}*/
}
//-----------------------------------------------------------------------
void cPlayer::ChangeState(ePlayerState aState)
{
if(aState == mState) return;
//Log("State %d --> %d\n",(int)mState, (int)aState);
mvStates[aState]->InitState(mvStates[mState]);
mState = aState;
}
//-----------------------------------------------------------------------
bool cPlayer::AddCrossHairPos(const cVector2f& avPos)
{
bool abEdge = false;
mvCrossHairPos += avPos;
if(mvCrossHairPos.x (799 - mvInteractMoveBorder.x)){
mvCrossHairPos.x =(799 - mvInteractMoveBorder.x);
abEdge = true;
}
if(mvCrossHairPos.y > (599 - mvInteractMoveBorder.y)){
mvCrossHairPos.y =(599 - mvInteractMoveBorder.y);
abEdge = true;
}
return abEdge;
}
//-----------------------------------------------------------------------
void cPlayer::AddCollideScript(eGameCollideScriptType aType,const tString &asFunc, const tString &asEntity)
{
cGameCollideScript *pCallback;
//Check if the function already exist
tGameCollideScriptMapIt it = m_mapCollideCallbacks.find(asEntity);
if(it != m_mapCollideCallbacks.end())
{
pCallback = it->second;
}
else
{
pCallback = hplNew( cGameCollideScript, () );
//Get the entity
iGameEntity *pEntity = mpInit->mpMapHandler->GetGameEntity(asEntity);
if(pEntity==NULL)
{
Warning("Couldn't find entity '%s'\n",asEntity.c_str());
hplDelete( pCallback );
return;
}
//Set the entity
pCallback->mpEntity = pEntity;
//Add to container
m_mapCollideCallbacks.insert(tGameCollideScriptMap::value_type(asEntity,pCallback));
}
pCallback->msFuncName[aType] = asFunc;
}
//-----------------------------------------------------------------------
void cPlayer::RemoveCollideScriptWithChildEntity(iGameEntity *apEntity)
{
tGameCollideScriptMapIt it = m_mapCollideCallbacks.begin();
for(; it != m_mapCollideCallbacks.end(); )
{
cGameCollideScript *pCallback = it->second;
tGameCollideScriptMapIt currentIt = it;
++it;
if(pCallback && pCallback->mpEntity == apEntity)
{
if(mbUpdatingCollisionCallbacks)
{
pCallback->mbDeleteMe = true;
}
else
{
hplDelete( pCallback );
m_mapCollideCallbacks.erase(currentIt);
}
}
}
}
//-----------------------------------------------------------------------
void cPlayer::RemoveCollideScript(eGameCollideScriptType aType,const tString &asEntity)
{
tGameCollideScriptMapIt it = m_mapCollideCallbacks.find(asEntity);
if(it != m_mapCollideCallbacks.end())
{
cGameCollideScript *pCallback = it->second;
pCallback->msFuncName[aType] = "";
//if there are no functions left, erase
if(pCallback->msFuncName[0]=="" && pCallback->msFuncName[1]=="" && pCallback->msFuncName[2]=="")
{
if(mbUpdatingCollisionCallbacks)
{
pCallback->mbDeleteMe = true;
}
else
{
hplDelete( pCallback );
m_mapCollideCallbacks.erase(it);
}
}
}
else
{
Warning("Entity '%s' callback doesn't exist in 'Player'\n",asEntity.c_str());
}
}
//-----------------------------------------------------------------------
void cPlayer::ClearCollideScripts()
{
STLMapDeleteAll(m_mapCollideCallbacks);
}
//-----------------------------------------------------------------------
void cPlayer::SetSpeedMul(float afSpeedMul)
{
mfSpeedMul = afSpeedMul;
mvMoveStates[mMoveState]->SetupBody();
}
//-----------------------------------------------------------------------
void cPlayer::SetHealthSpeedMul(float afHealthSpeedMul)
{
mfHealthSpeedMul = afHealthSpeedMul;
mvMoveStates[mMoveState]->SetupBody();
}
//-----------------------------------------------------------------------
void cPlayer::SetHealth(float afX)
{
mfHealth = afX;
if(mfHealth>100)
{
mfHealth = 100;
}
else if(mfHealth <= 0)
{
mpDeath->Start();
}
}
void cPlayer::AddHealth(float afX)
{
SetHealth(mfHealth + afX);
}
void cPlayer::Damage(float afDamage, ePlayerDamageType aType)
{
if(afDamage <= 0) return;
if(mpInit->mpMapHandler->IsChangingMap()) return;
if(mfHealth <=0) return;
if(mpInit->mDifficulty== eGameDifficulty_Easy) afDamage /= 2.0f;
if(mpInit->mDifficulty== eGameDifficulty_Hard) afDamage *= 2.0f;
if(mpInit->mbHasHaptics) afDamage /= 4.0f;
if(mpDeath->IsActive()) return;
float fSize =0.5f;
if(afDamage> 10) fSize = 1.5f;
if(afDamage> 20) fSize = 2.0f;
if(afDamage> 50) fSize = 3.0f;
if(afDamage> 80) fSize = 4.0f;
mpDamage->Start(fSize,aType);
AddHealth(-afDamage);
if(mpInit->mbHasHaptics && aType == ePlayerDamageType_BloodSplash)
{
if(mbDamageFromPos)
{
mbDamageFromPos = false;
cVector3f vDir = cMath::Vector3Normalize(mpCharBody->GetPosition() - mvDamagePos);
if(mpDamageDirForce->IsActive()) mpDamageDirForce->SetActive(false);
mpDamageDirForce->SetActive(true);
cMatrixf mtxProxy = cMath::MatrixRotate(cVector3f(-mpCamera->GetPitch(),-mpCamera->GetYaw(),
-mpCamera->GetRoll()),eEulerRotationOrder_YXZ);
vDir = cMath::MatrixMul(mtxProxy,vDir);
mpDamageDirForce->SetForce(vDir * fSize * 2.2f);
mpDamageDirForce->SetTimeControl(false,0.2f,0.5f,0.0f,0.15f);
}
else
{
mpDamageForce->SetAmp(fSize * 0.15f);
if(mpDamageForce->IsActive()) mpDamageForce->SetActive(false);
mpDamageForce->SetActive(true);
mpDamageForce->SetTimeControl(false,0.3f,0.0f,0.05f,0.25f);
}
}
}
//-----------------------------------------------------------------------
bool cPlayer::IsDead()
{
return mpDeath->IsActive();
}
//-----------------------------------------------------------------------
iPhysicsBody* cPlayer::GetPickedBody()
{
return mpPickRayCallback->mpPickedBody;
}
void cPlayer::SetPickedBody(iPhysicsBody* apBody)
{
mpPickRayCallback->mpPickedBody = apBody;
}
//-----------------------------------------------------------------------
float cPlayer::GetPickedDist()
{
//return mpPickRayCallback->mfPickedDist;
return cMath::Vector3Dist(mpCharBody->GetPosition(),mpPickRayCallback->mvPickedPos);
}
const cVector3f& cPlayer::GetPickedPos()
{
return mpPickRayCallback->mvPickedPos;
}
cPlayerPickRayCallback* cPlayer::GetPickRay()
{
return mpPickRayCallback;
}
//-----------------------------------------------------------------------
void cPlayer::DestroyWorldObjects()
{
//Body
if(mpCharBody) mpScene->GetWorld3D()->GetPhysicsWorld()->DestroyCharacterBody(mpCharBody);
//mpFlashLight->Destroy();
//mpGlowStick->Destroy();
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS - INTERACTIONS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cPlayer::MoveForwards(float afMul,float afTimeStep)
{
if(mvStates[mState]->OnMoveForwards(afMul,afTimeStep))
{
//Only move if on ground
if(mlGroundCount<=0 || afMul==0) return;
mpCharBody->Move(eCharDir_Forward,afMul,afTimeStep);
mbMoving = true;
mvMoveStates[mMoveState]->Start();
}
}
//-----------------------------------------------------------------------
void cPlayer::MoveSideways(float afMul,float afTimeStep)
{
if(mvStates[mState]->OnMoveSideways(afMul,afTimeStep))
{
//Only move if on ground
if(mlGroundCount<=0 || afMul==0) return;
mpCharBody->Move(eCharDir_Right,afMul,afTimeStep);
mbMoving = true;
mvMoveStates[mMoveState]->Start();
}
}
//-----------------------------------------------------------------------
void cPlayer::Lean(float afMul, float afTimeStep)
{
mpLean->Lean(afMul,afTimeStep);
}
//-----------------------------------------------------------------------
void cPlayer::AddYaw(float afVal)
{
if(mvStates[mState]->OnAddYaw(afVal))
{
mpCamera->AddYaw(-afVal * mfLookSpeed);
mpCharBody->SetYaw(mpCamera->GetYaw());
}
}
//-----------------------------------------------------------------------
void cPlayer::AddPitch(float afVal)
{
if(mvStates[mState]->OnAddPitch(afVal))
{
float fInvert = mpInit->mpButtonHandler->GetInvertMouseY() ? -1.0f : 1.0f;
mpCamera->AddPitch(-afVal * mfLookSpeed * fInvert);
}
}
//-----------------------------------------------------------------------
void cPlayer::StartInteract()
{
mvStates[mState]->OnStartInteract();
}
void cPlayer::StopInteract()
{
mvStates[mState]->OnStopInteract();
}
//-----------------------------------------------------------------------
void cPlayer::StartExamine()
{
mvStates[mState]->OnStartExamine();
}
void cPlayer::StopExamine()
{
mvStates[mState]->OnStopExamine();
}
//-----------------------------------------------------------------------
void cPlayer::StartHolster()
{
mvStates[mState]->OnStartHolster();
}
//-----------------------------------------------------------------------
void cPlayer::Jump()
{
if(mvStates[mState]->OnJump() && mlGroundCount >0)
{
if(mvMoveStates[mMoveState]->mType != ePlayerMoveState_Jump)
{
ChangeMoveState(ePlayerMoveState_Jump);
}
}
mfJumpCount = 0;
}
void cPlayer::SetJumpButtonDown(bool abX)
{
mbJumpButtonDown = abX;
if(mbJumpButtonDown)
{
mfJumpCount += mpInit->mpGame->GetStepSize();
}
else
{
mfJumpCount = mfMaxJumpCount;
}
}
//-----------------------------------------------------------------------
void cPlayer::StartRun()
{
mvStates[mState]->OnStartRun();
}
//-----------------------------------------------------------------------
void cPlayer::StopRun()
{
mvStates[mState]->OnStopRun();
}
//-----------------------------------------------------------------------
void cPlayer::StartCrouch()
{
mvStates[mState]->OnStartCrouch();
}
//-----------------------------------------------------------------------
void cPlayer::StopCrouch()
{
mvStates[mState]->OnStopCrouch();
}
//-----------------------------------------------------------------------
void cPlayer::StartInteractMode()
{
mvStates[mState]->OnStartInteractMode();
}
//-----------------------------------------------------------------------
void cPlayer::StartInventory()
{
if(mvStates[mState]->OnStartInventory())
{
mpInit->mpInventory->SetActive(true);
}
}
//-----------------------------------------------------------------------
void cPlayer::StartInventoryShortCut(int alNum)
{
if(mvStates[mState]->OnStartInventoryShortCut(alNum))
{
mpInit->mpInventory->OnShortcutDown(alNum);
}
}
//-----------------------------------------------------------------------
void cPlayer::StartFlashLightButton()
{
if(mpInit->mpInventory->GetItem("flashlight")!=NULL)
{
mpFlashLight->SetActive(!mpFlashLight->IsActive());
if(mpFlashLight->IsActive())
{
mpGlowStick->SetActive(false);
mpFlare->SetActive(false);
}
}
}
void cPlayer::StartGlowStickButton()
{
if(mpInit->mpInventory->GetItem("glowstick")!=NULL ||
mpInit->mpInventory->GetItem("glowst1")!=NULL)
{
mpGlowStick->SetActive(!mpGlowStick->IsActive());
if(mpGlowStick->IsActive())
{
mpFlashLight->SetActive(false);
mpFlare->SetActive(false);
}
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS - EVENTS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cPlayer::OnWorldLoad()
{
/////////////////////////////////////////////////////////
// Create body
mpCharBody = mpScene->GetWorld3D()->GetPhysicsWorld()->CreateCharacterBody("Player", mvSize);
mpCharBody->SetCamera(mpCamera);
mpCharBody->SetMass(mfMass);
//mpCamera->SetPosition(cVector3f(1,1.2f,-2));
mpCharBody->SetCameraPosAdd(cVector3f(0,mfCameraHeightAdd,0));
mpCharBody->SetCameraSmoothPosNum(6);
mpCharBody->SetCallback(mpBodyCallback);
mpCharBody->SetMaxGravitySpeed(40.0f);
mpCharBody->SetCustomGravityActive(true);
mpCharBody->SetCustomGravity(cVector3f(0,-18.0f,0));
mpCharBody->SetMaxPushMass(mpInit->mpGameConfig->GetFloat("Player","MaxPushMass",1));
mpCharBody->SetPushForce(mpInit->mpGameConfig->GetFloat("Player","PushForce",1));
mpCharBody->SetMaxStepSize(mpInit->mpGameConfig->GetFloat("Player","MaxStepSize",0));
mpCharBody->SetStepClimbSpeed(mpInit->mpGameConfig->GetFloat("Player","StepClimbSpeed",0));
mpCharBody->SetClimbForwardMul(1.75f);
mpCharBody->SetClimbHeightAdd(0.02f);
mpCharBody->SetAccurateClimbing(true);
mpCharBody->SetGroundFriction(mpInit->mpGameConfig->GetFloat("Player","GroundFriction",0));
mpCharBody->SetAirFriction(mpInit->mpGameConfig->GetFloat("Player","AirFriction",0));
//Add the crouch size
mpCharBody->AddExtraSize(cVector3f(mvSize.x, mfCrouchHeight,mvSize.z));
//Set so it is not saved:
mpCharBody->SetIsSaved(false);
mpCharBody->GetExtraBody(0)->SetIsSaved(false);
mpCharBody->GetExtraBody(1)->SetIsSaved(false);
mvMoveStates[mMoveState]->EnterState(NULL);
mvMoveStates[mMoveState]->Start();
mpFlashLight->OnWorldLoad();
//mpGlowStick->OnWorldLoad();
mpFlare->OnWorldLoad();
mpHidden->OnWorldLoad();
mpLean->OnWorldLoad();
if(mpInit->mbHasHaptics) mpHapticCamera->OnWorldLoad();
}
//-----------------------------------------------------------------------
void cPlayer::OnWorldExit()
{
DestroyWorldObjects();
mpGroundRayCallback->OnWorldExit();
mpPickRayCallback->OnWorldExit();
mpHidden->OnWorldExit();
if(mpInit->mbHasHaptics) mpHapticCamera->OnWorldExit();
}
//-----------------------------------------------------------------------
void cPlayer::OnStart()
{
}
//-----------------------------------------------------------------------
static inline tString GetCollideCommand(const tString &asFuncName,const tString &asParent,
const tString &asChild)
{
return asFuncName + "(\"" + asParent+"\", \""+asChild+"\")";
}
class cTempCheckProxy : public iPhysicsRayCallback
{
public:
bool mbCollided;
bool OnIntersect(iPhysicsBody *pBody,cPhysicsRayParams *apParams)
{
//if(apParams->mfT <0) return true;
if(pBody->GetCollide()==false || pBody->IsCharacter()) return true;
mbCollided = true;
return false;
}
};
cTempCheckProxy gTempCheckProxy;
void cPlayer::Update(float afTimeStep)
{
cSystem *pSystem = mpInit->mpGame->GetSystem();
unsigned int lTime = pSystem->GetLowLevel()->GetTime();
iPhysicsWorld *pPhysicsWorld = mpScene->GetWorld3D()->GetPhysicsWorld();
/////////////////////////////////////
// HaptX camera
if(cHaptic::GetIsUsed())
{
mpHapticCamera->Update(afTimeStep);
}
//LogUpdate(" Death\n");
////////////////////////////////////////
// Make sure player is dead if he should be
if(mfHealth <=0 && mpDeath->IsActive()==false)
{
mpDeath->Start();
}
////////////////////////////////////////
// Update Node and Footstep sounds
/*//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" Footstep sounds\n");
cMatrixf mtxChar = mpInit->mpGame->GetSound()->GetLowLevel()->GetListenerMatrix();
mtxChar.SetTranslation(mtxChar.GetTranslation() -
cVector3f(0,mpCharBody->GetSize().y/2,0));
mFeetNode.SetMatrix(mtxChar);
cSoundHandler *pSoundHandler = mpInit->mpGame->GetSound()->GetSoundHandler();
cEntityIterator entIt = mFeetNode.GetEntityInterator();
while(entIt.HasNext())
{
cSoundEntity *pSound = static_cast(entIt.Next());
cSoundEntry *pEntry = pSound->GetSoundEntry(eSoundEntityType_Main);
if( pEntry && pSoundHandler->IsValid(pEntry->mpSound))
{
pEntry->mpSound->SetPosition(pSound->GetWorldPosition());
}
}
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);*/
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" misc\n");
//////////////////////
//Reset roll
mpInit->mpPlayer->GetCamera()->SetRoll(0);
/////////////////////////////////////////////////
// Misc
mItemFlash.Update(afTimeStep);
/////////////////////////////////////////////////
// Damage
mpDamage->Update(afTimeStep);
/////////////////////////////////////////////////
// Death
mpDeath->Update(afTimeStep);
/////////////////////////////////////////////////
// Flashlight
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" flashlight");
mpFlashLight->Update(afTimeStep);
/////////////////////////////////////////////////
//Glowstick
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" glowstick\n");
mpGlowStick->Update(afTimeStep);
/////////////////////////////////////////////////
//Flare
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" flare\n");
mpFlare->Update(afTimeStep);
/////////////////////////////////////////////////
// Lean
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" more misc\n");
mpLean->Update(afTimeStep);
/////////////////////////////////////////////////
// Ear ring
mpEarRing->Update(afTimeStep);
//////////////////////////////////////////////////
// health
mpHealth->Update(afTimeStep);
////////////////////////////////////////
// Noise filter
mpNoiseFilter->Update(afTimeStep);
////////////////////////////////////////
// Fear filter
mpFearFilter->Update(afTimeStep);
////////////////////////////////////////
// Look at
mpLookAt->Update(afTimeStep);
////////////////////////////////////////
// Hidden
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" hidden\n");
mpHidden->Update(afTimeStep);
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" collide scripts\n");
/////////////////////////////////////////////////
// Collide script
pPhysicsWorld = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld();
cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D();
cCollideData collideData;
collideData.SetMaxSize(1);
mbUpdatingCollisionCallbacks = true;
tGameCollideScriptMapIt CollideIt = m_mapCollideCallbacks.begin();
for(; CollideIt != m_mapCollideCallbacks.end(); ++CollideIt)
{
cGameCollideScript *pCallback = CollideIt->second;
if(pCallback==NULL) continue;
if(pCallback->mpEntity==NULL) continue;
iGameEntity *pEntity = pCallback->mpEntity;
if(pEntity->IsActive() ==false)continue;
//LogUpdate(" callback %s %s %s\n",pCallback->msFuncName[0].c_str(),pCallback->msFuncName[1].c_str(),pCallback->msFuncName[2].c_str());
bool bCollide = false;
for(size_t j=0; j< pEntity->mvBodies.size(); ++j)
{
iPhysicsBody *pParentBody = mpCharBody->GetBody();
iPhysicsBody *pChildBody = pEntity->mvBodies[j];
if(cMath::CheckCollisionBV( *pParentBody->GetBV(),*pChildBody->GetBV()))
{
bCollide = pPhysicsWorld->CheckShapeCollision(pParentBody->GetShape(),
pParentBody->GetLocalMatrix(),
pChildBody->GetShape(),
pChildBody->GetLocalMatrix(),collideData,1);
}
if(bCollide) break;
}
//Run Collide scripts
//LogUpdate(" running script");
if(bCollide)
{
if(pCallback->mbCollides)
{
if(pCallback->msFuncName[eGameCollideScriptType_During] != "")
{
tString sCommand = GetCollideCommand(
pCallback->msFuncName[eGameCollideScriptType_During],
"Player", CollideIt->first);
mpInit->RunScriptCommand(sCommand);
}
}
else
{
if(pCallback->msFuncName[eGameCollideScriptType_Enter] != "")
{
tString sCommand = GetCollideCommand(
pCallback->msFuncName[eGameCollideScriptType_Enter],
"Player", CollideIt->first);
mpInit->RunScriptCommand(sCommand);
}
pCallback->mbCollides = true;
}
}
else
{
if(pCallback->mbCollides)
{
if(pCallback->msFuncName[eGameCollideScriptType_Leave] != "")
{
tString sCommand = GetCollideCommand(
pCallback->msFuncName[eGameCollideScriptType_Leave],
"Player", CollideIt->first);
mpInit->RunScriptCommand(sCommand);
}
pCallback->mbCollides = false;
}
}
}
mbUpdatingCollisionCallbacks = false;
//////////////////////////////////////////////////
//Check if any collide script should be deleted.
//LogUpdate(" Check collide script deleting\n");
CollideIt = m_mapCollideCallbacks.begin();
for(; CollideIt != m_mapCollideCallbacks.end(); )
{
cGameCollideScript *pCallback = CollideIt->second;
if(pCallback->mbDeleteMe)
{
hplDelete( pCallback );
m_mapCollideCallbacks.erase(CollideIt++);
} else {
++CollideIt;
}
}
/////////////////////////////////////////////////
// Update ground count, this is so that a little air born time still counts as on ground
if(mpCharBody->IsOnGround())
mlGroundCount = 25;
else if(mlGroundCount>0)
mlGroundCount--;
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" Check For ground\n");
//////////////////////////////
//Cast ray and check for ground.
cVector3f vStart,vEnd;
iCollideShape *pBodyShape = mpCharBody->GetShape();
vStart = mpCharBody->GetPosition() - cVector3f(0,pBodyShape->GetSize().y/2-0.3f,0);
vEnd = vStart + cVector3f(0,-0.6f,0);
mpGroundRayCallback->Clear();
pPhysicsWorld->CastRay(mpGroundRayCallback,vStart,vEnd,true,false,false);
//////////////////////////////
//Update movement
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" Movement\n");
if(mbMoving==false)
mvMoveStates[mMoveState]->Stop();
mvMoveStates[mMoveState]->Update(afTimeStep);
mpHeadMove->Update(afTimeStep);
mbMoving = false;
//////////////////////////////
//Update camera pos add
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" Camera pos\n");
if(mpCharBody)
{
float fYAdd = mfCameraHeightAdd + mpHeadMove->GetPos() + mfHeightAdd + mpDeath->GetHeighAdd() +
mpInit->mpEffectHandler->GetShakeScreen()->GetScreenAdd().y;
cVector3f vRight = mpCharBody->GetRight();
float fXAdd = mpLean->mfMovement * vRight.x +
mpInit->mpEffectHandler->GetShakeScreen()->GetScreenAdd().x;
float fZAdd = mpLean->mfMovement * vRight.z+
mpInit->mpEffectHandler->GetShakeScreen()->GetScreenAdd().x;
//Log("HEadMove: %f HeightAdd %f Death: %f\n",mpHeadMove->GetPos(),mfHeightAdd,mpDeath->GetHeighAdd());
mpCharBody->SetCameraPosAdd(cVector3f(fXAdd,fYAdd,fZAdd));
}
///////////////////////////
//Update state
//Clear picked body
//mpPushBody = NULL;
SetPickedBody(NULL);
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
lTime = pSystem->GetLowLevel()->GetTime();
//LogUpdate(" state %d\n",mState);
if(mpInit->mpInventory->IsActive() ==false &&
mpInit->mpNotebook->IsActive()==false)
{
mvStates[mState]->OnUpdate(afTimeStep);
}
//LogUpdate(" took %d ms\n",pSystem->GetLowLevel()->GetTime() - lTime);
}
//-----------------------------------------------------------------------
void cPlayer::Reset()
{
//Camera
mpCamera->SetPitchLimits(cVector2f(cMath::ToRad(70),cMath::ToRad(-70) ));
mpCamera->SetYawLimits(0);
mpCamera->SetFOV(cMath::ToRad(70));
cVector2f vScreenSize = mpInit->mpGame->GetGraphics()->GetLowLevel()->GetScreenSize();
mpCamera->SetAspect(vScreenSize.x / vScreenSize.y);
//Properties
mbItemFlash = false;
mfHealth = 100;
mbMoving = false;
mfMass = mfDefaultMass;
mbLandedFromJump = false;
mfSpeedMul = 1.0f;
mfHealthSpeedMul = 1.0f;
mbActive = true;
mfPower =0;
mfHeightAdd =0;
mfLookSpeed = 1.0f;
mpCharBody = NULL;
mpWeaponCallback = NULL;
mbUpdatingCollisionCallbacks = false;
mbDamageFromPos = false;
//jump properties
mbJumpButtonDown = false;
mfJumpCount = 0;
//States
mMoveState = ePlayerMoveState_Walk;
mState = ePlayerState_Normal;
//Crosshair
mCrossHairState = eCrossHairState_None;
mvCrossHairPos = cVector2f(400, 300);
//Stats
mlStat_NumOfSaves =0;
//Callbacks
STLMapDeleteAll(m_mapCollideCallbacks);
//Helpers
mpDeath->Reset();
mpFlashLight->Reset();
mpEarRing->Stop(true);
mpGlowStick->Reset();
mpFlare->Reset();
mpLookAt->Reset();
mpFearFilter->Reset();
mpLean->Reset();
mpEarRing->Reset();
mpHealth->Reset();
mpHidden->Reset();
mpGroundRayCallback->Reset();
if(mpInit->mbHasHaptics) mpHapticCamera->Reset();
}
//-----------------------------------------------------------------------
void cPlayer::OnDraw()
{
/////////////////////////////////
// Damage
mpDamage->Draw();
/////////////////////////////////
// Death
mpDeath->Draw();
////////////////////////////////////////
// Noise filter
mpNoiseFilter->Draw();
////////////////////////////////////////
// Fear filter
mpFearFilter->Draw();
////////////////////////////////////////
// Hidden
mpHidden->Draw();
mpHealth->Draw();
////////////////////////////////
//Cross hair
if(IsActive()==false)
{
//Do noting...
}
else if(mpInit->mbHasHaptics && mpHapticCamera->ShowCrosshair()==false)
{
if(mCrossHairState != eCrossHairState_None)
{
cVector3f vProjPos = cMath::MatrixMul( mpCamera->GetViewMatrix(),
mpHapticCamera->GetHandEntity()->GetWorldPosition());
vProjPos = cMath::MatrixMulDivideW(mpCamera->GetProjectionMatrix(),vProjPos);
cVector2f vPos( (vProjPos.x+1) * 0.5f, (-vProjPos.y+1)* 0.5f);
vPos *= cVector2f(800,600);
vPos += cVector2f(10,10);
cResourceImage *pImage = mvCrossHairs[mCrossHairState]->GetMaterial()->GetImage(eMaterialTexture_Diffuse);
cVector2l vSize = pImage->GetSize();
cVector2f vPosAdd(((float)vSize.x) / 2.0f, ((float)vSize.y) / 2.0f);
mpGfxDrawer->DrawGfxObject( mvCrossHairs[mCrossHairState],
cVector3f(0,0,100)+(vPos - vPosAdd));
}
}
else if(mCrossHairState == eCrossHairState_Item)
{
cGfxObject *pObject = mpCurrentItem->GetGfxObject();
cGfxObject *pAdditive = mpCurrentItem->GetGfxObjectAdditive();
if(pObject)
{
cVector2l vIntSize = pObject->GetMaterial()->GetImage(eMaterialTexture_Diffuse)->GetSize();
cVector2f vSize((float)vIntSize.x, (float)vIntSize.y);
cVector2f vPosAdd(((float)vSize.x) / 2.0f, ((float)vSize.y) / 2.0f);
if(mbItemFlash)
{
mpGfxDrawer->DrawGfxObject(pObject,cVector3f(0,0,100)+(mvCrossHairPos - vPosAdd),vSize,
cColor(1,1,1,1));
for(int i=0; i<2; ++i)
mpGfxDrawer->DrawGfxObject(pAdditive,cVector3f(0,0,101)+(mvCrossHairPos - vPosAdd),vSize,
cColor(1,1,1,mItemFlash.val));
/*mpGfxDrawer->DrawGfxObject(pAdditive,cVector3f(3,3,99)+(mvCrossHairPos - vPosAdd),vSize,
cColor(0,1,0,mItemFlash.val*0.8f));
mpGfxDrawer->DrawGfxObject(pAdditive,cVector3f(-3,-3,99)+(mvCrossHairPos - vPosAdd),vSize,
cColor(0,1,0,mItemFlash.val*0.8f));
mpGfxDrawer->DrawGfxObject(pAdditive,cVector3f(-3,3,99)+(mvCrossHairPos - vPosAdd),vSize,
cColor(0,1,0,mItemFlash.val*0.8f));
mpGfxDrawer->DrawGfxObject(pAdditive,cVector3f(3,-3,99)+(mvCrossHairPos - vPosAdd),vSize,
cColor(0,1,0,mItemFlash.val*0.8f));*/
}
else
{
mpGfxDrawer->DrawGfxObject(pObject,cVector3f(0,0,100)+(mvCrossHairPos - vPosAdd),vSize,
cColor(1,0.3f,0.3f,1.0f));
}
}
}
else if(mCrossHairState != eCrossHairState_None)
{
cResourceImage *pImage = mvCrossHairs[mCrossHairState]->GetMaterial()->GetImage(eMaterialTexture_Diffuse);
cVector2l vSize = pImage->GetSize();
cVector2f vPosAdd(((float)vSize.x) / 2.0f, ((float)vSize.y) / 2.0f);
mpGfxDrawer->DrawGfxObject(mvCrossHairs[mCrossHairState],cVector3f(0,0,100)+(mvCrossHairPos - vPosAdd));
}
else if(mpInit->mbShowCrossHair)
{
cVector3f vPos = cVector3f(400,300,0);
cResourceImage *pImage = mvCrossHairs[eCrossHairState_Cross]->GetMaterial()->GetImage(eMaterialTexture_Diffuse);
cVector2l vSize = pImage->GetSize();
cVector2f vPosAdd(((float)vSize.x) / 2.0f, ((float)vSize.y) / 2.0f);
mpGfxDrawer->DrawGfxObject(mvCrossHairs[eCrossHairState_Cross],cVector3f(0,0,100)+(vPos - vPosAdd));
}
//DEBUG: Memory
/*float fMbMem = ((float)cMemoryManager::mlTotalMemoryUsage) / (1024.0f * 1024.0f);
mpFont->Draw(cVector3f(5,5,0),12,cColor(1,1,1,1),eFontAlign_Left,_W("Memory used: %d (%.2f mb)"),
cMemoryManager::mlTotalMemoryUsage, fMbMem);
*/
//DEBUG: Mouse
//iMouse *pMouse = mpInit->mpGame->GetInput()->GetMouse();
//mpFont->Draw(cVector3f(5,5,0),12,cColor(1,1,1,1),eFontAlign_Left,_W("Left: %d Right: %d"),
// pMouse->ButtonIsDown(eMButton_Left),
// pMouse->ButtonIsDown(eMButton_Right));
//DEBUG: State
if(mpInit->mbHasHaptics)
{
/*tWString sState =_W("Unknown");
if(mState == ePlayerState_Normal) sState = _W("Normal");
else if(mState == ePlayerState_Push) sState = _W("Push");
else if(mState == ePlayerState_Move) sState = _W("Move");
else if(mState == ePlayerState_InteractMode) sState = _W("InteractMode");
else if(mState == ePlayerState_UseItem) sState = _W("UseItem");
else if(mState == ePlayerState_Message) sState = _W("Message");
else if(mState == ePlayerState_Grab) sState = _W("Grab");
else if(mState == ePlayerState_WeaponMelee) sState = _W("WeaponMelee");
else if(mState == ePlayerState_Throw) sState = _W("Throw");
else if(mState == ePlayerState_Climb) sState = _W("Climb");
mpFont->Draw(cVector3f(5,5,0),12,cColor(1,1,1,1),eFontAlign_Left,_W("State: %s"),
sState.c_str());*/
}
//DEBUG: MoveState
/*tString sState ="";
if(mMoveState == ePlayerMoveState_Jump) sState = "Jump";
else if(mMoveState == ePlayerMoveState_Crouch) sState = "Crouch";
else if(mMoveState == ePlayerMoveState_Walk) sState = "Walk";
else if(mMoveState == ePlayerMoveState_Run) sState = "Run";
else if(mMoveState == ePlayerMoveState_Still) sState = "Still";
mpFont->Draw(cVector3f(5,5,0),12,cColor(1,1,1,1),eFontAlign_Left,"MoveState: %s",
sState.c_str());*/
//DEBUG: Picked body
/*if(mpInit->mbHasHaptics)
{
if(mpPickRayCallback->mpPickedBody){
mpFont->Draw(cVector3f(5,35,0),12,cColor(1,1,1,1),eFontAlign_Left,_W("Body: %s"),
cString::To16Char(mpPickRayCallback->mpPickedBody->GetName()).c_str());
}
else{
mpFont->Draw(cVector3f(5,35,0),12,cColor(1,1,1,1),eFontAlign_Left,_W("Body: NULL"));
}
mpFont->Draw(cVector3f(5,46,0),12,cColor(1,1,1,1),eFontAlign_Left,_W("Dist: %f"),
mpPickRayCallback->mfPickedDist);
tWString sCState = _W("Unknown");
if(mCrossHairState == eCrossHairState_Inactive)sCState = _W("Inactive");
if(mCrossHairState == eCrossHairState_Active)sCState = _W("Active");
if(mCrossHairState == eCrossHairState_Invalid)sCState = _W("Invalid");
if(mCrossHairState == eCrossHairState_Grab)sCState = _W("Grab");
if(mCrossHairState == eCrossHairState_Examine)sCState = _W("Examine");
if(mCrossHairState == eCrossHairState_Pointer)sCState = _W("Pointer");
if(mCrossHairState == eCrossHairState_Item)sCState = _W("Item");
if(mCrossHairState == eCrossHairState_DoorLink)sCState = _W("DoorLink");
if(mCrossHairState == eCrossHairState_PickUp)sCState = _W("PickUp");
if(mCrossHairState == eCrossHairState_Ladder)sCState = _W("Ladder");
if(mCrossHairState == eCrossHairState_None)sCState = _W("None");
mpFont->Draw( cVector3f(5,66,0),12,cColor(1,1,1,1),eFontAlign_Left,
_W("CState: %s"),sCState.c_str());
}*/
//DEBUG: On ground and step material
/*mpFont->Draw(cVector3f(5,17,0),12,cColor(1,1,1,1),eFontAlign_Left,"Position: %f ClimbPos: %f ClimbCount: %f\n",
mpHeadMove->GetPosition(),
mpHeadMove->GetClimbPosition(),
mpHeadMove->GetClimbCount());*/
//mpFont->Draw(cVector3f(5,29,0),12,cColor(1,1,1,1),eFontAlign_Left,"Gravity: %f",
//mpCharBody->GetForceVelocity().y);
//mpFont->Draw(cVector3f(5,29,0),12,cColor(1,1,1,1),eFontAlign_Left,"CameraPos: %s",
// mpCamera->GetPosition().ToString().c_str());
//mpFont->Draw(cVector3f(5,43,0),12,cColor(1,1,1,1),eFontAlign_Left,"CharPos: %s",
// GetCharacterBody()->GetPosition().ToString().c_str());
/*if(mpRayCallback->mpMaterial)
mpFont->Draw(cVector3f(5,17,0),12,cColor(1,1,1,1),eFontAlign_Left,"Material: %s",
mpGroundRayCallback->mpMaterial->GetName().c_str());*/
//DEBUG: health
if(mbShowHealth)
{
mpFont->Draw(cVector3f(5,5,0),12,cColor(1,1,1,1),eFontAlign_Left,_W("Health: %.0f"),
mfHealth);
}
//DEBUG: misc
//mpFont->Draw(cVector3f(5,20,0),12,cColor(1,1,1,1),eFontAlign_Left,
// _W("Ground: %d Speed: %f ForceSpeed: %f"),
// mpCharBody->IsOnGround()?1:0,
// mpCharBody->GetMoveSpeed(eCharDir_Forward),
// mpCharBody->GetForceVelocity().Length()
// );
//cVector3f vGravity = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld()->GetGravity();
//mpFont->Draw(cVector3f(5,20,0),12,cColor(1,1,1,1),eFontAlign_Left,"Gravity: %s",
// vGravity.ToString().c_str());
//DEBUG: sounds playing
if(mbShowSoundsPlaying)
{
tStringVec vSoundNames;
std::vector vEntries;
//////////////////////////////
//Sound channels
tSoundEntryList *pEntryList = mpInit->mpGame->GetSound()->GetSoundHandler()->GetWorldEntryList();
for(tSoundEntryListIt it = pEntryList->begin(); it != pEntryList->end();++it)
{
iSoundChannel *pSound = it->mpSound;
vSoundNames.push_back(pSound->GetData()->GetName());
vEntries.push_back(&(*it));
}
vSoundNames.push_back("");
vEntries.push_back(NULL);
pEntryList = mpInit->mpGame->GetSound()->GetSoundHandler()->GetGuiEntryList();
for(tSoundEntryListIt it = pEntryList->begin(); it != pEntryList->end();++it)
{
iSoundChannel *pSound = it->mpSound;
vSoundNames.push_back(pSound->GetData()->GetName());
vEntries.push_back(&(*it));
}
mpFont->Draw(cVector3f(5,18,0),10,cColor(1,1,1,1),eFontAlign_Left,_W("Num of sounds: %d"),vSoundNames.size()-1);
int lRow=0, lCol=0;
for(int i=0; i< (int)vSoundNames.size(); i++)
{
cSoundEntry *pEntry = vEntries[i];
if(pEntry == NULL){
lRow = 4;
lCol =0;
continue;
}
mpFont->Draw(cVector3f((float)lCol*250,26+(float)lRow*11,0),10,cColor(1,1,1,1),eFontAlign_Left,
_W("%ls(%.2f (%.2f %.2f)->%.2f"),cString::To16Char(vSoundNames[i]).c_str(),
//_W("%ls(%.2f (%.2f %.2f)->%.2f %d %.2f/%.2f)"),cString::To16Char(vSoundNames[i]).c_str(),
pEntry->mpSound->GetVolume(),
pEntry->mfNormalVolumeMul,
pEntry->mfNormalVolumeFadeSpeed,
pEntry->mfNormalVolumeFadeDest,
pEntry->mpSound->GetPriority(),
pEntry->mpSound->GetElapsedTime(),
pEntry->mpSound->GetTotalTime()
);
// pEntry->mpSound->GetPriority(),
// pEntry->mpSound->IsBufferUnderrun()?1:0);
lCol++;
if(lCol == 3)
{
lCol =0;
lRow++;
}
}
//////////////////////////////
//Music
cMusicEntry *pMusic = mpInit->mpGame->GetSound()->GetMusicHandler()->GetCurrentSong();
if(pMusic){
iSoundChannel *pChannel = pMusic->mpStream;
mpFont->Draw(cVector3f(5,18+70,0),10,cColor(1,1,1,1),eFontAlign_Left,
_W("Music: '%ls' vol: %.2f playing: %d prio: %d elapsed: %.2f total time: %.2f"),
cString::To16Char(pChannel->GetData()->GetName()).c_str(),
pChannel->GetVolume(),
pChannel->IsPlaying(),
pChannel->GetPriority(),
pChannel->GetElapsedTime(),
pChannel->GetTotalTime()
);
}
}
//DEBUG: Portals
/*tString sPortals = "Portals: ";
cPortalContainer *pContainer = mpInit->mpGame->GetScene()->GetWorld3D()->GetPortalContainer();
tStringList* pStringList = pContainer->GetVisibleSectorsList();
for(tStringListIt it=pStringList->begin(); it != pStringList->end(); ++it)
{
sPortals += *it + ", ";
}
mpFont->Draw(cVector3f(5,5,0),12,cColor(1,1,1,1),eFontAlign_Left,"%s",
sPortals.c_str());*/
mvStates[mState]->OnDraw();
}
void cPlayer::OnPostSceneDraw()
{
cCamera3D *pCam = static_cast(mpScene->GetCamera());
iLowLevelGraphics *pLowGfx = mpInit->mpGame->GetGraphics()->GetLowLevel();
pLowGfx->SetMatrix(eMatrix_ModelView, pCam->GetViewMatrix());
pLowGfx->SetTexture(0,NULL);
pLowGfx->SetBlendActive(false);
/*mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawLine(mvLineStart,mvLineEnd,cColor(1,1,1,1));
mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawSphere(mvLineStart,0.1f,cColor(1,0,1,1));
mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawSphere(mvLineEnd,0.1f,cColor(1,0,1,1));*/
mpFlashLight->OnPostSceneDraw();
mvStates[mState]->OnPostSceneDraw();
///////////////////////////////
//Gui Hand effects
if(mpInit->mbHasHaptics)
{
mpHapticCamera->OnPostSceneDraw();
}
}
//////////////////////////////////////////////////////////////////////////
// SAVING
//////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------
void cPlayer::AddSaveData(cSavedWorld* apSavedWorld)
{
//Collide callbacks
tGameCollideScriptMapIt colIt = m_mapCollideCallbacks.begin();
for(; colIt != m_mapCollideCallbacks.end(); ++colIt)
{
cGameCollideScript *pScript = colIt->second;
cSaveGame_cGameCollideScript savedScript;
savedScript.LoadFrom(pScript);
apSavedWorld->mlstCollideCallbacks.Add(savedScript);
}
}
//-------------------------------------------------------------------
void cPlayer::LoadSaveData(cSavedWorld* apSavedWorld)
{
//Collide callbacks
//Collide scripts
cContainerListIterator colIt = apSavedWorld->mlstCollideCallbacks.GetIterator();
while(colIt.HasNext())
{
cSaveGame_cGameCollideScript &savedScript = colIt.Next();
cGameCollideScript *pCallback = hplNew( cGameCollideScript, () );
pCallback->mpEntity = mpInit->mpMapHandler->GetGameEntity(savedScript.msEntity);
if(pCallback->mpEntity==NULL)
{
Warning("Couldn't find entity '%s'\n",savedScript.msEntity.c_str());
hplDelete( pCallback );
continue;
}
savedScript.SaveTo(pCallback);
m_mapCollideCallbacks.insert(tGameCollideScriptMap::value_type(savedScript.msEntity,pCallback));
}
}
//-------------------------------------------------------------------
void cPlayer::SaveToGlobal(cPlayer_GlobalSave *apSave)
{
cPlayer_GlobalSave *pData = apSave;
//////////////////////////////
//Stats
kSaveData_SaveTo(mlStat_NumOfSaves);
//////////////////////////////
//Global
kSaveData_SaveTo(mfForwardUpMul);
kSaveData_SaveTo(mfForwardRightMul);
kSaveData_SaveTo(mfUpMul);
kSaveData_SaveTo(mfRightMul);
kSaveData_SaveTo(mbPickAtPoint);
kSaveData_SaveTo(mbRotateWithPlayer);
kSaveData_SaveTo(mbUseNormalMass);
kSaveData_SaveTo(mfGrabMassMul);
//////////////////////////////
//Private
kSaveData_SaveTo(mbActive);
kSaveData_SaveTo(mfHeightAdd);
kSaveData_SaveTo(mfSpeedMul);
kSaveData_SaveTo(mfHealthSpeedMul);
kSaveData_SaveTo(mfHeadMoveSizeMul);
kSaveData_SaveTo(mfHeadMoveSpeedMul);
kSaveData_SaveTo(mState);
kSaveData_SaveTo(mMoveState);
kSaveData_SaveTo(mCrossHairState);
kSaveData_SaveTo(mbItemFlash);
kSaveData_SaveTo(mfHealth);
kSaveData_SaveTo(mfPower);
kSaveData_SaveTo(mfMass);
///////////////////////////////////////
//Particles on camera
cNode3D *pNode = mpCamera->GetAttachmentNode();
pData->mvOnCameraPS.Clear();
cEntityIterator it = pNode->GetEntityIterator();
while(it.HasNext())
{
iEntity3D *pEntity3D = static_cast(it.Next());
if(pEntity3D->GetEntityType() == "ParticleSystem3D")
{
cParticleSystem3D *pPS = static_cast(pEntity3D);
cPlayer_GlobalSave_CameraPS cameraPS;
cameraPS.msName = pPS->GetName();
cameraPS.msFile = pPS->GetDataName();
pData->mvOnCameraPS.Add(cameraPS);
}
}
//////////////////////////////
// Lights
apSave->mbFlashlightActive = mpFlashLight->IsActive();
apSave->mbFlashlightDisabled = mpFlashLight->IsDisabled();
apSave->mbGlowstickActive = mpGlowStick->IsActive();
apSave->mbFlareActive = mpFlare->IsActive();
apSave->mfFlareTime = mpFlare->GetTime();
//////////////////////////////
//Body and Camera Specific
pData->mvPosition = mpCharBody->GetPosition();
pData->mfYaw = mpCharBody->GetYaw();
pData->mfPitch =mpCamera->GetPitch();
}
//-------------------------------------------------------------------
void cPlayer::LoadFromGlobal(cPlayer_GlobalSave *apSave)
{
cPlayer_GlobalSave *pData = apSave;
//////////////////////////////
//Stats
kSaveData_LoadFrom(mlStat_NumOfSaves);
//////////////////////////////
//Global
kSaveData_LoadFrom(mfForwardUpMul);
kSaveData_LoadFrom(mfForwardRightMul);
kSaveData_LoadFrom(mfUpMul);
kSaveData_LoadFrom(mfRightMul);
kSaveData_LoadFrom(mbPickAtPoint);
kSaveData_LoadFrom(mbRotateWithPlayer);
kSaveData_LoadFrom(mbUseNormalMass);
kSaveData_LoadFrom(mfGrabMassMul);
//////////////////////////////
//Private
SetActive(pData->mbActive);
kSaveData_LoadFrom(mfHeightAdd);
//Probably better of skipping these:
/*kSaveData_LoadFrom(mfSpeedMul);
kSaveData_LoadFrom(mfHealthSpeedMul);
kSaveData_LoadFrom(mfHeadMoveSizeMul);
kSaveData_LoadFrom(mfHeadMoveSpeedMul);*/
//Skip these for now.
ChangeMoveState(apSave->mMoveState,true);
//kSaveData_LoadFrom(mState);
//kSaveData_LoadFrom(mMoveState);
//kSaveData_LoadFrom(mCrossHairState);
kSaveData_LoadFrom(mbItemFlash);
kSaveData_LoadFrom(mfHealth);
kSaveData_LoadFrom(mfPower);
//kSaveData_LoadFrom(mfMass); //Skip this
///////////////////////////////////////
//Particles on camera
cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D();
for(size_t i=0;imvOnCameraPS.Size(); ++i)
{
cParticleSystem3D *pPS = pWorld->CreateParticleSystem(
pData->mvOnCameraPS[i].msName,
pData->mvOnCameraPS[i].msFile,
1,cMatrixf::Identity);
if(pPS)
{
mpCamera->AttachEntity(pPS);
}
}
//////////////////////////////
// Lights
if(apSave->mbFlashlightActive) mpFlashLight->SetActive(true);
if(apSave->mbFlashlightDisabled) mpFlashLight->SetDisabled(true);
if(apSave->mbGlowstickActive) mpGlowStick->SetActive(true);
if(apSave->mbFlareActive){
mpFlare->SetActive(true);
mpFlare->SetTime(apSave->mfFlareTime);
}
//////////////////////////////
//Body and Camera Specific
mpCharBody->SetPosition(pData->mvPosition);
mpCharBody->SetYaw(pData->mfYaw);
mpCamera->SetYaw(pData->mfYaw);
mpCamera->SetPitch(pData->mfPitch);
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// SAVE OBJECT STUFF
//////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------
kBeginSerializeBase(cSaveData_cPlayer)
kSerializeVar(mlStat_NumOfSaves,eSerializeType_Int32)
kSerializeClassContainer(mlstCollideCallbacks,cSaveGame_cGameCollideScript, eSerializeType_Class)
kEndSerialize()
//-----------------------------------------------------------------------
iSaveObject* cSaveData_cPlayer::CreateSaveObject(cSaveObjectHandler *apSaveObjectHandler,cGame *apGame)
{
cContainerListIterator it = mlstCollideCallbacks.GetIterator();
while(it.HasNext())
{
cSaveGame_cGameCollideScript& saveScript = it.Next();
iGameEntity* pEntity = gpInit->mpMapHandler->GetGameEntity(saveScript.msEntity);
if(pEntity==NULL){
Error("Couldn't find game entity '%s'\n",saveScript.msEntity.c_str());
continue;
}
cGameCollideScript *pCallback = hplNew( cGameCollideScript, () );
pCallback->mpEntity = pEntity;
saveScript.SaveTo(pCallback);
gpInit->mpPlayer->m_mapCollideCallbacks.insert(tGameCollideScriptMap::value_type(saveScript.msEntity,pCallback));
}
return NULL;
}
//-----------------------------------------------------------------------
int cSaveData_cPlayer::GetSaveCreatePrio()
{
return 10;
}
//-----------------------------------------------------------------------
iSaveData* cPlayer::CreateSaveData()
{
cSaveData_cPlayer *pData = hplNew( cSaveData_cPlayer, () );
//Collide callbacks
{
tGameCollideScriptMapIt it = m_mapCollideCallbacks.begin();
for(; it != m_mapCollideCallbacks.end(); ++it)
{
cGameCollideScript *pScript = it->second;
cSaveGame_cGameCollideScript saveScript;
saveScript.LoadFrom(pScript);
pData->mlstCollideCallbacks.Add(saveScript);
}
}
return pData;
}
//-----------------------------------------------------------------------