/* * 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 "GameMusicHandler.h" #include "Init.h" #include "MapHandler.h" #include "GameEnemy.h" #include "SaveHandler.h" #include "Player.h" #include "CharacterMove.h" ////////////////////////////////////////////////////////////////////////// // TRIGGER ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- cGameMusic::cGameMusic() { Reset(); } //----------------------------------------------------------------------- void cGameMusic::Reset() { msFile = ""; } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // CONSTRUCTORS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- cGameMusicHandler::cGameMusicHandler(cInit *apInit) : iUpdateable("GameMusicHandler") { mpInit = apInit; mpMusicHandler = mpInit->mpGame->GetSound()->GetMusicHandler(); mlMaxPrio = 10; mvGameMusic.resize(mlMaxPrio+1); Reset(); } //----------------------------------------------------------------------- cGameMusicHandler::~cGameMusicHandler(void) { } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- void cGameMusicHandler::OnStart() { } //----------------------------------------------------------------------- void cGameMusicHandler::Update(float afTimeStep) { /////////////////////////////////// //Check if close by music should be played. //Music not playing if(mbAttackPlaying==false) { if(mbEnemyClosePlaying==false) { tString sMusic =""; int lHighestPrio =-1; tGameEnemyIterator enemyIt = mpInit->mpMapHandler->GetGameEnemyIterator(); while(enemyIt.HasNext()) { iGameEnemy *pEnemy = enemyIt.Next(); if(pEnemy->GetHealth() <= 0 || pEnemy->IsActive()==false) continue; float fDist = cMath::Vector3Dist(pEnemy->GetMover()->GetCharBody()->GetFeetPosition(), mpInit->mpPlayer->GetCharacterBody()->GetFeetPosition()); if(fDist < pEnemy->GetCloseMusicStartDist()) { if(pEnemy->GetCloseMusic()!= "" && (sMusic=="" || lHighestPrio < pEnemy->GetCloseMusicPrio())) { sMusic = pEnemy->GetCloseMusic(); lHighestPrio = pEnemy->GetCloseMusicPrio(); } } } if(sMusic != "") { mfEnemyGoneCount =0; mfEnemyCloseCount += afTimeStep; if(mfEnemyCloseCount > 2.0f) { Play(sMusic,true,1,0.25f,5); mbEnemyClosePlaying = true; } } } //Music playing else { bool bFound; tGameEnemyIterator enemyIt = mpInit->mpMapHandler->GetGameEnemyIterator(); while(enemyIt.HasNext()) { iGameEnemy *pEnemy = enemyIt.Next(); if(pEnemy->GetHealth() <= 0 || pEnemy->IsActive()==false) continue; float fDist = cMath::Vector3Dist(pEnemy->GetMover()->GetCharBody()->GetFeetPosition(), mpInit->mpPlayer->GetCharacterBody()->GetFeetPosition()); if(fDist < pEnemy->GetCloseMusicStopDist()) { bFound = true; } } if(bFound == false) { mfEnemyCloseCount =0; mfEnemyGoneCount += afTimeStep; if(mfEnemyGoneCount > 6.0f) { Stop(0.2f,5); mbEnemyClosePlaying = false; } } } } /////////////////////////////////// //Check if attack music should be played. if(mbAttackPlaying==false && m_setAttackers.empty()==false) { mfAttackStopCount =0; mfAttackPlayCount += afTimeStep; if(mfAttackPlayCount > 1.5f) { ////////////////////// // Go through attackers and get music with highest priority tString sMusic = ""; int lMaxPrio = -9999; tAttackerSetIt it = m_setAttackers.begin(); for(; it != m_setAttackers.end(); ++it) { iGameEnemy *pEnemy = *it; if(pEnemy->GetAttackMusic() != "" && pEnemy->GetAttackMusicPrio() > lMaxPrio) { sMusic = pEnemy->GetAttackMusic(); lMaxPrio = pEnemy->GetAttackMusicPrio(); } } ////////////////////// // Play music if found if(sMusic != "") { if(mbEnemyClosePlaying){ mbEnemyClosePlaying = false; Stop(0.2f,5); } Play(sMusic,true,1,1.3f,9); mbAttackPlaying = true; //Log("Play!"); mfAttackPlayCount =0; } } } else if(mbAttackPlaying && m_setAttackers.empty()) { mfAttackPlayCount =0; mfAttackStopCount += afTimeStep; if(mfAttackStopCount > 1.2f) { mbAttackPlaying = false; Stop(0.2f,9); //Log("Stop!"); mfAttackStopCount =0; } } /////////////////////////////////// //Check if current song is over if(mlCurrentMaxPrio >=0) { if(mpMusicHandler->GetCurrentSong()==NULL) { mvGameMusic[mlCurrentMaxPrio].msFile = ""; mlCurrentMaxPrio = -1; PlayHighestPriority(); } } } //----------------------------------------------------------------------- void cGameMusicHandler::Reset() { for(size_t i=0; i< mvGameMusic.size(); ++i) { mvGameMusic[i].Reset(); } mlCurrentMaxPrio = -1; mbAttackPlaying = false; m_setAttackers.clear(); mfAttackPlayCount =0; mfAttackStopCount =0; mbEnemyClosePlaying = false; mfEnemyCloseCount =0; mfEnemyGoneCount =0; } //----------------------------------------------------------------------- void cGameMusicHandler::Play(const tString &asFile, bool abLoop,float afVolume, float afFade, int alPrio) { if(alPrio> mlMaxPrio) alPrio = mlMaxPrio; if(mvGameMusic[alPrio].msFile == asFile) return; //If higher or equal to song playing, start playing if(mlCurrentMaxPrio <= alPrio) { mpMusicHandler->Play(asFile,afVolume,afFade,abLoop); mlCurrentMaxPrio = alPrio; } //Set game music properites mvGameMusic[alPrio].mbLoop = abLoop; mvGameMusic[alPrio].mfVolume = afVolume; mvGameMusic[alPrio].msFile = asFile; } //----------------------------------------------------------------------- void cGameMusicHandler::Stop(float afFade, int alPrio) { if(alPrio> mlMaxPrio) alPrio = mlMaxPrio; //Check if there is any song playing at this prio if(mvGameMusic[alPrio].msFile != "") { mvGameMusic[alPrio].msFile = ""; //Check the current song playing is this if(alPrio == mlCurrentMaxPrio) { mpMusicHandler->Stop(afFade); //Play next song in priority if there is any. mlCurrentMaxPrio = -1; PlayHighestPriority(); } } } //----------------------------------------------------------------------- void cGameMusicHandler::AddAttacker(iGameEnemy *apEntity) { m_setAttackers.insert(apEntity); } //----------------------------------------------------------------------- void cGameMusicHandler::RemoveAttacker(iGameEnemy *apEntity) { m_setAttackers.erase(apEntity); } bool cGameMusicHandler::AttackerExist(iGameEnemy *apEntity) { tAttackerSetIt it = m_setAttackers.find(apEntity); if(it == m_setAttackers.end()) return false; return true; } //----------------------------------------------------------------------- void cGameMusicHandler::OnWorldLoad() { m_setAttackers.clear(); //Update(2.0f); } void cGameMusicHandler::OnWorldExit() { m_setAttackers.clear(); for(int i=0; i<60; ++i)Update(0.1f); } //----------------------------------------------------------------------- void cGameMusicHandler::LoadFromGlobal(cGameMusicHandler_GlobalSave *apSave) { mlCurrentMaxPrio = apSave->mlCurrentMaxPrio; mbEnemyClosePlaying = apSave->mbEnemyClosePlaying; mbAttackPlaying = apSave->mbAttackPlaying; for(size_t i=0; i< mvGameMusic.size(); ++i) { mvGameMusic[i].msFile = apSave->mvGameMusic[i].msFile; mvGameMusic[i].mfVolume = apSave->mvGameMusic[i].mfVolume; mvGameMusic[i].mbLoop = apSave->mvGameMusic[i].mbLoop; } } //----------------------------------------------------------------------- void cGameMusicHandler::SaveToGlobal(cGameMusicHandler_GlobalSave *apSave) { apSave->mlCurrentMaxPrio = mlCurrentMaxPrio; apSave->mbEnemyClosePlaying = mbEnemyClosePlaying; apSave->mbAttackPlaying = mbAttackPlaying; apSave->mvGameMusic.Resize( mvGameMusic.size()); for(size_t i=0; i< mvGameMusic.size(); ++i) { apSave->mvGameMusic[i].msFile = mvGameMusic[i].msFile; apSave->mvGameMusic[i].mfVolume = mvGameMusic[i].mfVolume; apSave->mvGameMusic[i].mbLoop = mvGameMusic[i].mbLoop; } } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PRIVATE METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- void cGameMusicHandler::PlayHighestPriority() { for(int i= mlMaxPrio; i>=0; --i) { if(mvGameMusic[i].msFile != "") { //If looped, play if(mvGameMusic[i].mbLoop) { mpMusicHandler->Play( mvGameMusic[i].msFile, mvGameMusic[i].mfVolume, 0.3f,true); mlCurrentMaxPrio = (int)i; break; } //If not looped remove else { mvGameMusic[i].msFile = ""; } } } } //-----------------------------------------------------------------------