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

Revision 102, 9.1 kB (checked in by yumileroy, 17 years ago)

[svn] Fixed copyright notices to comply with GPL.

Original author: w12x
Date: 2008-10-23 03:29:52-05:00

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