mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-10 11:51:52 +00:00
2302 lines
63 KiB
C++
2302 lines
63 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program 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.
|
|
*
|
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2006-2010 - Frictional Games
|
|
*
|
|
* This file is part of Penumbra Overture.
|
|
*/
|
|
|
|
#include "hpl1/penumbra-overture/PlayerHelper.h"
|
|
|
|
#include "hpl1/penumbra-overture/DeathMenu.h"
|
|
#include "hpl1/penumbra-overture/GameArea.h"
|
|
#include "hpl1/penumbra-overture/GameEnemy.h"
|
|
#include "hpl1/penumbra-overture/GameEntity.h"
|
|
#include "hpl1/penumbra-overture/GameMusicHandler.h"
|
|
#include "hpl1/penumbra-overture/GameObject.h"
|
|
#include "hpl1/penumbra-overture/Init.h"
|
|
#include "hpl1/penumbra-overture/Inventory.h"
|
|
#include "hpl1/penumbra-overture/MapHandler.h"
|
|
#include "hpl1/penumbra-overture/Notebook.h"
|
|
#include "hpl1/penumbra-overture/NumericalPanel.h"
|
|
#include "hpl1/penumbra-overture/Player.h"
|
|
#include "hpl1/penumbra-overture/PlayerHands.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->mfDist < mfMinDist && pBody->GetMaterial()->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;
|
|
}
|
|
|
|
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<cGameObject *>(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;
|
|
case eGameDifficulty_LastEnum:
|
|
break;
|
|
}
|
|
}
|
|
|
|
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; i < ePlayerDamageType_LastEnum; ++i)
|
|
mpDrawer->DestroyGfxObject(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());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} 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 *pEntity2 = mpInit->mpMapHandler->GetLatestEntity();
|
|
|
|
cVector3f vRot2 = cMath::MatrixMul(mtxStart.GetRotation(), cVector3f(1, 0.3f, 0));
|
|
|
|
for (int i = 0; i < pEntity2->GetBodyNum(); ++i) {
|
|
iPhysicsBody *pBody = pEntity2->GetBody(i);
|
|
pBody->AddImpulse(pCam->GetForward() * 3.0f);
|
|
pBody->AddTorque(vRot2);
|
|
}
|
|
|
|
// setup light
|
|
if (mfTime <= 30) {
|
|
float fRadius = (mfTime / 30.0f);
|
|
if (fRadius < 0)
|
|
fRadius = 0;
|
|
|
|
for (int i = 0; i < pEntity2->GetLightNum(); ++i) {
|
|
iLight3D *pLight = pEntity2->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; i < mlAmount; ++i) {
|
|
tString sFileName = "effect_noise0" + cString::ToString(i);
|
|
cGfxObject *pObject = mpDrawer->CreateGfxObject(sFileName, "smoke2d");
|
|
if (pObject == NULL) {
|
|
error("Error loading noise filter");
|
|
}
|
|
|
|
mvGfxNoise.push_back(pObject);
|
|
}
|
|
|
|
Hpl1::resizeAndFill(mvCurrentGfx, 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() {
|
|
// 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<cLight3DSpot *>(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; i < lPosAddNum; ++i) {
|
|
mbIntersected = false;
|
|
pPhysicsWorld->CastRay(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) {
|
|
// FIXME: Change value of FMaxDist when hidden?
|
|
// float fMaxDist = mbHidden ? 11.0f : 11.0f;
|
|
float fMaxDist = 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;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|