Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
Weather.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
9
10#include "Log.h"
11#include "ObjectMgr.h"
12#include "Opcodes.h"
13#include "Platform/TimeUtils.h"
14#include "Player.h"
15#include "ScriptMgr.h"
16#include "Util.h"
17#include "Weather.h"
18#include "World.h"
19#include "WorldPacket.h"
20#include "WorldSession.h"
21
23Weather::Weather(uint32 zone, WeatherData const* weatherChances)
24 : m_zone(zone), m_weatherChances(weatherChances)
25{
28 m_grade = 0;
29
30 SF_LOG_INFO("misc", "WORLD: Starting weather system for zone %u (change every %u minutes).", m_zone, (uint32)(m_timer.GetInterval() / (MINUTE * IN_MILLISECONDS)));
31}
32
35{
36 if (m_timer.GetCurrent() >= 0)
37 m_timer.Update(diff);
38 else
39 m_timer.SetCurrent(0);
40
42 if (m_timer.Passed())
43 {
44 m_timer.Reset();
45 // update only if Regenerate has changed the weather
46 if (ReGenerate())
47 {
49 if (!UpdateWeather())
50 return false;
51 }
52 }
53
54 sScriptMgr->OnWeatherUpdate(this, diff);
55 return true;
56}
57
60{
62 {
64 m_grade = 0.0f;
65 return false;
66 }
67
73 uint32 u = std::rand() % 99;
74
75 if (u < 30)
76 return false;
77
78 // remember old values
79 WeatherType old_type = m_type;
80 float old_grade = m_grade;
81
82 //78 days between January 1st and March 20nd; 365/4=91 days by season
83 // season source http://aa.usno.navy.mil/data/docs/EarthSeasons.html
84 time_t gtime = sWorld->GetGameTime();
85 struct tm ltime;
86 Skyfire::LocalTime(gtime, ltime);
87 uint32 season = ((ltime.tm_yday - 78 + 365) / 91) % 4;
88
89 static char const* seasonName[WEATHER_SEASONS] = { "spring", "summer", "fall", "winter" };
90
91 SF_LOG_INFO("misc", "Generating a change in %s weather for zone %u.", seasonName[season], m_zone);
92
93 if ((u < 60) && (m_grade < 0.33333334f)) // Get fair
94 {
96 m_grade = 0.0f;
97 }
98
99 if ((u < 60) && (m_type != WEATHER_TYPE_FINE)) // Get better
100 {
101 m_grade -= 0.33333334f;
102 return true;
103 }
104
105 if ((u < 90) && (m_type != WEATHER_TYPE_FINE)) // Get worse
106 {
107 m_grade += 0.33333334f;
108 return true;
109 }
110
112 {
117
118 if (m_grade < 0.33333334f)
119 {
120 m_grade = 0.9999f; // go nuts
121 return true;
122 }
123 else
124 {
125 if (m_grade > 0.6666667f)
126 {
127 // Severe change, but how severe?
128 uint32 rnd = std::rand() % 99;
129 if (rnd < 50)
130 {
131 m_grade -= 0.6666667f;
132 return true;
133 }
134 }
135 m_type = WEATHER_TYPE_FINE; // clear up
136 m_grade = 0;
137 }
138 }
139
140 // At this point, only weather that isn't doing anything remains but that have weather data
141 uint32 chance1 = m_weatherChances->data[season].rainChance;
142 uint32 chance2 = chance1 + m_weatherChances->data[season].snowChance;
143 uint32 chance3 = chance2 + m_weatherChances->data[season].stormChance;
144
145 uint32 rnd = std::rand() % 99;
146 if (rnd <= chance1)
148 else if (rnd <= chance2)
150 else if (rnd <= chance3)
152 else
154
160
162 {
163 m_grade = 0.0f;
164 }
165 else if (u < 90)
166 {
167 m_grade = (float)rand_norm() * 0.3333f;
168 }
169 else
170 {
171 // Severe change, but how severe?
172 rnd = std::rand() % 99;
173 if (rnd < 50)
174 m_grade = (float)rand_norm() * 0.3333f + 0.3334f;
175 else
176 m_grade = (float)rand_norm() * 0.3333f + 0.6667f;
177 }
178
179 // return true only in case weather changes
180 return m_type != old_type || m_grade != old_grade;
181}
182
184{
185 WorldPacket data(SMSG_WEATHER, 4 + 4 + 1);
186 data << uint32(GetWeatherState()); // WeatherID
187 data << float(m_grade); // Intensity
188 data.WriteBit(false); // Abrupt
189 data.FlushBits();
190 player->GetSession()->SendPacket(&data);
191}
192
195{
196 Player* player = sWorld->FindPlayerInZone(m_zone);
197 if (!player)
198 return false;
199
201 if (m_grade >= 1)
202 m_grade = 0.9999f;
203 else if (m_grade < 0)
204 m_grade = 0.0001f;
205
207
208 WorldPacket data(SMSG_WEATHER, 4 + 4 + 1);
209 data << uint32(state); // WeatherID
210 data << float(m_grade); // Intensity
211 data.WriteBit(false); // Abrupt
212 data.FlushBits();
213 player->SendMessageToSet(&data, true);
214
216 char const* wthstr;
217 switch (state)
218 {
220 wthstr = "fog";
221 break;
223 wthstr = "light rain";
224 break;
226 wthstr = "medium rain";
227 break;
229 wthstr = "heavy rain";
230 break;
232 wthstr = "light snow";
233 break;
235 wthstr = "medium snow";
236 break;
238 wthstr = "heavy snow";
239 break;
241 wthstr = "light sandstorm";
242 break;
244 wthstr = "medium sandstorm";
245 break;
247 wthstr = "heavy sandstorm";
248 break;
250 wthstr = "thunders";
251 break;
253 wthstr = "blackrain";
254 break;
256 default:
257 wthstr = "fine";
258 break;
259 }
260 SF_LOG_INFO("misc", "Change the weather of zone %u to %s.", m_zone, wthstr);
261
262 sScriptMgr->OnWeatherChange(this, state, m_grade);
263 return true;
264}
265
267void Weather::SetWeather(WeatherType type, float grade)
268{
269 if (m_type == type && m_grade == grade)
270 return;
271
272 m_type = type;
273 m_grade = grade;
275}
276
279{
280 if (m_grade < 0.27f)
281 return WEATHER_STATE_FINE;
282
283 switch (m_type)
284 {
286 if (m_grade < 0.40f)
288 else if (m_grade < 0.70f)
290 else
293 if (m_grade < 0.40f)
295 else if (m_grade < 0.70f)
297 else
300 if (m_grade < 0.40f)
302 else if (m_grade < 0.70f)
304 else
311 default:
312 return WEATHER_STATE_FINE;
313 }
314}
@ IN_MILLISECONDS
Definition Common.h:125
@ MINUTE
Definition Common.h:119
std::uint32_t uint32
Definition Define.h:77
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
#define sScriptMgr
Definition ScriptMgr.h:764
WeatherType
@ WEATHER_TYPE_RAIN
@ WEATHER_TYPE_STORM
@ WEATHER_TYPE_FINE
@ WEATHER_TYPE_SNOW
@ WEATHER_TYPE_THUNDERS
@ WEATHER_TYPE_BLACKRAIN
double rand_norm(void)
Definition Util.cpp:50
bool WriteBit(uint32 bit)
Definition ByteBuffer.h:164
void FlushBits()
Definition ByteBuffer.h:154
WorldSession * GetSession() const
Definition Player.h:2417
void SendMessageToSet(WorldPacket *data, bool self) override
Definition Player.h:2443
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
@ SMSG_WEATHER
Definition Opcodes.h:1065
#define sWorld
Definition World.h:910
WeatherType m_type
Definition Weather.h:72
uint32 m_zone
Definition Weather.h:71
WeatherState
Definition Weather.h:34
void SetWeather(WeatherType type, float grade)
Set the weather.
Definition Weather.cpp:267
float m_grade
Definition Weather.h:73
#define WEATHER_SEASONS
Definition Weather.h:19
bool UpdateWeather()
Send the new weather to all players in the zone.
Definition Weather.cpp:194
IntervalTimer m_timer
Definition Weather.h:74
bool ReGenerate()
Calculate the new weather.
Definition Weather.cpp:59
WeatherData const * m_weatherChances
Definition Weather.h:75
WeatherState GetWeatherState() const
Get the sound number associated with the current weather.
Definition Weather.cpp:278
Weather(uint32 zone, WeatherData const *weatherChances)
Create the Weather object.
Definition Weather.cpp:23
bool Update(uint32 diff)
Launch a weather update.
Definition Weather.cpp:34
void SendWeatherUpdateToPlayer(Player *player)
Definition Weather.cpp:183
@ CONFIG_INTERVAL_CHANGEWEATHER
Definition World.h:203
@ WEATHER_STATE_THUNDERS
Definition Weather.h:46
@ WEATHER_STATE_HEAVY_RAIN
Definition Weather.h:39
@ WEATHER_STATE_HEAVY_SANDSTORM
Definition Weather.h:45
@ WEATHER_STATE_MEDIUM_SNOW
Definition Weather.h:41
@ WEATHER_STATE_MEDIUM_RAIN
Definition Weather.h:38
@ WEATHER_STATE_MEDIUM_SANDSTORM
Definition Weather.h:44
@ WEATHER_STATE_FINE
Definition Weather.h:35
@ WEATHER_STATE_LIGHT_SNOW
Definition Weather.h:40
@ WEATHER_STATE_BLACKRAIN
Definition Weather.h:47
@ WEATHER_STATE_HEAVY_SNOW
Definition Weather.h:42
@ WEATHER_STATE_LIGHT_SANDSTORM
Definition Weather.h:43
@ WEATHER_STATE_FOG
Definition Weather.h:36
@ WEATHER_STATE_LIGHT_RAIN
Definition Weather.h:37
bool LocalTime(time_t const &time, tm &result)
Definition TimeUtils.h:57