diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 37dc2bba096..33d875a2ad1 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7529,14 +7529,9 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) if (!zone) return; - if (sWorld->getBoolConfig(CONFIG_WEATHER) && !HasAuraType(SPELL_AURA_FORCE_WEATHER)) - { - if (Weather* weather = WeatherMgr::FindWeather(zone->ID)) - weather->SendWeatherUpdateToPlayer(this); - else if (!WeatherMgr::AddWeather(zone->ID)) - // send fine weather packet to remove old zone's weather - WeatherMgr::SendFineWeatherUpdateToPlayer(this); - } + if (sWorld->getBoolConfig(CONFIG_WEATHER)) + GetMap()->GetOrGenerateZoneDefaultWeather(newZone); + GetMap()->SendZoneDynamicInfo(newZone, this); sScriptMgr->OnPlayerUpdateZone(this, newZone, newArea); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 51a8de322fc..98b76e96061 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -35,6 +35,8 @@ #include "Transport.h" #include "Vehicle.h" #include "VMapFactory.h" +#include "Weather.h" +#include "WeatherMgr.h" u_map_magic MapMagic = { {'M','A','P','S'} }; u_map_magic MapVersionMagic = { {'v','1','.','6'} }; @@ -48,6 +50,9 @@ u_map_magic MapLiquidMagic = { {'M','L','I','Q'} }; GridState* si_GridStates[MAX_GRID_STATE]; +ZoneDynamicInfo::ZoneDynamicInfo() : MusicId(0), DefaultWeather(nullptr), WeatherId(WEATHER_STATE_FINE), + WeatherGrade(0.0f), OverrideLightId(0), LightFadeInTime(0) { } + Map::~Map() { // UnloadAll must be called before deleting the map @@ -254,6 +259,8 @@ i_scriptLock(false), _defaultLight(GetDefaultMapLight(id)) //lets initialize visibility distance for map Map::InitVisibilityDistance(); + _weatherUpdateTimer.SetInterval(time_t(1 * IN_MILLISECONDS)); + sScriptMgr->OnCreateMap(this); } @@ -532,7 +539,6 @@ bool Map::AddPlayerToMap(Player* player) SendInitSelf(player); SendInitTransports(player); - SendZoneDynamicInfo(player); player->m_clientGUIDs.clear(); player->UpdateObjectVisibility(false); @@ -774,6 +780,15 @@ void Map::Update(const uint32 t_diff) i_scriptLock = false; } + if (_weatherUpdateTimer.Passed()) + { + for (auto&& zoneInfo : _zoneDynamicInfo) + if (zoneInfo.second.DefaultWeather && !zoneInfo.second.DefaultWeather->Update(_weatherUpdateTimer.GetInterval())) + zoneInfo.second.DefaultWeather.reset(); + + _weatherUpdateTimer.Reset(); + } + MoveAllCreaturesInMoveList(); MoveAllGameObjectsInMoveList(); @@ -3901,10 +3916,9 @@ void Map::RemoveOldCorpses() } } -void Map::SendZoneDynamicInfo(Player* player) +void Map::SendZoneDynamicInfo(uint32 zoneId, Player* player) const { - uint32 zoneId = GetZoneId(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); - ZoneDynamicInfoMap::const_iterator itr = _zoneDynamicInfo.find(zoneId); + auto itr = _zoneDynamicInfo.find(zoneId); if (itr == _zoneDynamicInfo.end()) return; @@ -3916,14 +3930,7 @@ void Map::SendZoneDynamicInfo(Player* player) player->SendDirectMessage(&data); } - if (uint32 weather = itr->second.WeatherId) - { - WorldPacket data(SMSG_WEATHER, 4 + 4 + 1); - data << uint32(weather); - data << float(itr->second.WeatherGrade); - data << uint8(0); - player->SendDirectMessage(&data); - } + SendZoneWeather(itr->second, player); if (uint32 overrideLight = itr->second.OverrideLightId) { @@ -3935,11 +3942,38 @@ void Map::SendZoneDynamicInfo(Player* player) } } +void Map::SendZoneWeather(uint32 zoneId, Player* player) const +{ + if (!player->HasAuraType(SPELL_AURA_FORCE_WEATHER)) + { + auto itr = _zoneDynamicInfo.find(zoneId); + if (itr == _zoneDynamicInfo.end()) + return; + + SendZoneWeather(itr->second, player); + } +} + +void Map::SendZoneWeather(ZoneDynamicInfo const& zoneDynamicInfo, Player* player) const +{ + if (WeatherState weatherId = zoneDynamicInfo.WeatherId) + { + WorldPacket data(SMSG_WEATHER, 4 + 4 + 1); + data << uint32(weatherId); + data << float(zoneDynamicInfo.WeatherGrade); + data << uint8(0); + player->SendDirectMessage(&data); + } + else if (zoneDynamicInfo.DefaultWeather) + { + zoneDynamicInfo.DefaultWeather->SendWeatherUpdateToPlayer(player); + } + else + Weather::SendFineWeatherUpdateToPlayer(player); +} + void Map::SetZoneMusic(uint32 zoneId, uint32 musicId) { - if (_zoneDynamicInfo.find(zoneId) == _zoneDynamicInfo.end()) - _zoneDynamicInfo.insert(ZoneDynamicInfoMap::value_type(zoneId, ZoneDynamicInfo())); - _zoneDynamicInfo[zoneId].MusicId = musicId; Map::PlayerList const& players = GetPlayers(); @@ -3947,7 +3981,7 @@ void Map::SetZoneMusic(uint32 zoneId, uint32 musicId) { for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) if (Player* player = itr->GetSource()) - if (player->GetZoneId() == zoneId) + if (player->GetZoneId() == zoneId && !player->HasAuraType(SPELL_AURA_FORCE_WEATHER)) { WorldPacket data(SMSG_PLAY_MUSIC, 4); data << uint32(musicId); @@ -3957,11 +3991,25 @@ void Map::SetZoneMusic(uint32 zoneId, uint32 musicId) } } -void Map::SetZoneWeather(uint32 zoneId, uint32 weatherId, float weatherGrade) +Weather* Map::GetOrGenerateZoneDefaultWeather(uint32 zoneId) { - if (_zoneDynamicInfo.find(zoneId) == _zoneDynamicInfo.end()) - _zoneDynamicInfo.insert(ZoneDynamicInfoMap::value_type(zoneId, ZoneDynamicInfo())); + WeatherData const* weatherData = WeatherMgr::GetWeatherData(zoneId); + if (!weatherData) + return nullptr; + ZoneDynamicInfo& info = _zoneDynamicInfo[zoneId]; + if (!info.DefaultWeather) + { + info.DefaultWeather = Trinity::make_unique(zoneId, weatherData); + info.DefaultWeather->ReGenerate(); + info.DefaultWeather->UpdateWeather(); + } + + return info.DefaultWeather.get(); +} + +void Map::SetZoneWeather(uint32 zoneId, WeatherState weatherId, float weatherGrade) +{ ZoneDynamicInfo& info = _zoneDynamicInfo[zoneId]; info.WeatherId = weatherId; info.WeatherGrade = weatherGrade; @@ -3983,9 +4031,6 @@ void Map::SetZoneWeather(uint32 zoneId, uint32 weatherId, float weatherGrade) void Map::SetZoneOverrideLight(uint32 zoneId, uint32 lightId, uint32 fadeInTime) { - if (_zoneDynamicInfo.find(zoneId) == _zoneDynamicInfo.end()) - _zoneDynamicInfo.insert(ZoneDynamicInfoMap::value_type(zoneId, ZoneDynamicInfo())); - ZoneDynamicInfo& info = _zoneDynamicInfo[zoneId]; info.OverrideLightId = lightId; info.LightFadeInTime = fadeInTime; diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index d42cb18a6ee..934ce7c2503 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -31,6 +31,7 @@ #include "DynamicTree.h" #include "GameObjectModel.h" #include "ObjectGuid.h" +#include "Weather.h" #include #include @@ -42,6 +43,7 @@ class InstanceScript; class Group; class InstanceSave; class Object; +class Weather; class WorldObject; class TempSummon; class Player; @@ -257,11 +259,11 @@ enum LevelRequirementVsMode struct ZoneDynamicInfo { - ZoneDynamicInfo() : MusicId(0), WeatherId(0), WeatherGrade(0.0f), - OverrideLightId(0), LightFadeInTime(0) { } + ZoneDynamicInfo(); uint32 MusicId; - uint32 WeatherId; + std::unique_ptr DefaultWeather; + WeatherState WeatherId; float WeatherGrade; uint32 OverrideLightId; uint32 LightFadeInTime; @@ -569,10 +571,14 @@ class TC_GAME_API Map : public GridRefManager void SendInitTransports(Player* player); void SendRemoveTransports(Player* player); void SendUpdateTransportVisibility(Player* player, std::set const& previousPhases); - void SendZoneDynamicInfo(Player* player); + void SendZoneDynamicInfo(uint32 zoneId, Player* player) const; + void SendZoneWeather(uint32 zoneId, Player* player) const; + void SendZoneWeather(ZoneDynamicInfo const& zoneDynamicInfo, Player* player) const; + void SetZoneMusic(uint32 zoneId, uint32 musicId); - void SetZoneWeather(uint32 zoneId, uint32 weatherId, float weatherGrade); + Weather* GetOrGenerateZoneDefaultWeather(uint32 zoneId); + void SetZoneWeather(uint32 zoneId, WeatherState weatherId, float weatherGrade); void SetZoneOverrideLight(uint32 zoneId, uint32 lightId, uint32 fadeInTime); void UpdateAreaDependentAuras(); @@ -749,6 +755,7 @@ class TC_GAME_API Map : public GridRefManager std::unordered_map _goRespawnTimes; ZoneDynamicInfoMap _zoneDynamicInfo; + IntervalTimer _weatherUpdateTimer; uint32 _defaultLight; template diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 4714e193ea5..6e1a410fbc6 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -6306,19 +6306,7 @@ void AuraEffect::HandleAuraForceWeather(AuraApplication const* aurApp, uint8 mod target->GetSession()->SendPacket(&data); } else - { - // send weather for current zone - if (Weather* weather = WeatherMgr::FindWeather(target->GetZoneId())) - weather->SendWeatherUpdateToPlayer(target); - else - { - if (!WeatherMgr::AddWeather(target->GetZoneId())) - { - // send fine weather packet to remove old weather - WeatherMgr::SendFineWeatherUpdateToPlayer(target); - } - } - } + target->GetMap()->SendZoneWeather(target->GetZoneId(), target); } void AuraEffect::HandleEnableAltPower(AuraApplication const* aurApp, uint8 mode, bool apply) const diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp index d80f9b4b76f..7c4b2662526 100644 --- a/src/server/game/Weather/Weather.cpp +++ b/src/server/game/Weather/Weather.cpp @@ -28,7 +28,7 @@ #include "Util.h" #include "ScriptMgr.h" #include "Opcodes.h" -#include "WorldSession.h" +#include "World.h" /// Create the Weather object Weather::Weather(uint32 zone, WeatherData const* weatherChances) @@ -197,7 +197,16 @@ void Weather::SendWeatherUpdateToPlayer(Player* player) data << uint32(GetWeatherState()); data << (float)m_grade; data << uint8(0); - player->GetSession()->SendPacket(&data); + player->SendDirectMessage(&data); +} + +void Weather::SendFineWeatherUpdateToPlayer(Player* player) +{ + WorldPacket data(SMSG_WEATHER, (4 + 4 + 1)); + data << uint32(WEATHER_STATE_FINE); + data << (float)0; + data << uint8(0); + player->SendDirectMessage(&data); } /// Send the new weather to all players in the zone diff --git a/src/server/game/Weather/Weather.h b/src/server/game/Weather/Weather.h index 7bc039fb6e7..86cfa29f1f3 100644 --- a/src/server/game/Weather/Weather.h +++ b/src/server/game/Weather/Weather.h @@ -74,6 +74,7 @@ class TC_GAME_API Weather bool UpdateWeather(); void SendWeatherUpdateToPlayer(Player* player); + static void SendFineWeatherUpdateToPlayer(Player* player); void SetWeather(WeatherType type, float grade); /// For which zone is this weather? diff --git a/src/server/game/Weather/WeatherMgr.cpp b/src/server/game/Weather/WeatherMgr.cpp index 70f95f625ba..7c30cb86fb8 100644 --- a/src/server/game/Weather/WeatherMgr.cpp +++ b/src/server/game/Weather/WeatherMgr.cpp @@ -21,63 +21,24 @@ */ #include "WeatherMgr.h" +#include "Containers.h" #include "Weather.h" #include "Log.h" #include "ObjectMgr.h" -#include "Player.h" +#include "Timer.h" #include "Opcodes.h" -#include "WorldSession.h" namespace WeatherMgr { namespace { - typedef std::unordered_map > WeatherMap; - typedef std::unordered_map WeatherZoneMap; - - WeatherMap m_weathers; - WeatherZoneMap mWeatherZoneMap; - - WeatherData const* GetWeatherData(uint32 zone_id) - { - WeatherZoneMap::const_iterator itr = mWeatherZoneMap.find(zone_id); - return (itr != mWeatherZoneMap.end()) ? &itr->second : NULL; - } + std::unordered_map _weatherData; } -/// Find a Weather object by the given zoneid -Weather* FindWeather(uint32 id) +WeatherData const* GetWeatherData(uint32 zone_id) { - WeatherMap::const_iterator itr = m_weathers.find(id); - return (itr != m_weathers.end()) ? itr->second.get() : nullptr; -} - -/// Remove a Weather object for the given zoneid -void RemoveWeather(uint32 id) -{ - // not called at the moment. Kept for completeness - WeatherMap::iterator itr = m_weathers.find(id); - - if (itr != m_weathers.end()) - m_weathers.erase(itr); -} - -/// Add a Weather object to the list -Weather* AddWeather(uint32 zone_id) -{ - WeatherData const* weatherChances = GetWeatherData(zone_id); - - // zone does not have weather, ignore - if (!weatherChances) - return NULL; - - Weather* w = new Weather(zone_id, weatherChances); - m_weathers[w->GetZone()].reset(w); - w->ReGenerate(); - w->UpdateWeather(); - - return w; + return Trinity::Containers::MapGetValuePtr(_weatherData, zone_id); } void LoadWeatherData() @@ -105,7 +66,7 @@ void LoadWeatherData() uint32 zone_id = fields[0].GetUInt32(); - WeatherData& wzc = mWeatherZoneMap[zone_id]; + WeatherData& wzc = _weatherData[zone_id]; for (uint8 season = 0; season < WEATHER_SEASONS; ++season) { @@ -141,29 +102,4 @@ void LoadWeatherData() TC_LOG_INFO("server.loading", ">> Loaded %u weather definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } -void SendFineWeatherUpdateToPlayer(Player* player) -{ - WorldPacket data(SMSG_WEATHER, (4 + 4 + 1)); - data << (uint32)WEATHER_STATE_FINE; - data << (float)0.0f; - data << uint8(0); - player->GetSession()->SendPacket(&data); -} - -void Update(uint32 diff) -{ - ///- Send an update signal to Weather objects - WeatherMap::iterator itr, next; - for (itr = m_weathers.begin(); itr != m_weathers.end(); itr = next) - { - next = itr; - ++next; - - ///- and remove Weather objects for zones with no player - // As interval > WorldTick - if (!itr->second->Update(diff)) - m_weathers.erase(itr); - } -} - } // namespace diff --git a/src/server/game/Weather/WeatherMgr.h b/src/server/game/Weather/WeatherMgr.h index 08c246ac197..c514ce1c00a 100644 --- a/src/server/game/Weather/WeatherMgr.h +++ b/src/server/game/Weather/WeatherMgr.h @@ -27,18 +27,12 @@ class Weather; class Player; +struct WeatherData; namespace WeatherMgr { TC_GAME_API void LoadWeatherData(); - - TC_GAME_API Weather* FindWeather(uint32 id); - TC_GAME_API Weather* AddWeather(uint32 zone_id); - TC_GAME_API void RemoveWeather(uint32 zone_id); - - TC_GAME_API void SendFineWeatherUpdateToPlayer(Player* player); - - TC_GAME_API void Update(uint32 diff); + TC_GAME_API WeatherData const* GetWeatherData(uint32 zone_id); } #endif diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 0328dd31fe4..a9b52795786 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1985,7 +1985,6 @@ void World::SetInitialWorldSettings() LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES(%u, %u, 0, '%s')", realm.Id.Realm, uint32(GameTime::GetStartTime()), GitRevision::GetFullVersion()); // One-time query - m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILLISECONDS); m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILLISECONDS); m_timers[WUPDATE_AUCTIONS_PENDING].SetInterval(250); m_timers[WUPDATE_UPTIME].SetInterval(m_int_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILLISECONDS); @@ -2247,13 +2246,6 @@ void World::Update(uint32 diff) UpdateSessions(diff); sWorldUpdateTime.RecordUpdateTimeDuration("UpdateSessions"); - ///
  • Handle weather updates when the timer has passed - if (m_timers[WUPDATE_WEATHERS].Passed()) - { - m_timers[WUPDATE_WEATHERS].Reset(); - WeatherMgr::Update(uint32(m_timers[WUPDATE_WEATHERS].GetInterval())); - } - ///
  • Update uptime table if (m_timers[WUPDATE_UPTIME].Passed()) { diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index de25b056cf0..e314c463f1c 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -80,7 +80,6 @@ enum WorldTimers { WUPDATE_AUCTIONS, WUPDATE_AUCTIONS_PENDING, - WUPDATE_WEATHERS, WUPDATE_UPTIME, WUPDATE_CORPSES, WUPDATE_EVENTS, diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index a105bee1f9d..9336cca8b47 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1412,10 +1412,7 @@ public: Player* player = handler->GetSession()->GetPlayer(); uint32 zoneid = player->GetZoneId(); - Weather* weather = WeatherMgr::FindWeather(zoneid); - - if (!weather) - weather = WeatherMgr::AddWeather(zoneid); + Weather* weather = player->GetMap()->GetOrGenerateZoneDefaultWeather(zoneid); if (!weather) { handler->SendSysMessage(LANG_NO_WEATHER); diff --git a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp index ca7383d5ada..5745c9301d4 100644 --- a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp +++ b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp @@ -136,6 +136,8 @@ class instance_lost_city_of_the_tolvir : public InstanceMapScript if (state == IN_PROGRESS && !CheckSiamatsPlatform()) if (Creature* siamat = GetCreature(DATA_SIAMAT)) siamat->AI()->EnterEvadeMode(); + if (state == DONE) + instance->SetZoneWeather(ZONE_ID_LOST_CITY, WEATHER_STATE_FOG, 1.0f); break; default: break;