#include "stdafx.h" #include "SGameEnvironmentService.h" #include "GameDefine.h" #include "WorldLocation.h" #include "SWorldLocationDB.h" #include "SEnvPrimitive.h" #include "SGameWeather.h" #include "SGameSky.h" #include "SGameLens.h" #include "SGameWeatherService.h" #include "SGameMilesSoundMgr.h" #include "SSoundResourceDB.h" using namespace env_fx; bool IEnvironmentState::IsValid( const SLerpArgument& arg ) const { if( m_tmBegin < m_tmEnd ) return ( m_tmBegin <= arg.tmTime && m_tmEnd > arg.tmTime ); else return ( m_tmBegin <= arg.tmTime || m_tmEnd > arg.tmTime ); } void IEnvironmentState::PrepareLerp( SLerpArgument& arg ) { arg.calcMinites = arg.tmTime.GetDiffMinitesFrom( m_tmBegin ); if( (int)arg.calcMinites < m_nLerpDuration_min_ ) { arg.lerpAction = SLerpArgument::LERP_PREV; arg.lerpTime = (float)arg.calcMinites / (float)m_nLerpDuration_min_; } else if( (int)arg.calcMinites > m_nActiveDuration_min_ - m_nLerpDuration_min_ ) { arg.lerpAction = SLerpArgument::LERP_NEXT; arg.lerpTime = 1.f - (float)( m_nActiveDuration_min_ - (int)arg.calcMinites ) / (float)m_nLerpDuration_min_; } else { arg.lerpAction = SLerpArgument::LERP_NONE; } } // sonador 1.1.17 던전 진입시 환경값 설정 오류 수정 const WorldLocationBase* IEnvironmentState::GetLocationDB( SLerpArgument& arg ) { int nTimeID = GetStateType(); const WorldLocationBase* data = GetWorldLocationDB().GetWLData( arg.localID, nTimeID, arg.weatherID ); if( !data ) data = GetWorldLocationDB().GetWLData( arg.localID, nTimeID, 0 ); return data; } void SEnvironmentDawn::OnEnter( SLerpArgument& arg ) { } void SEnvironmentDawn::OnLeave( SLerpArgument& arg ) { } void SEnvironmentDawn::OnPerform( SLerpArgument& arg ) { if( arg.isIndoor || arg.weatherID != 0 ) { arg.context->sky->SetVisibilitySun( true, 0.f, arg.time ); arg.context->sky->SetVisibilityMoon( true, 0.f, arg.time ); } else { arg.context->sky->SetVisibilitySun( true, 1.f, arg.time ); arg.context->sky->SetVisibilityMoon( true, 0.f, arg.time ); } arg.context->lensFlare->SetRenderFlag( FALSE ); } void SEnvironmentDaylight::OnEnter( SLerpArgument& arg ) { } void SEnvironmentDaylight::OnLeave( SLerpArgument& arg ) { } void SEnvironmentDaylight::OnPerform( SLerpArgument& arg ) { if( arg.isIndoor || arg.weatherID != 0 ) { arg.context->sky->SetVisibilitySun( true, 0.f, arg.time ); arg.context->sky->SetVisibilityMoon( true, 0.f, arg.time ); arg.context->lensFlare->SetRenderFlag( FALSE ); } else { arg.context->sky->SetVisibilitySun( true, 1.f, arg.time ); arg.context->sky->SetVisibilityMoon( true, 0.f, arg.time ); arg.context->lensFlare->SetRenderFlag( TRUE ); } } void SEnvironmentEvening::OnEnter( SLerpArgument& arg ) { } void SEnvironmentEvening::OnLeave( SLerpArgument& arg ) { } void SEnvironmentEvening::OnPerform( SLerpArgument& arg ) { if( arg.isIndoor || arg.weatherID != 0 ) { arg.context->sky->SetVisibilitySun( true, 0.f, arg.time ); arg.context->sky->SetVisibilityMoon( true, 0.f, arg.time ); } else { arg.context->sky->SetVisibilitySun( true, 0.f, arg.time ); arg.context->sky->SetVisibilityMoon( true, 1.f, arg.time ); } arg.context->lensFlare->SetRenderFlag( FALSE ); } void SEnvironmentNight::OnEnter( SLerpArgument& arg ) { } void SEnvironmentNight::OnLeave( SLerpArgument& arg ) { } void SEnvironmentNight::OnPerform( SLerpArgument& arg ) { if( arg.isIndoor || arg.weatherID != 0 ) { arg.context->sky->SetVisibilitySun( true, 0.f, arg.time ); arg.context->sky->SetVisibilityMoon( true, 0.f, arg.time ); } else { arg.context->sky->SetVisibilitySun( true, 0.f, arg.time ); arg.context->sky->SetVisibilityMoon( true, 1.f, arg.time ); } arg.context->lensFlare->SetRenderFlag( FALSE ); } SEnvironmentService::SEnvironmentService ( SGameSky* pSky , SGameLensFlare* pLensFlare , SGameWeatherService* pWeather , SGameMilesSoundMgr* pSoundMgr ) : m_pCurrentState ( 0 ) , m_pPreviousState ( 0 ) , m_pContext ( 0 ) , m_pSoundMgr ( pSoundMgr ) { tm begin, end; ::memset( (void*)&begin, 0, sizeof( tm ) ); ::memset( (void*)&end, 0, sizeof( tm ) ); begin.tm_hour = 5; begin.tm_min = 0; end.tm_hour = 8; end.tm_min = 0; m_ctEnvironmentStates.push_back( new SEnvironmentDawn( begin, end, 30 ) ); begin.tm_hour = 8; begin.tm_min = 0; end.tm_hour = 17; end.tm_min = 0; m_ctEnvironmentStates.push_back( new SEnvironmentDaylight( begin, end, 0 ) ); begin.tm_hour = 17; begin.tm_min = 0; end.tm_hour = 20; end.tm_min = 0; m_ctEnvironmentStates.push_back( new SEnvironmentEvening( begin, end, 30 ) ); begin.tm_hour = 20; begin.tm_min = 0; end.tm_hour = 5; end.tm_min = 0; m_ctEnvironmentStates.push_back( new SEnvironmentNight( begin, end, 0 ) ); m_pContext = new SEnvironmentContext(); m_pContext->sky = pSky; m_pContext->lensFlare = pLensFlare; m_pContext->weatherService = pWeather; } SEnvironmentService::~SEnvironmentService() { env_fx::util::wipe_seq( m_ctEnvironmentStates ); SAFE_DELETE( m_pContext ); } void SEnvironmentService::Perform( SLerpArgument& arg ) { // complete lerp argument _prepareLerpArgument( arg ); // change state IEnvironmentState* pState = 0; pState = _switchState( arg ); assert( pState && "there is wrong values in world time states" ); // enter & leave action bool stateChanged = false; if( m_pCurrentState != pState ) { if( m_pCurrentState ) { m_pCurrentState->OnLeave( arg ); m_pPreviousState = m_pCurrentState; } m_pCurrentState = pState; if( m_pCurrentState ) m_pCurrentState->OnEnter( arg ); stateChanged = true; } // proceed current state if( m_pCurrentState ) { // perform current state m_pCurrentState->OnPerform( arg ); // proceed lerp action m_pCurrentState->PrepareLerp( arg ); arg.timeState = m_pCurrentState->GetStateType(); if( arg.lerpAction == SLerpArgument::LERP_NONE ) { arg.locData = m_pCurrentState->GetLocationDB( arg ); arg.locLerpData = m_pCurrentState->GetLocationDB( arg ); } else if( arg.lerpAction == SLerpArgument::LERP_PREV ) { if( m_pPreviousState == 0 ) // sonador 1.1.20 환경값 보간 오류 수정 m_pPreviousState = _getPrevState( m_pCurrentState->GetStateType() ); arg.locData = m_pPreviousState->GetLocationDB( arg ); arg.locLerpData = m_pCurrentState->GetLocationDB( arg ); } else if( arg.lerpAction == SLerpArgument::LERP_NEXT ) { IEnvironmentState* pNext = _getNextState( m_pCurrentState->GetStateType() ); arg.locData = m_pCurrentState->GetLocationDB( arg ); arg.locLerpData = pNext->GetLocationDB( arg ); } } // change weather if( arg.context->weatherService ) { arg.context->weatherService->ChangeInOut( arg.isIndoor ); if( arg.weatherID != arg.context->weatherService->GetState() || stateChanged ) { int prevWeatherState = arg.context->weatherService->GetState(); float precipitation = 0.0f; if( arg.locLerpData ) precipitation = env_fx::util::GetRandomNumberInRange( arg.locLerpData->precipitation_min, arg.locLerpData->precipitation_max ) * 0.01f; arg.context->weatherService->ChangeState( arg.weatherID, precipitation, arg.weatherOptionFactor, true ); if( prevWeatherState != IGameWeatherState::WS_NONE ) arg.weatherChanged = true; } } // change env sound if( arg.locLerpData == 0 || m_pSoundMgr == 0 ) return; static DWORD m_dwEnvFxSoundTime = arg.time; static DWORD m_dwEnvFxSoundDelayTime = 20000; static int m_nPrevEnvFxSoundIndex = 0; static int m_nMusicFadeInTime = 10000; static int m_nMusicFadeOutTime = 10000; static std::string m_strCurEnvFxSoundName = ""; if( stateChanged || arg.weatherChanged ) { int nSoundIndex = rand() % 3; std::string soundFileName = GetResourceDB().GetSoundResourceName( arg.locLerpData->environmental_sound_ID[nSoundIndex] ); if( soundFileName != m_strCurEnvFxSoundName ) { m_strCurEnvFxSoundName = soundFileName; m_nPrevEnvFxSoundIndex = nSoundIndex; m_pSoundMgr->SwapPlayMusic( m_strCurEnvFxSoundName.c_str(), m_nMusicFadeInTime, m_nMusicFadeOutTime, m_pSoundMgr->GetEnvVolume(), true ); } } else if( m_dwEnvFxSoundTime != 0 && (arg.time - m_dwEnvFxSoundTime) > m_dwEnvFxSoundDelayTime ) { int nSoundIndex = rand() % 3; while( nSoundIndex == m_nPrevEnvFxSoundIndex ) { nSoundIndex = rand() % 3; } int nRand = rand() % 100; if(nRand > arg.locLerpData->environmental_sound_ratio[nSoundIndex] ) { std::string soundFileName = GetResourceDB().GetSoundResourceName( arg.locLerpData->environmental_sound_ID[nSoundIndex] ); if( soundFileName != m_strCurEnvFxSoundName ) { m_strCurEnvFxSoundName = soundFileName; m_nPrevEnvFxSoundIndex = nSoundIndex; m_pSoundMgr->SwapPlayMusic( m_strCurEnvFxSoundName.c_str(), m_nMusicFadeInTime, m_nMusicFadeOutTime, m_pSoundMgr->GetEnvVolume(), true ); } } m_dwEnvFxSoundTime = arg.time; } } void SEnvironmentService::_prepareLerpArgument( SLerpArgument& arg ) { arg.context = m_pContext; } IEnvironmentState* SEnvironmentService::_switchState( const SLerpArgument& arg ) { IEnvironmentState* pResult = 0; size_t state_size = m_ctEnvironmentStates.size(); for( size_t n = 0; n < state_size; ++n ) { IEnvironmentState* pState = m_ctEnvironmentStates[ n ]; if( pState->IsValid( arg ) ) { pResult = pState; break; } } return pResult; } IEnvironmentState* SEnvironmentService::_getNextState( int nCurrentState ) { IEnvironmentState* pResult = 0; size_t state_size = m_ctEnvironmentStates.size(); size_t nNext = (size_t)nCurrentState + 1; if( nNext >= state_size ) nNext = 0; pResult = m_ctEnvironmentStates[ nNext ]; return pResult; } IEnvironmentState* SEnvironmentService::_getPrevState( int nCurrentState ) // sonador 1.1.20 환경값 보간 오류 수정 { IEnvironmentState* pResult = 0; size_t nPrev = 0; if( (size_t)nCurrentState <= 0 ) nPrev = m_ctEnvironmentStates.size() - 1; else nPrev = (size_t)nCurrentState - 1; pResult = m_ctEnvironmentStates[ nPrev ]; return pResult; }