diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index c6a4a00c9..a446784bb 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -1034,7 +1034,8 @@ void GameObject::Use(Unit* user) break; } - player->CastedCreatureOrGO(info->id, GetObjectGuid(), 0); + player->RewardPlayerAndGroupAtCast(this); + } if (uint32 trapEntry = info->goober.linkedTrapId) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index ebccec773..830836da6 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -14331,71 +14331,75 @@ void Player::KilledMonsterCredit( uint32 entry, ObjectGuid guid ) } } -void Player::CastedCreatureOrGO( uint32 entry, ObjectGuid guid, uint32 spell_id ) +void Player::CastedCreatureOrGO( uint32 entry, ObjectGuid guid, uint32 spell_id, bool original_caster ) { bool isCreature = guid.IsCreature(); uint32 addCastCount = 1; - for( int i = 0; i < MAX_QUEST_LOG_SIZE; ++i) + for(int i = 0; i < MAX_QUEST_LOG_SIZE; ++i) { uint32 questid = GetQuestSlotQuestId(i); - if(!questid) + if (!questid) continue; Quest const* qInfo = sObjectMgr.GetQuestTemplate(questid); - if ( !qInfo ) + if (!qInfo) + continue; + + if (!original_caster && !qInfo->HasFlag(QUEST_FLAGS_SHARABLE)) + continue; + + if (!qInfo->HasFlag(QUEST_MANGOS_FLAGS_KILL_OR_CAST)) continue; QuestStatusData& q_status = mQuestStatus[questid]; - if ( q_status.m_status == QUEST_STATUS_INCOMPLETE ) + if (q_status.m_status != QUEST_STATUS_INCOMPLETE) + continue; + + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) { - if( qInfo->HasFlag( QUEST_MANGOS_FLAGS_KILL_OR_CAST ) ) + // skip kill creature objective (0) or wrong spell casts + if (qInfo->ReqSpell[j] != spell_id) + continue; + + uint32 reqTarget = 0; + + if (isCreature) { - for (int j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) - { - // skip kill creature objective (0) or wrong spell casts - if(qInfo->ReqSpell[j] != spell_id ) - continue; - - uint32 reqTarget = 0; - - if(isCreature) - { - // creature activate objectives - if(qInfo->ReqCreatureOrGOId[j] > 0) - // checked at quest_template loading - reqTarget = qInfo->ReqCreatureOrGOId[j]; - } - else - { - // GO activate objective - if(qInfo->ReqCreatureOrGOId[j] < 0) - // checked at quest_template loading - reqTarget = - qInfo->ReqCreatureOrGOId[j]; - } - - // other not this creature/GO related objectives - if( reqTarget != entry ) - continue; - - uint32 reqCastCount = qInfo->ReqCreatureOrGOCount[j]; - uint32 curCastCount = q_status.m_creatureOrGOcount[j]; - if ( curCastCount < reqCastCount ) - { - q_status.m_creatureOrGOcount[j] = curCastCount + addCastCount; - if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; - - SendQuestUpdateAddCreatureOrGo( qInfo, guid, j, curCastCount, addCastCount); - } - - if ( CanCompleteQuest( questid ) ) - CompleteQuest( questid ); - - // same objective target can be in many active quests, but not in 2 objectives for single quest (code optimization). - break; - } + // creature activate objectives + if (qInfo->ReqCreatureOrGOId[j] > 0) + // checked at quest_template loading + reqTarget = qInfo->ReqCreatureOrGOId[j]; } + else + { + // GO activate objective + if (qInfo->ReqCreatureOrGOId[j] < 0) + // checked at quest_template loading + reqTarget = - qInfo->ReqCreatureOrGOId[j]; + } + + // other not this creature/GO related objectives + if (reqTarget != entry) + continue; + + uint32 reqCastCount = qInfo->ReqCreatureOrGOCount[j]; + uint32 curCastCount = q_status.m_creatureOrGOcount[j]; + if (curCastCount < reqCastCount) + { + q_status.m_creatureOrGOcount[j] = curCastCount + addCastCount; + if (q_status.uState != QUEST_NEW) + q_status.uState = QUEST_CHANGED; + + SendQuestUpdateAddCreatureOrGo( qInfo, guid, j, curCastCount, addCastCount); + } + + if (CanCompleteQuest(questid)) + CompleteQuest(questid); + + // same objective target can be in many active quests, but not in 2 objectives for single quest (code optimization). + break; } } } @@ -20170,6 +20174,29 @@ void Player::RewardPlayerAndGroupAtEvent(uint32 creature_id, WorldObject* pRewar KilledMonsterCredit(creature_id, creature_guid); } +void Player::RewardPlayerAndGroupAtCast(WorldObject* pRewardSource, uint32 spellid) +{ + // prepare data for near group iteration + if(Group *pGroup = GetGroup()) + { + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* pGroupGuy = itr->getSource(); + if(!pGroupGuy) + continue; + + if(!pGroupGuy->IsAtGroupRewardDistance(pRewardSource)) + continue; // member (alive or dead) or his corpse at req. distance + + // quest objectives updated only for alive group member or dead but with not released body + if(pGroupGuy->isAlive()|| !pGroupGuy->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + pGroupGuy->CastedCreatureOrGO(pRewardSource->GetEntry(), pRewardSource->GetObjectGuid(), spellid, pGroupGuy == this); + } + } + else // if (!pGroup) + CastedCreatureOrGO(pRewardSource->GetEntry(), pRewardSource->GetObjectGuid(), spellid); +} + bool Player::IsAtGroupRewardDistance(WorldObject const* pRewardSource) const { if (pRewardSource->IsWithinDistInMap(this,sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE))) diff --git a/src/game/Player.h b/src/game/Player.h index 371ed886f..ebb629571 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1404,7 +1404,7 @@ class MANGOS_DLL_SPEC Player : public Unit void ItemRemovedQuestCheck( uint32 entry, uint32 count ); void KilledMonster( CreatureInfo const* cInfo, ObjectGuid guid ); void KilledMonsterCredit( uint32 entry, ObjectGuid guid ); - void CastedCreatureOrGO( uint32 entry, ObjectGuid guid, uint32 spell_id ); + void CastedCreatureOrGO( uint32 entry, ObjectGuid guid, uint32 spell_id, bool original_caster = true ); void TalkedToCreature( uint32 entry, ObjectGuid guid ); void MoneyChanged( uint32 value ); void ReputationChanged(FactionEntry const* factionEntry ); @@ -1906,6 +1906,7 @@ class MANGOS_DLL_SPEC Player : public Unit bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const; void RewardSinglePlayerAtKill(Unit* pVictim); void RewardPlayerAndGroupAtEvent(uint32 creature_id,WorldObject* pRewardSource); + void RewardPlayerAndGroupAtCast(WorldObject* pRewardSource, uint32 spellid = 0); bool isHonorOrXPTarget(Unit* pVictim) const; ReputationMgr& GetReputationMgr() { return m_reputationMgr; } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index c06273bb0..994d5fe26 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1083,7 +1083,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) // ignore pets or autorepeat/melee casts for speed (not exist quest for spells (hm... ) if (real_caster && !((Creature*)unit)->isPet() && !IsAutoRepeat() && !IsNextMeleeSwingSpell() && !IsChannelActive()) if (Player* p = real_caster->GetCharmerOrOwnerPlayerOrPlayerItself()) - p->CastedCreatureOrGO(unit->GetEntry(), unit->GetObjectGuid(), m_spellInfo->Id); + p->RewardPlayerAndGroupAtCast(unit, m_spellInfo->Id); if(((Creature*)unit)->AI()) ((Creature*)unit)->AI()->SpellHit(m_caster, m_spellInfo); @@ -1249,7 +1249,7 @@ void Spell::DoAllEffectOnTarget(GOTargetInfo *target) if( !IsAutoRepeat() && !IsNextMeleeSwingSpell() && !IsChannelActive() ) { if ( Player* p = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself() ) - p->CastedCreatureOrGO(go->GetEntry(), go->GetObjectGuid(), m_spellInfo->Id); + p->RewardPlayerAndGroupAtCast(go, m_spellInfo->Id); } } @@ -3147,7 +3147,7 @@ void Spell::update(uint32 difftime) if (unit == NULL) continue; - p->CastedCreatureOrGO(unit->GetEntry(), unit->GetObjectGuid(), m_spellInfo->Id); + p->RewardPlayerAndGroupAtCast(unit, m_spellInfo->Id); } for(std::list::iterator ihit = m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit) @@ -3158,7 +3158,7 @@ void Spell::update(uint32 difftime) if(!go) continue; - p->CastedCreatureOrGO(go->GetEntry(), go->GetObjectGuid(), m_spellInfo->Id); + p->RewardPlayerAndGroupAtCast(go, m_spellInfo->Id); } } } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3c7c66877..7f993ed97 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10027" + #define REVISION_NR "10028" #endif // __REVISION_NR_H__