/* * 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 "StdAfx.h" #include "GameItem.h" #include "Init.h" #include "Inventory.h" #include "MapHandler.h" #include "Player.h" #include "GameItemType.h" #include "GlobalInit.h" ////////////////////////////////////////////////////////////////////////// // RAY CAST ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- void cGameItem_InViewRay::SetUp(iPhysicsBody *apSkipBody) { mpSkipBody = apSkipBody; mbIntersected = false; } bool cGameItem_InViewRay::OnIntersect(iPhysicsBody *apBody,cPhysicsRayParams *apParams) { float &fDist = apParams->mfDist; //Must be positive if(apParams->mfT < 0 || apParams->mfT >1) return true; //No characters or skip body allowed if(apBody->IsCharacter() || apBody == mpSkipBody) return true; if(apBody->GetCollide()==false || apBody->IsActive()==false) return true; mbIntersected = true; return false; } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // LOADER ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- cEntityLoader_GameItem::cEntityLoader_GameItem(const tString &asName, cInit *apInit) : cEntityLoader_Object(asName) { mpInit = apInit; } cEntityLoader_GameItem::~cEntityLoader_GameItem() { } //----------------------------------------------------------------------- void cEntityLoader_GameItem::BeforeLoad(TiXmlElement *apRootElem, const cMatrixf &a_mtxTransform, cWorld3D *apWorld) { } //----------------------------------------------------------------------- void cEntityLoader_GameItem::AfterLoad(TiXmlElement *apRootElem, const cMatrixf &a_mtxTransform, cWorld3D *apWorld) { cGameItem *pObject = hplNew( cGameItem, (mpInit,mpEntity->GetName()) ); pObject->msSubType = msSubType; pObject->msFileName = msFileName; pObject->m_mtxOnLoadTransform = a_mtxTransform; // Set the engine objects to the object pObject->SetBodies(mvBodies); pObject->SetMeshEntity(mpEntity); pObject->SetHapticShapes(mvHapticShapes); /////////////////////////////////// // Add a the object as user data to the body, to get the obejct later on. for(size_t i=0; iSetUserData((void*)pObject); } /////////////////////////////////// // Load game properties TiXmlElement *pGameElem = apRootElem->FirstChildElement("GAME"); if(pGameElem) { pObject->mfEnterFlashDist = cString::ToFloat(pGameElem->Attribute("EnterFlashDist"),3); pObject->mfExitFlashDist = cString::ToFloat(pGameElem->Attribute("ExitFlashDistt"),6); pObject->mbSkipRayCheck = cString::ToBool(pGameElem->Attribute("SkipRayCheck"),false); pObject->msImageFile = cString::ToString(pGameElem->Attribute("ImageFile"),""); pObject->mbCanBeDropped = cString::ToBool(pGameElem->Attribute("CanBeDropped"),true); pObject->mbHasCount = cString::ToBool(pGameElem->Attribute("HasCount"),false); pObject->mlCount = cString::ToInt(pGameElem->Attribute("Count"),1); pObject->msPickUpSound = cString::ToString(pGameElem->Attribute("PickUpSound"),"player_pickup_generic"); tString sNameCat = cString::ToString(pGameElem->Attribute("NameCat"),""); tString sNameEntry = cString::ToString(pGameElem->Attribute("NameEntry"),""); tString sDescCat = cString::ToString(pGameElem->Attribute("DescCat"),""); tString sDescEntry = cString::ToString(pGameElem->Attribute("DescEntry"),""); pObject->mItemType = ToItemType(pGameElem->Attribute("ItemType")); pObject->msHudModelFile = cString::ToString(pGameElem->Attribute("HudModelFile"),""); pObject->msHudModelName = cString::ToString(pGameElem->Attribute("HudModelName"),""); pObject->SetGameName(kTranslate(sNameCat, sNameEntry)); pObject->SetDescription(kTranslate(sDescCat, sDescEntry)); } else { Error("Couldn't find game element for entity '%s'\n",mpEntity->GetName().c_str()); } ///////////////////////////////// // Add to map handler mpInit->mpMapHandler->AddGameEntity(pObject); mpInit->mpMapHandler->AddGameItem(pObject); } //----------------------------------------------------------------------- eGameItemType cEntityLoader_GameItem::ToItemType(const char* apString) { if(apString==NULL) return eGameItemType_Normal; tString asType = cString::ToLowerCase(apString); if(asType == "normal") return eGameItemType_Normal; else if(asType == "food") return eGameItemType_Food; else if(asType == "note") return eGameItemType_Note; else if(asType == "map") return eGameItemType_Map; else if(asType == "flashlight") return eGameItemType_Flashlight; else if(asType == "notebook") return eGameItemType_Notebook; else if(asType == "battery") return eGameItemType_Battery; else if(asType == "glowstick") return eGameItemType_GlowStick; else if(asType == "flare") return eGameItemType_Flare; else if(asType == "painkillers") return eGameItemType_Painkillers; else if(asType == "weaponmelee") return eGameItemType_WeaponMelee; else if(asType == "throw") return eGameItemType_Throw; return eGameItemType_Normal; } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // CONSTRUCTORS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- cGameItem::cGameItem(cInit *apInit,const tString& asName) : iGameEntity(apInit,asName) { mType = eGameEntityType_Item; mbHasInteraction = true; mfMaxInteractDist = 2.0f; mfMaxExamineDist = 4.0f; mfCheckFlashCount =0; mfCheckFlashMax = 1.0f / 20.0f; mfStartFlashCount =0; mfFlashAlpha =0; mfFlashAlphaAdd = -1; mbHasBeenFlashed = false; mfEnterFlashDist = 2; mfExitFlashDist = 5; } //----------------------------------------------------------------------- cGameItem::~cGameItem(void) { mpInit->mpMapHandler->RemoveGameItem(this); } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- void cGameItem::OnWorldLoad() { } //----------------------------------------------------------------------- void cGameItem::OnPlayerPick() { if(mpInit->mpPlayer->GetPickedDist() <= mfMaxInteractDist) { mpInit->mpPlayer->SetCrossHairState(eCrossHairState_PickUp); } } //----------------------------------------------------------------------- void cGameItem::OnPlayerInteract() { if(mpInit->mpPlayer->GetPickedDist() <= mfMaxInteractDist) { mpInit->mpInventory->AddItem(this); mpInit->mpGame->GetSound()->GetSoundHandler()->PlayGui(msPickUpSound,false,1); mbDestroyMe = true; } } //----------------------------------------------------------------------- bool cGameItem::IsInView(float afMinDist) { cCamera3D *pCam = mpInit->mpPlayer->GetCamera(); //Distance float fDistSqr = cMath::Vector3DistSqr( pCam->GetPosition(), mvBodies[0]->GetWorldPosition()); if(fDistSqr > afMinDist*afMinDist){ return false; } //Angle cVector3f vToMesh = mvBodies[0]->GetWorldPosition() - pCam->GetPosition(); vToMesh.Normalise(); float fAngle = cMath::Vector3Angle(pCam->GetForward(), vToMesh); if(fAngle > cMath::ToRad(43)){ return false; } if(mbSkipRayCheck) return true; //Raycast iPhysicsWorld *pPhysicsWorld = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld(); mRayCallback.SetUp(mvBodies[0]); pPhysicsWorld->CastRay(&mRayCallback,pCam->GetPosition(), mpMeshEntity->GetBoundingVolume()->GetWorldCenter(),//mvBodies[0]->GetWorldPosition(), false,false,false); if(mRayCallback.mbIntersected){ return false; } return true; } //----------------------------------------------------------------------- void cGameItem::Update(float afTimeStep) { if(mbActive==false) return; if(mpInit->mbFlashItems == false) return; ////////////////////////////////////// // Update flash if(mfFlashAlphaAdd > 0 || mfFlashAlpha > 0) { if(mfFlashAlphaAdd <0) { mfFlashAlpha += mfFlashAlphaAdd * afTimeStep * 0.8f; if(mfFlashAlpha <=0) { mfFlashAlpha =0; //mfFlashAlphaAdd = -mfFlashAlphaAdd; } } else { mfFlashAlpha += mfFlashAlphaAdd * afTimeStep * 1.5f; if(mfFlashAlpha >=1) { mfFlashAlpha =1; mfFlashAlphaAdd = -mfFlashAlphaAdd; } } } ////////////////////////////////////// // Check if player is near else if(mbHasBeenFlashed == false) { mfCheckFlashCount += afTimeStep; if(mfCheckFlashCount >= mfCheckFlashMax) { mfCheckFlashCount =0; if(IsInView(mfEnterFlashDist)) { mfStartFlashCount += mfCheckFlashMax; } else { mfStartFlashCount -= mfCheckFlashMax; if(mfStartFlashCount<0)mfStartFlashCount =0; } } if(mfStartFlashCount >= 0.1f) { mfStartFlashCount =0; mbHasBeenFlashed = true; mfFlashAlpha =0; mfFlashAlphaAdd = 1; } } ////////////////////////////////////// // Check if player is out of flash area. else { mfCheckFlashCount += afTimeStep; if(mfCheckFlashCount >= mfCheckFlashMax) { mfCheckFlashCount =0; if(IsInView(mfExitFlashDist)==false) { mfStartFlashCount += mfCheckFlashMax; } else { mfStartFlashCount -= mfCheckFlashMax; if(mfStartFlashCount<0)mfStartFlashCount =0; } } if(mfStartFlashCount >= 0.75f) { mbHasBeenFlashed = false; mfStartFlashCount =0; } } } //----------------------------------------------------------------------- void cGameItem::OnPostSceneDraw() { /*iLowLevelGraphics *pLowGfx = mpInit->mpGame->GetGraphics()->GetLowLevel(); cCamera3D *pCam = mpInit->mpPlayer->GetCamera(); pLowGfx->SetDepthTestActive(true); pLowGfx->SetDepthWriteActive(false); pLowGfx->SetBlendActive(true); pLowGfx->SetBlendFunc(eBlendFunc_One,eBlendFunc_One); for(int i=0; i< mpMeshEntity->GetMesh()->GetSubMeshNum(); i++) { cSubMeshEntity *pSubEntity = mpMeshEntity->GetSubMeshEntity(i); cSubMesh *pSubMesh = mpMeshEntity->GetMesh()->GetSubMesh(i); iVertexBuffer *pVtxBuffer = pSubEntity->GetVertexBuffer(); pLowGfx->SetTexture(0,NULL); pVtxBuffer->Bind(); pVtxBuffer->Draw(); pVtxBuffer->UnBind(); } pLowGfx->SetBlendActive(false); pLowGfx->SetDepthTestActive(true); pLowGfx->SetDepthWriteActive(true);*/ } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PRIVATE METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // SAVE OBJECT STUFF ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- kBeginSerialize(cGameItem_SaveData,iGameEntity_SaveData) kSerializeVar(mbHasBeenFlashed,eSerializeType_Bool) kSerializeVar(mfEnterFlashDist, eSerializeType_Float32) kSerializeVar(mfExitFlashDist, eSerializeType_Float32) kEndSerialize() //----------------------------------------------------------------------- iGameEntity* cGameItem_SaveData::CreateEntity() { return NULL; } //----------------------------------------------------------------------- iGameEntity_SaveData* cGameItem::CreateSaveData() { return hplNew( cGameItem_SaveData, () ); } //----------------------------------------------------------------------- void cGameItem::SaveToSaveData(iGameEntity_SaveData *apSaveData) { __super::SaveToSaveData(apSaveData); cGameItem_SaveData *pData = static_cast(apSaveData); kCopyToVar(pData,mbHasBeenFlashed); kCopyToVar(pData,mfEnterFlashDist); kCopyToVar(pData,mfExitFlashDist); } //----------------------------------------------------------------------- void cGameItem::LoadFromSaveData(iGameEntity_SaveData *apSaveData) { __super::LoadFromSaveData(apSaveData); cGameItem_SaveData *pData = static_cast(apSaveData); kCopyFromVar(pData,mbHasBeenFlashed); kCopyFromVar(pData,mfEnterFlashDist); kCopyFromVar(pData,mfExitFlashDist); } //-----------------------------------------------------------------------