root/trunk/src/game/SkillDiscovery.cpp @ 206

Revision 206, 6.0 kB (checked in by yumileroy, 17 years ago)

[svn] * Switch from hashmap to unordered map. - cleanup source - mangos. Help - Aokromes

Original author: KingPin?
Date: 2008-11-10 06:53:00-06: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#include "Database/DatabaseEnv.h"
22#include "Log.h"
23#include "ProgressBar.h"
24#include "Policies/SingletonImp.h"
25#include "ObjectAccessor.h"
26#include "World.h"
27#include "Util.h"
28#include "SkillDiscovery.h"
29#include "SpellMgr.h"
30#include <map>
31
32struct SkillDiscoveryEntry
33{
34    uint32  spellId;
35    float   chance;
36
37    SkillDiscoveryEntry()
38        : spellId(0), chance(0) {}
39
40    SkillDiscoveryEntry(uint16 _spellId, float _chance)
41        : spellId(_spellId), chance(_chance) {}
42};
43
44typedef std::list<SkillDiscoveryEntry> SkillDiscoveryList;
45typedef UNORDERED_MAP<int32, SkillDiscoveryList> SkillDiscoveryMap;
46
47static SkillDiscoveryMap SkillDiscoveryStore;
48
49void LoadSkillDiscoveryTable()
50{
51
52    SkillDiscoveryStore.clear();                            // need for reload
53
54    uint32 count = 0;
55
56    //                                                 0        1         2
57    QueryResult *result = WorldDatabase.Query("SELECT spellId, reqSpell, chance FROM skill_discovery_template");
58
59    if (result)
60    {
61        barGoLink bar(result->GetRowCount());
62
63        std::ostringstream ssNonDiscoverableEntries;
64
65        do
66        {
67            Field *fields = result->Fetch();
68            bar.step();
69
70            uint32 spellId         = fields[0].GetUInt32();
71            int32  reqSkillOrSpell = fields[1].GetInt32();
72            float  chance          = fields[2].GetFloat();
73
74            if( chance <= 0 )                               // chance
75            {
76                ssNonDiscoverableEntries << "spellId = " << spellId << " reqSkillOrSpell = " << reqSkillOrSpell << " chance = " << chance << "\n";
77                continue;
78            }
79
80            if(reqSkillOrSpell > 0)                         // spell case
81            {
82                SpellEntry const* spellEntry = sSpellStore.LookupEntry(reqSkillOrSpell);
83                if( !spellEntry )
84                {
85                    sLog.outErrorDb("Spell (ID: %u) have not existed spell (ID: %i) in `reqSpell` field in `skill_discovery_template` table",spellId,reqSkillOrSpell);
86                    continue;
87                }
88
89                if( spellEntry->Mechanic != MECHANIC_DISCOVERY )
90                {
91                    sLog.outErrorDb("Spell (ID: %u) not have have MECHANIC_DISCOVERY (28) value in Mechanic field in spell.dbc but listed in `skill_discovery_template` table",spellId);
92                    continue;
93                }
94
95                SkillDiscoveryStore[reqSkillOrSpell].push_back( SkillDiscoveryEntry(spellId, chance) );
96            }
97            else if( reqSkillOrSpell == 0 )                 // skill case
98            {
99                SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellId);
100                SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellId);
101
102                if(lower==upper)
103                {
104                    sLog.outErrorDb("Spell (ID: %u) not listed in `SkillLineAbility.dbc` but listed with `reqSpell`=0 in `skill_discovery_template` table",spellId);
105                    continue;
106                }
107
108                for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
109                {
110                    SkillDiscoveryStore[-int32(_spell_idx->second->skillId)].push_back( SkillDiscoveryEntry(spellId, chance) );
111                }
112            }
113            else
114            {
115                sLog.outErrorDb("Spell (ID: %u) have negative value in `reqSpell` field in `skill_discovery_template` table",spellId);
116                continue;
117            }
118            ++count;
119        } while (result->NextRow());
120
121        delete result;
122
123        sLog.outString();
124        sLog.outString( ">> Loaded %u skill discovery definitions", count );
125        if(!ssNonDiscoverableEntries.str().empty())
126            sLog.outErrorDb("Some items can't be successfully discovered: have in chance field value < 0.000001 in `skill_discovery_template` DB table . List:\n%s",ssNonDiscoverableEntries.str().c_str());
127    }
128    else
129    {
130        sLog.outString();
131        sLog.outString( ">> Loaded 0 skill discovery definitions. DB table `skill_discovery_template` is empty." );
132    }
133}
134
135uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player)
136{
137    // check spell case
138    SkillDiscoveryMap::iterator tab = SkillDiscoveryStore.find(spellId);
139
140    if(tab != SkillDiscoveryStore.end())
141    {
142        for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter)
143        {
144            if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY))
145                && !player->HasSpell(item_iter->spellId) )
146                return item_iter->spellId;
147        }
148
149        return 0;
150    }
151
152    // check skill line case
153    tab = SkillDiscoveryStore.find(-(int32)skillId);
154    if(tab != SkillDiscoveryStore.end())
155    {
156        for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter)
157        {
158            if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY))
159                && !player->HasSpell(item_iter->spellId) )
160                return item_iter->spellId;
161        }
162
163        return 0;
164    }
165
166    return 0;
167}
Note: See TracBrowser for help on using the browser.