/* * 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 "GameSwingDoor.h" #include "Init.h" #include "MapHandler.h" #include "Player.h" #include "EffectHandler.h" //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // LOADER ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- cEntityLoader_GameSwingDoor::cEntityLoader_GameSwingDoor(const tString &asName, cInit *apInit) : cEntityLoader_Object(asName) { mpInit = apInit; } cEntityLoader_GameSwingDoor::~cEntityLoader_GameSwingDoor() { } //----------------------------------------------------------------------- void cEntityLoader_GameSwingDoor::BeforeLoad(TiXmlElement *apRootElem, const cMatrixf &a_mtxTransform, cWorld3D *apWorld) { } //----------------------------------------------------------------------- void cEntityLoader_GameSwingDoor::AfterLoad(TiXmlElement *apRootElem, const cMatrixf &a_mtxTransform, cWorld3D *apWorld) { cGameSwingDoor *pObject = hplNew( cGameSwingDoor, (mpInit,mpEntity->GetName()) ); pObject->msFileName = msFileName; pObject->m_mtxOnLoadTransform = a_mtxTransform; // Set the engine objects to the object pObject->SetBodies(mvBodies); pObject->SetJoints(mvJoints); pObject->SetMeshEntity(mpEntity); pObject->SetHapticShapes(mvHapticShapes); /////////////////////////////////// // Load game properties TiXmlElement *pGameElem = apRootElem->FirstChildElement("GAME"); if(pGameElem) { pObject->mfHealth = cString::ToFloat(pGameElem->Attribute("Health"),0); pObject->mlToughness = cString::ToInt(pGameElem->Attribute("Toughness"),0); pObject->msBreakSound = cString::ToString(pGameElem->Attribute("BreakSound"),""); pObject->msBreakEntity = cString::ToString(pGameElem->Attribute("BreakEntity"),""); pObject->msBreakPS = cString::ToString(pGameElem->Attribute("BreakPS"),""); } else { Error("Couldn't find game element for entity '%s'\n",mpEntity->GetName().c_str()); } /////////////////////////////////// // Add a the object as user data to the body, to get the obejct later on. for(size_t i=0; iSetUserData((void*)pObject); } } pObject->SetupPhysics(apWorld); pObject->SetupBreakObject(); ///////////////////////////////// // Add to map handler mpInit->mpMapHandler->AddGameEntity(pObject); } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // CONSTRUCTORS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- cGameSwingDoor::cGameSwingDoor(cInit *apInit,const tString& asName) : iGameEntity(apInit,asName) { mType = eGameEntityType_SwingDoor; mbHasInteraction = true; mbPauseControllers = true; mbPauseGravity = true; mbLocked = false; mfHealth = 100.0f; } //----------------------------------------------------------------------- cGameSwingDoor::~cGameSwingDoor(void) { iPhysicsWorld *pPhysicsWorld = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld(); //for(size_t i=0; iDestroyController(mvStopControllers[i]); //} } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- void cGameSwingDoor::SetupPhysics(cWorld3D *apWorld) { mvJointDefaults.resize(mvJoints.size()); iPhysicsWorld *pPhysicsWorld = apWorld->GetPhysicsWorld(); for(size_t i=0; iCreateController("Stop"); //pController->SetBody(pJoint->GetChildBody()); //pController->SetJoint(pJoint); pController->SetActive(true); pController->SetType(ePhysicsControllerType_Pid); pController->SetA(1.5f); pController->SetB(1.0f); pController->SetC(0.0f); pController->SetPidIntegralSize(20); pController->SetInputType(ePhysicsControllerInput_AngularSpeed,ePhysicsControllerAxis_Y); pController->SetDestValue(.0f); pController->SetOutputType(ePhysicsControllerOutput_Torque,ePhysicsControllerAxis_Y); pController->SetMaxOutput(0.0f); pController->SetMulMassWithOutput(true); pJoint->AddController(pController); mvStopControllers.push_back(pController); /////////////////////////////////// //Set defaults iPhysicsJointHinge *pHingeJoint = static_cast(pJoint); mvJointDefaults[i].mfMin = pHingeJoint->GetMinAngle(); mvJointDefaults[i].mfMax = pHingeJoint->GetMaxAngle(); } } //----------------------------------------------------------------------- void cGameSwingDoor::OnPlayerPick() { } //----------------------------------------------------------------------- void cGameSwingDoor::OnPlayerInteract() { float fDist = mpInit->mpPlayer->GetPickedDist(); if(fDist > mfMaxInteractDist) return; if(mpInit->mbHasHaptics && mpInit->mpPlayer->mbProxyTouching==false) return; //Set some properties mpInit->mpPlayer->mfForwardUpMul = 1.0f; mpInit->mpPlayer->mfForwardRightMul = 1.0f; mpInit->mpPlayer->mfUpMul = 1.0f; mpInit->mpPlayer->mfRightMul = 1.0f; mpInit->mpPlayer->mfCurrentMaxInteractDist = mfMaxInteractDist; if(!mpInit->mbHasHaptics) { mpInit->mpPlayer->SetPushBody(mpInit->mpPlayer->GetPickedBody()); mpInit->mpPlayer->ChangeState(ePlayerState_Move); } else { mpInit->mpPlayer->mbPickAtPoint = true; mpInit->mpPlayer->mbRotateWithPlayer = false; mpInit->mpPlayer->mbUseNormalMass = false; mpInit->mpPlayer->mfGrabMassMul = 1; mpInit->mpPlayer->mfHapticTorqueMul = 1.0f; mpInit->mpPlayer->mbCanBeThrown = true; mpInit->mpPlayer->mbGrabbingMoveBody = true; mpInit->mpPlayer->SetPushBody(mpInit->mpPlayer->GetPickedBody()); mpInit->mpPlayer->ChangeState(ePlayerState_Grab); } } //----------------------------------------------------------------------- void cGameSwingDoor::Update(float afTimeStep) { } //----------------------------------------------------------------------- void cGameSwingDoor::SetLocked(bool abX) { if(mbLocked == abX) return; mbLocked = abX; for(size_t i=0; i(pJoint); if(mbLocked) { if(std::abs(pHingeJoint->GetMinAngle()) > std::abs(pHingeJoint->GetMaxAngle())) pHingeJoint->SetMinAngle(cMath::ToRad(-1)); else pHingeJoint->SetMaxAngle(cMath::ToRad(1)); } else { pHingeJoint->SetMinAngle(mvJointDefaults[i].mfMin); pHingeJoint->SetMaxAngle(mvJointDefaults[i].mfMax); } } for(size_t i=0; iSetEnabled(true); } } //----------------------------------------------------------------------- void cGameSwingDoor::OnDamage(float afDamage) { } //----------------------------------------------------------------------- void cGameSwingDoor::OnDeath(float afDamage) { if(msBreakSound != "") { cSoundEntity *pSound = mpInit->mpGame->GetScene()->GetWorld3D()->CreateSoundEntity("Break",msBreakSound,true); if(pSound) pSound->SetPosition(mvBodies[0]->GetWorldPosition()); } if(msBreakEntity == "") { /////////////////////////// //Break all joints. for(size_t i=0; i< mvJoints.size();++i) { mvJoints[i]->Break(); } mvJoints.clear(); } else { Break(); } } //----------------------------------------------------------------------- void cGameSwingDoor::BreakAction() { if(mvBodies.empty()) return; iPhysicsBody *pDynBody = NULL; iPhysicsBody *pStaticBody = NULL; for(size_t i=0; i < mvBodies.size();++i) { if(mvBodies[i]->GetMass()!=0) pDynBody = mvBodies[i]; if(mvBodies[i]->GetMass()==0) pStaticBody = mvBodies[i]; } if(pDynBody==NULL && pStaticBody==NULL) return; ////////////////// //Script if(mvCallbackScripts[eGameEntityScriptType_OnBreak]) { tString sCommand = GetScriptCommand(eGameEntityScriptType_OnBreak); mpInit->RunScriptCommand(sCommand); } cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D(); ////////////////// //Check if player os holding object if( (mpInit->mpPlayer->GetState()==ePlayerState_Grab || mpInit->mpPlayer->GetState()==ePlayerState_Move || mpInit->mpPlayer->GetState()==ePlayerState_Push) && (mpInit->mpPlayer->GetPushBody() == pDynBody || mpInit->mpPlayer->GetPushBody() == pStaticBody)) { mpInit->mpPlayer->ChangeState(ePlayerState_Normal); } cBoundingVolume *pBV = mpMeshEntity->GetBoundingVolume(); ////////////////// //Particle System if(msBreakPS!="") { cParticleSystem3D *pPS = pWorld->CreateParticleSystem("Break",msBreakPS,cVector3f(1,1,1), pDynBody->GetWorldMatrix()); } ////////////////// //Entity if(msBreakEntity != "") { iEntity3D * pEntity = pWorld->CreateEntity(mpMeshEntity->GetName() + "_broken", pDynBody->GetWorldMatrix(), msBreakEntity, true); if(pEntity) { iGameEntity *pGameEntity = mpInit->mpMapHandler->GetLatestEntity(); cVector3f vImpulse = mvLastImpulse * 2;// / (float)pGameEntity->GetBodyNum(); for(int i=0; i< pGameEntity->GetBodyNum(); ++i) { //Add the object velocity iPhysicsBody *pNewBody = pGameEntity->GetBody(i); if(pNewBody->GetMass()==0 && pStaticBody) { pNewBody->SetMatrix(pStaticBody->GetWorldMatrix()); } //pNewBody->SetLinearVelocity(pBody->GetLinearVelocity()); pNewBody->AddImpulse(vImpulse); } } } mpInit->mpGame->ResetLogicTimer(); } //----------------------------------------------------------------------- void cGameSwingDoor::SetupBreakObject() { if(msBreakEntity!="") PreloadModel(msBreakEntity); if(msBreakPS!="") { cParticleSystem3D *pPS = mpInit->mpGame->GetResources()->GetParticleManager()->CreatePS3D( "",msBreakPS,1,cMatrixf::Identity); hplDelete( pPS ); } if(msBreakSound!="") { mpInit->PreloadSoundEntityData(msBreakSound); } } //----------------------------------------------------------------------- //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // SAVE OBJECT STUFF ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- kBeginSerialize(cGameSwingDoor_SaveData,iGameEntity_SaveData) kSerializeVar(mbLocked, eSerializeType_Bool) kSerializeVar(msBreakSound, eSerializeType_String) kSerializeVar(msBreakEntity, eSerializeType_String) kSerializeVar(msBreakPS, eSerializeType_String) kEndSerialize() //----------------------------------------------------------------------- iGameEntity* cGameSwingDoor_SaveData::CreateEntity() { return NULL; } //----------------------------------------------------------------------- iGameEntity_SaveData* cGameSwingDoor::CreateSaveData() { return hplNew( cGameSwingDoor_SaveData, () ); } //----------------------------------------------------------------------- void cGameSwingDoor::SaveToSaveData(iGameEntity_SaveData *apSaveData) { __super::SaveToSaveData(apSaveData); cGameSwingDoor_SaveData *pData = static_cast(apSaveData); kCopyToVar(pData,mbLocked); kCopyToVar(pData,msBreakSound); kCopyToVar(pData,msBreakEntity); kCopyToVar(pData,msBreakPS); } //----------------------------------------------------------------------- void cGameSwingDoor::LoadFromSaveData(iGameEntity_SaveData *apSaveData) { __super::LoadFromSaveData(apSaveData); cGameSwingDoor_SaveData *pData = static_cast(apSaveData); kCopyFromVar(pData,msBreakSound); kCopyFromVar(pData,msBreakEntity); kCopyFromVar(pData,msBreakPS); SetLocked(pData->mbLocked); } //----------------------------------------------------------------------- //-----------------------------------------------------------------------