Core/Quests: Implement new logic for selecting spell casters for accept/reward spells based on quest flags (#21316)

This commit is contained in:
Lopfest
2019-08-30 19:36:10 +02:00
committed by Shauren
parent 3df2e379ef
commit 7d2cbd4e7c
5 changed files with 64 additions and 23 deletions

View File

@@ -26,6 +26,8 @@
#include "Player.h"
#include "QuestDef.h"
#include "QuestPackets.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "World.h"
#include "WorldSession.h"
@@ -447,8 +449,20 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU
packet.QuestFlags[1] = quest->GetFlagsEx();
packet.SuggestedPartyMembers = quest->GetSuggestedPlayers();
if (quest->GetSrcSpell())
packet.LearnSpells.push_back(quest->GetSrcSpell());
// RewardSpell can teach multiple spells in trigger spell effects. But not all effects must be SPELL_EFFECT_LEARN_SPELL. See example spell 33950
if (quest->GetRewSpell())
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpell());
if (spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL))
{
SpellEffectInfoVector effects = spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE);
for (SpellEffectInfoVector::const_iterator itr = effects.begin(); itr != effects.end(); ++itr)
{
if ((*itr)->IsEffect(SPELL_EFFECT_LEARN_SPELL))
packet.LearnSpells.push_back((*itr)->TriggerSpell);
}
}
}
quest->BuildQuestRewards(packet.Rewards, _session->GetPlayer());

View File

@@ -15181,6 +15181,17 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
UpdatePvPState();
}
if (quest->GetSrcSpell() > 0)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetSrcSpell());
Unit* caster = this;
if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ON_ACCEPT) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER) && !spellInfo->HasTargetType(TARGET_DEST_CASTER_SUMMON))
if (Unit* unit = questGiver->ToUnit())
unit->CastSpell(this, quest->GetSrcSpell(), true);
caster->CastSpell(this, quest->GetSrcSpell(), true);
}
SetQuestSlot(log_slot, quest_id, qtime);
m_QuestStatusSave[quest_id] = QUEST_DEFAULT_SAVE_TYPE;
@@ -15498,16 +15509,12 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
if (quest->GetRewSpell() > 0)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpell());
if (questGiver && questGiver->isType(TYPEMASK_UNIT) &&
!spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_LEARN_SPELL) &&
!spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_CREATE_ITEM) &&
!spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_APPLY_AURA))
{
Unit* caster = this;
if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ON_COMPLETE) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER))
if (Unit* unit = questGiver->ToUnit())
unit->CastSpell(this, quest->GetRewSpell(), true);
}
else
CastSpell(this, quest->GetRewSpell(), true);
caster = unit;
caster->CastSpell(this, quest->GetRewSpell(), true);
}
else
{
@@ -15516,15 +15523,12 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
if (quest->RewardDisplaySpell[i] > 0)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->RewardDisplaySpell[i]);
if (questGiver && questGiver->isType(TYPEMASK_UNIT) &&
!spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_LEARN_SPELL) &&
!spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_CREATE_ITEM))
{
if (Unit* unit = questGiver->ToUnit())
unit->CastSpell(this, quest->RewardDisplaySpell[i], true);
}
else
CastSpell(this, quest->RewardDisplaySpell[i], true);
Unit* caster = this;
if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ON_COMPLETE) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER))
if (Unit * unit = questGiver->ToUnit())
caster = unit;
caster->CastSpell(this, quest->RewardDisplaySpell[i], true);
}
}
}

View File

@@ -201,9 +201,6 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG
_player->PlayerTalkClass->SendCloseGossip();
if (quest->GetSrcSpell() > 0)
_player->CastSpell(_player, quest->GetSrcSpell(), true);
return;
}
}

View File

@@ -1319,6 +1319,30 @@ bool SpellInfo::HasOnlyDamageEffects() const
return true;
}
bool SpellInfo::HasTargetType(::Targets target) const
{
for (auto itr = _effects.begin(); itr != _effects.end(); ++itr)
{
for (SpellEffectInfo const* effect : itr->second)
{
if (effect && (effect->TargetA.GetTarget() == target || effect->TargetB.GetTarget() == target))
return true;
}
}
return false;
}
bool SpellInfo::HasTargetType(uint32 difficulty, ::Targets target) const
{
SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty);
for (SpellEffectInfo const* effect : effects)
{
if (effect && (effect->TargetA.GetTarget() == target || effect->TargetB.GetTarget() == target))
return true;
}
return false;
}
bool SpellInfo::HasAnyAuraInterruptFlag() const
{
return std::find_if(AuraInterruptFlags.begin(), AuraInterruptFlags.end(), [](uint32 flag) { return flag != 0; }) != AuraInterruptFlags.end();

View File

@@ -534,6 +534,8 @@ class TC_GAME_API SpellInfo
bool HasAreaAuraEffect(uint32 difficulty) const;
bool HasAreaAuraEffect() const;
bool HasOnlyDamageEffects() const;
bool HasTargetType(::Targets target) const;
bool HasTargetType(uint32 difficulty, ::Targets target) const;
bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); }
bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); }