Files
Leviathan/Client/Game/game/Env/SGameEnvironmentService.cpp
2026-06-01 12:46:52 +02:00

356 lines
9.8 KiB
C++

#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;
}