root/trunk/src/game/Weather.cpp @ 2

Revision 2, 9.0 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19/** \file
20    \ingroup world
21*/
22
23#include "Weather.h"
24#include "WorldPacket.h"
25#include "WorldSession.h"
26#include "Player.h"
27#include "World.h"
28#include "Log.h"
29#include "ObjectMgr.h"
30#include "Util.h"
31
32/// Create the Weather object
33Weather::Weather(uint32 zone, WeatherZoneChances const* weatherChances) : m_zone(zone), m_weatherChances(weatherChances)
34{
35    m_timer.SetInterval(sWorld.getConfig(CONFIG_INTERVAL_CHANGEWEATHER));
36    m_type = WEATHER_TYPE_FINE;
37    m_grade = 0;
38
39    sLog.outDetail("WORLD: Starting weather system for zone %u (change every %u minutes).", m_zone, (uint32)(m_timer.GetInterval() / (1000*MINUTE)) );
40}
41
42/// Launch a weather update
43bool Weather::Update(time_t diff)
44{
45    if (m_timer.GetCurrent()>=0)
46        m_timer.Update(diff);
47    else m_timer.SetCurrent(0);
48
49    ///- If the timer has passed, ReGenerate the weather
50    if(m_timer.Passed())
51    {
52        m_timer.Reset();
53        // update only if Regenerate has changed the weather
54        if(ReGenerate())
55        {
56            ///- Weather will be removed if not updated (no players in zone anymore)
57            if(!UpdateWeather())
58                return false;
59        }
60    }
61    return true;
62}
63
64/// Calculate the new weather
65bool Weather::ReGenerate()
66{
67    if (!m_weatherChances)
68    {
69        m_type = WEATHER_TYPE_FINE;
70        m_grade = 0.0f;
71        return false;
72    }
73
74    /// Weather statistics:
75    ///- 30% - no change
76    ///- 30% - weather gets better (if not fine) or change weather type
77    ///- 30% - weather worsens (if not fine)
78    ///- 10% - radical change (if not fine)
79    uint32 u = urand(0, 99);
80
81    if (u < 30)
82        return false;
83
84    // remember old values
85    WeatherType old_type = m_type;
86    float old_grade = m_grade;
87
88    //78 days between January 1st and March 20nd; 365/4=91 days by season
89    // season source http://aa.usno.navy.mil/data/docs/EarthSeasons.html
90    time_t gtime = sWorld.GetGameTime();
91    struct tm * ltime = localtime(&gtime);
92    uint32 season = ((ltime->tm_yday - 78 + 365)/91)%4;
93
94    static char const* seasonName[WEATHER_SEASONS] = { "spring", "summer", "fall", "winter" };
95
96    sLog.outDebug("Generating a change in %s weather for zone %u.", seasonName[season], m_zone);
97
98    if ((u < 60) && (m_grade < 0.33333334f))                // Get fair
99    {
100        m_type = WEATHER_TYPE_FINE;
101        m_grade = 0.0f;
102    }
103
104    if ((u < 60) && (m_type != WEATHER_TYPE_FINE))          // Get better
105    {
106        m_grade -= 0.33333334f;
107        return true;
108    }
109
110    if ((u < 90) && (m_type != WEATHER_TYPE_FINE))          // Get worse
111    {
112        m_grade += 0.33333334f;
113        return true;
114    }
115
116    if (m_type != WEATHER_TYPE_FINE)
117    {
118        /// Radical change:
119        ///- if light -> heavy
120        ///- if medium -> change weather type
121        ///- if heavy -> 50% light, 50% change weather type
122
123        if (m_grade < 0.33333334f)
124        {
125            m_grade = 0.9999f;                              // go nuts
126            return true;
127        }
128        else
129        {
130            if (m_grade > 0.6666667f)
131            {
132                                                            // Severe change, but how severe?
133                uint32 rnd = urand(0,99);
134                if (rnd < 50)
135                {
136                    m_grade -= 0.6666667f;
137                    return true;
138                }
139            }
140            m_type = WEATHER_TYPE_FINE;                     // clear up
141            m_grade = 0;
142        }
143    }
144
145    // At this point, only weather that isn't doing anything remains but that have weather data
146    uint32 chance1 =          m_weatherChances->data[season].rainChance;
147    uint32 chance2 = chance1+ m_weatherChances->data[season].snowChance;
148    uint32 chance3 = chance2+ m_weatherChances->data[season].stormChance;
149
150    uint32 rnd = urand(0, 99);
151    if(rnd <= chance1)
152        m_type = WEATHER_TYPE_RAIN;
153    else if(rnd <= chance2)
154        m_type = WEATHER_TYPE_SNOW;
155    else if(rnd <= chance3)
156        m_type = WEATHER_TYPE_STORM;
157    else
158        m_type = WEATHER_TYPE_FINE;
159
160    /// New weather statistics (if not fine):
161    ///- 85% light
162    ///- 7% medium
163    ///- 7% heavy
164    /// If fine 100% sun (no fog)
165
166    if (m_type == WEATHER_TYPE_FINE)
167    {
168        m_grade = 0.0f;
169    }
170    else if (u < 90)
171    {
172        m_grade = rand_norm() * 0.3333f;
173    }
174    else
175    {
176        // Severe change, but how severe?
177        rnd = urand(0, 99);
178        if (rnd < 50)
179            m_grade = rand_norm() * 0.3333f + 0.3334f;
180        else
181            m_grade = rand_norm() * 0.3333f + 0.6667f;
182    }
183
184    // return true only in case weather changes
185    return m_type != old_type || m_grade != old_grade;
186}
187
188void Weather::SendWeatherUpdateToPlayer(Player *player)
189{
190    WorldPacket data( SMSG_WEATHER, (4+4+4) );
191
192    data << uint32(GetWeatherState()) << (float)m_grade << uint8(0);
193    player->GetSession()->SendPacket( &data );
194}
195
196void Weather::SendFineWeatherUpdateToPlayer(Player *player)
197{
198    WorldPacket data( SMSG_WEATHER, (4+4+4) );
199
200    data << (uint32)WEATHER_STATE_FINE << (float)0.0f << uint8(0);
201    player->GetSession()->SendPacket( &data );
202}
203
204/// Send the new weather to all players in the zone
205bool Weather::UpdateWeather()
206{
207    Player* player = sWorld.FindPlayerInZone(m_zone);
208    if(!player)
209        return false;
210
211    ///- Send the weather packet to all players in this zone
212    if (m_grade >= 1)
213        m_grade = 0.9999f;
214    else if (m_grade < 0)
215        m_grade = 0.0001f;
216
217    WeatherState state = GetWeatherState();
218
219    WorldPacket data( SMSG_WEATHER, (4+4+4) );
220    data << uint32(state) << (float)m_grade << uint8(0);
221    player->SendMessageToSet( &data, true );
222
223    ///- Log the event
224    char const* wthstr;
225    switch(state)
226    {
227        case WEATHER_STATE_LIGHT_RAIN:
228            wthstr = "light rain";
229            break;
230        case WEATHER_STATE_MEDIUM_RAIN:
231            wthstr = "medium rain";
232            break;
233        case WEATHER_STATE_HEAVY_RAIN:
234            wthstr = "heavy rain";
235            break;
236        case WEATHER_STATE_LIGHT_SNOW:
237            wthstr = "light snow";
238            break;
239        case WEATHER_STATE_MEDIUM_SNOW:
240            wthstr = "medium snow";
241            break;
242        case WEATHER_STATE_HEAVY_SNOW:
243            wthstr = "heavy snow";
244            break;
245        case WEATHER_STATE_LIGHT_SANDSTORM:
246            wthstr = "light sandstorm";
247            break;
248        case WEATHER_STATE_MEDIUM_SANDSTORM:
249            wthstr = "medium sandstorm";
250            break;
251        case WEATHER_STATE_HEAVY_SANDSTORM:
252            wthstr = "heavy sandstorm";
253            break;
254        case WEATHER_STATE_THUNDERS:
255            wthstr = "thunders";
256            break;
257        case WEATHER_STATE_BLACKRAIN:
258            wthstr = "blackrain";
259            break;
260        case WEATHER_STATE_FINE:
261        default:
262            wthstr = "fine";
263            break;
264    }
265    sLog.outDetail("Change the weather of zone %u to %s.", m_zone, wthstr);
266
267    return true;
268}
269
270/// Set the weather
271void Weather::SetWeather(WeatherType type, float grade)
272{
273    if(m_type == type && m_grade == grade)
274        return;
275
276    m_type = type;
277    m_grade = grade;
278    UpdateWeather();
279}
280
281/// Get the sound number associated with the current weather
282WeatherState Weather::GetWeatherState() const
283{
284    if (m_grade<0.27f)
285        return WEATHER_STATE_FINE;
286
287    switch(m_type)
288    {
289        case WEATHER_TYPE_RAIN:
290            if(m_grade<0.40f)
291                return WEATHER_STATE_LIGHT_RAIN;
292            else if(m_grade<0.70f)
293                return WEATHER_STATE_MEDIUM_RAIN;
294            else
295                return WEATHER_STATE_HEAVY_RAIN;
296        case WEATHER_TYPE_SNOW:
297            if(m_grade<0.40f)
298                return WEATHER_STATE_LIGHT_SNOW;
299            else if(m_grade<0.70f)
300                return WEATHER_STATE_MEDIUM_SNOW;
301            else
302                return WEATHER_STATE_HEAVY_SNOW;
303        case WEATHER_TYPE_STORM:
304            if(m_grade<0.40f)
305                return WEATHER_STATE_LIGHT_SANDSTORM;
306            else if(m_grade<0.70f)
307                return WEATHER_STATE_MEDIUM_SANDSTORM;
308            else
309                return WEATHER_STATE_HEAVY_SANDSTORM;
310        case WEATHER_TYPE_BLACKRAIN:
311            return WEATHER_STATE_BLACKRAIN;
312        case WEATHER_TYPE_THUNDERS:
313            return WEATHER_STATE_THUNDERS;
314        case WEATHER_TYPE_FINE:
315        default:
316            return WEATHER_STATE_FINE;
317    }
318}
Note: See TracBrowser for help on using the browser.