/* 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 . * */ /* * Copyright (C) 2006-2010 - Frictional Games * * This file is part of Penumbra Overture. */ #include "hpl1/penumbra-overture/Player.h" #include "hpl1/penumbra-overture/GameEntity.h" #include "hpl1/penumbra-overture/Init.h" #include "hpl1/penumbra-overture/MapHandler.h" #include "hpl1/penumbra-overture/PlayerHelper.h" #include "hpl1/penumbra-overture/PlayerMoveStates.h" #include "hpl1/penumbra-overture/PlayerState_Interact.h" #include "hpl1/penumbra-overture/PlayerState_Misc.h" #include "hpl1/penumbra-overture/PlayerState_Weapon.h" #include "hpl1/penumbra-overture/ButtonHandler.h" #include "hpl1/penumbra-overture/EffectHandler.h" #include "hpl1/penumbra-overture/Inventory.h" #include "hpl1/penumbra-overture/Notebook.h" #include "hpl1/penumbra-overture/SaveHandler.h" #include "hpl1/penumbra-overture/TriggerHandler.h" #include "hpl1/penumbra-overture/Triggers.h" #include "hpl1/penumbra-overture/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; mpPushBody = nullptr; 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); 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"); // Set up variable values Reset(); } //----------------------------------------------------------------------- cPlayer::~cPlayer(void) { 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 < mvInteractMoveBorder.x) { mvCrossHairPos.x = mvInteractMoveBorder.x; abEdge = true; } if (mvCrossHairPos.y < mvInteractMoveBorder.y) { mvCrossHairPos.y = mvInteractMoveBorder.y; abEdge = true; } 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 (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); } //----------------------------------------------------------------------- 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(); } //----------------------------------------------------------------------- void cPlayer::OnWorldExit() { DestroyWorldObjects(); mpGroundRayCallback->OnWorldExit(); mpPickRayCallback->OnWorldExit(); mpHidden->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; } }; void cPlayer::Update(float afTimeStep) { // cSystem *pSystem = mpInit->mpGame->GetSystem(); // unsigned int lTime = pSystem->GetLowLevel()->getTime(); iPhysicsWorld *pPhysicsWorld = mpScene->GetWorld3D()->GetPhysicsWorld(); // 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"); 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(); } //----------------------------------------------------------------------- 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 (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: 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, Common::U32String::format("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; Common::Array 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, Common::U32String::format("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, Common::U32String::format("%S(%.2f (%.2f %.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, Common::U32String::format("Music: '%S' 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(); } ////////////////////////////////////////////////////////////////////////// // 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; i < pData->mvOnCameraPS.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; } //-----------------------------------------------------------------------