*drop spell_elixir table

*add spell_group table for storage of groups of spell (kinda obvious, isn't it?) and populate the table with converted spell_elixir table data
*the table is going to be maintained by core team
*fix percentage display at spell_ranks table loading
*add TARGET_UNIT_CASTER to allowed learn spell targets in npc_trainer table, thanks to Aokromes for noticing the issue.

--HG--
branch : trunk
This commit is contained in:
QAston
2010-02-01 19:22:32 +01:00
parent 65705a16c1
commit a1256d88ee
13 changed files with 516 additions and 216 deletions
+1 -1
View File
@@ -497,7 +497,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "spell_required", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellRequiredCommand, "", NULL },
{ "spell_area", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellAreaCommand, "", NULL },
{ "spell_bonus_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellBonusesCommand, "", NULL },
{ "spell_elixir", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL },
{ "spell_group", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellGroupsCommand, "", NULL },
{ "spell_learn_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL },
{ "spell_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSpellCommand, "", NULL },
{ "spell_linked_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLinkedSpellCommand, "", NULL },
+1 -1
View File
@@ -410,7 +410,7 @@ class TRINITY_DLL_SPEC ChatHandler
bool HandleReloadSkillFishingBaseLevelCommand(const char* args);
bool HandleReloadSpellRequiredCommand(const char* args);
bool HandleReloadSpellAreaCommand(const char* args);
bool HandleReloadSpellElixirCommand(const char* args);
bool HandleReloadSpellGroupsCommand(const char* args);
bool HandleReloadSpellLearnSpellCommand(const char* args);
bool HandleReloadSpellLinkedSpellCommand(const char* args);
bool HandleReloadSpellProcEventCommand(const char* args);
+5 -5
View File
@@ -651,7 +651,7 @@ bool ChatHandler::HandleReloadAllSpellCommand(const char*)
HandleReloadSkillExtraItemTemplateCommand("a");
HandleReloadSpellRequiredCommand("a");
HandleReloadSpellAreaCommand("a");
HandleReloadSpellElixirCommand("a");
HandleReloadSpellGroupsCommand("a");
HandleReloadSpellLearnSpellCommand("a");
HandleReloadSpellLinkedSpellCommand("a");
HandleReloadSpellProcEventCommand("a");
@@ -1030,11 +1030,11 @@ bool ChatHandler::HandleReloadSpellRequiredCommand(const char*)
return true;
}
bool ChatHandler::HandleReloadSpellElixirCommand(const char*)
bool ChatHandler::HandleReloadSpellGroupsCommand(const char*)
{
sLog.outString( "Re-Loading Spell Elixir types..." );
spellmgr.LoadSpellElixirs();
SendGlobalGMSysMessage("DB table `spell_elixir` (spell elixir types) reloaded.");
sLog.outString( "Re-Loading Spell Groups..." );
spellmgr.LoadSpellGroups();
SendGlobalGMSysMessage("DB table `spell_group` (spell elixir types) reloaded.");
return true;
}
+4 -3
View File
@@ -8020,14 +8020,15 @@ void ObjectMgr::LoadTrainerSpell()
{
if(spellinfo->Effect[i] != SPELL_EFFECT_LEARN_SPELL)
continue;
if (trainerSpell.learnedSpell[0] == spell)
trainerSpell.learnedSpell[0] = 0;
// player must be able to cast spell on himself
if (spellinfo->EffectImplicitTargetA[i] != 0 && spellinfo->EffectImplicitTargetA[i] != TARGET_UNIT_TARGET_ALLY && spellinfo->EffectImplicitTargetA[i] != TARGET_UNIT_TARGET_ANY)
if (spellinfo->EffectImplicitTargetA[i] != 0 && spellinfo->EffectImplicitTargetA[i] != TARGET_UNIT_TARGET_ALLY
&& spellinfo->EffectImplicitTargetA[i] != TARGET_UNIT_TARGET_ANY && spellinfo->EffectImplicitTargetA[i] != TARGET_UNIT_CASTER)
{
sLog.outErrorDb("Table `npc_trainer` has spell %u for trainer entry %u with learn effect which has incorrect target type, ignoring learn effect!", spell, entry);
continue;
}
if (trainerSpell.learnedSpell[0] == spell)
trainerSpell.learnedSpell[0] = 0;
trainerSpell.learnedSpell[i] = spellinfo->EffectTriggerSpell[i];
}
+1 -1
View File
@@ -1085,7 +1085,7 @@ enum SpellImmunity
enum Targets
{
TARGET_UNIT_CASTER = 1,
TARGET_UNIT_NEARBY_ENEMY = 2, // only one spell has that, but regardless, it's a target type after all
TARGET_UNIT_NEARBY_ENEMY = 2,
TARGET_UNIT_NEARBY_ALLY = 3,
TARGET_UNIT_NEARBY_ALLY_UNK = 4,
TARGET_UNIT_PET = 5,
+42 -20
View File
@@ -3196,44 +3196,66 @@ void Spell::EffectEnergize(uint32 i)
m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power);
// Mad Alchemist's Potion
if (m_spellInfo->Id == 45051)
if (m_spellInfo->Id == SPELL_MAD_ALCHEMISTS_POTION_45051)
{
// find elixirs on target
uint32 elixir_mask = 0;
bool guardianFound = false;
bool battleFound = false;
Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras();
for (Unit::AuraApplicationMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
{
uint32 spell_id = itr->second->GetBase()->GetId();
if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
elixir_mask |= mask;
if (!guardianFound)
if(spellmgr.IsSpellMemberOfSpellGroup(spell_id, SPELL_GROUP_ELIXIR_GUARDIAN))
guardianFound = true;
if (!battleFound)
if(spellmgr.IsSpellMemberOfSpellGroup(spell_id, SPELL_GROUP_ELIXIR_BATTLE))
battleFound = true;
if (battleFound && guardianFound)
break;
}
// get available elixir mask any not active type from battle/guardian (and flask if no any)
elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
// get all available elixirs by mask and spell level
std::vector<uint32> elixirs;
SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
for (SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
std::list<uint32> avalibleElixirs;
if (!guardianFound)
{
if (itr->second & elixir_mask)
SpellGroupSpellMapBounds guardianGroup = spellmgr.GetSpellGroupSpellMapBounds(SPELL_GROUP_ELIXIR_GUARDIAN);
for ( SpellGroupSpellMap::const_iterator itr = guardianGroup.first; itr != guardianGroup.second ; ++itr)
{
if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->second);
if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
continue;
elixirs.push_back(itr->first);
if(spellmgr.IsSpellMemberOfSpellGroup(itr->second, SPELL_GROUP_ELIXIR_SHATTRATH))
continue;
if(spellmgr.IsSpellMemberOfSpellGroup(itr->second, SPELL_GROUP_ELIXIR_UNSTABLE))
continue;
avalibleElixirs.push_back(itr->second);
}
}
if (!battleFound)
{
SpellGroupSpellMapBounds battleGroup = spellmgr.GetSpellGroupSpellMapBounds(SPELL_GROUP_ELIXIR_BATTLE);
for ( SpellGroupSpellMap::const_iterator itr = battleGroup.first; itr != battleGroup.second ; ++itr)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->second);
if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
continue;
if(spellmgr.IsSpellMemberOfSpellGroup(itr->second, SPELL_GROUP_ELIXIR_SHATTRATH))
continue;
if(spellmgr.IsSpellMemberOfSpellGroup(itr->second, SPELL_GROUP_ELIXIR_UNSTABLE))
continue;
avalibleElixirs.push_back(itr->second);
}
}
avalibleElixirs.unique();
if (!elixirs.empty())
if (!avalibleElixirs.empty())
{
// cast random elixir on target
uint32 rand_spell = urand(0,elixirs.size()-1);
m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
uint32 rand_spell = urand(0,avalibleElixirs.size()-1);
std::list<uint32>::iterator itr = avalibleElixirs.begin();
std::advance(itr, rand_spell);
m_caster->CastSpell(unitTarget,*itr,true,m_CastItem);
}
}
}
+26 -15
View File
@@ -1465,14 +1465,15 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellPr
return false;
}
void SpellMgr::LoadSpellElixirs()
void SpellMgr::LoadSpellGroups()
{
mSpellElixirs.clear(); // need for reload case
mSpellSpellGroup.clear(); // need for reload case
mSpellGroupSpell.clear();
uint32 count = 0;
// 0 1
QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, mask FROM spell_elixir");
// 0 1
QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id, spell_id FROM spell_group");
if( !result )
{
@@ -1481,7 +1482,7 @@ void SpellMgr::LoadSpellElixirs()
bar.step();
sLog.outString();
sLog.outString( ">> Loaded %u spell elixir definitions", count );
sLog.outString( ">> Loaded %u spell group definitions", count );
return;
}
@@ -1493,24 +1494,36 @@ void SpellMgr::LoadSpellElixirs()
bar.step();
uint32 entry = fields[0].GetUInt32();
uint8 mask = fields[1].GetUInt8();
uint32 group_id = fields[0].GetUInt32();
uint32 spell_id = fields[1].GetUInt32();
SpellEntry const* spellInfo = sSpellStore.LookupEntry(entry);
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
if (!spellInfo)
{
sLog.outErrorDb("Spell %u listed in `spell_elixir` does not exist", entry);
sLog.outErrorDb("Spell %u listed in `spell_group` does not exist", spell_id);
continue;
}
mSpellElixirs[entry] = mask;
if (GetSpellRank(spell_id) > 1)
{
sLog.outErrorDb("Spell %u listed in `spell_group` is not first rank of spell", spell_id);
continue;
}
if (IsSpellMemberOfSpellGroup(spell_id, (SpellGroup)group_id))
{
sLog.outErrorDb("Spell %u listed in `spell_group` is added twice to one group %u", spell_id, group_id);
continue;
}
mSpellSpellGroup.insert(SpellSpellGroupMap::value_type(spell_id, (SpellGroup)group_id));
mSpellGroupSpell.insert(SpellGroupSpellMap::value_type((SpellGroup)group_id, spell_id));
++count;
} while( result->NextRow() );
sLog.outString();
sLog.outString( ">> Loaded %u spell elixir definitions", count );
sLog.outString( ">> Loaded %u spell group definitions", count );
}
void SpellMgr::LoadSpellStackMasks()
@@ -3311,8 +3324,6 @@ void SpellMgr::LoadSpellRanks()
// fill one chain
while(currentSpell == lastSpell && !finished)
{
bar.step();
Field *fields = result->Fetch();
currentSpell = fields[0].GetUInt32();
@@ -3324,6 +3335,7 @@ void SpellMgr::LoadSpellRanks()
// don't drop the row if we're moving to the next rank
if (currentSpell == lastSpell)
{
bar.step();
rankChain.push_back(std::make_pair(spell_id, rank));
if (!result->NextRow())
finished = true;
@@ -3371,6 +3383,7 @@ void SpellMgr::LoadSpellRanks()
std::list<std::pair<int32, int32> >::iterator itr = rankChain.begin();
do
{
++rows;
int32 addedSpell = itr->first;
mSpellChains[addedSpell].first = lastSpell;
mSpellChains[addedSpell].last = rankChain.back().first;
@@ -3387,8 +3400,6 @@ void SpellMgr::LoadSpellRanks()
mSpellChains[addedSpell].next = itr->first;
}
while (true);
++rows;
} while (!finished);
sLog.outString();
+55 -28
View File
@@ -633,14 +633,23 @@ struct SpellEnchantProcEntry
typedef UNORDERED_MAP<uint32, SpellEnchantProcEntry> SpellEnchantProcEventMap;
typedef UNORDERED_MAP<uint32, SpellBonusEntry> SpellBonusMap;
#define ELIXIR_BATTLE_MASK 0x01
#define ELIXIR_GUARDIAN_MASK 0x02
#define ELIXIR_FLASK_MASK (ELIXIR_BATTLE_MASK|ELIXIR_GUARDIAN_MASK)
#define ELIXIR_UNSTABLE_MASK 0x04
#define ELIXIR_SHATTRATH_MASK 0x08
#define ELIXIR_WELL_FED 0x10 // Some foods have SPELLFAMILY_POTION
enum SpellGroup
{
SPELL_GROUP_ELIXIR_BATTLE = 1,
SPELL_GROUP_ELIXIR_GUARDIAN = 2,
SPELL_GROUP_ELIXIR_UNSTABLE = 3,
SPELL_GROUP_ELIXIR_SHATTRATH = 4,
SPELL_GROUP_WELL_FED = 5,
};
// spell_id, group_id
typedef std::multimap<uint32, SpellGroup> SpellSpellGroupMap;
typedef std::pair<SpellSpellGroupMap::const_iterator,SpellSpellGroupMap::const_iterator> SpellSpellGroupMapBounds;
// group_id, spell_id
typedef std::multimap<SpellGroup, uint32> SpellGroupSpellMap;
typedef std::pair<SpellGroupSpellMap::const_iterator,SpellGroupSpellMap::const_iterator> SpellGroupSpellMapBounds;
typedef std::map<uint32, uint8> SpellElixirMap;
typedef std::map<uint32, uint16> SpellThreatMap;
typedef std::map<uint32, uint32> SpellStackMaskMap;
@@ -860,30 +869,47 @@ class SpellMgr
bool IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const;
SpellElixirMap const& GetSpellElixirMap() const { return mSpellElixirs; }
uint32 GetSpellElixirMask(uint32 spellid) const
SpellSpellGroupMapBounds GetSpellSpellGroupMapBounds(uint32 spell_id) const
{
SpellElixirMap::const_iterator itr = mSpellElixirs.find(spellid);
if(itr==mSpellElixirs.end())
return 0x0;
return itr->second;
spell_id = GetFirstSpellInChain(spell_id);
return SpellSpellGroupMapBounds(mSpellSpellGroup.lower_bound(spell_id),mSpellSpellGroup.upper_bound(spell_id));
}
uint32 IsSpellMemberOfSpellGroup(uint32 spellid, SpellGroup groupid) const
{
SpellSpellGroupMapBounds spellGroup = GetSpellSpellGroupMapBounds(spellid);
for ( SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second ; ++itr)
{
if (itr->second == groupid)
return true;
}
return false;
}
SpellGroupSpellMapBounds GetSpellGroupSpellMapBounds(SpellGroup group_id) const
{
return SpellGroupSpellMapBounds(mSpellGroupSpell.lower_bound(group_id),mSpellGroupSpell.upper_bound(group_id));
}
SpellSpecific GetSpellElixirSpecific(uint32 spellid) const
{
uint32 mask = GetSpellElixirMask(spellid);
if((mask & ELIXIR_FLASK_MASK)==ELIXIR_FLASK_MASK)
return SPELL_SPECIFIC_FLASK_ELIXIR;
else if(mask & ELIXIR_BATTLE_MASK)
return SPELL_SPECIFIC_BATTLE_ELIXIR;
else if(mask & ELIXIR_GUARDIAN_MASK)
return SPELL_SPECIFIC_GUARDIAN_ELIXIR;
else if(mask & ELIXIR_WELL_FED)
return SPELL_SPECIFIC_WELL_FED;
else
return SPELL_SPECIFIC_NORMAL;
SpellSpecific spec = SPELL_SPECIFIC_NORMAL;
SpellSpellGroupMapBounds spellGroup = GetSpellSpellGroupMapBounds(spellid);
for ( SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second ; ++itr)
{
if (itr->second == SPELL_GROUP_ELIXIR_BATTLE
|| itr->second == SPELL_GROUP_ELIXIR_GUARDIAN)
{
if (spec)
{
spec = SPELL_SPECIFIC_FLASK_ELIXIR;
break;
}
else if (itr->second == SPELL_GROUP_ELIXIR_BATTLE)
spec = SPELL_SPECIFIC_BATTLE_ELIXIR;
else if (itr->second == SPELL_GROUP_ELIXIR_GUARDIAN)
spec = SPELL_SPECIFIC_GUARDIAN_ELIXIR;
}
}
return spec;
}
// Used for stacking in spellmgr, and possibly in cancast checks
@@ -1224,7 +1250,7 @@ class SpellMgr
void LoadSpellLearnSkills();
void LoadSpellLearnSpells();
void LoadSpellScriptTarget();
void LoadSpellElixirs();
void LoadSpellGroups();
void LoadSpellProcEvents();
void LoadSpellBonusess();
void LoadSpellTargetPositions();
@@ -1251,7 +1277,8 @@ class SpellMgr
SpellLearnSkillMap mSpellLearnSkills;
SpellLearnSpellMap mSpellLearnSpells;
SpellTargetPositionMap mSpellTargetPositions;
SpellElixirMap mSpellElixirs;
SpellSpellGroupMap mSpellSpellGroup;
SpellGroupSpellMap mSpellGroupSpell;
SpellThreatMap mSpellThreatMap;
SpellProcEventMap mSpellProcEventMap;
SpellBonusMap mSpellBonusMap;
+1 -1
View File
@@ -1312,7 +1312,7 @@ void World::SetInitialWorldSettings()
spellmgr.LoadSpellRequired();
sLog.outString("Loading Spell Elixir types...");
spellmgr.LoadSpellElixirs();
spellmgr.LoadSpellGroups();
sLog.outString("Loading Spell Learn Skills...");
spellmgr.LoadSpellLearnSkills(); // must be after LoadSpellRanks