OregonCore  revision 3611e8a-git
Your Favourite TBC server
SkillDiscovery.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Database/DatabaseEnv.h"
19 #include "Log.h"
20 #include "ObjectAccessor.h"
21 #include "World.h"
22 #include "Util.h"
23 #include "SkillDiscovery.h"
24 #include "SpellMgr.h"
25 #include <map>
26 
28 {
30  float chance;
31 
33  : spellId(0), chance(0) {}
34 
35  SkillDiscoveryEntry(uint16 _spellId, float _chance)
36  : spellId(_spellId), chance(_chance) {}
37 };
38 
39 typedef std::list<SkillDiscoveryEntry> SkillDiscoveryList;
40 typedef UNORDERED_MAP<int32, SkillDiscoveryList> SkillDiscoveryMap;
41 
42 static SkillDiscoveryMap SkillDiscoveryStore;
43 
45 {
46 
47  SkillDiscoveryStore.clear(); // need for reload
48 
49  uint32 count = 0;
50 
51  // 0 1 2
52  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT spellId, reqSpell, chance FROM skill_discovery_template");
53 
54  if (result)
55  {
56 
57  std::ostringstream ssNonDiscoverableEntries;
58 
59  do
60  {
61  Field* fields = result->Fetch();
62 
63  uint32 spellId = fields[0].GetUInt32();
64  int32 reqSkillOrSpell = fields[1].GetInt32();
65  float chance = fields[2].GetFloat();
66 
67  if (chance <= 0) // chance
68  {
69  ssNonDiscoverableEntries << "spellId = " << spellId << " reqSkillOrSpell = " << reqSkillOrSpell << " chance = " << chance << "\n";
70  continue;
71  }
72 
73  if (reqSkillOrSpell > 0) // spell case
74  {
75  SpellEntry const* spellEntry = sSpellStore.LookupEntry(reqSkillOrSpell);
76  if (!spellEntry)
77  {
78  sLog.outErrorDb("Spell (ID: %u) has invalid spell (ID: %i) in reqSpell field in skill_discovery_template table", spellId, reqSkillOrSpell);
79  continue;
80  }
81 
82  if (spellEntry->Mechanic != MECHANIC_DISCOVERY)
83  {
84  sLog.outErrorDb("Spell (ID: %u) does not have MECHANIC_DISCOVERY (28) value in Mechanic field in spell.dbc but listed in skill_discovery_template table", spellId);
85  continue;
86  }
87 
88  SkillDiscoveryStore[reqSkillOrSpell].push_back(SkillDiscoveryEntry(spellId, chance));
89  }
90  else if (reqSkillOrSpell == 0) // skill case
91  {
92  SkillLineAbilityMap::const_iterator lower = sSpellMgr.GetBeginSkillLineAbilityMap(spellId);
93  SkillLineAbilityMap::const_iterator upper = sSpellMgr.GetEndSkillLineAbilityMap(spellId);
94 
95  if (lower == upper)
96  {
97  sLog.outErrorDb("Spell (ID: %u) not listed in SkillLineAbility.dbc but listed with reqSpell=0 in skill_discovery_template table", spellId);
98  continue;
99  }
100 
101  for (SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
102  SkillDiscoveryStore[-int32(_spell_idx->second->skillId)].push_back(SkillDiscoveryEntry(spellId, chance));
103  }
104  else
105  {
106  sLog.outErrorDb("Spell (ID: %u) has negative value in reqSpell field in skill_discovery_template table", spellId);
107  continue;
108  }
109  ++count;
110  }
111  while (result->NextRow());
112 
113  sLog.outString(">> Loaded %u skill discovery definitions", count);
114  if (!ssNonDiscoverableEntries.str().empty())
115  sLog.outErrorDb("Some items can't be successfully discovered: has chance field value < 0.000001 in skill_discovery_template DB table . List:\n%s", ssNonDiscoverableEntries.str().c_str());
116  }
117  else
118  sLog.outString(">> Loaded 0 skill discovery definitions. DB table skill_discovery_template is empty.");
119 }
120 
122 {
123  // check spell case
124  SkillDiscoveryMap::iterator tab = SkillDiscoveryStore.find(spellId);
125 
126  if (tab != SkillDiscoveryStore.end())
127  {
128  for (SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter)
129  {
130  if (roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY))
131  && !player->HasSpell(item_iter->spellId))
132  return item_iter->spellId;
133  }
134 
135  return 0;
136  }
137 
138  // check skill line case
139  tab = SkillDiscoveryStore.find(-(int32)skillId);
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  return 0;
153 }
154 
DatabaseType WorldDatabase
Accessor to the world database.
Definition: Main.cpp:53
UNORDERED_MAP< int32, SkillDiscoveryList > SkillDiscoveryMap
Definition: Field.h:24
bool roll_chance_f(float chance)
Definition: Util.h:67
#define sLog
Log class singleton.
Definition: Log.h:187
ACE_INT32 int32
Definition: Define.h:67
QueryResult_AutoPtr Query(const char *sql)
Definition: Database.cpp:383
DBCStorage< SpellEntry > sSpellStore(SpellEntryfmt)
bool HasSpell(uint32 spell) const override
Definition: Player.cpp:3813
void LoadSkillDiscoveryTable()
std::list< SkillDiscoveryEntry > SkillDiscoveryList
#define sSpellMgr
Definition: SpellMgr.h:1239
SkillDiscoveryEntry(uint16 _spellId, float _chance)
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player *player)
uint32 Mechanic
Definition: DBCStructure.h:678
#define sWorld
Definition: World.h:860
ACE_UINT16 uint16
Definition: Define.h:72
ACE_UINT32 uint32
Definition: Define.h:71
Definition: Player.h:922