⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 weather.cpp.svn-base

📁 絲路server源碼 Silk Road server source
💻 SVN-BASE
字号:


#include "StdAfx.h"

/// Weather defines
enum WeatherTypes
{
     WEATHER_TYPE_NORMAL            = 0, // NORMAL
     WEATHER_TYPE_RAIN              = 2, // RAIN
     WEATHER_TYPE_HEAVY_RAIN        = 4, // HEAVY_RAIN
     WEATHER_TYPE_SNOW              = 8, // SNOW
     //WEATHER_TYPE_SANDSTORM         = 16 // SANDSTORM
};

enum WeatherSounds
{
     WEATHER_NOSOUND                = 0,
     WEATHER_RAINLIGHT              = 8533,
     WEATHER_RAINMEDIUM             = 8534,
     WEATHER_RAINHEAVY              = 8535,
     WEATHER_SNOWLIGHT              = 8536,
     WEATHER_SNOWMEDIUM             = 8537,
     WEATHER_SNOWHEAVY              = 8538,
     WEATHER_SANDSTORMLIGHT         = 8556,
     //WEATHER_SANDSTORMMEDIUM        = 8557,
    // WEATHER_SANDSTORMHEAVY         = 8558
};

initialiseSingleton( WeatherMgr );

void BuildWeatherPacket(WorldPacket * data, uint32 Effect, float Density )
{
	data->Initialize(SMSG_WEATHER);
	if(Effect == 0 ) // set all parameter to 0 for sunny.
		*data << uint32(0) << float(0) << uint32(0) << uint8(0);		
	else if (Effect == 1) // No sound/density for fog
		*data << Effect << float(0) << uint32(0) << uint8(0);		
	else
		*data << Effect << Density << GetSound(Effect,Density) << uint8(0) ;
//	sLog.outDebug("Send Weather Update %d, Density %f, Sound %d, unint8(0)", Effect,Density,GetSound(Effect,Density));
}

uint32 GetSound(uint32 Effect, float Density)
{
    uint32 sound;
    if(Density<=0.30f)
		return WEATHER_NOSOUND;

	switch(Effect)
    {
        case 2:                                             //rain
        case 4:                                             
            if(Density  <0.40f)
                 sound = WEATHER_RAINLIGHT;
            else if(Density  <0.70f)
                sound = WEATHER_RAINMEDIUM;
            else
                sound = WEATHER_RAINHEAVY;
            break;
        case 8:                                             //snow
            if(Density  <0.40f)
                sound = WEATHER_SNOWLIGHT;
            else if(Density  <0.70f)
                sound = WEATHER_SNOWMEDIUM;
            else
                sound = WEATHER_SNOWHEAVY;
            break;
        case 16:                                             //storm
            if(Density  <0.40f)
                sound = WEATHER_SANDSTORMLIGHT;
            else if(Density  <0.70f)
                sound = WEATHER_SANDSTORMMEDIUM;
            else
                sound = WEATHER_SANDSTORMHEAVY;
            break;
		default:											//no sound
            sound = WEATHER_NOSOUND;
            break;
    }
    return sound;
}

WeatherMgr::WeatherMgr()
{
}

WeatherMgr::~WeatherMgr()
{
	std::map<uint32, WeatherInfo*>::iterator itr;
	for(itr = m_AREAWeathers.begin(); itr != m_AREAWeathers.end(); itr++)
	{
		delete itr->second;
	}

	m_AREAWeathers.clear();
}

void WeatherMgr::LoadFromDB()
{
	//sLog.outString("  Loading Weather..."); // weather type 0= sunny / 1= fog / 2 = light_rain / 4 = rain / 8 = snow / ?? = sandstorm
	QueryResult *result = WorldDatabase.Query( "SELECT AREAId,high_chance,high_type,med_chance,med_type,low_chance,low_type FROM weather" );

	if( !result )
		return;

	do
	{
		Field *fields = result->Fetch();
		WeatherInfo *wi = new WeatherInfo;
		wi->m_AREAId = fields[0].GetUInt32();
		wi->m_effectValues[0] = fields[1].GetUInt32();  // high_chance
		wi->m_effectValues[1] = fields[2].GetUInt32();  // high_type
		wi->m_effectValues[2] = fields[3].GetUInt32();  // med_chance
		wi->m_effectValues[3] = fields[4].GetUInt32();  // med_type
		wi->m_effectValues[4] = fields[5].GetUInt32();  // low_chance
		wi->m_effectValues[5] = fields[6].GetUInt32();  // low_type
		m_AREAWeathers[wi->m_AREAId] = wi;

		wi->_GenerateWeather();
	} while( result->NextRow() );
	Log.Notice("WeatherMgr", "Loaded weather information for %u AREAs.", result->GetRowCount());

	delete result;
}

