[10028] Reward group for shareable quests at cast event to creature/go.

This commit is contained in:
VladimirMangos 2010-06-04 18:37:27 +04:00
parent ff3fb9b727
commit 6ebbcd8dbb
5 changed files with 85 additions and 56 deletions

View file

@ -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)

View file

@ -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)))

View file

@ -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; }

View file

@ -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<GOTargetInfo>::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);
}
}
}

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "10027"
#define REVISION_NR "10028"
#endif // __REVISION_NR_H__