Files
Leviathan/Server/GameServer/Game/world/StructWorldLocation.cpp
T
2026-06-01 12:46:52 +02:00

327 lines
7.4 KiB
C++

#include <ctime>
#include <toolkit/ILock.h>
#include <toolkit/XRandom.h>
#include <mmo/ArcadiaServer.h>
#include <toolkit/XEnv.h>
#include "StructWorldLocation.h"
#include "StructPlayer.h"
#include "GameMessage.h"
#include "SendMessage.h"
static XCriticalSection s_LocationCS;
unsigned int GetCurrentTimeIdx()
{
time_t t = time( NULL );
struct tm local_tm;
localtime_s( &local_tm, &t );
if( local_tm.tm_hour >= 12 )
local_tm.tm_hour -= 12;
if( local_tm.tm_hour >= 4 && ( local_tm.tm_hour < 8 || ( local_tm.tm_hour == 8 && local_tm.tm_min < 30 ) ) )
{
return StructWorldLocation::TIME_DAYTIME;
}
if( local_tm.tm_hour < 4 && ( local_tm.tm_hour > 2 || ( local_tm.tm_hour == 2 && local_tm.tm_min >= 30 ) ) )
{
return StructWorldLocation::TIME_DAWN;
}
if( local_tm.tm_hour < 10 && ( local_tm.tm_hour > 8 || ( local_tm.tm_hour == 8 && local_tm.tm_min >= 30 ) ) )
{
return StructWorldLocation::TIME_EVENING;
}
return StructWorldLocation::TIME_NIGHT;
}
WorldLocationManager::WorldLocationManager()
{
}
WorldLocationManager::~WorldLocationManager()
{
}
bool WorldLocationManager::Init()
{
ArcadiaServer::Instance().SetObjectPriority( this, ArSchedulerObject::UPDATE_PRIORITY_LOW );
return true;
}
bool WorldLocationManager::DeInit()
{
ArcadiaServer::Instance().SetObjectPriority( this, ArSchedulerObject::UPDATE_PRIORITY_IDLE );
return true;
}
WorldLocationManager & WorldLocationManager::Instance()
{
static WorldLocationManager _inst;
return _inst;
}
void WorldLocationManager::onProcess( int nThreadIdx )
{
char buf[255];
s_sprintf( buf, _countof( buf ), "thread.scheduler.%d.proc", nThreadIdx );
ENV().Set( buf, "WorldLocationManager" );
AR_TIME t = GetArTime();
extern __declspec( thread ) XSEH::THREAD_INFO s_ThreadInfo;
s_sprintf( s_ThreadInfo.job_info, _countof( s_ThreadInfo.job_info ), "WorldLocationManager(0x%08X)", (UINT_PTR)this );
s_ThreadInfo.last_execute_time = t;
unsigned time_idx = GetCurrentTimeIdx();
THREAD_SYNCRONIZE( &s_LocationCS );
std::vector< StructWorldLocation >::iterator it;
for( it = m_vWorldLocation.begin(); it != m_vWorldLocation.end(); ++it )
{
if( !(*it).last_changed_time || (*it).last_changed_time + (*it).weather_change_time < t )
{
(*it).last_changed_time = t;
unsigned current_weather = (*it).current_weather;
unsigned char ratio = XRandom( 0, 99 );
for( unsigned i = 0; i < StructWorldLocation::WEATHER_MAX; ++i )
{
if( ratio < (*it).weather_ratio[time_idx][i] )
{
(*it).current_weather = i;
if( (*it).current_weather != current_weather )
{
// broadcasting
std::vector< StructPlayer * >::iterator itPlayer;
TS_SC_WEATHER_INFO msg;
msg.region_id = (*it).idx;
msg.weather_id = (*it).current_weather;
for( itPlayer = (*it).m_vIncludeClient.begin(); itPlayer != (*it).m_vIncludeClient.end(); ++itPlayer )
{
PendMessage( (*itPlayer), &msg );
}
}
break;
}
ratio -= (*it).weather_ratio[time_idx][i];
}
}
}
}
const StructWorldLocation * WorldLocationManager::AddToLocation( unsigned int idx, struct StructPlayer * pPlayer )
{
if( pPlayer->GetLocationId() )
{
RemoveFromLocation( pPlayer );
}
std::vector< StructWorldLocation >::iterator it;
THREAD_SYNCRONIZE( &s_LocationCS );
for( it = m_vWorldLocation.begin(); it != m_vWorldLocation.end(); ++it )
{
if( (*it).idx == idx )
{
(*it).m_vIncludeClient.push_back( pPlayer );
TS_SC_WEATHER_INFO msg;
msg.region_id = idx;
msg.weather_id = (*it).current_weather;
PendMessage( pPlayer, &msg );
return &(*it);
}
}
return NULL;
}
bool WorldLocationManager::RemoveFromLocation( struct StructPlayer * pPlayer )
{
std::vector< StructWorldLocation >::iterator it;
THREAD_SYNCRONIZE( &s_LocationCS );
for( it = m_vWorldLocation.begin(); it != m_vWorldLocation.end(); ++it )
{
if( (*it).idx == pPlayer->GetLocationId() )
{
std::vector< struct StructPlayer * >::iterator itPlayer;
for( itPlayer = (*it).m_vIncludeClient.begin(); itPlayer != (*it).m_vIncludeClient.end(); ++itPlayer )
{
if( (*itPlayer) == pPlayer )
{
(*it).m_vIncludeClient.erase( itPlayer );
break;
}
}
return true;
}
}
return false;
}
bool WorldLocationManager::SendWeatherInfo( unsigned int idx, struct StructPlayer * pPlayer )
{
std::vector< StructWorldLocation >::iterator it;
THREAD_SYNCRONIZE( &s_LocationCS );
for( it = m_vWorldLocation.begin(); it != m_vWorldLocation.end(); ++it )
{
if( (*it).idx == idx )
{
TS_SC_WEATHER_INFO msg;
msg.region_id = idx;
msg.weather_id = (*it).current_weather;
PendMessage( pPlayer, &msg );
return true;
}
}
return false;
}
const unsigned char WorldLocationManager::GetLocationType( const unsigned int idx )
{
std::vector< StructWorldLocation >::iterator it;
THREAD_SYNCRONIZE( &s_LocationCS );
for( it = m_vWorldLocation.begin(); it != m_vWorldLocation.end(); ++it )
{
if( (*it).idx == idx )
return (*it).location_type;
}
return StructWorldLocation::LOCATION_ETC;
}
const ItemBase::ItemCode WorldLocationManager::GetShovelableItem( const unsigned int idx )
{
ItemBase::ItemCode nCode = 0;
THREAD_SYNCRONIZE( &s_LocationCS );
for( std::vector< StructWorldLocation >::iterator it = m_vWorldLocation.begin(); it != m_vWorldLocation.end(); ++it )
{
if( (*it).idx == idx )
{
nCode = (*it).shovelable_item;
break;
}
}
return nCode;
}
const int WorldLocationManager::GetShovelableMonster( const unsigned int idx )
{
std::vector< int > * pvMonsterID = NULL;
if( !m_hsMonsterID.lookup( idx, pvMonsterID ) )
return 0;
int nCode = 0;
int nCount = 0;
do
{
nCode = (*pvMonsterID)[ XRandom( 0, static_cast< int >( pvMonsterID->size() ) - 1 ) ];
// 몬스터 등급 체계 변경에 따른 수정, 삽질은 현재 사용하지 않는 시스템이지만 추후 문제가 생긴다면 변경 필요
MonsterBase *pMonsterBase = GameContent::GetMonsterInfo( nCode );
if( pMonsterBase->fight_type != MonsterBase::FIGHT_TYPE_NORMAL ||
pMonsterBase->monster_type != MonsterBase::MONSTER_TYPE_MIDDLE_1_STAR )
{
nCode = 0;
}
} while( !nCode && ++nCount < 5 );
return nCode;
}
void WorldLocationManager::RegisterWorldLocation( unsigned int idx, unsigned char location_type, unsigned int time_id, unsigned int weather_id, unsigned char ratio, AR_TIME weather_change_time, const int shovelable_item )
{
std::vector< StructWorldLocation >::iterator it;
StructWorldLocation * pLocation = NULL;
for( it = m_vWorldLocation.begin(); it != m_vWorldLocation.end(); ++it )
{
if( (*it).idx == idx )
{
pLocation = &(*it);
break;
}
}
if( pLocation == NULL )
{
m_vWorldLocation.push_back( StructWorldLocation() );
pLocation = &m_vWorldLocation.back();
pLocation->idx = idx;
pLocation->location_type = location_type;
pLocation->weather_change_time = weather_change_time;
}
pLocation->weather_ratio[time_id][weather_id] = ratio;
pLocation->shovelable_item = shovelable_item;
}
void WorldLocationManager::RegisterMonsterLocation( const unsigned int idx, unsigned int monster_id )
{
std::vector< int > * pvMonsterID = NULL;
if( !m_hsMonsterID.lookup( idx, pvMonsterID ) )
{
pvMonsterID = new std::vector< int >;
m_hsMonsterID.add( idx, pvMonsterID );
}
for( std::vector< int >::iterator it = pvMonsterID->begin() ; it != pvMonsterID->end() ; ++it )
{
if( (*it) == monster_id )
{
return;
}
}
pvMonsterID->push_back( monster_id );
}