/*
* 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 "MapHandler.h"
#include "Init.h"
#include "Player.h"
#include "PlayerHands.h"
#include "GameEntity.h"
#include "GameEnemy.h"
#include "GameArea.h"
#include "GameLink.h"
#include "GameItem.h"
#include "GameLadder.h"
#include "GameStickArea.h"
#include "GameDamageArea.h"
#include "GameForceArea.h"
#include "GameLiquidArea.h"
#include "FadeHandler.h"
#include "SaveHandler.h"
#include "TriggerHandler.h"
#include "Triggers.h"
#include "GraphicsHelper.h"
#include "SaveTypes.h"
#include "GameMusicHandler.h"
#include "GameMessageHandler.h"
#include "Inventory.h"
#include "MapLoadText.h"
//////////////////////////////////////////////////////////////////////////
// WORLD CACHE
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cWorldCache::cWorldCache(cInit *apInit)
{
mpInit = apInit;
mpResources = mpInit->mpGame->GetResources();
mlCount =0;
}
cWorldCache::~cWorldCache()
{
DecResources();
}
//-----------------------------------------------------------------------
void cWorldCache::AddResources()
{
////////////////////////////
// Materials
{
cResourceBaseIterator it = mpResources->GetMaterialManager()->GetResourceBaseIterator();
while(it.HasNext())
{
iResourceBase *pResource = it.Next();
pResource->IncUserCount();
mlstMaterials.push_back(pResource);
}
}
////////////////////////////
// Meshes
{
cResourceBaseIterator it = mpResources->GetMeshManager()->GetResourceBaseIterator();
while(it.HasNext())
{
iResourceBase *pResource = it.Next();
pResource->IncUserCount();
mlstMeshes.push_back(pResource);
}
}
////////////////////////////
// Animations
{
cResourceBaseIterator it = mpResources->GetAnimationManager()->GetResourceBaseIterator();
while(it.HasNext())
{
iResourceBase *pResource = it.Next();
pResource->IncUserCount();
mlstAnimations.push_back(pResource);
}
}
//mlCount++;
}
//-----------------------------------------------------------------------
void cWorldCache::DecResources()
{
////////////////////////////
// Materials
{
tResourceBaseListIt it = mlstMaterials.begin();
for(; it != mlstMaterials.end(); ++it)
{
iResourceBase *pResource = *it;
mpResources->GetMaterialManager()->Destroy(pResource);
}
mlstMaterials.clear();
}
////////////////////////////
// Meshes
{
tResourceBaseListIt it = mlstMeshes.begin();
for(; it != mlstMeshes.end(); ++it)
{
iResourceBase *pResource = *it;
mpResources->GetMeshManager()->Destroy(pResource);
}
mlstMeshes.clear();
}
////////////////////////////
// Animations
{
tResourceBaseListIt it = mlstAnimations.begin();
for(; it != mlstAnimations.end(); ++it)
{
iResourceBase *pResource = *it;
mpResources->GetAnimationManager()->Destroy(pResource);
}
mlstAnimations.clear();
}
//mlCount--;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// SOUND CALLBACK
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cMapHandlerSoundCallback::cMapHandlerSoundCallback(cInit *apInit)
{
mpInit = apInit;
///////////////////////////////////////////
//Load all sounds that can heard by enemies
tString sFile = "sounds/EnemySounds.dat";
TiXmlDocument* pXmlDoc = hplNew( TiXmlDocument, (sFile.c_str()) );
if(pXmlDoc->LoadFile()==false){
Error("Couldn't load XML file '%s'!\n",sFile.c_str());
hplDelete( pXmlDoc ); return;
}
//Get the root.
TiXmlElement* pRootElem = pXmlDoc->RootElement();
TiXmlElement* pChildElem = pRootElem->FirstChildElement();
for(; pChildElem != NULL; pChildElem = pChildElem->NextSiblingElement())
{
tString sName = cString::ToString(pChildElem->Attribute("name"),"");
mvEnemyHearableSounds.push_back(sName);
}
hplDelete( pXmlDoc );
}
//-----------------------------------------------------------------------
void cMapHandlerSoundCallback::OnStart(cSoundEntity *apSoundEntity)
{
///////////////////////////
//Check if the sound is something to worry bout
tString sTypeName = apSoundEntity->GetData()->GetName();
bool bUsed=false;
for(size_t i=0; i< mvEnemyHearableSounds.size(); ++i)
{
tString &sName = mvEnemyHearableSounds[i];
if(sTypeName.size() >= sName.size() && sName == sTypeName.substr(0,sName.size()))
{
bUsed = true;
}
}
if(bUsed == false) return;
//Add a sound trigger
cGameTrigger_Sound *pSound = hplNew( cGameTrigger_Sound, () );
pSound->mpSound = apSoundEntity->GetData();
mpInit->mpTriggerHandler->Add(pSound, eGameTriggerType_Sound,
apSoundEntity->GetWorldPosition(),
10, 1.0f/60.0f, apSoundEntity->GetData()->GetMaxDistance());
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// LIGHT FLASH
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cEffectLightFlash::cEffectLightFlash(cInit *apInit,const cVector3f& avPos,
float afRadius, const cColor &aColor,
float afAddTime, float afNegTime)
{
mpInit = apInit;
cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D();
mpLight = pWorld->CreateLightPoint("Flash");
mpLight->SetFarAttenuation(afRadius);
mpLight->SetDiffuseColor(cColor(0,0));
mpLight->SetCastShadows(true);
mpLight->SetIsSaved(false);
mpLight->SetPosition(avPos);
mfRadius = afRadius;
mfNegTime = afNegTime;
//Log("Fade to %s : %f in time %f\n",aColor.ToString().c_str(),mfRadius,afAddTime);
mpLight->FadeTo(aColor,mfRadius,afAddTime);
mbIsDying = false;
mbDead = false;
}
cEffectLightFlash::~cEffectLightFlash()
{
cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D();
pWorld->DestroyLight(mpLight);
}
//-----------------------------------------------------------------------
void cEffectLightFlash::Update(float afTimeStep)
{
cColor Col = mpLight->GetDiffuseColor();
//Log("Update...\n");
if(mbIsDying==false)
{
if(mpLight->IsFading()==false)
{
//Log("Fade to black\n");
mpLight->FadeTo(cColor(0,0),mfRadius,mfNegTime);
mbIsDying = true;
}
}
else
{
if(mpLight->IsFading()==false)
{
//Log("Kill\n");
mbDead = true;
}
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cMapHandler::cMapHandler(cInit *apInit) : iUpdateable("MapHandler")
{
mpInit = apInit;
mbPreUpdating = false;
mpScene = apInit->mpGame->GetScene();
mpResources = apInit->mpGame->GetResources();
mpWorldCache = hplNew( cWorldCache, (apInit) );
mfGameTime =0;
mbDestroyingAll = false;
Reset();
mpSoundCallback = hplNew( cMapHandlerSoundCallback, (apInit) );
cSoundEntity::AddGlobalCallback(mpSoundCallback);
mpMapChangeTexture = mpInit->mpGame->GetResources()->GetTextureManager()->Create2D("other_mapchange.jpg",false);
}
//-----------------------------------------------------------------------
cMapHandler::~cMapHandler(void)
{
if(mpMapChangeTexture)mpInit->mpGame->GetResources()->GetTextureManager()->Destroy(mpMapChangeTexture);
hplDelete(mpSoundCallback );
hplDelete( mpWorldCache );
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
#ifdef DEMO_VERSION
static int glNumOfLoads = 0;
#endif
bool cMapHandler::Load(const tString &asFile,const tString& asStartPos)
{
tString sMapName = cString::ToLowerCase(cString::SetFileExt(asFile,""));
cWorld3D *pWorld=NULL;
cWorld3D *pLastMap = NULL;
bool bFirstTime = false;
double fTimeSinceVisit=0;
#ifdef DEMO_VERSION
glNumOfLoads++;
if(glNumOfLoads > 5){
CreateMessageBoxW( _W("Demo not playable any more!\n"),
_W("The limits of the demo have been exceeded!\n"));
exit(0);
}
#endif
unsigned long lStartTime = mpInit->mpGame->GetSystem()->GetLowLevel()->GetTime();
if(sMapName != msCurrentMap)
{
////////////////////////////////////////
// DESTRUCTION OF STUFF NOT SAVED //////
//remove all local timer
//RemoveLocalTimers();
//Exit script
if(mpScene->GetWorld3D())
{
//OnMapLoad for all entities
tGameEntityMapIt GIt = m_mapGameEntities.begin();
for(; GIt != m_mapGameEntities.end(); ++GIt)
{
iGameEntity *pEntity = GIt->second;
pEntity->OnWorldExit();
}
mpScene->GetWorld3D()->GetScript()->Run("OnExit()");
pLastMap = mpScene->GetWorld3D();
}
mpInit->mpMusicHandler->OnWorldExit();
//Destroy the player objects so they are no saved.
mpInit->mpPlayer->OnWorldExit();
mpInit->mpPlayerHands->OnWorldExit();
mpInit->mpGameMessageHandler->OnWorldExit();
////////////////////////////////////////
// SAVING /////////////////////////////
//Save the map
if(msCurrentMap != "" && mpScene->GetWorld3D() != NULL)
{
mpInit->mpSaveHandler->SaveData(msCurrentMap);
}
msCurrentMap = sMapName;
////////////////////////////////////////
// DESTRUCTION OF SAVED STUFF //////////
mpInit->mpInventory->ClearCallbacks();
//Reset the rendering.
mpInit->mpGame->GetGraphics()->GetRenderer3D()->SetAmbientColor(cColor(0,1));
mpInit->mpGame->GetGraphics()->GetRenderer3D()->SetSkyBoxActive(false);
mpInit->mpGame->GetGraphics()->GetRenderer3D()->SetFogActive(false);
//Remove all current objects
mpInit->mbDestroyGraphics =false;
DestroyAll();
mpInit->mbDestroyGraphics =true;
//Destroy all sound entities on previous map.
if(mpScene->GetWorld3D())
{
mpScene->GetWorld3D()->DestroyAllSoundEntities();
}
mpInit->mpPlayer->ClearCollideScripts();
//Stop all sound
mpInit->mpGame->GetSound()->GetSoundHandler()->StopAll(eSoundDest_World);
mpInit->mpGame->GetSound()->Update(1.0f/60.0f);
//Destroy Haptic shapes
if(mpInit->mbHasHaptics)
mpInit->mpGame->GetHaptic()->GetLowLevel()->DestroyAllShapes();
////////////////////////////////////////
// LOAD THE MAP ////////////////////////
//Load
if(mpScene->HasLoadedWorld(asFile))
{
//Log("-------- Loaded NOT first time! ----------------\n");
pWorld = mpScene->LoadWorld3D(asFile,true, eWorldLoadFlag_NoGameEntities);
//eWorldLoadFlag_NoLights |
//eWorldLoadFlag_NoEntities |
//eWorldLoadFlag_NoGameEntities);
if(pWorld)
mpScene->SetWorld3D(pWorld);
else {
Error("Couldn't load map '%s'\n",asFile.c_str());
return false;
}
mpInit->mpSaveHandler->LoadData(msCurrentMap);
mpInit->mpGame->GetResources()->GetSoundManager()->DestroyUnused(mpInit->mlMaxSoundDataNum);
mpInit->mpGame->GetResources()->GetParticleManager()->DestroyUnused(mpInit->mlMaxPSDataNum);
}
else
{
//Log("-------- FIRST TIME first time! ----------------\n");
pWorld = mpScene->LoadWorld3D(asFile,true,0);
mpInit->mpGame->GetResources()->GetSoundManager()->DestroyUnused(mpInit->mlMaxSoundDataNum);
mpInit->mpGame->GetResources()->GetParticleManager()->DestroyUnused(mpInit->mlMaxPSDataNum);
if(pWorld)
mpScene->SetWorld3D(pWorld);
else {
Error("Couldn't load map '%s'\n",asFile.c_str());
return false;
}
bFirstTime = true;
}
///////////////////////////
//Add to cache
mpWorldCache->DecResources();
mpWorldCache->AddResources();
///////////////////////////
//Destroy old map
if(pLastMap)
{
mpScene->DestroyWorld3D(pLastMap);
}
fTimeSinceVisit = AddLoadedMap(pWorld);
pWorld->GetPhysicsWorld()->SetMaxTimeStep(mpInit->mfMaxPhysicsTimeStep);
//OnMapLoad for all entities
tGameEntityMapIt GIt = m_mapGameEntities.begin();
for(; GIt != m_mapGameEntities.end(); ++GIt)
{
iGameEntity *pEntity = GIt->second;
pEntity->OnWorldLoad();
}
//OnMapLoad for player
mpInit->mpPlayer->OnWorldLoad();
mpInit->mpPlayerHands->OnWorldLoad();
mpInit->mpMusicHandler->OnWorldLoad();
if(bFirstTime)
{
//Set a default name
msMapGameName = cString::To16Char(cString::SetFileExt(asFile,""));
//Init script
if(pWorld->GetScript()) pWorld->GetScript()->Run("OnStart()");
}
}
else
{
if(mpScene->GetWorld3D() != NULL)
{
pWorld = mpScene->GetWorld3D();
}
else
{
Error("No world has been loaded!\n");
return false;
}
}
mpInit->mpPlayer->SetStartPos(asStartPos);
//Run global script
if(mpInit->mpGlobalScript)
{
if(bFirstTime) mpInit->mpGlobalScript->Run("OnMapStart()");
mpInit->mpGlobalScript->Run("OnMapLoad()");
}
if(pWorld->GetScript())
{
pWorld->GetScript()->Run("OnLoad()");
}
//After script has been run callback
tGameEntityMapIt GIt = m_mapGameEntities.begin();
for(; GIt != m_mapGameEntities.end(); ++GIt)
{
iGameEntity *pEntity = GIt->second;
pEntity->OnPostLoadScripts();
}
//Log("After load and before preupdate:\n");
unsigned long lTime = mpInit->mpGame->GetSystem()->GetLowLevel()->GetTime() - lStartTime;
Log("Loading map '%s' took: %d ms\n",pWorld->GetFileName().c_str(),lTime);
PreUpdate(fTimeSinceVisit);
mpInit->mpGame->ResetLogicTimer();
//mpInit->mpGame->GetSound()->GetSoundHandler()->ResumeAll(eSoundDest_World | eSoundDest_Gui);
//Log("After load and preupdate:\n");
//Set physics accuracy
pWorld->GetPhysicsWorld()->SetAccuracyLevel(mpInit->mPhysicsAccuracy);
return true;
}
//-----------------------------------------------------------------------
bool cMapHandler::LoadSimple(const tString &asFile, bool abLoadEntities)
{
tString sMapName = cString::ToLowerCase(cString::SetFileExt(asFile,""));
cWorld3D *pWorld=NULL;
DestroyAll();
mpInit->mpGame->GetSound()->GetSoundHandler()->StopAll(eSoundDest_World);
mpInit->mpGame->GetSound()->Update(1.0f/60.0f);
mpInit->mpGame->GetGraphics()->GetRenderer3D()->SetAmbientColor(cColor(0,1));
cWorld3D *pOldWorld = mpScene->GetWorld3D();
//Haptic
if(mpInit->mbHasHaptics)
mpInit->mpGame->GetHaptic()->GetLowLevel()->DestroyAllShapes();
//Delete all sound entities
if(pOldWorld)
{
pOldWorld->DestroyAllSoundEntities();
}
//Set the current map.
msCurrentMap = sMapName;
if(abLoadEntities==false)
{
pWorld = mpScene->LoadWorld3D(asFile,true, eWorldLoadFlag_NoGameEntities);
//eWorldLoadFlag_NoLights |
//eWorldLoadFlag_NoEntities |
//eWorldLoadFlag_NoGameEntities);
if(pWorld==NULL){
Error("Couldn't load map '%s'\n",asFile.c_str());
return false;
}
mpInit->mpSaveHandler->LoadData(msCurrentMap);
mpInit->mpGame->GetResources()->GetSoundManager()->DestroyUnused(mpInit->mlMaxSoundDataNum);
mpInit->mpGame->GetResources()->GetParticleManager()->DestroyUnused(mpInit->mlMaxPSDataNum);
}
else
{
pWorld = mpScene->LoadWorld3D(asFile,true,0);
mpInit->mpGame->GetResources()->GetSoundManager()->DestroyUnused(mpInit->mlMaxSoundDataNum);
mpInit->mpGame->GetResources()->GetParticleManager()->DestroyUnused(mpInit->mlMaxPSDataNum);
if(pWorld==NULL){
Error("Couldn't load map '%s'\n",asFile.c_str());
return false;
}
}
//Destroy old world, if there is any.
if(pOldWorld)
{
mpScene->DestroyWorld3D(pOldWorld);
}
//Set physics update
if(pWorld->GetPhysicsWorld())pWorld->GetPhysicsWorld()->SetMaxTimeStep(mpInit->mfMaxPhysicsTimeStep);
//OnMapLoad for all entities
tGameEntityMapIt GIt = m_mapGameEntities.begin();
for(; GIt != m_mapGameEntities.end(); ++GIt)
{
iGameEntity *pEntity = GIt->second;
pEntity->OnWorldLoad();
}
//OnMapLoad for player
mpInit->mpPlayer->OnWorldLoad();
mpInit->mpGame->ResetLogicTimer();
//Physics set up
pWorld->GetPhysicsWorld()->SetAccuracyLevel(mpInit->mPhysicsAccuracy);
return true;
}
//-----------------------------------------------------------------------
void cMapHandler::ChangeMap(const tString &asMap, const tString &asPos, const tString &asStartSound,
const tString &asStopSound, float afFadeOutTime, float afFadeInTime,
tString asLoadTextCat, tString asLoadTextEntry)
{
mMapChanger.msNewMap = asMap;
mMapChanger.msPosName = asPos;
mMapChanger.msDoneSound = asStopSound;
mMapChanger.mfFadeInTime = afFadeInTime;
mMapChanger.mbActive = true;
mMapChanger.msLoadTextCat = asLoadTextCat;
mMapChanger.msLoadTextEntry = asLoadTextEntry;
mpInit->mpFadeHandler->FadeOut(afFadeOutTime);
if(asStartSound!="")
mpInit->mpGame->GetSound()->GetSoundHandler()->PlayGui(asStartSound,false,1);
mpInit->mpPlayer->SetActive(false);
}
//-----------------------------------------------------------------------
void cMapHandler::AddSaveData(cSavedWorld* apSavedWorld)
{
cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D();
/////////////////////////
//Properties
apSavedWorld->msGameName = msMapGameName;
/////////////////////////
//Local timers
for(tGameTimerListIt it = mlstTimers.begin(); it != mlstTimers.end(); ++it)
{
cGameTimer *pTimer = *it;
if(pTimer->mbGlobal==false)
{
apSavedWorld->mlstTimers.Add(*pTimer);
}
}
/////////////////////////
//Map script vars
tScriptVarMap *pVarMap = mpScene->GetLocalVarMap();
tScriptVarMapIt varIt = pVarMap->begin();
for(; varIt != pVarMap->end(); ++varIt)
{
cScriptVar &scriptVar = varIt->second;
scriptVar.mlVal = scriptVar.mlVal;
scriptVar.msName = scriptVar.msName;
apSavedWorld->mlstVars.Add(scriptVar);
}
//////////////////
//Engine data
//Lights
{
cLight3DListIterator it = pWorld->GetLightIterator();
while(it.HasNext())
{
iLight3D *pLight = it.Next();
cEngineLight_SaveData saveLight;
if(pLight->IsSaved() && pLight->GetParent() == NULL && pLight->GetEntityParent()==NULL)
{
saveLight.FromLight(pLight);
apSavedWorld->mlstLights.Add(saveLight);
}
}
}
//Particle systems
{
cParticleSystem3DIterator it = pWorld->GetParticleSystemIterator();
while(it.HasNext())
{
cParticleSystem3D *pPS = it.Next();
cEnginePS_SaveData savePS;
if( pPS->IsSaved() && pPS->GetParent() == NULL && pPS->GetEntityParent()==NULL
&& pPS->IsDying()==false)
{
savePS.FromPS(pPS);
apSavedWorld->mlstPS.Add(savePS);
}
}
}
//Beams
{
cBeamIterator it = pWorld->GetBeamIterator();
while(it.HasNext())
{
cBeam *pBeam = it.Next();
cEngineBeam_SaveData saveBeam;
if(pBeam->IsSaved() && pBeam->GetParent() == NULL && pBeam->GetEntityParent()==NULL)
{
saveBeam.FromBeam(pBeam);
apSavedWorld->mlstBeams.Add(saveBeam);
}
}
}
//Sounds
{
cSoundEntityIterator it = pWorld->GetSoundEntityIterator();
while(it.HasNext())
{
cSoundEntity *pSound = it.Next();
cEngineSound_SaveData saveSound;
if(pSound->IsSaved() && pSound->GetParent() == NULL && pSound->GetEntityParent()==NULL)
{
//Check if the sound should be saved.
if(pSound->GetRemoveWhenOver() && pSound->GetData()->GetLoop()==false) continue;
saveSound.FromSound(pSound);
apSavedWorld->mlstSounds.Add(saveSound);
}
}
}
//Joints
{
cPhysicsJointIterator it = pWorld->GetPhysicsWorld()->GetJointIterator();
while(it.HasNext())
{
iPhysicsJoint *pJoint = it.Next();
cEngineJoint_SaveData saveJoint;
if(pJoint->IsSaved())
{
//Check if the joint should be saved.
if(pJoint->IsBroken()) continue;
saveJoint.FromJoint(pJoint);
apSavedWorld->mlstJoints.Add(saveJoint);
}
}
}
//////////////////
//Map handler
tGameEntityMapIt GIt = m_mapGameEntities.begin();
for(; GIt != m_mapGameEntities.end(); ++GIt)
{
iGameEntity *pEntity = GIt->second;
if(pEntity->IsSaved())
{
//Log("Saving entity: '%s'\n",pEntity->GetName().c_str());
iGameEntity_SaveData *pSaveData = pEntity->CreateSaveData();
pEntity->SaveToSaveData(pSaveData);
apSavedWorld->mlstEntities.Add(pSaveData);
//Log("Adding save data: %d\n", pSaveData);
}
else
{
//Log("Skipping entity: '%s'\n",pEntity->GetName().c_str());
}
}
}
//-----------------------------------------------------------------------
void cMapHandler::LoadSaveData(cSavedWorld* apSavedWorld)
{
cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D();
iPhysicsWorld *pPhysicsWorld = pWorld->GetPhysicsWorld();
std::list lstEntities;
/////////////////////////
//Properties
msMapGameName = apSavedWorld->msGameName;
////////////////////////////////
//Script variables
cContainerListIterator scriptVar = apSavedWorld->mlstVars.GetIterator();
while(scriptVar.HasNext())
{
cScriptVar &var = scriptVar.Next();
cScriptVar *pVar = mpScene->CreateLocalVar(var.msName);
pVar->mlVal = var.mlVal;
}
/////////////////////////
//Local timers
cContainerListIterator timerIt = apSavedWorld->mlstTimers.GetIterator();
while(timerIt.HasNext())
{
cGameTimer& savedTimer = timerIt.Next();
cGameTimer *pTimer = hplNew( cGameTimer, () );
*pTimer = savedTimer;
mlstTimers.push_back(pTimer);
}
////////////////////////////////
//Engine data
{
///////////////////////
//Lights
cContainerListIterator it = apSavedWorld->mlstLights.GetIterator();
while(it.HasNext())
{
cEngineLight_SaveData &saveLight = it.Next();
iLight3D *pLight = pWorld->GetLight(saveLight.msName);
if(pLight)
{
saveLight.ToLight(pLight);
}
else
{
//Create light
//This is most probably a temp light so skip it.
}
}
}
{
//////////////////////////
//Particle systems
//Go through particle systems and throw away those not present.
cParticleSystem3DIterator psIt = pWorld->GetParticleSystemIterator();
while(psIt.HasNext())
{
cParticleSystem3D *pPS = psIt.Next();
if(apSavedWorld->PSExists(pPS)==false)
{
pPS->KillInstantly();
}
}
//Set data to map particle systems or create if no system exist.
cContainerListIterator it = apSavedWorld->mlstPS.GetIterator();
while(it.HasNext())
{
cEnginePS_SaveData &savePS = it.Next();
cParticleSystem3D *pPS = pWorld->GetParticleSystem(savePS.msName);
if(pPS)
{
savePS.ToPS(pPS);
}
else
{
pPS = pWorld->CreateParticleSystem(savePS.msName,savePS.msType,savePS.mvSize,
savePS.m_mtxTransform);
savePS.ToPS(pPS);
}
}
}
//////////////////////////
//Beams
{
//Go through beams and throw away those not present.
cBeamIterator beamIt = pWorld->GetBeamIterator();
while(beamIt.HasNext())
{
cBeam *pBeam = beamIt.Next();
if(apSavedWorld->BeamExists(pBeam)==false)
{
mpScene->GetWorld3D()->DestroyBeam(pBeam);
}
}
//Set data to map particle systems or create if no system exist.
cContainerListIterator it = apSavedWorld->mlstBeams.GetIterator();
while(it.HasNext())
{
cEngineBeam_SaveData &saveBeam = it.Next();
cBeam *pBeam = pWorld->GetBeam(saveBeam.msName);
if(pBeam)
{
saveBeam.ToBeam(pBeam);
}
else
{
pBeam = pWorld->CreateBeam(saveBeam.msName);
saveBeam.ToBeam(pBeam);
}
}
}
{
//////////////////////////
//Sounds
//Go through sound entities and throw away those not present.
cSoundEntityIterator soundIt = pWorld->GetSoundEntityIterator();
while(soundIt.HasNext())
{
cSoundEntity *pSound = soundIt.Next();
if(apSavedWorld->SoundExists(pSound)==false)
{
mpScene->GetWorld3D()->DestroySoundEntity(pSound);
}
}
//Set data to map sound entities
cContainerListIterator it = apSavedWorld->mlstSounds.GetIterator();
while(it.HasNext())
{
cEngineSound_SaveData &saveSound = it.Next();
cSoundEntity *pSound = pWorld->GetSoundEntity(saveSound.msName);
if(pSound)
{
saveSound.ToSound(pSound);
}
}
}
////////////////////////////////
//Create Entities
cContainerListIterator it = apSavedWorld->mlstEntities.GetIterator();
while(it.HasNext())
{
iGameEntity_SaveData *pSaveEntity = it.Next();
//////////////////////////////////
//The entity is loaded from file
if(pSaveEntity->msFileName!="")
{
if(pWorld->CreateEntity(pSaveEntity->msName,pSaveEntity->m_mtxTransform,pSaveEntity->msFileName, true))
{
iGameEntity *pGameEntity = mpInit->mpMapHandler->GetLatestEntity();
pGameEntity->LoadFromSaveData(pSaveEntity);
pGameEntity->SetSaveData(pSaveEntity);
lstEntities.push_back(pGameEntity);
}
}
//////////////////////////////////
//The entity is an area.
else
{
cVector3f vSize =0;
tString sType = "";
//Get type and size
switch(pSaveEntity->mType)
{
case eGameEntityType_Area:
vSize = static_cast(pSaveEntity)->mvSize;
sType = "script";
break;
case eGameEntityType_Link:
vSize = static_cast(pSaveEntity)->mvSize;
sType = "link";
break;
case eGameEntityType_StickArea:
vSize = static_cast(pSaveEntity)->mvSize;
sType = "stick";
break;
case eGameEntityType_SaveArea:
vSize = static_cast(pSaveEntity)->mvSize;
sType = "save";
break;
case eGameEntityType_Ladder:
vSize = static_cast(pSaveEntity)->mvSize;
sType = "ladder";
break;
case eGameEntityType_DamageArea:
vSize = static_cast(pSaveEntity)->mvSize;
sType = "damage";
break;
case eGameEntityType_ForceArea:
vSize = static_cast(pSaveEntity)->mvSize;
sType = "force";
break;
case eGameEntityType_LiquidArea:
vSize = static_cast(pSaveEntity)->mvSize;
sType = "liquid";
break;
}
//Load entity
if(sType!="")
{
iArea3DLoader *pLoader = pWorld->GetResources()->GetArea3DLoader(sType);
if(pLoader)
{
pLoader->Load(pSaveEntity->msName,vSize,pSaveEntity->m_mtxTransform,pWorld);
iGameEntity *pGameEntity = mpInit->mpMapHandler->GetLatestEntity();
pGameEntity->LoadFromSaveData(pSaveEntity);
pGameEntity->SetSaveData(pSaveEntity);
lstEntities.push_back(pGameEntity);
}
}
}
}
////////////////////////////////
//Setup Entities
std::list::iterator entIt = lstEntities.begin();
for(; entIt != lstEntities.end(); ++entIt)
{
iGameEntity* pEntity = *entIt;
pEntity->SetupSaveData(pEntity->GetSaveData());
}
{
//////////////////////////
//Joints
// this need to be done after entity creation so all joints are created.
//Go through joints and throw away those not present.
cPhysicsJointIterator jointIt = pPhysicsWorld->GetJointIterator();
while(jointIt.HasNext())
{
iPhysicsJoint *pJoint = jointIt.Next();
if(apSavedWorld->JointExists(pJoint)==false)
{
pPhysicsWorld->DestroyJoint(pJoint);
}
}
//Set data to map Joint entities
cContainerListIterator it = apSavedWorld->mlstJoints.GetIterator();
while(it.HasNext())
{
cEngineJoint_SaveData &saveJoint = it.Next();
iPhysicsJoint *pJoint = pPhysicsWorld->GetJoint(saveJoint.msName);
if(pJoint)
{
saveJoint.ToJoint(pJoint);
}
}
}
}
//-----------------------------------------------------------------------
void cMapHandler::OnStart()
{
}
//-----------------------------------------------------------------------
void cMapHandler::OnWorldLoad()
{
}
//-----------------------------------------------------------------------
void cMapHandler::OnDraw()
{
tGameEntityMapIt GIt = m_mapGameEntities.begin();
for(; GIt != m_mapGameEntities.end(); ++GIt)
{
iGameEntity *pEntity = GIt->second;
pEntity->OnDraw();
}
}
void cMapHandler::RenderItemEffect()
{
if(mpInit->mbFlashItems == false) return;
//Check if any item needs the effect.
bool bFound = false;
tGameItemListIt it = mlstGameItems.begin();
for(; it != mlstGameItems.end(); ++it)
{
cGameItem *pItem = *it;
if(pItem->IsActive() && pItem->GetFlashAlpha() >0)
{
bFound = true;
break;
}
}
if(bFound==false) return;
cCamera3D *pCam = static_cast(mpScene->GetCamera());
iLowLevelGraphics *pLowGfx = mpInit->mpGame->GetGraphics()->GetLowLevel();
pLowGfx->SetDepthTestActive(true);
pLowGfx->SetDepthWriteActive(false);
pLowGfx->SetBlendActive(true);
pLowGfx->SetBlendFunc(eBlendFunc_One,eBlendFunc_One);
pLowGfx->SetActiveTextureUnit(0);
pLowGfx->SetTextureEnv(eTextureParam_ColorSource1,eTextureSource_Constant);
pLowGfx->SetTextureEnv(eTextureParam_ColorSource0,eTextureSource_Texture);
pLowGfx->SetTextureEnv(eTextureParam_ColorFunc, eTextureFunc_Modulate);
it = mlstGameItems.begin();
for(; it != mlstGameItems.end(); ++it)
{
cGameItem *pItem = *it;
if(pItem->IsActive()==false) continue;
if(pItem->GetFlashAlpha() <=0) continue;
cMeshEntity *pMeshEntity = pItem->GetMeshEntity();
pLowGfx->SetTextureConstantColor(cColor(pItem->GetFlashAlpha(),0));
pLowGfx->SetMatrix(eMatrix_ModelView, cMath::MatrixMul(pCam->GetViewMatrix(),
pMeshEntity->GetWorldMatrix()));
for(int i=0; i< pMeshEntity->GetMesh()->GetSubMeshNum(); i++)
{
cSubMeshEntity *pSubEntity = pMeshEntity->GetSubMeshEntity(i);
cSubMesh *pSubMesh = pMeshEntity->GetMesh()->GetSubMesh(i);
iVertexBuffer *pVtxBuffer = pSubEntity->GetVertexBuffer();
iMaterial *pMaterial = pSubEntity->GetMaterial();
iGpuProgram *pVtxProg = pMaterial->GetVertexProgram(eMaterialRenderType_Z,0,NULL);
if(pVtxProg)
{
pVtxProg->Bind();
pVtxProg->SetMatrixf("worldViewProj",
eGpuProgramMatrix_ViewProjection,
eGpuProgramMatrixOp_Identity);
}
iGpuProgram *pFragProg = pMaterial->GetFragmentProgram(eMaterialRenderType_Z,0,NULL);
if(pFragProg)
{
pFragProg->SetColor3f("ambientColor", pItem->GetFlashAlpha());
pFragProg->Bind();
}
pLowGfx->SetTexture(0,pMaterial->GetTexture(eMaterialTexture_Diffuse));
pVtxBuffer->Bind();
pVtxBuffer->Draw();
pVtxBuffer->UnBind();
if(pFragProg) pFragProg->UnBind();
if(pVtxProg) pVtxProg->UnBind();
}
}
pLowGfx->SetTexture(0,NULL);
pLowGfx->SetActiveTextureUnit(0);
pLowGfx->SetTextureEnv(eTextureParam_ColorSource1,eTextureSource_Previous);
pLowGfx->SetTextureEnv(eTextureParam_ColorSource0,eTextureSource_Texture);
pLowGfx->SetBlendActive(false);
pLowGfx->SetDepthTestActive(true);
pLowGfx->SetDepthWriteActive(true);
}
//-----------------------------------------------------------------------
void cMapHandler::OnPostSceneDraw()
{
////////////////////////////////////
// Draw effect on items
RenderItemEffect();
cCamera3D *pCam = static_cast(mpScene->GetCamera());
mpInit->mpGame->GetGraphics()->GetLowLevel()->SetMatrix(eMatrix_ModelView, pCam->GetViewMatrix());
//mpScene->GetWorld3D()->GetPhysicsWorld()->RenderDebugGeometry(
// mpInit->mpGame->GetGraphics()->GetLowLevel(),cColor(1,0.5f,1));
/*mpInit->mpGame->GetGraphics()->GetLowLevel()->SetDepthTestActive(false);
cParticleSystem3DIterator PIt = mpScene->GetWorld3D()->GetParticleSystemIterator();
while(PIt.HasNext())
{
cParticleSystem3D*pPS = PIt.Next();
//if(pPS->GetName() == "tripod01_tripodflame")
//{
// static bool bStatic = true;
// if(bStatic){//pPS->SetTransformUpdated(true);
// Log("Once!!!\n");
// }
// bStatic =false;
//pPS->SetPosition(pPS->GetLocalPosition());
mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawSphere(pPS->GetWorldPosition(),
0.3f,cColor(1,0,1));
mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawBoxMaxMin(
pPS->GetEmitter(0)->GetBoundingVolume()->GetMax(),
pPS->GetEmitter(0)->GetBoundingVolume()->GetMin(),
cColor(0,1,1));
}
mpInit->mpGame->GetGraphics()->GetLowLevel()->SetDepthTestActive(true);*/
////////////////////////////////////
// Let Entities post draw
tGameEntityMapIt GIt = m_mapGameEntities.begin();
for(; GIt != m_mapGameEntities.end(); ++GIt)
{
iGameEntity *pEntity = GIt->second;
pEntity->OnPostSceneDraw();
}
return;
mpInit->mpGame->GetGraphics()->GetLowLevel()->SetTexture(0,NULL);
mpInit->mpGame->GetGraphics()->GetLowLevel()->SetBlendActive(false);
mpInit->mpGame->GetGraphics()->GetLowLevel()->SetDepthTestActive(false);
cVector3f vMin = mpScene->GetWorld3D()->GetPhysicsWorld()->GetWorldSizeMin();
cVector3f vMax = mpScene->GetWorld3D()->GetPhysicsWorld()->GetWorldSizeMax();
//mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawBoxMaxMin(vMax,vMin,cColor(1,0,1));
//mpScene->GetWorld3D()->DrawMeshBoundingBoxes(cColor(1,0.5f,1),false);
//mpScene->GetWorld3D()->GetPhysicsWorld()->RenderDebugGeometry(
// mpInit->mpGame->GetGraphics()->GetLowLevel(),cColor(1,0.5f,1));
//mpScene->GetWorld3D()->GetPhysicsWorld()->SetSaveContactPoints(true);
//mpScene->GetWorld3D()->GetPhysicsWorld()->RenderContactPoints(mpInit->mpGame->GetGraphics()->GetLowLevel(),cColor(1,0.5f,1),
// cColor(1,1,0.5f));
cLight3DListIterator lightIt = mpScene->GetWorld3D()->GetLightIterator();
while(lightIt.HasNext())
{
iLight3D *pLight = lightIt.Next();
if(pLight->IsVisible() && pLight->IsActive() && pLight->GetLightType() == eLight3DType_Spot)
{
cBoundingVolume *pBV = pLight->GetBoundingVolume();
mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawBoxMaxMin(
pBV->GetMax(),pBV->GetMin(),cColor(1,0,1));
}
}
/*mpInit->mpGame->GetGraphics()->GetLowLevel()->SetDepthTestActive(false);
cBillboardIterator billIt = mpScene->GetWorld3D()->GetBillboardIterator();
while(billIt.HasNext())
{
cBillboard *pBillboard = billIt.Next();
mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawBoxMaxMin(
pBillboard->GetBoundingVolume()->GetMax(),
pBillboard->GetBoundingVolume()->GetMin(),cColor(1,0,1));
}*/
GIt = m_mapGameEntities.begin();
for(; GIt != m_mapGameEntities.end(); ++GIt)
{
iGameEntity *pEntity = GIt->second;
//if(pEntity->GetBodyNum()<=0) continue;
//mpInit->mpGame->GetGraphics()->GetLowLevel()->SetDepthTestActive(false);
//mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawBoxMaxMin(
// pEntity->GetMeshEntity()->GetBoundingVolume()->GetMax(),
// pEntity->GetMeshEntity()->GetBoundingVolume()->GetMin(),cColor(1,0,1));
/*for(int i=0; i < pEntity->GetBodyNum(); ++i)
{
iPhysicsBody* pBody = pEntity->GetBody(i);
if(pBody){
cBoundingVolume *pBV = pBody->GetBV();
mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawBoxMaxMin(pBV->GetMax(),pBV->GetMin(),
cColor(1,0.5f,1));
//pBody->RenderDebugGeometry(mpInit->mpGame->GetGraphics()->GetLowLevel(),cColor(1,0.5f,1));
}
}*/
}
mpInit->mpGame->GetGraphics()->GetLowLevel()->SetDepthTestActive(true);
}
//-----------------------------------------------------------------------
void cMapHandler::Update(float afTimeStep)
{
mfGameTime += (double)afTimeStep;
//iLowLevelSystem *pLowLevelSystem =mpInit->mpGame->GetSystem()->GetLowLevel();
//LogUpdate(" Flashes!\n");
////////////////////////////
//Update light flashes
tEffectLightFlashListIt FlashIt = mlstLightFlashes.begin();
for(; FlashIt != mlstLightFlashes.end(); )
{
cEffectLightFlash *pFlash = *FlashIt;
pFlash->Update(afTimeStep);
if(pFlash->IsDead())
{
hplDelete( pFlash );
FlashIt = mlstLightFlashes.erase(FlashIt);
}
else
{
++FlashIt;
}
}
//LogUpdate(" Timers\n");
////////////////////////////
//Update timers
UpdateTimers(afTimeStep);
//LogUpdate(" Entities!\n");
////////////////////////////
//Update entities.
tGameEntityMapIt GIt = m_mapGameEntities.begin();
for(; GIt != m_mapGameEntities.end();)
{
iGameEntity *pEntity = GIt->second;
//unsigned int lTime = pLowLevelSystem->GetTime();
//LogUpdate(" %s\n",pEntity->GetName().c_str());
if(pEntity->IsActive()){
pEntity->OnUpdate(afTimeStep);
}
if(pEntity->GetDestroyMe() || pEntity->GetBreakMe())
{
//LogUpdate(" destroying\n");
if(pEntity->GetBreakMe()) pEntity->BreakAction();
m_mapGameEntities.erase(GIt++);
hplDelete( pEntity );
//LogUpdate(" done destroying\n");
}
else
{
////LogUpdate(" updating %s took %d ms\n", pEntity->GetName().c_str(),
// pLowLevelSystem->GetTime() - lTime);
++GIt;
}
}
////////////////////////////
//Check for map change
//LogUpdate(" Map change\n");
if(mMapChanger.mbActive && mpInit->mpFadeHandler->IsActive()==false)
{
mMapChanger.mbActive = false;
//Log("---------- CHANGING TO MAP: '%s' ------------------\n",mMapChanger.msNewMap.c_str());
//Make sure that the graphics are not destroyed at the end of the map so
//That the next map doesn't have to reload em.
mpInit->mbDestroyGraphics = false;
//Draw Loading image
if(mMapChanger.msLoadTextCat != "")
{
mpInit->mpMapLoadText->SetText(mMapChanger.msLoadTextCat,mMapChanger.msLoadTextEntry);
mpInit->mpMapLoadText->SetActive(true);
}
else
{
mpInit->mpGraphicsHelper->DrawLoadingScreen("other_loading.jpg");
}
//Fade in here so that script will over ride it.
mpInit->mpFadeHandler->FadeIn(mMapChanger.mfFadeInTime);
Load(mMapChanger.msNewMap,mMapChanger.msPosName);
mpInit->mbDestroyGraphics = true;
if(mMapChanger.msDoneSound!="")
mpInit->mpGame->GetSound()->GetSoundHandler()->PlayGui(mMapChanger.msDoneSound,false,1);
mpInit->mpPlayer->SetActive(true);
//Log("Map change over...\n");
}
}
//-----------------------------------------------------------------------
void cMapHandler::Reset()
{
#ifdef DEMO_VERSION
glNumOfLoads = 0;
#endif
mMapChanger.mbActive = false;
msCurrentMap = "";
if(mpInit->mbResetCache) mpWorldCache->DecResources();
mvLoadedMaps.clear();
//Timers
STLDeleteAll(mlstTimers);
DestroyAll();
//Haptic
if(mpInit->mbHasHaptics)
{
mpInit->mpGame->GetHaptic()->GetLowLevel()->DestroyAllShapes();
mpInit->mpGame->GetHaptic()->GetLowLevel()->StopAllForces();
}
//World3D
if(mpScene->GetWorld3D()) mpScene->DestroyWorld3D(mpScene->GetWorld3D());
mpScene->SetWorld3D(NULL);
//Make sure no occulssion queries are left.
mpInit->mpGame->GetGraphics()->GetRenderer3D()->GetRenderList()->Clear();
}
//-----------------------------------------------------------------------
void cMapHandler::DestroyAll()
{
mbDestroyingAll = true;
RemoveLocalTimers();
//Game entities
STLMapDeleteAll(m_mapGameEntities);
m_mapGameEntities.clear();
mlstGameEnemies.clear();
mlstGameItems.clear();
//Light flashes
STLDeleteAll(mlstLightFlashes);
mlstLightFlashes.clear();
mbDestroyingAll = false;
}
//-----------------------------------------------------------------------
cGameTimer * cMapHandler::CreateTimer(const tString& asName,float afTime, const tString& asCallback, bool abGlobal)
{
cGameTimer *pTimer = hplNew( cGameTimer, () );
pTimer->msName = asName;
pTimer->msCallback = asCallback;
pTimer->mfTime = afTime;
pTimer->mbGlobal = abGlobal;
mlstTimers.push_back(pTimer);
return pTimer;
}
cGameTimer * cMapHandler::GetTimer(const tString& asName)
{
return (cGameTimer*)STLFindByName(mlstTimers,asName);
}
//-----------------------------------------------------------------------
void cMapHandler::AddLightFlash(const cVector3f& avPos,float afRadius, const cColor &aColor, float afAddTime, float afNegTime)
{
cEffectLightFlash *pFlash = hplNew( cEffectLightFlash, (mpInit,avPos,afRadius,aColor,afAddTime,afNegTime) );
mlstLightFlashes.push_back(pFlash);
}
//-----------------------------------------------------------------------
void cMapHandler::AddStickArea(cGameStickArea *apArea)
{
mlstGameStickAreas.push_back(apArea);
}
//-----------------------------------------------------------------------
void cMapHandler::RemoveStickArea(cGameStickArea *apArea)
{
tGameStickAreaListIt it = mlstGameStickAreas.begin();
for(; it != mlstGameStickAreas.end(); ++it)
{
if(*it == apArea)
{
mlstGameStickAreas.erase(it);
break;
}
}
}
//-----------------------------------------------------------------------
cGameStickArea* cMapHandler::GetBodyStickArea(iPhysicsBody *apBody)
{
tGameStickAreaListIt it = mlstGameStickAreas.begin();
for(; it != mlstGameStickAreas.end(); ++it)
{
cGameStickArea *pArea = *it;
if(pArea->GetAttachedBody() == apBody)
{
return pArea;
}
}
return NULL;
}
//-----------------------------------------------------------------------
void cMapHandler::AddGameEnemy(iGameEnemy *apEnemy)
{
mlstGameEnemies.push_back(apEnemy);
}
tGameEnemyIterator cMapHandler::GetGameEnemyIterator()
{
return tGameEnemyIterator(&mlstGameEnemies);
}
//-----------------------------------------------------------------------
void cMapHandler::AddGameItem(cGameItem *apItem)
{
mlstGameItems.push_back(apItem);
}
void cMapHandler::RemoveGameItem(cGameItem *apItem)
{
tGameItemListIt it = mlstGameItems.begin();
for(; it != mlstGameItems.end(); ++it)
{
cGameItem *pItem = *it;
if(pItem == apItem){
mlstGameItems.erase(it);
break;
}
}
}
//-----------------------------------------------------------------------
void cMapHandler::AddGameEntity(iGameEntity *apEntity)
{
iGameEntity *pSameNameEntity = GetGameEntity(apEntity->GetName(),false);
if(pSameNameEntity)
{
Warning("Entity '%s' with file '%s' has name already taken by '%s'!\n",
apEntity->GetName().c_str(),
apEntity->GetFileName().c_str(),
pSameNameEntity->GetFileName().c_str());
}
mpLatestEntity = apEntity;
m_mapGameEntities.insert(tGameEntityMap::value_type(apEntity->GetName(),apEntity));
}
void cMapHandler::RemoveGameEntity(iGameEntity *apEntity)
{
m_mapGameEntities.erase(apEntity->GetName());
//If the entity is an enemy remove that aswel
{
tGameEnemyListIt it = mlstGameEnemies.begin();
for(; it != mlstGameEnemies.end(); ++it)
{
iGameEntity *pEnemy = *it;
if(pEnemy == apEntity)
{
mlstGameEnemies.erase(it);
break;
}
}
}
hplDelete( apEntity );
}
iGameEntity* cMapHandler::GetGameEntity(const tString &asName, bool abErrorMessage)
{
tGameEntityMapIt it = m_mapGameEntities.find(asName);
if(it == m_mapGameEntities.end())
{
if(abErrorMessage) Error("Couldn't find game entity '%s'\n",asName.c_str());
return NULL;
}
return it->second;
}
//-----------------------------------------------------------------------
tGameEntityIterator cMapHandler::GetGameEntityIterator()
{
return tGameEntityIterator(&m_mapGameEntities);
}
//-----------------------------------------------------------------------
iGameEntity* cMapHandler::GetLatestEntity()
{
return mpLatestEntity;
}
//-----------------------------------------------------------------------
void cMapHandler::SaveToGlobal(cMapHandler_GlobalSave *apSave)
{
cMapHandler_GlobalSave *pData = apSave;
/////////////////
//Variables
kSaveData_SaveTo(mfGameTime);
kSaveData_SaveTo(msCurrentMap);
/////////////////
//Containers
//Loaded maps
pData->mvLoadedMaps.Resize(mvLoadedMaps.size());
for(size_t i=0; i < mvLoadedMaps.size(); ++i)
{
pData->mvLoadedMaps[i].mfTime = mvLoadedMaps[i].mfTime;
pData->mvLoadedMaps[i].msName = mvLoadedMaps[i].msName;
}
//Timers
tGameTimerListIt it = mlstTimers.begin();
for(; it != mlstTimers.end(); ++it)
{
cGameTimer *pTimer = *it;
cMapHandlerTimer_GlobalSave timerSave;
if(pTimer->mbGlobal)
{
timerSave.mfTime = pTimer->mfTime;
timerSave.msName = pTimer->msName;
timerSave.msCallback = pTimer->msCallback;
timerSave.mbGlobal = pTimer->mbGlobal;
timerSave.mbDeleteMe = pTimer->mbDeleteMe;
timerSave.mbPaused = pTimer->mbPaused;
pData->mlstTimers.Add(timerSave);
}
}
}
void cMapHandler::LoadFromGlobal(cMapHandler_GlobalSave *apSave)
{
cMapHandler_GlobalSave *pData = apSave;
/////////////////
//Variables
kSaveData_LoadFrom(mfGameTime);
//Should not be loadead so that current map is ""
//kSaveData_LoadFrom(msCurrentMap);
/////////////////
//Containers
//Loaded maps
mvLoadedMaps.resize(pData->mvLoadedMaps.Size());
for(size_t i=0; i < mvLoadedMaps.size(); ++i)
{
mvLoadedMaps[i].mfTime = pData->mvLoadedMaps[i].mfTime;
mvLoadedMaps[i].msName = pData->mvLoadedMaps[i].msName;
}
//Timers
cContainerListIterator it = pData->mlstTimers.GetIterator();
while(it.HasNext())
{
cGameTimer *pTimer = hplNew( cGameTimer, () );
cMapHandlerTimer_GlobalSave &timerSave = it.Next();
pTimer->mfTime = timerSave.mfTime;
pTimer->msName = timerSave.msName;
pTimer->msCallback = timerSave.msCallback;
pTimer->mbGlobal = timerSave.mbGlobal;
pTimer->mbDeleteMe = timerSave.mbDeleteMe;
pTimer->mbPaused = timerSave.mbPaused;
mlstTimers.push_back(pTimer);
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
//////////////////////////////////////////////////////////////////////////
void cMapHandler::PrintSoundsPlaying()
{
Log("Sounds: ");
tSoundEntryList *pEntryList = mpInit->mpGame->GetSound()->GetSoundHandler()->GetWorldEntryList();
for(tSoundEntryListIt it = pEntryList->begin(); it != pEntryList->end();++it)
{
iSoundChannel *pSound = it->mpSound;
Log("'%s', ",pSound->GetData()->GetName().c_str());
}
Log("\n");
}
//-----------------------------------------------------------------------
void cMapHandler::UpdateTimers(float afTimeStep)
{
for(tGameTimerListIt it=mlstTimers.begin(); it != mlstTimers.end(); )
{
cGameTimer *pTimer = *it;
if(pTimer->mbDeleteMe)
{
it = mlstTimers.erase(it);
hplDelete( pTimer );
}
else
{
if(pTimer->mbPaused==false)
pTimer->mfTime -= afTimeStep;
if(pTimer->mfTime <= 0)
{
tString sCommand = pTimer->msCallback + "(\""+pTimer->msName+"\")";
mpInit->RunScriptCommand(sCommand);
it = mlstTimers.erase(it);
hplDelete( pTimer );
}
else
{
++it;
}
}
}
}
void cMapHandler::RemoveLocalTimers()
{
for(tGameTimerListIt it=mlstTimers.begin(); it != mlstTimers.end(); )
{
cGameTimer *pTimer = *it;
if(pTimer->mbGlobal==false)
{
it = mlstTimers.erase(it);
hplDelete( pTimer );
}
else
{
++it;
}
}
}
//-----------------------------------------------------------------------
void cMapHandler::PreUpdate(double afTimeSinceVisit)
{
cWorld3D* pWorld = mpScene->GetWorld3D();
iPhysicsWorld *pPhysicsWorld = pWorld->GetPhysicsWorld();
mbPreUpdating = true;
unsigned long lStart = mpInit->mpGame->GetSystem()->GetLowLevel()->GetTime();
//Enable all physic bodies
cPhysicsBodyIterator bodyIt = pPhysicsWorld->GetBodyIterator();
while(bodyIt.HasNext())
{
iPhysicsBody *pBody = bodyIt.Next();
pBody->SetEnabled(true);
}
//////////////////////////////////////
//Pre update game stuff
if(afTimeSinceVisit ==0)
{
pWorld->PreUpdate(2.0f, mpInit->mpGame->GetStepSize());
}
else
{
float fTime = (float)afTimeSinceVisit;
if(fTime > 3) fTime = 3;
float fStepSize = mpInit->mpGame->GetStepSize();
mpInit->mpGame->GetSound()->GetSoundHandler()->SetSilent(true);
while(fTime>0)
{
//if(pWorld->GetPhysicsWorld()) pWorld->GetPhysicsWorld()->Update(fStepSize);
//pWorld->UpdateParticles(fStepSize);
pWorld->Update(fStepSize);
tGameEnemyListIt it = mlstGameEnemies.begin();
for(; it != mlstGameEnemies.end(); ++it)
{
iGameEnemy *pEnemy = *it;
pEnemy->Update(fStepSize);
}
fTime -= fStepSize;
}
mpInit->mpGame->GetSound()->GetSoundHandler()->SetSilent(false);
}
unsigned long lTime = mpInit->mpGame->GetSystem()->GetLowLevel()->GetTime() - lStart;
//Log("PREUPDATE time: %d\n",lTime);
mbPreUpdating = false;
}
//-----------------------------------------------------------------------
double cMapHandler::AddLoadedMap(cWorld3D *apWorld)
{
//Check if map is loaded
for(size_t i=0; i< mvLoadedMaps.size();++i)
{
if(mvLoadedMaps[i].msName == apWorld->GetName())
{
double fTime = mvLoadedMaps[i].mfTime;
mvLoadedMaps[i].mfTime = GetGameTime();
return GetGameTime() - fTime;
}
}
cLoadedMap LoadedMap;
LoadedMap.msName = apWorld->GetName();
LoadedMap.mfTime = GetGameTime();
mvLoadedMaps.push_back(LoadedMap);
return 0;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// SAVE DATA
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------