2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
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.
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.
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
19 #include "Database/DatabaseEnv.h"
21 #include "ProgressBar.h"
22 #include "Policies/SingletonImp.h"
23 #include "ObjectAccessor.h"
26 #include "SkillDiscovery.h"
30 struct SkillDiscoveryEntry
36 : spellId(0), chance(0) {}
38 SkillDiscoveryEntry(uint16 _spellId
, float _chance
)
39 : spellId(_spellId
), chance(_chance
) {}
42 typedef std::list
<SkillDiscoveryEntry
> SkillDiscoveryList
;
43 typedef UNORDERED_MAP
<int32
, SkillDiscoveryList
> SkillDiscoveryMap
;
45 static SkillDiscoveryMap SkillDiscoveryStore
;
47 void LoadSkillDiscoveryTable()
50 SkillDiscoveryStore
.clear(); // need for reload
55 QueryResult
*result
= WorldDatabase
.Query("SELECT spellId, reqSpell, chance FROM skill_discovery_template");
59 barGoLink
bar(result
->GetRowCount());
61 std::ostringstream ssNonDiscoverableEntries
;
65 Field
*fields
= result
->Fetch();
68 uint32 spellId
= fields
[0].GetUInt32();
69 int32 reqSkillOrSpell
= fields
[1].GetInt32();
70 float chance
= fields
[2].GetFloat();
72 if( chance
<= 0 ) // chance
74 ssNonDiscoverableEntries
<< "spellId = " << spellId
<< " reqSkillOrSpell = " << reqSkillOrSpell
<< " chance = " << chance
<< "\n";
78 if(reqSkillOrSpell
> 0) // spell case
80 SpellEntry
const* spellEntry
= sSpellStore
.LookupEntry(reqSkillOrSpell
);
83 sLog
.outErrorDb("Spell (ID: %u) have not existed spell (ID: %i) in `reqSpell` field in `skill_discovery_template` table",spellId
,reqSkillOrSpell
);
87 if( spellEntry
->Mechanic
!= MECHANIC_DISCOVERY
)
89 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
);
93 SkillDiscoveryStore
[reqSkillOrSpell
].push_back( SkillDiscoveryEntry(spellId
, chance
) );
95 else if( reqSkillOrSpell
== 0 ) // skill case
97 SkillLineAbilityMap::const_iterator lower
= spellmgr
.GetBeginSkillLineAbilityMap(spellId
);
98 SkillLineAbilityMap::const_iterator upper
= spellmgr
.GetEndSkillLineAbilityMap(spellId
);
102 sLog
.outErrorDb("Spell (ID: %u) not listed in `SkillLineAbility.dbc` but listed with `reqSpell`=0 in `skill_discovery_template` table",spellId
);
106 for(SkillLineAbilityMap::const_iterator _spell_idx
= lower
; _spell_idx
!= upper
; ++_spell_idx
)
108 SkillDiscoveryStore
[-int32(_spell_idx
->second
->skillId
)].push_back( SkillDiscoveryEntry(spellId
, chance
) );
113 sLog
.outErrorDb("Spell (ID: %u) have negative value in `reqSpell` field in `skill_discovery_template` table",spellId
);
117 } while (result
->NextRow());
122 sLog
.outString( ">> Loaded %u skill discovery definitions", count
);
123 if(!ssNonDiscoverableEntries
.str().empty())
124 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());
129 sLog
.outString( ">> Loaded 0 skill discovery definitions. DB table `skill_discovery_template` is empty." );
133 uint32
GetSkillDiscoverySpell(uint32 skillId
, uint32 spellId
, Player
* player
)
136 SkillDiscoveryMap::iterator tab
= SkillDiscoveryStore
.find(spellId
);
138 if(tab
!= SkillDiscoveryStore
.end())
140 for(SkillDiscoveryList::iterator item_iter
= tab
->second
.begin(); item_iter
!= tab
->second
.end(); ++item_iter
)
142 if( roll_chance_f(item_iter
->chance
* sWorld
.getRate(RATE_SKILL_DISCOVERY
))
143 && !player
->HasSpell(item_iter
->spellId
) )
144 return item_iter
->spellId
;
150 // check skill line case
151 tab
= SkillDiscoveryStore
.find(-(int32
)skillId
);
152 if(tab
!= SkillDiscoveryStore
.end())
154 for(SkillDiscoveryList::iterator item_iter
= tab
->second
.begin(); item_iter
!= tab
->second
.end(); ++item_iter
)
156 if( roll_chance_f(item_iter
->chance
* sWorld
.getRate(RATE_SKILL_DISCOVERY
))
157 && !player
->HasSpell(item_iter
->spellId
) )
158 return item_iter
->spellId
;