/*
* 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 "PlayerHelper.h"
#include "Init.h"
#include "GameEntity.h"
#include "GameObject.h"
#include "GameArea.h"
#include "Player.h"
#include "Inventory.h"
#include "Notebook.h"
#include "NumericalPanel.h"
#include "DeathMenu.h"
#include "GameEnemy.h"
#include "MapHandler.h"
#include "PlayerHands.h"
#include "GameMusicHandler.h"
//////////////////////////////////////////////////////////////////////////
// HIT GROUND CALLBACK
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerBodyCallback::cPlayerBodyCallback(cPlayer *apPlayer)
{
mpPlayer = apPlayer;
cInit *pInit = apPlayer->GetInit();
mfFallSpeed_Min = pInit->mpGameConfig->GetFloat("Player","FallSpeed_Min",0);
mfFallDamage_Min = pInit->mpGameConfig->GetFloat("Player","FallDamage_Min",0);
msFallSound_Min = pInit->mpGameConfig->GetString("Player","FallSound_Min","");
mfFallSpeed_Med = pInit->mpGameConfig->GetFloat("Player","FallSpeed_Med",0);
mfFallDamage_Med = pInit->mpGameConfig->GetFloat("Player","FallDamage_Med",0);
msFallSound_Med = pInit->mpGameConfig->GetString("Player","FallSound_Med","");
mfFallSpeed_Max = pInit->mpGameConfig->GetFloat("Player","FallSpeed_Max",0);
mfFallDamage_Max = pInit->mpGameConfig->GetFloat("Player","FallDamage_Max",0);
msFallSound_Max = pInit->mpGameConfig->GetString("Player","FallSound_Max","");
}
//-----------------------------------------------------------------------
void cPlayerBodyCallback::OnHitGround(iCharacterBody *apCharBody,const cVector3f &avVel)
{
//if(avVel.y < -5.5f)
// mpPlayer->FootStep(1.0f,"run",true);
if(mpPlayer->GetMoveState() == ePlayerMoveState_Jump)
{
if(avVel.y < 0)
{
if(avVel.y < - 3.5f)
{
mpPlayer->FootStep(1.0f,"run",true);
}
mpPlayer->SetLandedFromJump(true);
}
}
else if(avVel.y < -8.5f)
{
mpPlayer->FootStep(1.0f,"run",true);
}
tString sSound = "";
float fVol = 1.0f;
cSoundHandler *pSoundHandler = mpPlayer->GetInit()->mpGame->GetSound()->GetSoundHandler();
//Log("Speed: %f\n",avVel.y);
/////////////////////
//Fall damage
//Hard
if(avVel.y < mfFallSpeed_Max)
{
sSound = msFallSound_Max;
fVol = 1.0f;
mpPlayer->Damage(mfFallDamage_Max,ePlayerDamageType_BloodSplash);
pSoundHandler->PlayGui("player_fall_damage",false,1);
//Log("Hard\n");
}
//Medium
else if(avVel.y < mfFallSpeed_Med)
{
sSound = msFallSound_Med;
fVol = 1.0f;
mpPlayer->Damage(mfFallDamage_Med,ePlayerDamageType_BloodSplash);
pSoundHandler->PlayGui("player_fall_damage",false,0.75f);
//Log("Medium\n");
}
//Light
else if(avVel.y < mfFallSpeed_Min)
{
sSound = msFallSound_Min;
fVol = 1.0f;
mpPlayer->Damage(mfFallDamage_Min,ePlayerDamageType_BloodSplash);
pSoundHandler->PlayGui("player_fall_damage",false,0.5f);
//Log("Light\n");
}
if(sSound != "")
{
cWorld3D *pWorld = mpPlayer->GetInit()->mpGame->GetScene()->GetWorld3D();
cSoundEntity *pSound = pWorld->CreateSoundEntity("HitGround",sSound,true);
if(pSound)
{
iCharacterBody *pCharBody = mpPlayer->GetCharacterBody();
pSound->SetVolume(fVol * pSound->GetVolume());
pSound->SetPosition(pCharBody->GetPosition() - cVector3f(0,pCharBody->GetSize().y/2 - 0.2f,0));
}
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// GROUND RAY CALLBACK
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerGroundRayCallback::cPlayerGroundRayCallback()
{
mpMaterial = NULL;
mbOnGround = false;
}
//-----------------------------------------------------------------------
void cPlayerGroundRayCallback::Clear()
{
mfMinDist = 1000;
mpMaterial = NULL;
}
//-----------------------------------------------------------------------
void cPlayerGroundRayCallback::OnWorldExit()
{
mpMaterial = NULL;
}
void cPlayerGroundRayCallback::Reset()
{
mpMaterial = NULL;
}
//-----------------------------------------------------------------------
bool cPlayerGroundRayCallback::OnIntersect(iPhysicsBody *pBody,cPhysicsRayParams *apParams)
{
mbOnGround = true;
if(apParams->mfDistGetMaterial()->GetSurfaceData() &&
pBody->GetMaterial()->GetSurfaceData()->GetStepType()!="")
{
mpMaterial = pBody->GetMaterial();
mfMinDist = apParams->mfDist;
}
return true;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PICK RAY CALLBACK
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerPickRayCallback::cPlayerPickRayCallback()
{
mfMaxDistance = 10.0f;
mpPickedBody = NULL;
mLastEntityType = eGameEntityType_LastEnum;
}
//-----------------------------------------------------------------------
void cPlayerPickRayCallback::Clear()
{
mfPickedDist = mfMaxDistance+10.0f;
mfPickedAreaDist = mfMaxDistance+10.0f;
mpPickedBody = NULL;
mpPickedAreaBody = NULL;
mfMinStaticDist = mfMaxDistance+10.0f;
}
//-----------------------------------------------------------------------
void cPlayerPickRayCallback::OnWorldExit()
{
mpPickedBody = NULL;
}
//-----------------------------------------------------------------------
bool cPlayerPickRayCallback::OnIntersect(iPhysicsBody *apBody,cPhysicsRayParams *apParams)
{
float &fDist = apParams->mfDist;
//Must be positive
if(fDist < 0) return true;
//Must be below max distance
if(fDist > mfMaxDistance) return true;
//No characters allowed
if(apBody->IsCharacter()) return true;
//Check if is below current picked dist
iGameEntity *pEntity = NULL;
if(apBody->GetUserData()) pEntity = (iGameEntity*)apBody->GetUserData();
//////////////////////////////
// Entity
if(pEntity)
{
//Skip stick area
if(pEntity->GetType() == eGameEntityType_StickArea) return true;
//Area
if( pEntity->GetType() == eGameEntityType_Area ||
pEntity->GetType()== eGameEntityType_StickArea ||
pEntity->GetType()== eGameEntityType_DamageArea ||
pEntity->GetType()== eGameEntityType_ForceArea)
{
if( mfPickedAreaDist > fDist &&
(pEntity->GetDescription() != _W("") ||
pEntity->GetCallbackScript(eGameEntityScriptType_PlayerInteract) != NULL ||
pEntity->GetCallbackScript(eGameEntityScriptType_PlayerExamine) != NULL ||
pEntity->GetHasInteraction()))
{
mfPickedAreaDist = fDist;
mvPickedAreaPos = apParams->mvPoint;
mpPickedAreaBody = apBody;
}
}
//Other entity
else
{
if(mfPickedDist > fDist)
{
mfPickedDist = fDist;
mvPickedPos = apParams->mvPoint;
mpPickedBody = apBody;
}
}
}
///////////////////////////////
// Non Entity
else
{
if(mfPickedDist > fDist)
{
mfPickedDist = fDist;
mpPickedBody = NULL;
}
}
return true;
/*float &fDist = apParams->mfDist;
iGameEntity *pEntity = NULL;
if(apBody->GetUserData()) pEntity = (iGameEntity*)apBody->GetUserData();
//Don't wanna pick characters
if(apBody->IsCharacter() && apBody->GetUserData()==NULL) return true;
if(pEntity && pEntity->IsActive()==false) return true;
//If it is outside of the examine distance skip
if(pEntity && pEntity->GetMaxExamineDist() < fDist) return true;
////////////////////////////
//Not picked
bool bStatic = false;
if(pEntity && pEntity->GetType()== eGameEntityType_Object)
{
cGameObject* pObject = static_cast(pEntity);
if(pObject->GetInteractMode() == eObjectInteractMode_Static)
{
bStatic = true;
}
}
if( pEntity==NULL || bStatic)
{
if(fDist < mfPickedDist)
{
mfMinStaticDist = fDist;
mfPickedDist = fDist;
mpPickedBody = NULL;
mvPickedPos = apParams->mvPoint;
mLastEntityType = eGameEntityType_LastEnum;
}
}
////////////////////////////
//Picked
else
{
if(pEntity->GetType() == eGameEntityType_Area)
{
if(fDist < mfPickedDist)
{
mpPickedBody = apBody;
mLastEntityType = pEntity->GetType();
mvPickedPos = apParams->mvPoint;
mfPickedDist = fDist;
}
}
else
{
if (fDist < mfPickedDist ||
(mLastEntityType == eGameEntityType_Area))
{
mpPickedBody = apBody;
mLastEntityType = pEntity->GetType();
mvPickedPos = apParams->mvPoint;
mfPickedDist = fDist;
}
}
}
return true;*/
}
void cPlayerPickRayCallback::CalculateResults()
{
//Check if an area is closer than the closest normal body
if(mpPickedAreaBody && mfPickedAreaDist < mfPickedDist)
{
bool bUseArea = false;
if(mpPickedBody)
{
iGameEntity *pEntity = (iGameEntity*)mpPickedBody->GetUserData();
cGameArea *pArea = (cGameArea*)mpPickedAreaBody->GetUserData();
if(pEntity)
{
//Too for from object
if(pEntity->GetMaxExamineDist() < mfPickedDist) bUseArea = true;
//No description for object and it is not possible to interact with it
else if(pEntity->GetDescription()==_W(""))
{
if( mpPickedBody->GetMass()==0) bUseArea = true;
else if(pEntity->GetType() == eGameEntityType_Object)
{
cGameObject *pObject = static_cast(pEntity);
if(pObject->GetInteractMode() == eObjectInteractMode_Static) bUseArea= true;
}
}
}
else
{
bUseArea = true;
}
}
else
{
bUseArea = true;
}
if(bUseArea)
{
mpPickedBody = mpPickedAreaBody;
mfPickedDist = mfPickedAreaDist;
mvPickedPos = mvPickedAreaPos;
}
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// HEAD MOVE
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerHeadMove::cPlayerHeadMove(cPlayer *apPlayer)
{
mfAdd =0;
mfPos =0;
mbActive = false;
mpPlayer = apPlayer;
mbFootStepped = false;
mbWasActive = false;
mfClimbCount = 0;
mfClimbPos = 0;
}
//-----------------------------------------------------------------------
void cPlayerHeadMove::Update(float afTimeStep)
{
///////////////////////////////
//Climb count
iCharacterBody *pBody = mpPlayer->GetCharacterBody();
/*float fUpVel = (pBody->GetPosition().y - pBody->GetLastPosition().y) / afTimeStep;*/
if(pBody->IsClimbing() && mfClimbCount==0)
{
mfClimbCount = 0.5f;
mfClimbPos = mfPos;
}
else if(mfClimbCount > 0)
{
mfClimbCount -= afTimeStep;
if(mfClimbCount < 0)
{
mfClimbCount = 0;
mfPos = mfClimbPos;
mfAdd = mfHeadMoveSpeed;
}
}
///////////////////////////////
//Head movement
if(mbActive)
{
mbWasActive = true;
mfPos += mfAdd*afTimeStep * mpPlayer->GetHeadMoveSpeedMul();
if(mfAdd < 0)
{
if(mfPos <= mfMinHeadMove * mpPlayer->GetHeadMoveSpeedMul())
{
mfPos = mfMinHeadMove * mpPlayer->GetHeadMoveSpeedMul();
mfAdd = mfHeadMoveSpeed;
//Create a footstep.
if(mfFootStepMul>0)
mpPlayer->FootStep(mfFootStepMul);
mbFootStepped = true;
}
}
else
{
if(mfPos >= mfMaxHeadMove * mpPlayer->GetHeadMoveSpeedMul())
{
mfPos = mfMaxHeadMove * mpPlayer->GetHeadMoveSpeedMul();
mfAdd = -mfHeadMoveSpeed;
}
}
}
else
{
if(mbWasActive==true && (mbFootStepped==false || (mfPos < 0 && mfAdd<0)) )
{
if(mfFootStepMul>0)
mpPlayer->FootStep(mfFootStepMul*0.6f);
}
mbFootStepped = false;
mbWasActive = false;
if(mfPos==0) return;
if(mfPos <0){
mfPos += mfHeadMoveBackSpeed*afTimeStep;
if(mfPos > 0){
mfPos = 0;
}
}
else
{
mfPos -= mfHeadMoveBackSpeed*afTimeStep;
if(mfPos < 0){
mfPos = 0;
}
}
}
}
//-----------------------------------------------------------------------
void cPlayerHeadMove::Start()
{
if(mbActive==false)
{
mbActive = true;
}
if(fabs(fabs(mfAdd) - mfHeadMoveSpeed) > 0.001f)
{
mfAdd = mfHeadMoveSpeed;
}
}
void cPlayerHeadMove::Stop()
{
mbActive = false;
}
//-----------------------------------------------------------------------
float cPlayerHeadMove::GetPos()
{
if(mfClimbCount > 0) return mfClimbPos;
return mfPos;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// HEALTH
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerHealth::cPlayerHealth(cInit *apInit)
{
mpInit = apInit;
mfTimeCount = 0;
mpDrawer = mpInit->mpGame->GetGraphics()->GetDrawer();
mpDamageGfx = mpDrawer->CreateGfxObject("player_hurt.bmp","diffalpha2d");
mfGfxAlpha =0;
mfGfxAlphaAdd =0;
mfGfxGlobalAlpha =0;
mfTerrorCheckCount =0;
mpSoundEntry = NULL;
}
//-----------------------------------------------------------------------
void cPlayerHealth::Reset()
{
mfTerrorCheckCount =0;
if(mpSoundEntry) mpSoundEntry->mpSound->Stop();
mpSoundEntry = NULL;
mlTerrorLevel =0;
}
//-----------------------------------------------------------------------
void cPlayerHealth::Update(float afTimeStep)
{
cPlayer *pPlayer = mpInit->mpPlayer;
if(pPlayer->GetHealth() <= 0)
{
if(mpSoundEntry) mpSoundEntry->mpSound->Stop();
mpSoundEntry = NULL;
mfGfxAlpha -= afTimeStep *2.0f;
return;
}
////////////////////////////
//ALpha
mfGfxAlpha += mfGfxAlphaAdd * afTimeStep;
if(mfGfxAlphaAdd < 0 && mfGfxAlpha < 0) mfGfxAlpha = 0;
if(mfGfxAlphaAdd > 0 && mfGfxAlpha >= 1.0f)
{
mfGfxAlpha = 1.0f;
mfGfxAlphaAdd = -1.5;
}
////////////////////////////
//Heart timer
if(mfTimeCount<=0)
{
if(pPlayer->GetHealth() >50)
{
pPlayer->SetHealthSpeedMul(1.0f);
mfGfxGlobalAlpha =0;
}
else
{
float fVolume = 0.5;
if(pPlayer->GetHealth() >25)
{
mfTimeCount = 1.7f;
pPlayer->SetHealthSpeedMul(0.8f);
mfGfxGlobalAlpha = 0.5f;
}
else if(pPlayer->GetHealth()>10)
{
mfTimeCount = 1.0;
fVolume = 0.75f;
pPlayer->SetHealthSpeedMul(0.6f);
mfGfxGlobalAlpha = 0.75f;
}
else
{
mfTimeCount = 0.7f;
fVolume = 1.0f;
pPlayer->SetHealthSpeedMul(0.4f);
mfGfxGlobalAlpha = 1.0f;
}
mpInit->mpGame->GetSound()->GetSoundHandler()->PlayGui("player_heartbeat",false,fVolume);
mfGfxAlphaAdd = 3.5f;
}
}
else
{
mfTimeCount -= afTimeStep;
}
////////////////////////////
//Increase health over time:
switch(mpInit->mDifficulty)
{
case eGameDifficulty_Easy:
pPlayer->AddHealth(afTimeStep * 1.4f); break;
case eGameDifficulty_Normal:
pPlayer->AddHealth(afTimeStep * 0.4f); break;
case eGameDifficulty_Hard:
pPlayer->AddHealth(afTimeStep * 0.14f); break;
}
////////////////////////////
//Check for enemies.
/*if(mfTerrorCheckCount <=0)
{
//Check the current terror level.
int lTerrorLevel =0;
tGameEnemyIterator it = mpInit->mpMapHandler->GetGameEnemyIterator();
while(it.HasNext())
{
iGameEnemy *pEnemy = it.Next();
if(pEnemy->IsActive()==false || pEnemy->GetHealth() <=0) continue;
int lState = pEnemy->GetStateMachine()->CurrentState()->GetId();
if(lState == eGameEnemyState_Hunt || lState == eGameEnemyState_Attack)
{
lTerrorLevel = 3;
}
else if(lTerrorLevel < 2 && lState == eGameEnemyState_Investigate)
{
lTerrorLevel = 2;
}
else if(lTerrorLevel < 1)
{
lTerrorLevel = 1;
}
}
if(mlTerrorLevel != lTerrorLevel)
{
mlTerrorLevel = lTerrorLevel;
cSoundHandler *pSoundHandler = mpInit->mpGame->GetSound()->GetSoundHandler();
//Fade out the current sound if there is any.
if(mpSoundEntry)
{
mpSoundEntry->mfNormalVolumeFadeDest = 0;
mpSoundEntry->mfNormalVolumeFadeSpeed = -0.25f;
mpSoundEntry = NULL;
}
mpSoundEntry = NULL;
tString sSound="";
float fVolume;
if(mlTerrorLevel==0)
{
}
else if(mlTerrorLevel==1)
{
sSound = "horror_roach_idle";
fVolume = 0.3f;
}
else if(mlTerrorLevel==2)
{
sSound = "horror_roach_notice";
fVolume = 0.45f;
}
else if(mlTerrorLevel==3)
{
sSound = "horror_roach_attack";
fVolume = 0.6f;
}
if(sSound != "")
{
iSoundChannel *pChannel = pSoundHandler->PlayGui(sSound, true, fVolume);
pChannel->SetPriority(200);
mpSoundEntry = pSoundHandler->GetEntryFromSound(pChannel);
mpSoundEntry->mfNormalVolumeMul =0;
mpSoundEntry->mfNormalVolumeFadeDest =1;
mpSoundEntry->mfNormalVolumeFadeSpeed = 0.55f;
}
}
mfTerrorCheckCount = 0.2f;
}
else
{
mfTerrorCheckCount -= afTimeStep;
}*/
}
void cPlayerHealth::Draw()
{
if(mfGfxAlpha <=0) return;
mpDrawer->DrawGfxObject(mpDamageGfx,cVector3f(0,0,50),cVector2f(800,600),
cColor(1, mfGfxGlobalAlpha * mfGfxAlpha));
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// EAR RING
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerEarRing::cPlayerEarRing(cInit *apInit,cPlayer *apPlayer)
{
mpInit = apInit;
mpPlayer = apPlayer;
mpSoundEntry = NULL;
mfTimeCount =0;
mbDeaf = false;
}
//-----------------------------------------------------------------------
void cPlayerEarRing::Reset()
{
cSoundHandler *pSoundHandler = mpInit->mpGame->GetSound()->GetSoundHandler();
if(mpSoundEntry) mpSoundEntry->mpSound->Stop();
pSoundHandler->SetVolume(1.0f,0.1f,eSoundDest_World);
mpSoundEntry = NULL;
mfTimeCount =0;
mbDeaf = false;
}
//-----------------------------------------------------------------------
void cPlayerEarRing::Update(float afTimeStep)
{
if(mfTimeCount >0)
{
cSoundHandler *pSoundHandler = mpInit->mpGame->GetSound()->GetSoundHandler();
mfTimeCount -= afTimeStep;
mfDeafTime -= afTimeStep;
if(mbDeaf && mfDeafTime <= 0)
{
mbDeaf = false;
pSoundHandler->SetVolume(0.2f,1.5f,eSoundDest_World);
}
if(mfTimeCount <= 0)
{
mfTimeCount =0;
pSoundHandler->SetVolume(1.0f,3.5f,eSoundDest_World);
if(mpSoundEntry)
{
mpSoundEntry->mfNormalVolumeFadeDest = 0;
mpSoundEntry->mfNormalVolumeFadeSpeed = -0.25f;
mpSoundEntry = NULL;
}
}
}
}
//-----------------------------------------------------------------------
void cPlayerEarRing::Start(float afTime)
{
if(mpInit->mpPlayer->GetHealth() <=0) return;
if(mfTimeCount >0)
{
}
else
{
cSoundHandler *pSoundHandler = mpInit->mpGame->GetSound()->GetSoundHandler();
iSoundChannel *pChannel = pSoundHandler->PlayGui("player_ear_ring", true, 0.5f);
pChannel->SetPriority(200);
mpSoundEntry = pSoundHandler->GetEntryFromSound(pChannel);
mpSoundEntry->mfNormalVolumeMul =0;
mpSoundEntry->mfNormalVolumeFadeDest =1;
mpSoundEntry->mfNormalVolumeFadeSpeed = 0.55f;
pSoundHandler->SetVolume(0.0f,1.2f,eSoundDest_World);
}
mfTimeCount = afTime;
mbDeaf = true;
mfDeafTime = afTime *0.3f;
}
//-----------------------------------------------------------------------
void cPlayerEarRing::Stop(bool abStopDirectly)
{
cSoundHandler *pSoundHandler = mpInit->mpGame->GetSound()->GetSoundHandler();
if(abStopDirectly)
{
if(mpSoundEntry) mpSoundEntry->mpSound->Stop();
mpSoundEntry = NULL;
pSoundHandler->SetVolume(1,5,eSoundDest_World);
}
else
{
mfTimeCount =0;
pSoundHandler->SetVolume(1.0f,3.5f,eSoundDest_World);
if(mpSoundEntry)
{
mpSoundEntry->mfNormalVolumeFadeDest = 0;
mpSoundEntry->mfNormalVolumeFadeSpeed = -0.25f;
mpSoundEntry = NULL;
}
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// LEAN
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerLean::cPlayerLean(cInit *apInit, cPlayer *apPlayer)
{
mpPlayer = apPlayer;
mpInit = apInit;
mfMaxMovement = 0.5f;
mfMaxRotation = cMath::ToRad(15);
mpHeadShape = NULL;
}
void cPlayerLean::Reset()
{
mfDir = 0;
mfMaxTime = 0.8f;
mfMovement = 0;
mfRotation =0;
mfMoveSpeed = 0;
mbPressed = false;
}
//-----------------------------------------------------------------------
void cPlayerLean::OnWorldLoad()
{
iPhysicsWorld *pPhysicsWorld = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld();
float fRadius = mpInit->mpPlayer->GetSize().x/2 * 0.63f;
float fHeight = mpInit->mpPlayer->GetCameraHeightAdd()*2;
if(fHeight < 0)fHeight = fHeight * -1;
cMatrixf mtxOffset = cMath::MatrixRotateZ(kPi2f);
mpHeadShape = pPhysicsWorld->CreateCylinderShape(fRadius,fHeight,&mtxOffset);
}
//-----------------------------------------------------------------------
void cPlayerLean::Update(float afTimeStep)
{
////////////////////////////////
//If pressed move in direction
if(mbPressed)
{
mbPressed = false;
float fGoalPos = mfMaxMovement * mfDir;
float fGoalRot = mfMaxRotation * -mfDir;
//////////////
//Position
float fPrevMovement = mfMovement;
float fMoveSpeed = (fGoalPos - mfMovement);
if(fabsf(fMoveSpeed) <0.1f) fMoveSpeed = 0.1f*mfDir;
mfMovement += fMoveSpeed * afTimeStep * 3;
if(fGoalPos < 0 && mfMovement < fGoalPos) mfMovement =fGoalPos;
if(fGoalPos > 0 && mfMovement > fGoalPos) mfMovement =fGoalPos;
//////////////
//Rotation
float fPrevRotation = mfRotation;
float fRotSpeed = fGoalRot - mfRotation;
if(fabsf(fRotSpeed) <0.13f) fRotSpeed = 0.13f*-mfDir;
mfRotation += fRotSpeed * afTimeStep * 2;
if(fGoalRot < 0 && mfRotation < fGoalRot) mfRotation = fGoalRot;
if(fGoalRot > 0 && mfRotation > fGoalRot) mfRotation = fGoalRot;
////////////////////
//Check collision
cCamera3D *pCam = mpInit->mpPlayer->GetCamera();
iPhysicsWorld *pPhysicsWorld = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld();
float fReverseMov = fPrevMovement - mfMovement;
float fReverseRot = fPrevRotation - mfRotation;
iCharacterBody *pCharBody = mpPlayer->GetCharacterBody();
float fHeightAdd = mpPlayer->GetSize().y + mpPlayer->GetHeightAdd() + mpPlayer->GetCameraHeightAdd();
cVector3f vStartPos = pCharBody->GetFeetPosition() + cVector3f(0,fHeightAdd,0);
cVector3f vPos = vStartPos + pCam->GetRight() * mfMovement;
int lCount = 0;
while(pPhysicsWorld->CheckShapeWorldCollision(NULL,mpHeadShape,
cMath::MatrixTranslate(vPos),NULL,false,true,NULL,false))
{
mfMovement += fReverseMov;
mfRotation += fReverseRot;
if(fReverseMov < 0 && mfMovement <0) {
mfMovement =0;
mfRotation =0;
break;
}
if(fReverseMov > 0 && mfMovement >0){
mfMovement =0;
mfRotation =0;
break;
}
vPos = vStartPos + pCam->GetRight() * mfMovement;
lCount++;
if(lCount >10){
mfMovement =0;
mfRotation =0;
break;
}
}
}
////////////////////////////
// Not pressed move back
else
{
float fMoveSpeed = (0 - mfMovement);
mfMovement += fMoveSpeed * afTimeStep * 6;
float fRotSpeed = 0 - mfRotation;
mfRotation += fRotSpeed * afTimeStep * 3;
}
mpPlayer->GetCamera()->AddRoll(mfRotation);
}
//-----------------------------------------------------------------------
bool cPlayerLean::OnIntersect(iPhysicsBody *pBody,cPhysicsRayParams *apParams)
{
if(pBody == mpPlayer->GetCharacterBody()->GetBody())return true;
mbIntersect = true;
return false;
}
//-----------------------------------------------------------------------
void cPlayerLean::Lean(float afMul, float afTimeStep)
{
mbPressed = true;
mfDir = afMul;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// DAMAGE
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerDamage::cPlayerDamage(cInit *apInit)
{
mpInit = apInit;
mpDrawer = mpInit->mpGame->GetGraphics()->GetDrawer();
mpPostEffects = mpInit->mpGame->GetGraphics()->GetRendererPostEffects();
mbActive = false;
mType = ePlayerDamageType_BloodSplash;
mvHitGfx[ePlayerDamageType_BloodSplash] = mpDrawer->CreateGfxObject("player_hit_blood_splash.bmp","diffalpha2d");
mvHitGfx[ePlayerDamageType_Ice] = mpDrawer->CreateGfxObject("player_hit_ice.bmp","diffalpha2d");
mvHeadSwingAcc = cVector2f(17.0f, 17.0f);
}
cPlayerDamage::~cPlayerDamage()
{
for(int i=0; iDestroyGfxObject(mvHitGfx[i]);
}
//-----------------------------------------------------------------------
void cPlayerDamage::Start(float afSize, ePlayerDamageType aType)
{
if(mbActive) return;
mfSize = afSize;
mType = aType;
mfAlpha = 0;
mfAlphaAdd = 4.3f;
mbActive = true;
if(!mpInit->mpPlayer->GetFearFilter()->IsActive())
{
mpPostEffects->SetImageTrailActive(true);
mpPostEffects->SetImageTrailAmount(0);
}
mvHeadSwingSpeed = cVector2f(cMath::RandRectf(-1,1), cMath::RandRectf(0,0.5f));
if(mvHeadSwingSpeed.x == 0 && mvHeadSwingSpeed.y == 0) mvHeadSwingSpeed.x = 1;
else mvHeadSwingSpeed.Normalise();
mvHeadSwingSpeed = mvHeadSwingSpeed * afSize*1.5f;
mpInit->mpPlayer->GetCharacterBody()->SetMoveSpeed(eCharDir_Forward,0);
mpInit->mpPlayer->GetCharacterBody()->SetMoveSpeed(eCharDir_Right,0);
}
//-----------------------------------------------------------------------
void cPlayerDamage::Update(float afTimeStep)
{
if(mbActive==false) return;
//Alpha update
mfAlpha += mfAlphaAdd * afTimeStep;
if(mfAlphaAdd >0)
{
if(mfAlpha >= 1){
mfAlpha = 1;
mfAlphaAdd = -2.2f;
}
}
else if(mfAlphaAdd <0)
{
if(mfAlpha <= 0){
mfAlpha = 0;
}
}
//Update swing
mpInit->mpPlayer->GetCamera()->AddYaw(mvHeadSwingSpeed.x*afTimeStep);
mpInit->mpPlayer->GetCamera()->AddPitch(mvHeadSwingSpeed.y*afTimeStep);
if(mvHeadSwingSpeed.x >0){
mvHeadSwingSpeed.x -= (mvHeadSwingAcc.x/mfSize) * afTimeStep * 2.2f;
if(mvHeadSwingSpeed.x <0) mvHeadSwingSpeed.x =0;
}
else {
mvHeadSwingSpeed.x += (mvHeadSwingAcc.x/mfSize) * afTimeStep * 2.2f;
if(mvHeadSwingSpeed.x >0) mvHeadSwingSpeed.x =0;
}
if(mvHeadSwingSpeed.y >0){
mvHeadSwingSpeed.y -= (mvHeadSwingAcc.x/mfSize) * afTimeStep * 2.2f;
if(mvHeadSwingSpeed.y <0) mvHeadSwingSpeed.y =0;
}
else {
mvHeadSwingSpeed.y += (mvHeadSwingAcc.x/mfSize) * afTimeStep * 2.2f;
if(mvHeadSwingSpeed.y >0) mvHeadSwingSpeed.y =0;
}
//Blur update
if(mpInit->mpPlayer->IsDead()==false)
{
if(!mpInit->mpPlayer->GetFearFilter()->IsActive())
{
mpPostEffects->SetImageTrailAmount(mfAlpha *0.92f);
}
}
//Has it ended?
if(mvHeadSwingSpeed.x == 0 && mvHeadSwingSpeed.y == 0 && mfAlpha ==0)
{
mbActive = false;
if(mpInit->mpPlayer->IsDead()==false)
{
if(!mpInit->mpPlayer->GetFearFilter()->IsActive())
{
mpPostEffects->SetImageTrailActive(false);
mpPostEffects->SetImageTrailAmount(0);
}
}
}
}
//-----------------------------------------------------------------------
void cPlayerDamage::Draw()
{
if(mbActive==false) return;
mpDrawer->DrawGfxObject(mvHitGfx[mType],cVector3f(0,0,3),cVector2f(800, 600),cColor(1,mfAlpha*0.6f));
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// DEATH
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerDeath::cPlayerDeath(cInit *apInit)
{
mpInit = apInit;
mpDrawer = mpInit->mpGame->GetGraphics()->GetDrawer();
mpPostEffects = mpInit->mpGame->GetGraphics()->GetRendererPostEffects();
mpFadeGfx = mpDrawer->CreateGfxObject("player_death_fade.bmp","smoke2d");
mpBlackGfx = mpDrawer->CreateGfxObject("player_death_black.bmp","smoke2d");
}
cPlayerDeath::~cPlayerDeath()
{
mpDrawer->DestroyGfxObject(mpFadeGfx);
}
//-----------------------------------------------------------------------
void cPlayerDeath::Reset()
{
mbActive = false;
mfHeightAdd =0;
mfRoll =0;
mpPostEffects->SetImageTrailActive(false);
}
//-----------------------------------------------------------------------
void cPlayerDeath::Start()
{
if(mbActive) return;
if(mpInit->mpInventory->IsActive()) mpInit->mpInventory->SetActive(false);
if(mpInit->mpNotebook->IsActive()) mpInit->mpNotebook->SetActive(false);
if(mpInit->mpNumericalPanel->IsActive()) mpInit->mpNumericalPanel->SetActive(false);
mpInit->mpPlayer->GetFlashLight()->SetActive(false);
mpInit->mpPlayer->GetGlowStick()->SetActive(false);
mpInit->mpPlayer->GetFlare()->SetActive(false);
mpInit->mpPlayerHands->SetCurrentModel(0,"");
mpInit->mpPlayerHands->SetCurrentModel(1,"");
mpInit->mpPlayer->ChangeState(ePlayerState_Normal);
mfHeightAdd =0;
mfRoll =0;
mfMinHeightAdd = -1.3f;
if(mpInit->mpPlayer->GetMoveState() == ePlayerMoveState_Crouch) mfMinHeightAdd = -0.7f;
mbActive = true;
mbStartFade = false;
mfFadeAlpha =0;
mfBlackAlpha = 0;
mpPostEffects->SetImageTrailActive(true);
mpPostEffects->SetImageTrailAmount(0.7f);
mpInit->mpPlayer->GetEarRing()->Stop(false);
for(int i=0; i<=10;++i)
{
mpInit->mpMusicHandler->Stop(0.2f,i);
}
}
//-----------------------------------------------------------------------
void cPlayerDeath::Update(float afTimeStep)
{
if(mbActive==false) return;
mfHeightAdd-= 0.95f*afTimeStep;
if(mfHeightAdd < mfMinHeightAdd){
mfHeightAdd = mfMinHeightAdd;
mbStartFade = true;
mpInit->mpDeathMenu->SetActive(true);
}
mfRoll += cMath::ToRad(40.0f)*afTimeStep;
if(mfRoll > cMath::ToRad(65.0f)) mfRoll = cMath::ToRad(65.0f);
mpInit->mpPlayer->GetCamera()->AddRoll(mfRoll);
if(mbStartFade)
{
mfFadeAlpha += 0.7f * afTimeStep;
if(mfFadeAlpha > 1) mfFadeAlpha = 1;
if(mfFadeAlpha > 0.6f){
mfBlackAlpha += 0.45f * afTimeStep;
if(mfBlackAlpha >1) mfBlackAlpha =1;
}
}
}
//-----------------------------------------------------------------------
void cPlayerDeath::Draw()
{
if(mbActive==false) return;
cVector3f vPos(-mfFadeAlpha*400 - mfBlackAlpha*200,-mfFadeAlpha*400 - mfBlackAlpha*200,4);
cVector2f vSize(800 + mfFadeAlpha*800 + mfBlackAlpha*400, 600 + mfFadeAlpha*800+ mfBlackAlpha*400);
mpDrawer->DrawGfxObject(mpFadeGfx,vPos,vSize,cColor(mfFadeAlpha,0));
mpDrawer->DrawGfxObject(mpBlackGfx,cVector3f(0,0,5),cVector2f(800,600),cColor(mfBlackAlpha,0));
}
//-----------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////
// FLASHLIGHT
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerFlashLight::cPlayerFlashLight(cInit *apInit)
{
mpInit = apInit;
mpInit->mpPlayerHands->AddModelFromFile("hud_object_flashlight.hud");
Reset();
}
//-----------------------------------------------------------------------
cPlayerFlashLight::~cPlayerFlashLight()
{
}
//-----------------------------------------------------------------------
void cPlayerFlashLight::Reset()
{
mbActive = false;
mfAlpha =0;
mfFlickerTime =0;
mfRayCastTime = 0;
mpClosestBody = NULL;
mfClosestDist = 10000.0f;
mbDisabled = false;
}
//-----------------------------------------------------------------------
bool cPlayerFlashLight::OnIntersect(iPhysicsBody *pBody,cPhysicsRayParams *apParams)
{
if(pBody->GetCollide()==false) return true;
if(pBody->IsCharacter() && pBody == mpInit->mpPlayer->GetCharacterBody()->GetBody()) return true;
if(apParams->mfDist < mfClosestDist)
{
mfClosestDist = apParams->mfDist;
mpClosestBody = pBody;
}
return true;
}
//-----------------------------------------------------------------------
void cPlayerFlashLight::OnWorldLoad()
{
}
//-----------------------------------------------------------------------
void cPlayerFlashLight::Update(float afTimeStep)
{
if(mbActive)
{
//////////////////////////
//Hits enemy
if(mfRayCastTime >= 1)//1.0f/20.0f)
{
mfRayCastTime =0;
cCamera3D *pCam = mpInit->mpPlayer->GetCamera();
iPhysicsWorld *pPhysicsWorld = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld();
iHudModel *pHudModel = mpInit->mpPlayerHands->GetModel("Flashlight");
cVector3f vForward = pCam->GetForward();
if(pHudModel && pHudModel->GetEntity())
{
vForward = cMath::MatrixMul(
pHudModel->GetEntity()->GetWorldMatrix().GetRotation(),
cVector3f(0,-1,0));
}
if(pHudModel == mpInit->mpPlayerHands->GetCurrentModel(0))
{
tGameEnemyIterator it = mpInit->mpMapHandler->GetGameEnemyIterator();
while(it.HasNext())
{
iGameEnemy *pEnemy = it.Next();
if(pEnemy->GetHealth() <=0 || pEnemy->IsActive()==false) continue;
cVector3f vToEnemy = pEnemy->GetMover()->GetCharBody()->GetPosition() -
mpInit->mpPlayer->GetCharacterBody()->GetPosition();
float fSqrDist = vToEnemy.SqrLength();
vToEnemy.Normalise();
if(fSqrDist < 100.0f)
{
float fAngle = cMath::Vector3Angle(vToEnemy,vForward);
if(fAngle < cMath::ToRad(25))
{
cVector3f vStart = pCam->GetPosition();
cVector3f vEnd = pEnemy->GetMover()->GetCharBody()->GetPosition();
mvStart =vStart;
mvEnd = vEnd;
mpClosestBody = NULL; mfClosestDist = 10000.0f;
pPhysicsWorld->CastRay(this,vStart,vEnd,true,false,false,false);
if( mpClosestBody == NULL || mpClosestBody->IsCharacter()==true)
{
if(pEnemy->GetUsesTriggers())
{
pEnemy->OnFlashlight(pCam->GetPosition());
}
}
}
}
}
//////////////////////////////
//Get forward
//cVector3f vForward = pCam->GetForward();
/*float fAngleX = cMath::RandRectf(cMath::ToRad(-3),cMath::ToRad(3));
float fAngleY = cMath::RandRectf(0,k2Pif);
cVector3f vForward = cMath::MatrixMul(
cMath::MatrixRotate(cVector3f(fAngleX,fAngleY,0),eEulerRotationOrder_XYZ),
cVector3f(0,1,0));
vForward = cMath::MatrixMul(
pHudModel->GetEntity()->GetWorldMatrix().GetRotation(),
//cMath::MatrixInverse(pCam->GetViewMatrix().GetRotation()),
//cMath::MatrixRotate(cVector3f(pCam->GetPitch(),pCam->GetYaw(),pCam->GetRoll()),
// eEulerRotationOrder_YXZ),
vForward*-1);
//////////////////////////////
//Get start and end
cVector3f vStart = pCam->GetPosition();
cVector3f vEnd = pCam->GetPosition() + vForward* 20.0f;
mvStart =vStart;
mvEnd = vEnd;
mpClosestBody = NULL; mfClosestDist = 10000.0f;
pPhysicsWorld->CastRay(this,vStart,vEnd,true,false,false,false);
if(mpClosestBody)
{
iGameEntity *pEntity = (iGameEntity*)mpClosestBody->GetUserData();
if( pEntity && pEntity->GetType() == eGameEntityType_Enemy &&
pEntity->IsActive() && pEntity->GetHealth() >0)
{
iGameEnemy *pEnemy = static_cast(pEntity);
if(pEnemy->GetUsesTriggers())
pEnemy->OnFlashlight(vStart);
}
}*/
//mpInit->mpEffectHandler->GetSubTitle()->Add("Cast rays!\n",0.5f);
}
}
else
{
mfRayCastTime += afTimeStep;
}
}
iHudModel *pHudModel = mpInit->mpPlayerHands->GetCurrentModel(0);
//////////////////////////
//Player power
if( mbActive &&
mpInit->mpInventory->IsActive()==false &&
mpInit->mpNotebook->IsActive() == false &&
mpInit->mpNumericalPanel->IsActive() == false)
{
mpInit->mpPlayer->AddPower(-0.1f * afTimeStep);
if(mpInit->mpPlayer->GetPower()==0)
{
SetActive(false);
}
}
//////////////////////////
//Flicker at low energy
if(mbActive && mpInit->mpInventory->IsActive()==false &&
pHudModel->msName == "Flashlight")
{
if(mpInit->mpPlayer->GetPower() < 3.0f)
{
if(mfFlickerTime <= 0)
{
if(pHudModel->mvLights[0]->IsVisible())
{
pHudModel->mvLights[0]->SetVisible(false);
pHudModel->mvBillboards[0]->SetVisible(false);
mfFlickerTime = cMath::RandRectf(0.04f,0.15f);
cSoundHandler *pSoundHanlder = mpInit->mpGame->GetSound()->GetSoundHandler();
pSoundHanlder->PlayGui("item_flashlight_flicker",false,1);
}
else
{
pHudModel->mvLights[0]->SetVisible(true);
pHudModel->mvBillboards[0]->SetVisible(true);
mfFlickerTime = cMath::RandRectf(0.05f,1.5f);
}
}
else
{
mfFlickerTime -= afTimeStep;
}
}
}
}
//-----------------------------------------------------------------------
void cPlayerFlashLight::SetActive(bool abX)
{
cSoundHandler *pSoundHanlder = mpInit->mpGame->GetSound()->GetSoundHandler();
if(abX && (mpInit->mpPlayer->GetPower()==0 || mbDisabled)) {
pSoundHanlder->PlayGui("item_flashlight_nopower",false,1);
return;
}
if(mbActive == abX) return;
mbActive = abX;
/////////////////////////////
//Active
if(mbActive)
{
mpInit->mpPlayerHands->SetCurrentModel(0,"Flashlight");
//pSoundHanlder->PlayGui("item_flashlight_on",false,1);
}
/////////////////////////////
//Not active
else if(mpInit->mpPlayerHands->GetCurrentModel(0) &&
mpInit->mpPlayerHands->GetCurrentModel(0)->msName == "Flashlight" &&
mpInit->mpPlayerHands->GetCurrentModel(0)->GetState() != eHudModelState_Unequip)
{
mpInit->mpPlayerHands->SetCurrentModel(0,"");
if(mpInit->mpPlayer->GetPower()==0)
pSoundHanlder->PlayGui("item_flashlight_nopower",false,1);
//else
// pSoundHanlder->PlayGui("item_flashlight_off",false,1);
}
}
//-----------------------------------------------------------------------
void cPlayerFlashLight::SetDisabled(bool abX)
{
if(abX==true) SetActive(false);
mbDisabled = abX;
}
//-----------------------------------------------------------------------
void cPlayerFlashLight::OnPostSceneDraw()
{
/*iLowLevelGraphics *mpLowGfx = mpInit->mpGame->GetGraphics()->GetLowLevel();
mpLowGfx->DrawLine(mvStart,mvEnd,cColor(1,0,1));*/
}
//-----------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////
// GLOW STICK
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerGlowStick::cPlayerGlowStick(cInit *apInit)
{
mpInit = apInit;
mpInit->mpPlayerHands->AddModelFromFile("hud_object_glowstick.hud");
Reset();
}
//-----------------------------------------------------------------------
cPlayerGlowStick::~cPlayerGlowStick()
{
}
//-----------------------------------------------------------------------
void cPlayerGlowStick::Reset()
{
mbActive = false;
}
//-----------------------------------------------------------------------
void cPlayerGlowStick::OnWorldLoad()
{
}
//-----------------------------------------------------------------------
void cPlayerGlowStick::Destroy()
{
}
//-----------------------------------------------------------------------
void cPlayerGlowStick::Update(float afTimeStep)
{
}
//-----------------------------------------------------------------------
void cPlayerGlowStick::SetActive(bool abX)
{
if(mbActive == abX) return;
mbActive = abX;
cSoundHandler *pSoundHanlder = mpInit->mpGame->GetSound()->GetSoundHandler();
if(mbActive)
{
//Log("Setting the glowstick to TRUE\n");
mpInit->mpPlayerHands->SetCurrentModel(0,"Glowstick");
//pSoundHanlder->PlayGui("item_glowstick_on",false,1);
}
else if(mpInit->mpPlayerHands->GetCurrentModel(0) &&
mpInit->mpPlayerHands->GetCurrentModel(0)->msName == "Glowstick" &&
mpInit->mpPlayerHands->GetCurrentModel(0)->GetState() != eHudModelState_Unequip)
{
//Log("Setting the glowstick to FALSE\n");
mpInit->mpPlayerHands->SetCurrentModel(0,"");
//pSoundHanlder->PlayGui("item_glowstick_off",false,1);
}
}
//-----------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////
// FLARE
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerFlare::cPlayerFlare(cInit *apInit)
{
mpInit = apInit;
mpInit->mpPlayerHands->AddModelFromFile("hud_object_flare.hud");
mfTime = mpInit->mpGameConfig->GetFloat("Items","FlareGlowTime",1);
mfLightPulse = 1.0f;
mfLightPulseAdd = 0.88f;
mpLight =NULL;
Reset();
}
//-----------------------------------------------------------------------
cPlayerFlare::~cPlayerFlare()
{
}
//-----------------------------------------------------------------------
void cPlayerFlare::Reset()
{
mbActive = false;
mpLight =NULL;
}
//-----------------------------------------------------------------------
void cPlayerFlare::OnWorldLoad()
{
mpLight =NULL;
}
//-----------------------------------------------------------------------
void cPlayerFlare::Update(float afTimeStep)
{
if(mbActive)
{
//////////////////////////////////////
// Model entities are loaded and light gotten
if(mpLight)
{
//////////////////////
// Fade at end
if(mfTime <=30)
{
mfLightRadius = (mfTime/30.0f) * mfMaxLightRadius;
}
float fRadius = mfLightRadius;
//////////////////////
// Pulse
mfLightPulse += mfLightPulseAdd*afTimeStep;
if(mfLightPulseAdd >0 && mfLightPulse >= 1.0f)
{
mfLightPulse = 1.0f;
mfLightPulseAdd = -mfLightPulseAdd;
}
if(mfLightPulseAdd <0 && mfLightPulse <= 0.0f)
{
mfLightPulse = 0.0f;
mfLightPulseAdd = -mfLightPulseAdd;
}
fRadius = (mfLightPulse*0.4f +0.8f)*mfLightRadius;
if(mpLight) mpLight->SetFarAttenuation(fRadius);
//////////////////////
// Time
if( mpInit->mpInventory->IsActive()==false &&
mpInit->mpNotebook->IsActive() == false &&
mpInit->mpNumericalPanel->IsActive() == false)
{
mfTime -= afTimeStep;
if(mfTime <=0)
{
SetActive(false);
}
}
}
//////////////////////////////////////
// Model entities not loaded yet
else
{
if(mpModel == mpInit->mpPlayerHands->GetCurrentModel(0))
{
if(mpModel->mvLights.empty()==false)
{
mpLight = mpModel->mvLights[0];
mfMaxLightRadius = mpLight->GetFarAttenuation();
mfLightRadius = mfMaxLightRadius;
}
else
{
Warning("No lights in flare!\n");
}
}
}
}
}
//-----------------------------------------------------------------------
void cPlayerFlare::SetActive(bool abX)
{
if(mbActive == abX) return;
mbActive = abX;
cSoundHandler *pSoundHanlder = mpInit->mpGame->GetSound()->GetSoundHandler();
if(mbActive)
{
mpInit->mpPlayerHands->SetCurrentModel(0,"Flare");
if(mpInit->mpPlayer->GetFlashLight()->IsActive())
mpInit->mpPlayer->GetFlashLight()->SetActive(false);
if(mpInit->mpPlayer->GetGlowStick()->IsActive())
mpInit->mpPlayer->GetGlowStick()->SetActive(false);
mfTime = mpInit->mpGameConfig->GetFloat("Items","FlareGlowTime",1);
mpModel = mpInit->mpPlayerHands->GetModel("Flare");
mpLight = NULL;
}
else
{
///////////////////////////////
//Check if hud model should be put down.
if(mpInit->mpPlayerHands->GetCurrentModel(0) &&
mpInit->mpPlayerHands->GetCurrentModel(0)->msName == "Flare" &&
mpInit->mpPlayerHands->GetCurrentModel(0)->GetState() != eHudModelState_Unequip)
{
mpInit->mpPlayerHands->SetCurrentModel(0,"");
}
///////////////////////////////
//Create entity
cCamera3D *pCam = mpInit->mpPlayer->GetCamera();
cVector3f vRot = cVector3f(pCam->GetPitch(),pCam->GetYaw(), pCam->GetRoll());
cMatrixf mtxStart = cMath::MatrixRotate(vRot, eEulerRotationOrder_XYZ);
mtxStart.SetTranslation(pCam->GetPosition());
iEntity3D *pEntity = mpInit->mpGame->GetScene()->GetWorld3D()->CreateEntity("Throw",mtxStart,
"items_flare_thrown.ent", true);
if(pEntity)
{
iGameEntity *pEntity = mpInit->mpMapHandler->GetLatestEntity();
cVector3f vRot =cMath::MatrixMul(mtxStart.GetRotation(),cVector3f(1,0.3f,0));
for(int i=0; i< pEntity->GetBodyNum(); ++i)
{
iPhysicsBody *pBody = pEntity->GetBody(i);
pBody->AddImpulse(pCam->GetForward() * 3.0f);
pBody->AddTorque(vRot);
}
//setup light
if(mfTime <=30)
{
float fRadius = (mfTime/30.0f);
if(fRadius <0)fRadius =0;
for(int i=0; i< pEntity->GetLightNum(); ++i)
{
iLight3D *pLight = pEntity->GetLight(i);
pLight->SetFarAttenuation(pLight->GetFarAttenuation() * fRadius);
}
}
}
}
}
//-----------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////
// NOISE FILTER
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerNoiseFilter::cPlayerNoiseFilter(cInit *apInit)
{
mpInit = apInit;
mpDrawer = mpInit->mpGame->GetGraphics()->GetDrawer();
mlAmount = 6;
for(int i=0; iCreateGfxObject(sFileName,"smoke2d");
if(pObject==NULL)
{
FatalError("Error loading noise filter!\n");
}
mvGfxNoise.push_back(pObject);
}
mvCurrentGfx.resize(20 * 15,cMath::RandRectl(0,mlAmount-1));
mfAlpha = 0.3f;
mfTimeCount =0;
mbActive = mpInit->mpConfig->GetBool("Graphics", "NoiseFilter",true);
}
//-----------------------------------------------------------------------
cPlayerNoiseFilter::~cPlayerNoiseFilter()
{
mpInit->mpConfig->SetBool("Graphics", "NoiseFilter",mbActive);
for(size_t i=0; i< mvGfxNoise.size(); ++i)
{
mpDrawer->DestroyGfxObject(mvGfxNoise[i]);
}
}
//-----------------------------------------------------------------------
void cPlayerNoiseFilter::Draw()
{
if(mbActive == false) return;
for(int x=0;x <20;++x)
for(int y=0; y< 15; ++y)
{
cVector3f vPos((float)x*40, (float)y*40,0);
mpDrawer->DrawGfxObject(mvGfxNoise[mvCurrentGfx[x*y]],vPos,40,cColor(mfAlpha,0));
//mpDrawer->DrawGfxObject(mvGfxNoise[0],vPos,40,cColor(mfAlpha,mfAlpha));
}
}
//-----------------------------------------------------------------------
void cPlayerNoiseFilter::Update(float afTimeStep)
{
if(mbActive == false) return;
if(mfTimeCount <=0)
{
for(int x=0;x <20;++x)
for(int y=0; y< 15; ++y)
{
//Change the image
int lCurrent = mvCurrentGfx[x*y];
int lRand = cMath::RandRectl(0,mlAmount-1);
if(lRand == lCurrent){
++lRand;
if(lRand >= mlAmount) lRand=0;
}
mvCurrentGfx[x*y] = lRand;
}
mfTimeCount = 1 / 15.0f;
}
else
{
mfTimeCount -= afTimeStep;
}
}
//-----------------------------------------------------------------------
void cPlayerNoiseFilter::SetActive(bool abX)
{
mbActive = abX;
}
//-----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
// FEAR FILTER
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerFearFilter::cPlayerFearFilter(cInit *apInit)
{
mpInit = apInit;
Reset();
}
//-----------------------------------------------------------------------
cPlayerFearFilter::~cPlayerFearFilter()
{
}
//-----------------------------------------------------------------------
void cPlayerFearFilter::Draw()
{
}
//-----------------------------------------------------------------------
void cPlayerFearFilter::Update(float afTimeStep)
{
if(mpInit->mpPlayer->IsDead())return;
if(mbActive)
{
mfAlpha += afTimeStep * 0.5f;
if(mfAlpha > mfMaxAlpha) mfAlpha = mfMaxAlpha;
mpInit->mpGame->GetGraphics()->GetRendererPostEffects()->SetImageTrailAmount(mfAlpha);
}
else if(mfAlpha >0)
{
mfAlpha -= afTimeStep * 0.15f;
if(mfAlpha < 0)
{
mfAlpha =0;
mpInit->mpGame->GetGraphics()->GetRendererPostEffects()->SetImageTrailActive(false);
}
else
{
mpInit->mpGame->GetGraphics()->GetRendererPostEffects()->SetImageTrailAmount(mfAlpha);
}
}
}
//-----------------------------------------------------------------------
void cPlayerFearFilter::Reset()
{
mbActive = false;
mfAlpha =0;
mfMaxAlpha = 0.58f;
}
//-----------------------------------------------------------------------
void cPlayerFearFilter::SetActive(bool abX)
{
if(mbActive == abX) return;
mbActive = abX;
mfAlpha =0;
mpInit->mpGame->GetGraphics()->GetRendererPostEffects()->SetImageTrailActive(true);
mpInit->mpGame->GetGraphics()->GetRendererPostEffects()->SetImageTrailAmount(0);
}
//-----------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////
// LOOK AT
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerLookAt::cPlayerLookAt(cPlayer *apPlayer)
{
mpPlayer = apPlayer;
Reset();
}
//-----------------------------------------------------------------------
cPlayerLookAt::~cPlayerLookAt()
{
}
//-----------------------------------------------------------------------
void cPlayerLookAt::Update(float afTimeStep)
{
if(mbActive==false) return;
cCamera3D *pCam = mpPlayer->GetCamera();
cVector3f vGoalAngle = cMath::GetAngleFromPoints3D(pCam->GetPosition(),mvTargetPos);
//Get distance to goal
cVector3f vDist;
vDist.x = cMath::GetAngleDistanceRad(pCam->GetPitch(),vGoalAngle.x);
vDist.y = cMath::GetAngleDistanceRad(pCam->GetYaw(),vGoalAngle.y);
//Get the Speed
cVector3f vSpeed;
vSpeed.x = cMath::Min(vDist.x * mfSpeedMul, mfMaxSpeed);
vSpeed.y = cMath::Min(vDist.y * mfSpeedMul, mfMaxSpeed);
//Add Pitch
pCam->AddPitch(vSpeed.x * afTimeStep);
//Add yaw
pCam->AddYaw(vSpeed.y * afTimeStep);
mpPlayer->GetCharacterBody()->SetYaw(pCam->GetYaw());
}
void cPlayerLookAt::Reset()
{
mbActive = false;
mfMaxSpeed = 9999.0f;
mfSpeedMul = 1.0f;
mvTargetPos = cVector3f(0,1,0);
}
void cPlayerLookAt::SetTarget(const cVector3f &avTargetPos, float afSpeedMul, float afMaxSpeed)
{
mvTargetPos = avTargetPos;
mfSpeedMul = afSpeedMul;
mfMaxSpeed = afMaxSpeed;
}
void cPlayerLookAt::SetActive(bool abX)
{
mbActive = abX;
}
//-----------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////
// HIDDEN
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cPlayerHidden::cPlayerHidden(cInit *apInit)
{
mpInit = apInit;
mpRenderer = mpInit->mpGame->GetGraphics()->GetRenderer3D();
mpDrawer = mpInit->mpGame->GetGraphics()->GetDrawer();
mpSoundHandler = mpInit->mpGame->GetSound()->GetSoundHandler();
mfUpdateCount = 1.0f / 3.0f;
cVector2f vScreenSize = mpInit->mpGame->GetGraphics()->GetLowLevel()->GetScreenSize();
mfStartEffectOffset = 40;
mfHiddenEffectOffset = 0;
mfEffectOffsetAdd = mfStartEffectOffset - mfHiddenEffectOffset;
mfStartAspect = vScreenSize.x / vScreenSize.y;
mfHiddenAspect = mfStartAspect*0.82f;
mfAspectAdd = mfStartAspect - mfHiddenAspect;
mfStartFov = cMath::ToRad(70);
mfHiddenFov = cMath::ToRad(78);
mfFovAdd = mfHiddenFov- mfStartFov;
mfEnemyTooCloseMax = 4.5f;
mfCloseEffectFovMax = cMath::ToRad(2);
mfCloseEffectFovMin = cMath::ToRad(-11);
Reset();
//Get images
mpInShadowGfx = mpDrawer->CreateGfxObject("player_in_shadow.jpg","diffadditive2d");
//Get font
mpFont = mpInit->mpGame->GetResources()->GetFontManager()->CreateFontData("verdana.fnt");
}
//-----------------------------------------------------------------------
cPlayerHidden::~cPlayerHidden()
{
}
//-----------------------------------------------------------------------
void cPlayerHidden::OnWorldLoad()
{
cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D();
mpLight = pWorld->CreateLightPoint("HiddenLight");
mpLight->SetFarAttenuation(13);
mpLight->SetDiffuseColor(cColor(0,0,0,0));
mpLight->SetVisible(false);
mpLight->SetCastShadows(false);
}
void cPlayerHidden::OnWorldExit()
{
}
//-----------------------------------------------------------------------
void cPlayerHidden::Draw()
{
/*if(mfLight <= mfMaxLight)
{
mpFont->Draw(5,12,cColor(0.3f,1,0.3f),eFontAlign_Left,_W("Light: %f\n"),mfLight);
if(!mbHidden)
mpFont->Draw(cVector3f(5,19,5),12,cColor(1,1,1),eFontAlign_Left,_W("Hidden count: %f"),mfHiddenCount);
}
else
{
mpFont->Draw(5,12,cColor(1,0.3f,0.3f),eFontAlign_Left,_W("Light: %f\n"),mfLight);
}
if(mbHidden)
mpFont->Draw(cVector3f(5,19,5),12,cColor(1,1,1),eFontAlign_Left,_W("Hidden\n"));
*/
/*float fAdd =0;
if(mfCloseEffectFov >= 0)
{
float fT = mfCloseEffectFov / mfCloseEffectFovMax;
fAdd = sin(fT * kPi2f) * mfCloseEffectFovMax;
}
else
{
float fT = mfCloseEffectFov / mfCloseEffectFovMin;
fAdd = sin(fT * kPi2f) * mfCloseEffectFovMin;
}
mpFont->Draw(5,12,cColor(1,1,1),eFontAlign_Left,"CloseCount: %f TooClose: %d\n",
mfEnemyTooCloseCount,
mbEnemyTooClose);
mpFont->Draw(cVector3f(5,19,5),12,cColor(1,1,1),eFontAlign_Left,"Fov: %f Add: %f\n",
mfCloseEffectFov,fAdd);*/
//Draw in shadow effect
if(mfInShadowAlpha>0)
{
float fAlpha = (mfInShadowPulse*0.5f + 0.5f) * mfInShadowAlpha *0.85f;
mpDrawer->DrawGfxObject(mpInShadowGfx,cVector3f(-mfEffectOffset,-mfEffectOffset,0),
cVector2f(800+mfEffectOffset*2, 600+mfEffectOffset*2),
cColor(fAlpha,fAlpha));
}
}
//-----------------------------------------------------------------------
void cPlayerHidden::UnHide()
{
if(mbHidden){
mpLight->FadeTo(cColor(0,0,0,0),mpLight->GetFarAttenuation(),mfHiddenOffTime);
if(mfHiddenOnCount >2)
mpSoundHandler->PlayGui("player_hidden_off",false,1);
}
mbHidden = false;
mfHiddenCount =0;
mfHiddenOnCount =0;
if(mbEnemyTooClose)
{
mpInit->mpGame->GetGraphics()->GetRendererPostEffects()->SetImageTrailActive(false);
}
mfEnemyTooCloseCount =0;
mbEnemyTooClose = false;
}
//-----------------------------------------------------------------------
bool cPlayerHidden::InShadows()
{
if(mfLight <= mfMaxLight) return true;
return false;
}
//-----------------------------------------------------------------------
static float GetMaxRGB(const cColor &aCol)
{
float fAmount = aCol.r;
if(fAmount < aCol.g) fAmount = aCol.g;
if(fAmount < aCol.b) fAmount = aCol.b;
return fAmount;
}
void cPlayerHidden::Update(float afTimeStep)
{
iCharacterBody *pCharBody = mpInit->mpPlayer->GetCharacterBody();
bool bIsCrouching = false;
if(mpInit->mpPlayer->GetMoveState() == ePlayerMoveState_Crouch) bIsCrouching = true;
///////////////////////////////////
// Update Hidden effect
if(mbHidden)
{
//Aspect
if(mfAspect > mfHiddenAspect)
{
mfAspect -= afTimeStep * mfAspectAdd *(1/mfHiddenOnTime);
if(mfAspect < mfHiddenAspect) mfAspect = mfHiddenAspect;
mpInit->mpPlayer->GetCamera()->SetAspect(mfAspect);
}
//FOV
if(mfFov < mfHiddenFov)
{
mfFov += afTimeStep * mfFovAdd*(1/mfHiddenOnTime);
if(mfFov > mfHiddenFov) mfFov = mfHiddenFov;
mpInit->mpPlayer->GetCamera()->SetFOV(mfFov);
}
//Effect offset
if(mfEffectOffset > mfHiddenEffectOffset)
{
mfEffectOffset -= afTimeStep * mfEffectOffsetAdd*(1/mfHiddenOnTime);
if(mfEffectOffset < mfHiddenEffectOffset) mfEffectOffset = mfHiddenEffectOffset;
}
}
else
{
//Aspect
if(mfAspect < mfStartAspect)
{
mfAspect += afTimeStep * mfAspectAdd * (1/mfHiddenOffTime);
if(mfAspect > mfStartAspect) mfAspect = mfStartAspect;
mpInit->mpPlayer->GetCamera()->SetAspect(mfAspect);
}
//FOV
if(mfFov > mfStartFov)
{
mfFov -= afTimeStep * mfFovAdd * (1/mfHiddenOffTime);
if(mfFov < mfStartFov) mfFov = mfStartFov;
mpInit->mpPlayer->GetCamera()->SetFOV(mfFov);
}
//Effect offset
if(mfEffectOffset < mfStartEffectOffset)
{
mfEffectOffset += afTimeStep * mfEffectOffsetAdd * (1/mfHiddenOffTime);
if(mfEffectOffset > mfStartEffectOffset) mfEffectOffset = mfStartEffectOffset;
}
}
///////////////////////////////////
// Update In Shadow effect
//Alpha
if(mfLight <= mfMaxLight && bIsCrouching)
{
mfInShadowAlpha += afTimeStep;
if(mfInShadowAlpha>1) mfInShadowAlpha = 1;
}
else
{
mfInShadowAlpha -= afTimeStep;
if(mfInShadowAlpha<0) mfInShadowAlpha = 0;
}
//Pulse
mfInShadowPulse += afTimeStep * mfInShadowPulseAdd;
if(mfInShadowPulseAdd<0 && mfInShadowPulse<0)
{
mfInShadowPulse =0;
mfInShadowPulseAdd = -mfInShadowPulseAdd;
}
else if(mfInShadowPulseAdd>0 && mfInShadowPulse>1)
{
mfInShadowPulse =1;
mfInShadowPulseAdd = -mfInShadowPulseAdd;
}
if(mbInShadows)
mpLight->SetPosition(mpInit->mpPlayer->GetCamera()->GetPosition());
//////////////////////////////////////////
// Check if the player is hidden
if( mfLight <= mfMaxLight && bIsCrouching && mpInit->mpPlayer->GetHealth()>0)
{
cVector3f vDiff = pCharBody->GetLastPosition() - pCharBody->GetPosition();
if(fabsf(vDiff.x) < 0.01f && fabsf(vDiff.y) < 0.01f && fabsf(vDiff.z) < 0.01f)
{
if(!mbHidden)
{
if(mfHiddenCount >= mfHiddenTime)
{
mbInShadows = false;
mbHidden = true;
mpLight->SetVisible(true);
mpLight->SetPosition(mpInit->mpPlayer->GetCamera()->GetPosition());
mpLight->FadeTo(cColor(0.1f,0.1f,0.6f,0),12,mfHiddenOnTime);
mpSoundHandler->PlayGui("player_hidden_on",false,1);
}
else
{
mfHiddenCount += afTimeStep;
}
}
else
{
mfHiddenOnCount += afTimeStep;
}
}
else
{
UnHide();
}
if(!mbHidden)
{
if(!mbInShadows)
{
mpLight->FadeTo(cColor(0.09f,0.09f,0.28f,0),6,1);
mpLight->SetVisible(true);
}
mbInShadows = true;
}
}
else
{
if(mbInShadows)
{
mbInShadows = false;
mpLight->FadeTo(cColor(0,0,0,0),8,1);
}
UnHide();
}
//////////////////////////////////////////7
// Update the current light level
if(mfUpdateCount <= 0)
{
mfUpdateCount = 1.0f / 2.0f;
mfLight = GetMaxRGB(mpInit->mpGame->GetGraphics()->GetRenderer3D()->GetAmbientColor());
cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D();
if(pWorld==NULL) return;
iPhysicsWorld *pPhysicsWorld = pWorld->GetPhysicsWorld();
cBoundingVolume *pPlayerBV = pCharBody->GetBody()->GetBV();
//Just to be sure...
if(mpInit->mpPlayer->GetFlashLight()->IsActive()) mfLight+= 0.5;
//Iterate lights
cLight3DListIterator lightIt = pWorld->GetLightIterator();
while(lightIt.HasNext())
{
iLight3D *pLight = lightIt.Next();
if(pLight == mpLight) continue;
if(pLight->IsActive()==false || pLight->IsVisible()==false) continue;
if(cMath::CheckCollisionBV(*pPlayerBV,*pLight->GetBoundingVolume()))
{
//Check line of sight
if(HasLineOfSight(pLight,pPhysicsWorld)==false) continue;
//Get highest value of rg b
float fAmount = GetMaxRGB(pLight->GetDiffuseColor());
//Get distance to the light
float fDist = cMath::Vector3Dist( pLight->GetWorldPosition(),
pPlayerBV->GetWorldCenter());
//Calculate attenuation
float fT = 1 - fDist / pLight->GetFarAttenuation();
if(fT<0)fT =0;
fAmount *= fT;
mfLight += fAmount;
}
}
}
else
{
mfUpdateCount -= afTimeStep;
}
////////////////////////////////////////////////////
//Check if enemy is too close and act accordingly.
UpdateEnemyTooClose(afTimeStep);
}
//-----------------------------------------------------------------------
bool cPlayerHidden::OnIntersect(iPhysicsBody *pBody,cPhysicsRayParams *apParams)
{
//bool bDebug = pBody->GetName() == "polySurface76";
if(pBody->IsCharacter() || pBody->GetCollide()==false || pBody->GetBlocksLight()==false)
{
//if(bDebug)Log("Out on first!\n");
return true;
}
iGameEntity* pEntity = (iGameEntity*)pBody->GetUserData();
if(pEntity && pEntity->GetMeshEntity())
{
cMeshEntity *pMeshEntity = pEntity->GetMeshEntity();
if(pMeshEntity->IsShadowCaster()==false) return true;
bool bFoundSolid = false;
for(int i=0; i< pMeshEntity->GetSubMeshEntityNum(); ++i)
{
iMaterial *pMaterial = pMeshEntity->GetSubMeshEntity(i)->GetMaterial();
if(pMaterial &&
(pMaterial->IsTransperant()==false && pMaterial->HasAlpha()==false))
{
bFoundSolid = true;
break;
}
}
if(bFoundSolid==false){
//if(bDebug)Log("Out on non solid!\n");
return true;
}
}
mbIntersected = true;
//if(bDebug)Log("Intersection!!\n");
return false;
}
//-----------------------------------------------------------------------
bool cPlayerHidden::HasLineOfSight(iLight3D *pLight,iPhysicsWorld *pPhysicsWorld)
{
if(pLight->GetCastShadows()==false) return true;
if(mpRenderer->GetShowShadows()== eRendererShowShadows_None) return true;
iCharacterBody *pCharBody = mpInit->mpPlayer->GetCharacterBody();
cVector3f vPlayerPos = pCharBody->GetPosition();
//Check frustum of spotlight
if(pLight->GetLightType() == eLight3DType_Spot)
{
cLight3DSpot *pSpotLight = static_cast(pLight);
if(pSpotLight->GetFrustum()->CollideBoundingVolume(pLight->GetBoundingVolume()) ==
eFrustumCollision_Outside)
{
return false;
}
}
int lCount =0;
cVector3f vPosAdd[5];
int lPosAddNum = 5;
//Centre
vPosAdd[0] = cVector3f(0,0,0);
//Head
vPosAdd[1] = cVector3f(0,pCharBody->GetSize().y/2 -0.1f,0);
//Feet
vPosAdd[2] = cVector3f(0,-(pCharBody->GetSize().y/2 + 0.1f),0);
cVector3f vRight = cMath::Vector3Cross( cMath::Vector3Normalize(pLight->GetWorldPosition()-vPlayerPos),
cVector3f(0,1,0));
//Right
vPosAdd[3] = vRight * (pCharBody->GetSize().x *0.4f);
//Left
vPosAdd[4] = vRight * (pCharBody->GetSize().x *-0.4f);
for(int i=0; iCastRay( this,vPlayerPos + vPosAdd[i], pLight->GetWorldPosition(),
false,false,false,false);
if(mbIntersected)
++lCount;
else {
break;
}
}
return lCount < lPosAddNum;
}
//-----------------------------------------------------------------------
void cPlayerHidden::UpdateEnemyTooClose(float afTimeStep)
{
cCamera3D *pCam = mpInit->mpPlayer->GetCamera();
cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D();
if(pWorld==NULL) return;
/////////////////////////////
// Update too close effect
if(mbEnemyTooClose && mfEnemyTooCloseCount >1.2f)
{
if(mfCloseEffectFovAdd > 0)
{
mfCloseEffectFov += mfCloseEffectFovAdd*afTimeStep;
if(mfCloseEffectFov >= mfCloseEffectFovMax)
{
mfCloseEffectFovAdd = -mfCloseEffectFovAdd;
mfCloseEffectFov = mfCloseEffectFovMax;
if(mfEnemyTooCloseCount > mfEnemyTooCloseMax*0.4f)
mpSoundHandler->PlayGui("player_scare_mid",false,1);
else
mpSoundHandler->PlayGui("player_scare_low",false,1);
}
}
else
{
mfCloseEffectFov += mfCloseEffectFovAdd*afTimeStep;
if(mfCloseEffectFov <= mfCloseEffectFovMin)
{
mfCloseEffectFovAdd = -mfCloseEffectFovAdd;
mfCloseEffectFov = mfCloseEffectFovMin;
//if(mfEnemyTooCloseCount > mfEnemyTooCloseMax*0.6f)
// mpSoundHandler->PlayGui("player_scare_mid",false,1);
//else
// mpSoundHandler->PlayGui("player_scare_low",false,1);
}
}
float fAdd =0;
if(mfCloseEffectFov >= 0)
{
float fT = mfCloseEffectFov / mfCloseEffectFovMax;
fAdd = sin(fT * kPi2f) * mfCloseEffectFovMax;
}
else
{
float fT = mfCloseEffectFov / mfCloseEffectFovMin;
fAdd = sin(fT * kPi2f) * mfCloseEffectFovMin;
}
pCam->SetFOV(mfFov + fAdd);
mpInit->mpGame->GetGraphics()->GetRendererPostEffects()->SetImageTrailActive(true);
mpInit->mpGame->GetGraphics()->GetRendererPostEffects()->SetImageTrailAmount(0.8f);
}
else if(mfCloseEffectFov !=0)
{
mpInit->mpGame->GetGraphics()->GetRendererPostEffects()->SetImageTrailActive(false);
if(mfCloseEffectFov < 0)
{
mfCloseEffectFov += afTimeStep * cMath::ToRad(7);
if(mfCloseEffectFov>0) mfCloseEffectFov =0;
}
else
{
mfCloseEffectFov -= afTimeStep * cMath::ToRad(7);
if(mfCloseEffectFov<0) mfCloseEffectFov =0;
}
float fAdd =0;
if(mfCloseEffectFov >= 0)
{
float fT = mfCloseEffectFov / mfCloseEffectFovMax;
fAdd = sin(fT * kPi2f) * mfCloseEffectFovMax;
}
else
{
float fT = mfCloseEffectFov / mfCloseEffectFovMin;
fAdd = sin(fT * kPi2f) * mfCloseEffectFovMin;
}
pCam->SetFOV(mfFov + fAdd);
}
/////////////////////////////
//Update the count
if(InShadows())//mbHidden)
{
if(mfCheckEnemyCloseCount <=0)
{
float fMaxDist = mbHidden ? 11.0f : 11.0f;
float fMaxDistSqr = fMaxDist*fMaxDist;
//Reset variables
mbEnemyTooClose = false;
mfCheckEnemyCloseCount = 0.3f;
///Get needed data
iPhysicsWorld *pPhysicsWorld = pWorld->GetPhysicsWorld();
//Iterate enemies
tGameEnemyIterator enemyIt = mpInit->mpMapHandler->GetGameEnemyIterator();
while(enemyIt.HasNext())
{
iGameEnemy *pEnemy = enemyIt.Next();
if(pEnemy->GetHealth() <=0 || pEnemy->IsActive()==false) continue;
iCharacterBody *pCharBody = pEnemy->GetMover()->GetCharBody();
//Check if the enemy is close enough
float fDistSqr = cMath::Vector3DistSqr(pCam->GetPosition(), pCharBody->GetPosition());
if(fDistSqr > fMaxDistSqr) continue;
//Check if enemy is in FOV
cVector3f vDir = pCharBody->GetPosition() - pCam->GetPosition();
vDir.Normalise();
float fAngle = cMath::Vector3Angle(pCam->GetForward(),vDir);
if(fAngle > pCam->GetFOV()*0.5f) continue;
//Check if ther is a line of sight
mbIntersected = false;
pPhysicsWorld->CastRay( this,pCam->GetPosition(), pCharBody->GetPosition(),
false,false,false,false);
if(mbIntersected==false)
{
mbEnemyTooClose = true;
break;
}
}
}
else
{
mfCheckEnemyCloseCount -= afTimeStep;
}
////////////////////////////////
// Update the count if enemy is near
if(mbEnemyTooClose)
{
mfEnemyTooCloseCount+= afTimeStep;
//Do some effect
//Check if limit is reached
if(mfEnemyTooCloseCount> mfEnemyTooCloseMax)
{
UnHide();
mpInit->mpPlayer->ChangeMoveState(ePlayerMoveState_Walk);
mpSoundHandler->PlayGui("player_scare_high",false,1);
cSoundEntity *pSound = pWorld->CreateSoundEntity("Scare","player_scare_high",true);
if(pSound)
{
pSound->SetPosition(pCam->GetPosition());
}
//Show player to nearby enemies.
tGameEnemyIterator enemyIt = mpInit->mpMapHandler->GetGameEnemyIterator();
while(enemyIt.HasNext())
{
iGameEnemy *pEnemy = enemyIt.Next();
if(pEnemy->GetHealth() <=0 || pEnemy->IsActive()==false) continue;
iCharacterBody *pCharBody = pEnemy->GetMover()->GetCharBody();
//Check if the enemy is close enough
float fDist = cMath::Vector3Dist(pCam->GetPosition(), pCharBody->GetPosition());
if(fDist <= 8)
{
pEnemy->ShowPlayer(mpInit->mpPlayer->GetCharacterBody()->GetFeetPosition());
}
}
}
}
else if(mfEnemyTooCloseCount >0)
{
mfEnemyTooCloseCount-= afTimeStep;
mpInit->mpGame->GetGraphics()->GetRendererPostEffects()->SetImageTrailActive(false);
}
}
}
//-----------------------------------------------------------------------
void cPlayerHidden::Reset()
{
mpLight = NULL;
mfHiddenOnTime = 1;
mfHiddenOffTime = 0.5f;
mfHiddenOnCount = 0;
mfEffectOffset = mfStartEffectOffset;
mfAspect = mfStartAspect;
mfFov = mfStartFov;
mbInShadows = false;
mfLight = 1.0f;
mfMaxLight = 0.25f;
mfHiddenCount = 0;
mfHiddenTime = 1.4f;
mbHidden = false;
mfInShadowAlpha = 0;
mfInShadowPulse = 0;
mfInShadowPulseAdd = 1;
mfCheckEnemyCloseCount =0;
mfEnemyTooCloseCount =0;
mbEnemyTooClose = false;
mfCloseEffectFovAdd = cMath::ToRad(15);
mfCloseEffectFov = 0;
}
//-----------------------------------------------------------------------