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