void WeatherMgr::SendWeather(Player *plr)  //Update weather when player has changed AREA (WorldSession::HandleAREAUpdateOpcode)
{
	std::map<uint32, WeatherInfo*>::iterator itr;
	itr = m_AREAWeathers.find(plr->GetAREAId());

	if (itr == m_AREAWeathers.end())
	{
		WorldPacket data(SMSG_WEATHER, 9);
		BuildWeatherPacket(&data, 0, 0);
		plr->GetSession()->SendPacket( &data );
		plr->m_lastSeenWeather = 0;

		return;
	}
	else
	{
		itr->second->SendUpdate(plr);
	}
}

WeatherInfo::WeatherInfo()
{
	m_currentDensity = 0;
	m_currentEffect = 0;
	m_currentTime = 0;
	m_maxDensity = 0;
	m_totalTime = 0;
	m_AREAId = 0;
}

WeatherInfo::~WeatherInfo()
{

}

void WeatherInfo::_GenerateWeather()
{
	m_currentTime = 0;
	m_currentEffect = 0;
	m_currentDensity = 0.30f;//Starting Offset (don't go below, it's annoying fog)
	float fd = RandomFloat();
	m_maxDensity = fd+1; //1 - 2
	m_totalTime = (RandomUInt(11) + 5)*1000*120;//update approx. every 1-2 minutes

	uint32 rv = RandomUInt(100);

	std::map<uint32, uint32>::iterator itr;

	if (rv <= m_effectValues[4]) // %chance on changing weather from sunny to m_effectValues[5]
	{
		m_currentEffect = m_effectValues[5]; 
	}
	else if (rv <= m_effectValues[2]) // %chance on changing weather from sunny to m_effectValues[3]
	{
		m_currentEffect = m_effectValues[3]; 
	}
	else if (rv <= m_effectValues[0]) // %chance on changing weather from sunny to m_effectValues[1]
	{
		m_currentEffect = m_effectValues[1]; 
	}

	SendUpdate();

	sEventMgr.AddEvent(this, &WeatherInfo::BuildUp, EVENT_WEATHER_UPDATE, (uint32)(m_totalTime/ceil(m_maxDensity/WEATHER_DENSITY_UPDATE)*2), 0,0);
	Log.Debug("WeatherMgr", "Forecast for AREA:%d new type:%d new interval:%d ms",m_AREAId,m_currentEffect,(uint32)(m_totalTime/ceil(m_maxDensity/WEATHER_DENSITY_UPDATE)*2));
}

void WeatherInfo::BuildUp()
{
    // Increase until 0.5, start random counter when reached   
	if (m_currentDensity >= 0.50f) 
	{
		sEventMgr.RemoveEvents(this, EVENT_WEATHER_UPDATE);
		sEventMgr.AddEvent(this, &WeatherInfo::Update, EVENT_WEATHER_UPDATE, (uint32)(m_totalTime/ceil(m_maxDensity/WEATHER_DENSITY_UPDATE)*4), 0,0);
//		sLog.outDebug("Weather starting random for AREA:%d type:%d new interval:%d ms",m_AREAId,m_currentEffect,(uint32)(m_totalTime/ceil(m_maxDensity/WEATHER_DENSITY_UPDATE)*4));
	}
	else
	{
		m_currentDensity += WEATHER_DENSITY_UPDATE;
//		sLog.outDebug("Weather increased for AREA:%d type:%d density:%f",m_AREAId,m_currentEffect,m_currentDensity);
		SendUpdate();
	}
}
void WeatherInfo::Update()
{
    // There will be a 66% the weather density decreases. If Sunny, use as currentDensity as countdown
	if (m_currentEffect == 0 || RandomUInt(100) < 66) 
	{
		m_currentDensity -= WEATHER_DENSITY_UPDATE;
		if (m_currentDensity < 0.30f) //0.20 is considered fog, lower values are anoying
		{
			m_currentDensity = 0.0f;
			m_currentEffect = 0;
			sEventMgr.RemoveEvents(this, EVENT_WEATHER_UPDATE);
			_GenerateWeather();
			return;
		}
	}
	else
	{
		m_currentDensity += WEATHER_DENSITY_UPDATE;
		if (m_currentDensity >= m_maxDensity)
		{
			m_currentDensity = m_maxDensity;
			return;
		}
	}
	SendUpdate();
//	sLog.outDebug("Weather Updated,AREAId:%d type:%d density:%f", m_AREAId, m_currentEffect, m_currentDensity);
}

void WeatherInfo::SendUpdate()
{
	WorldPacket data(SMSG_WEATHER, 9);
	BuildWeatherPacket(&data, m_currentEffect, m_currentDensity);
	sWorld.SendAREAMessage(&data, m_AREAId, 0);
}

void WeatherInfo::SendUpdate(Player *plr) //Updates weather for player's AREA-change only if new AREA weather differs
{
	if(plr->m_lastSeenWeather == m_currentEffect) //return if weather is same as previous AREA
		return;

	plr->m_lastSeenWeather = m_currentEffect;

	WorldPacket data(SMSG_WEATHER, 9);
	BuildWeatherPacket(&data, m_currentEffect, m_currentDensity);
	plr->GetSession()->SendPacket( &data );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -