aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2015-01-30 23:58:16 +0100
committerShauren <shauren.trinity@gmail.com>2015-01-30 23:58:16 +0100
commit3f28fd304d833eadefff8d343ab45caf8d0575c2 (patch)
treed62b98f75a4607bd1e7cdc2944dce7f730981f6d /src/server/game/Spells
parentbeb1a06ea56526de838cc8e0de15317660a9ddcf (diff)
Core/Spells: Reimplemented automatic spell learning
* Fixed learning/unlearning talents
Diffstat (limited to 'src/server/game/Spells')
-rw-r--r--src/server/game/Spells/Spell.cpp113
-rw-r--r--src/server/game/Spells/Spell.h14
-rw-r--r--src/server/game/Spells/SpellEffects.cpp39
-rw-r--r--src/server/game/Spells/SpellInfo.cpp68
-rw-r--r--src/server/game/Spells/SpellInfo.h1
-rw-r--r--src/server/game/Spells/SpellMgr.cpp82
-rw-r--r--src/server/game/Spells/SpellMgr.h1
7 files changed, 172 insertions, 146 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index d729d76a1d5..173c9a027b2 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -109,34 +109,43 @@ void SpellDestination::RelocateOffset(Position const& offset)
_position.RelocateOffset(offset);
}
-SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0), m_strTarget()
+SpellCastTargets::SpellCastTargets() : m_targetMask(0), m_objectTarget(nullptr), m_itemTarget(nullptr),
+ m_itemTargetEntry(0), m_elevation(0.0f), m_speed(0.0f)
{
- m_objectTarget = NULL;
- m_itemTarget = NULL;
-
- m_itemTargetEntry = 0;
-
- m_targetMask = 0;
}
-SpellCastTargets::SpellCastTargets(Unit* caster, uint32 targetMask, ObjectGuid targetGuid, ObjectGuid itemTargetGuid, ObjectGuid srcTransportGuid, ObjectGuid destTransportGuid, Position srcPos, Position destPos, float elevation, float missileSpeed, std::string targetString) :
- m_targetMask(targetMask), m_objectTargetGUID(targetGuid), m_itemTargetGUID(itemTargetGuid), m_elevation(elevation), m_speed(missileSpeed), m_strTarget(targetString)
+SpellCastTargets::SpellCastTargets(Unit* caster, WorldPackets::Spells::SpellTargetData const& spellTargetData) :
+ m_targetMask(spellTargetData.Flags), m_objectTarget(nullptr), m_itemTarget(nullptr),
+ m_objectTargetGUID(spellTargetData.Unit), m_itemTargetGUID(spellTargetData.Item),
+ m_itemTargetEntry(0), m_elevation(0.0f), m_speed(0.0f), m_strTarget(spellTargetData.Name)
{
- m_objectTarget = NULL;
- m_itemTarget = NULL;
- m_itemTargetEntry = 0;
+ if (spellTargetData.SrcLocation.HasValue)
+ {
+ m_src._transportGUID = spellTargetData.SrcLocation.Value.Transport;
+ Position* pos;
+ if (!m_src._transportGUID.IsEmpty())
+ pos = &m_src._transportOffset;
+ else
+ pos = &m_src._position;
- m_src._transportGUID = srcTransportGuid;
- if (m_src._transportGUID != ObjectGuid::Empty)
- m_src._transportOffset.Relocate(srcPos);
- else
- m_src._position.Relocate(srcPos);
+ pos->Relocate(spellTargetData.SrcLocation.Value.Location);
+ if (spellTargetData.Orientation.HasValue)
+ pos->SetOrientation(spellTargetData.Orientation.Value);
+ }
- m_dst._transportGUID = destTransportGuid;
- if (m_dst._transportGUID != ObjectGuid::Empty)
- m_dst._transportOffset.Relocate(destPos);
- else
- m_dst._position.Relocate(destPos);
+ if (spellTargetData.DstLocation.HasValue)
+ {
+ m_dst._transportGUID = spellTargetData.DstLocation.Value.Transport;
+ Position* pos;
+ if (!m_dst._transportGUID.IsEmpty())
+ pos = &m_dst._transportOffset;
+ else
+ pos = &m_dst._position;
+
+ pos->Relocate(spellTargetData.DstLocation.Value.Location);
+ if (spellTargetData.Orientation.HasValue)
+ pos->SetOrientation(spellTargetData.Orientation.Value);
+ }
Update(caster);
}
@@ -230,39 +239,6 @@ void SpellCastTargets::Write(WorldPackets::Spells::SpellTargetData& data)
if (m_targetMask & TARGET_FLAG_STRING)
data.Name = m_strTarget;
- /*data << uint32(m_targetMask);
-
- if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_MINIPET))
- data << m_objectTargetGUID.WriteAsPacked();
-
- if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM))
- {
- if (m_itemTarget)
- data << m_itemTarget->GetPackGUID();
- else
- data << uint8(0);
- }
-
- if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
- {
- data << m_src._transportGUID.WriteAsPacked(); // relative position guid here - transport for example
- if (!m_src._transportGUID.IsEmpty())
- data << m_src._transportOffset.PositionXYZStream();
- else
- data << m_src._position.PositionXYZStream();
- }
-
- if (m_targetMask & TARGET_FLAG_DEST_LOCATION)
- {
- data << m_dst._transportGUID.WriteAsPacked(); // relative position guid here - transport for example
- if (!m_dst._transportGUID.IsEmpty())
- data << m_dst._transportOffset.PositionXYZStream();
- else
- data << m_dst._position.PositionXYZStream();
- }
-
- if (m_targetMask & TARGET_FLAG_STRING)
- data << m_strTarget;*/
}
ObjectGuid SpellCastTargets::GetOrigUnitTargetGUID() const
@@ -665,7 +641,7 @@ m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)),
m_procEx = 0;
focusObject = NULL;
m_cast_count = 0;
- m_glyphIndex = 0;
+ m_misc.Data = 0;
m_preCastSpell = 0;
m_triggeredByAuraSpell = NULL;
m_spellAura = NULL;
@@ -3744,7 +3720,7 @@ void Spell::SendCastResult(SpellCastResult result)
if (m_caster->ToPlayer()->GetSession()->PlayerLoading()) // don't send cast results at loading time
return;
- SendCastResult(m_caster->ToPlayer(), m_spellInfo, m_cast_count, result, m_customError);
+ SendCastResult(m_caster->ToPlayer(), m_spellInfo, m_cast_count, result, m_customError, SMSG_CAST_FAILED, m_misc.Data);
}
void Spell::SendPetCastResult(SpellCastResult result)
@@ -3756,10 +3732,10 @@ void Spell::SendPetCastResult(SpellCastResult result)
if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
return;
- SendCastResult(owner->ToPlayer(), m_spellInfo, m_cast_count, result, SPELL_CUSTOM_ERROR_NONE, SMSG_PET_CAST_FAILED);
+ SendCastResult(owner->ToPlayer(), m_spellInfo, m_cast_count, result, SPELL_CUSTOM_ERROR_NONE, SMSG_PET_CAST_FAILED, m_misc.Data);
}
-void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/, OpcodeServer opcode /*= SMSG_CAST_FAILED*/)
+void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/, OpcodeServer opcode /*= SMSG_CAST_FAILED*/, uint32 misc /*= 0*/)
{
if (result == SPELL_CAST_OK)
return;
@@ -3870,6 +3846,12 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas
packet.FailedArg1 = missingItem; // first missing item
break;
}
+ case SPELL_FAILED_CANT_UNTALENT:
+ {
+ if (TalentEntry const* talent = sTalentStore.LookupEntry(misc))
+ packet.FailedArg1 = talent->SpellID;
+ break;
+ }
// TODO: SPELL_FAILED_NOT_STANDING
default:
break;
@@ -5606,12 +5588,25 @@ SpellCastResult Spell::CheckCast(bool strict)
break;
}
case SPELL_EFFECT_TALENT_SPEC_SELECT:
+ {
// can't change during already started arena/battleground
if (m_caster->GetTypeId() == TYPEID_PLAYER)
if (Battleground const* bg = m_caster->ToPlayer()->GetBattleground())
if (bg->GetStatus() == STATUS_IN_PROGRESS)
return SPELL_FAILED_NOT_IN_BATTLEGROUND;
break;
+ }
+ case SPELL_EFFECT_REMOVE_TALENT:
+ {
+ if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ return SPELL_FAILED_BAD_TARGETS;
+ TalentEntry const* talent = sTalentStore.LookupEntry(m_misc.TalentId);
+ if (!talent)
+ return SPELL_FAILED_DONT_REPORT;
+ if (m_caster->ToPlayer()->HasSpellCooldown(talent->SpellID))
+ return SPELL_FAILED_CANT_UNTALENT;
+ break;
+ }
default:
break;
}
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index a8ff53b5cb1..48a62ab0e10 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -107,7 +107,7 @@ class SpellCastTargets
{
public:
SpellCastTargets();
- SpellCastTargets(Unit* caster, uint32 targetMask, ObjectGuid targetGuid, ObjectGuid itemTargetGuid, ObjectGuid srcTransportGuid, ObjectGuid destTransportGuid, Position srcPos, Position destPos, float elevation, float missileSpeed, std::string targetString);
+ SpellCastTargets(Unit* caster, WorldPackets::Spells::SpellTargetData const& spellTargetData);
~SpellCastTargets();
void Read(ByteBuffer& data, Unit* caster);
@@ -364,6 +364,7 @@ class Spell
void EffectGiveCurrency(SpellEffIndex effIndex);
void EffectResurrectWithAura(SpellEffIndex effIndex);
void EffectCreateAreaTrigger(SpellEffIndex effIndex);
+ void EffectRemoveTalent(SpellEffIndex effIndex);
typedef std::set<Aura*> UsedSpellMods;
@@ -444,7 +445,7 @@ class Spell
void CheckSrc() { if (!m_targets.HasSrc()) m_targets.SetSrc(*m_caster); }
void CheckDst() { if (!m_targets.HasDst()) m_targets.SetDst(*m_caster); }
- static void SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError = SPELL_CUSTOM_ERROR_NONE, OpcodeServer opcode = SMSG_CAST_FAILED);
+ static void SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError = SPELL_CUSTOM_ERROR_NONE, OpcodeServer opcode = SMSG_CAST_FAILED, uint32 misc = 0);
void SendCastResult(SpellCastResult result);
void SendPetCastResult(SpellCastResult result);
void SendSpellStart();
@@ -475,7 +476,14 @@ class Spell
ObjectGuid m_castItemGUID;
uint32 m_castItemEntry;
uint8 m_cast_count;
- uint32 m_glyphIndex;
+ union
+ {
+ // Alternate names for this value
+ uint32 TalentId;
+ uint32 GlyphSlot;
+
+ uint32 Data;
+ } m_misc;
uint32 m_preCastSpell;
SpellCastTargets m_targets;
int8 m_comboPointGain;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 64e74424f70..7c5ab810ce4 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -250,7 +250,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectUnused, //178 SPELL_EFFECT_178 unused
&Spell::EffectCreateAreaTrigger, //179 SPELL_EFFECT_CREATE_AREATRIGGER
&Spell::EffectNULL, //180 SPELL_EFFECT_UPDATE_AREATRIGGER
- &Spell::EffectNULL, //181 SPELL_EFFECT_REMOVE_TALENT
+ &Spell::EffectRemoveTalent, //181 SPELL_EFFECT_REMOVE_TALENT
&Spell::EffectNULL, //182 SPELL_EFFECT_182
&Spell::EffectNULL, //183 SPELL_EFFECT_183
&Spell::EffectNULL, //184 SPELL_EFFECT_REPUTATION
@@ -3938,7 +3938,7 @@ void Spell::EffectStuck(SpellEffIndex /*effIndex*/)
{
if (!player->GetDeathTimer())
player->RepopAtGraveyard();
-
+
return;
}
@@ -3948,7 +3948,7 @@ void Spell::EffectStuck(SpellEffIndex /*effIndex*/)
player->Kill(player);
return;
}
-
+
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation(), TELE_TO_SPELL);
// Stuck spell trigger Hearthstone cooldown
@@ -4005,7 +4005,7 @@ void Spell::EffectApplyGlyph(SpellEffIndex /*effIndex*/)
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
return;
- if (m_glyphIndex >= MAX_GLYPH_SLOT_INDEX)
+ if (m_misc.GlyphSlot >= MAX_GLYPH_SLOT_INDEX)
return;
Player* player = m_caster->ToPlayer();
@@ -4014,7 +4014,7 @@ void Spell::EffectApplyGlyph(SpellEffIndex /*effIndex*/)
// glyph sockets level requirement
uint8 minLevel = 0;
- switch (m_glyphIndex)
+ switch (m_misc.GlyphSlot)
{
case 0:
case 1:
@@ -4038,7 +4038,7 @@ void Spell::EffectApplyGlyph(SpellEffIndex /*effIndex*/)
{
if (GlyphPropertiesEntry const* newGlyphProperties = sGlyphPropertiesStore.LookupEntry(newGlyph))
{
- if (GlyphSlotEntry const* newGlyphSlot = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
+ if (GlyphSlotEntry const* newGlyphSlot = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_misc.GlyphSlot)))
{
if (newGlyphProperties->Type != newGlyphSlot->Type)
{
@@ -4048,26 +4048,26 @@ void Spell::EffectApplyGlyph(SpellEffIndex /*effIndex*/)
}
// remove old glyph
- if (uint32 oldGlyph = player->GetGlyph(player->GetActiveTalentGroup(), m_glyphIndex))
+ if (uint32 oldGlyph = player->GetGlyph(player->GetActiveTalentGroup(), m_misc.GlyphSlot))
{
if (GlyphPropertiesEntry const* oldGlyphProperties = sGlyphPropertiesStore.LookupEntry(oldGlyph))
{
player->RemoveAurasDueToSpell(oldGlyphProperties->SpellID);
- player->SetGlyph(m_glyphIndex, 0);
+ player->SetGlyph(m_misc.GlyphSlot, 0);
}
}
player->CastSpell(m_caster, newGlyphProperties->SpellID, true);
- player->SetGlyph(m_glyphIndex, newGlyph);
+ player->SetGlyph(m_misc.GlyphSlot, newGlyph);
player->SendTalentsInfoData();
}
}
- else if (uint32 oldGlyph = player->GetGlyph(player->GetActiveTalentGroup(), m_glyphIndex)) // Removing the glyph, get the old one
+ else if (uint32 oldGlyph = player->GetGlyph(player->GetActiveTalentGroup(), m_misc.GlyphSlot)) // Removing the glyph, get the old one
{
if (GlyphPropertiesEntry const* oldGlyphProperties = sGlyphPropertiesStore.LookupEntry(oldGlyph))
{
player->RemoveAurasDueToSpell(oldGlyphProperties->SpellID);
- player->SetGlyph(m_glyphIndex, 0);
+ player->SetGlyph(m_misc.GlyphSlot, 0);
player->SendTalentsInfoData();
}
}
@@ -5768,3 +5768,20 @@ void Spell::EffectCreateAreaTrigger(SpellEffIndex /*effIndex*/)
if (!areaTrigger->CreateAreaTrigger(sObjectMgr->GetGenerator<HighGuid::AreaTrigger>()->Generate(), triggerEntry, GetCaster(), GetSpellInfo(), pos))
delete areaTrigger;
}
+
+void Spell::EffectRemoveTalent(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ TalentEntry const* talent = sTalentStore.LookupEntry(m_misc.TalentId);
+ if (!talent)
+ return;
+
+ Player* player = unitTarget ? unitTarget->ToPlayer() : nullptr;
+ if (!player)
+ return;
+
+ player->RemoveTalent(talent);
+ player->SendTalentsInfoData();
+}
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 1f6b5238137..a70c73de6df 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -875,9 +875,71 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 177 SPELL_EFFECT_177
{EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 178 SPELL_EFFECT_178
{EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 179 SPELL_EFFECT_CREATE_AREATRIGGER
- {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 180 SPELL_EFFECT_180
- {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 181 SPELL_EFFECT_181
- {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 182 SPELL_EFFECT_182
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 180 SPELL_EFFECT_UPDATE_AREATRIGGER
+ {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 181 SPELL_EFFECT_REMOVE_TALENT
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 182 SPELL_EFFECT_182
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 183 SPELL_EFFECT_183
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 184 SPELL_EFFECT_REPUTATION_2
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 185 SPELL_EFFECT_185
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 186 SPELL_EFFECT_186
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 187 SPELL_EFFECT_RANDOMIZE_ARCHAEOLOGY_DIGSITES
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 188 SPELL_EFFECT_188
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 189 SPELL_EFFECT_LOOT
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 190 SPELL_EFFECT_190
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 191 SPELL_EFFECT_TELEPORT_TO_DIGSITE
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 192 SPELL_EFFECT_192
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 193 SPELL_EFFECT_193
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 194 SPELL_EFFECT_194
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 195 SPELL_EFFECT_195
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 196 SPELL_EFFECT_196
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 197 SPELL_EFFECT_197
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 198 SPELL_EFFECT_198
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 199 SPELL_EFFECT_199
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 200 SPELL_EFFECT_HEAL_BATTLEPET_PCT
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 201 SPELL_EFFECT_ENABLE_BATTLE_PETS
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 202 SPELL_EFFECT_202
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 203 SPELL_EFFECT_203
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 204 SPELL_EFFECT_204
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 205 SPELL_EFFECT_205
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 206 SPELL_EFFECT_206
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 207 SPELL_EFFECT_207
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 208 SPELL_EFFECT_208
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 209 SPELL_EFFECT_209
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 210 SPELL_EFFECT_210
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 211 SPELL_EFFECT_211
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 212 SPELL_EFFECT_212
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 213 SPELL_EFFECT_213
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 214 SPELL_EFFECT_214
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 215 SPELL_EFFECT_215
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 216 SPELL_EFFECT_216
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 217 SPELL_EFFECT_217
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 218 SPELL_EFFECT_218
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 219 SPELL_EFFECT_219
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 220 SPELL_EFFECT_220
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 221 SPELL_EFFECT_221
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 222 SPELL_EFFECT_222
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 223 SPELL_EFFECT_223
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 224 SPELL_EFFECT_224
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 225 SPELL_EFFECT_225
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 226 SPELL_EFFECT_226
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 227 SPELL_EFFECT_227
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 228 SPELL_EFFECT_228
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 229 SPELL_EFFECT_229
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 230 SPELL_EFFECT_230
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 231 SPELL_EFFECT_231
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 232 SPELL_EFFECT_232
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 233 SPELL_EFFECT_233
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 234 SPELL_EFFECT_234
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 235 SPELL_EFFECT_235
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 236 SPELL_EFFECT_236
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 237 SPELL_EFFECT_237
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 238 SPELL_EFFECT_238
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 239 SPELL_EFFECT_239
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 240 SPELL_EFFECT_240
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 241 SPELL_EFFECT_241
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 242 SPELL_EFFECT_242
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 243 SPELL_EFFECT_243
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 244 SPELL_EFFECT_244
};
SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntryMap effects)
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 5b9cfacb56b..b585588726e 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -186,6 +186,7 @@ enum SpellCustomAttributes
SPELL_ATTR0_CU_CONE_LINE = 0x00000004,
SPELL_ATTR0_CU_SHARE_DAMAGE = 0x00000008,
SPELL_ATTR0_CU_NO_INITIAL_THREAT = 0x00000010,
+ SPELL_ATTR0_CU_IS_TALENT = 0x00000020,
SPELL_ATTR0_CU_AURA_CC = 0x00000040,
SPELL_ATTR0_CU_DIRECT_DAMAGE = 0x00000100,
SPELL_ATTR0_CU_CHARGE = 0x00000200,
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index d8bfed43c2b..85a04c6bf4e 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -1251,73 +1251,8 @@ void SpellMgr::UnloadSpellInfoChains()
mSpellChains.clear();
}
-void SpellMgr::LoadSpellTalentRanks()
-{
- /* TODO: 6.x remove this
- // cleanup core data before reload - remove reference to ChainNode from SpellInfo
- UnloadSpellInfoChains();
-
- for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
- {
- TalentEntry const* talentInfo = sTalentStore.LookupEntry(i);
- if (!talentInfo)
- continue;
-
- SpellInfo const* lastSpell = NULL;
- for (uint8 rank = MAX_TALENT_RANK - 1; rank > 0; --rank)
- {
- if (talentInfo->RankID[rank])
- {
- lastSpell = GetSpellInfo(talentInfo->RankID[rank]);
- break;
- }
- }
-
- if (!lastSpell)
- continue;
-
- SpellInfo const* firstSpell = GetSpellInfo(talentInfo->RankID[0]);
- if (!firstSpell)
- {
- TC_LOG_ERROR("spells", "SpellMgr::LoadSpellTalentRanks: First Rank Spell %u for TalentEntry %u does not exist.", talentInfo->RankID[0], i);
- continue;
- }
-
- SpellInfo const* prevSpell = NULL;
- for (uint8 rank = 0; rank < MAX_TALENT_RANK; ++rank)
- {
- uint32 spellId = talentInfo->RankID[rank];
- if (!spellId)
- break;
-
- SpellInfo const* currentSpell = GetSpellInfo(spellId);
- if (!currentSpell)
- {
- TC_LOG_ERROR("spells", "SpellMgr::LoadSpellTalentRanks: Spell %u (Rank: %u) for TalentEntry %u does not exist.", spellId, rank + 1, i);
- break;
- }
-
- SpellChainNode node;
- node.first = firstSpell;
- node.last = lastSpell;
- node.rank = rank + 1;
-
- node.prev = prevSpell;
- node.next = node.rank < MAX_TALENT_RANK ? GetSpellInfo(talentInfo->RankID[node.rank]) : NULL;
-
- mSpellChains[spellId] = node;
- mSpellInfoMap[spellId]->ChainEntry = &mSpellChains[spellId];
-
- prevSpell = currentSpell;
- }
- }*/
-}
-
void SpellMgr::LoadSpellRanks()
{
- // cleanup data and load spell ranks for talents from dbc
- LoadSpellTalentRanks();
-
uint32 oldMSTime = getMSTime();
// 0 1 2
@@ -1553,7 +1488,8 @@ void SpellMgr::LoadSpellLearnSpells()
node.active = fields[2].GetBool();
node.autoLearned = false;
- if (!GetSpellInfo(spell_id))
+ SpellInfo const* spellInfo = GetSpellInfo(spell_id);
+ if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "Spell %u listed in `spell_learn_spell` does not exist", spell_id);
continue;
@@ -1565,7 +1501,7 @@ void SpellMgr::LoadSpellLearnSpells()
continue;
}
- if (GetTalentBySpellID(node.spell))
+ if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IS_TALENT))
{
TC_LOG_ERROR("sql.sql", "Spell %u listed in `spell_learn_spell` attempt learning talent spell %u, skipped", spell_id, node.spell);
continue;
@@ -1603,7 +1539,7 @@ void SpellMgr::LoadSpellLearnSpells()
// talent or passive spells or skill-step spells auto-cast and not need dependent learning,
// pet teaching spells must not be dependent learning (cast)
// other required explicit dependent learning
- dbc_node.autoLearned = effect->TargetA.GetTarget() == TARGET_UNIT_PET || GetTalentBySpellID(spell) || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP);
+ dbc_node.autoLearned = effect->TargetA.GetTarget() == TARGET_UNIT_PET || entry->HasAttribute(SPELL_ATTR0_CU_IS_TALENT) || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP);
SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(spell);
@@ -1654,7 +1590,7 @@ void SpellMgr::LoadSpellLearnSpells()
{
if (itr->second.spell == mastery)
{
- TC_LOG_ERROR("sql.sql", "Found redundant record (entry: %u, SpellID: %u) in `spell_learn_spell`, spell added automatically as mastery learned spell from TalentTab.dbc", masteryMainSpell, mastery);
+ TC_LOG_ERROR("sql.sql", "Found redundant record (entry: %u, SpellID: %u) in `spell_learn_spell`, spell added automatically as mastery learned spell from ChrSpecialization.dbc", masteryMainSpell, mastery);
found = true;
break;
}
@@ -2873,6 +2809,11 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
TC_LOG_INFO("server.loading", ">> Loaded %u spell custom attributes from DB in %u ms", count, GetMSTimeDiffToNow(oldMSTime2));
}
+ std::set<uint32> talentSpells;
+ for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
+ if (TalentEntry const* talentInfo = sTalentStore.LookupEntry(i))
+ talentSpells.insert(talentInfo->SpellID);
+
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
spellInfo = mSpellInfoMap[i];
@@ -2986,6 +2927,9 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
if (spellInfo->SpellVisual[0] == 3879)
spellInfo->AttributesCu |= SPELL_ATTR0_CU_CONE_BACK;
+ if (talentSpells.count(spellInfo->Id))
+ spellInfo->AttributesCu |= SPELL_ATTR0_CU_IS_TALENT;
+
switch (spellInfo->SpellFamilyName)
{
case SPELLFAMILY_WARRIOR:
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 74423f6e4f3..36ffe105c54 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -695,7 +695,6 @@ class SpellMgr
// Loading data at server startup
void UnloadSpellInfoChains();
- void LoadSpellTalentRanks();
void LoadSpellRanks();
void LoadSpellRequired();
void LoadSpellLearnSkills();