mirror of
https://github.com/mangosfour/server.git
synced 2025-12-18 19:37:01 +00:00
[10631] Small code style cleanup in quest related functions
Signed-off-by: NoFantasy <nofantasy@nf.no>
This commit is contained in:
parent
da07caba28
commit
2fe87fc3c7
2 changed files with 125 additions and 103 deletions
|
|
@ -13269,12 +13269,12 @@ Quest const* Player::GetNextQuest(uint64 guid, Quest const *pQuest)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::CanSeeStartQuest( Quest const *pQuest ) const
|
bool Player::CanSeeStartQuest(Quest const *pQuest) const
|
||||||
{
|
{
|
||||||
if (SatisfyQuestClass(pQuest, false) && SatisfyQuestRace(pQuest, false) && SatisfyQuestSkill(pQuest, false) &&
|
if (SatisfyQuestClass(pQuest, false) && SatisfyQuestRace(pQuest, false) && SatisfyQuestSkill(pQuest, false) &&
|
||||||
SatisfyQuestExclusiveGroup( pQuest, false ) && SatisfyQuestReputation( pQuest, false ) &&
|
SatisfyQuestExclusiveGroup(pQuest, false) && SatisfyQuestReputation(pQuest, false) &&
|
||||||
SatisfyQuestPreviousQuest( pQuest, false ) && SatisfyQuestNextChain( pQuest, false ) &&
|
SatisfyQuestPreviousQuest(pQuest, false) && SatisfyQuestNextChain(pQuest, false) &&
|
||||||
SatisfyQuestPrevChain( pQuest, false ) && SatisfyQuestDay( pQuest, false ) && SatisfyQuestWeek( pQuest, false ))
|
SatisfyQuestPrevChain(pQuest, false) && SatisfyQuestDay(pQuest, false) && SatisfyQuestWeek(pQuest, false))
|
||||||
{
|
{
|
||||||
return getLevel() + sWorld.getConfig(CONFIG_UINT32_QUEST_HIGH_LEVEL_HIDE_DIFF) >= pQuest->GetMinLevel();
|
return getLevel() + sWorld.getConfig(CONFIG_UINT32_QUEST_HIGH_LEVEL_HIDE_DIFF) >= pQuest->GetMinLevel();
|
||||||
}
|
}
|
||||||
|
|
@ -13282,19 +13282,19 @@ bool Player::CanSeeStartQuest( Quest const *pQuest ) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::CanTakeQuest( Quest const *pQuest, bool msg ) const
|
bool Player::CanTakeQuest(Quest const *pQuest, bool msg) const
|
||||||
{
|
{
|
||||||
return SatisfyQuestStatus( pQuest, msg ) && SatisfyQuestExclusiveGroup( pQuest, msg )
|
return SatisfyQuestStatus(pQuest, msg) && SatisfyQuestExclusiveGroup(pQuest, msg) &&
|
||||||
&& SatisfyQuestClass(pQuest, msg) && SatisfyQuestRace(pQuest, msg) && SatisfyQuestLevel(pQuest, msg)
|
SatisfyQuestClass(pQuest, msg) && SatisfyQuestRace(pQuest, msg) && SatisfyQuestLevel(pQuest, msg) &&
|
||||||
&& SatisfyQuestSkill(pQuest, msg) && SatisfyQuestReputation(pQuest, msg)
|
SatisfyQuestSkill(pQuest, msg) && SatisfyQuestReputation(pQuest, msg) &&
|
||||||
&& SatisfyQuestPreviousQuest( pQuest, msg ) && SatisfyQuestTimed( pQuest, msg )
|
SatisfyQuestPreviousQuest(pQuest, msg) && SatisfyQuestTimed(pQuest, msg) &&
|
||||||
&& SatisfyQuestNextChain( pQuest, msg ) && SatisfyQuestPrevChain( pQuest, msg )
|
SatisfyQuestNextChain(pQuest, msg) && SatisfyQuestPrevChain(pQuest, msg) &&
|
||||||
&& SatisfyQuestDay( pQuest, msg ) && SatisfyQuestWeek( pQuest, msg );
|
SatisfyQuestDay(pQuest, msg) && SatisfyQuestWeek(pQuest, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::CanAddQuest( Quest const *pQuest, bool msg ) const
|
bool Player::CanAddQuest(Quest const *pQuest, bool msg) const
|
||||||
{
|
{
|
||||||
if (!SatisfyQuestLog( msg ))
|
if (!SatisfyQuestLog(msg))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!CanGiveQuestSourceItem(pQuest))
|
if (!CanGiveQuestSourceItem(pQuest))
|
||||||
|
|
@ -13303,7 +13303,7 @@ bool Player::CanAddQuest( Quest const *pQuest, bool msg ) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::CanCompleteQuest( uint32 quest_id ) const
|
bool Player::CanCompleteQuest(uint32 quest_id) const
|
||||||
{
|
{
|
||||||
if (!quest_id)
|
if (!quest_id)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -13342,7 +13342,7 @@ bool Player::CanCompleteQuest( uint32 quest_id ) const
|
||||||
// incomplete quest have status data
|
// incomplete quest have status data
|
||||||
QuestStatusData const& q_status = q_itr->second;
|
QuestStatusData const& q_status = q_itr->second;
|
||||||
|
|
||||||
if (qInfo->HasFlag( QUEST_MANGOS_FLAGS_DELIVER ))
|
if (qInfo->HasFlag(QUEST_MANGOS_FLAGS_DELIVER))
|
||||||
{
|
{
|
||||||
for(int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
|
for(int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -13363,10 +13363,10 @@ bool Player::CanCompleteQuest( uint32 quest_id ) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qInfo->HasFlag( QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT ) && !q_status.m_explored)
|
if (qInfo->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT) && !q_status.m_explored)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (qInfo->HasFlag( QUEST_MANGOS_FLAGS_TIMED ) && q_status.m_timer == 0)
|
if (qInfo->HasFlag(QUEST_MANGOS_FLAGS_TIMED) && q_status.m_timer == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (qInfo->GetRewOrReqMoney() < 0)
|
if (qInfo->GetRewOrReqMoney() < 0)
|
||||||
|
|
@ -13382,7 +13382,7 @@ bool Player::CanCompleteQuest( uint32 quest_id ) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::CanCompleteRepeatableQuest( Quest const *pQuest ) const
|
bool Player::CanCompleteRepeatableQuest(Quest const *pQuest) const
|
||||||
{
|
{
|
||||||
// Solve problem that player don't have the quest and try complete it.
|
// Solve problem that player don't have the quest and try complete it.
|
||||||
// if repeatable she must be able to complete event if player don't have it.
|
// if repeatable she must be able to complete event if player don't have it.
|
||||||
|
|
@ -13390,7 +13390,7 @@ bool Player::CanCompleteRepeatableQuest( Quest const *pQuest ) const
|
||||||
if (!CanTakeQuest(pQuest, false))
|
if (!CanTakeQuest(pQuest, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (pQuest->HasFlag( QUEST_MANGOS_FLAGS_DELIVER) )
|
if (pQuest->HasFlag(QUEST_MANGOS_FLAGS_DELIVER))
|
||||||
for(int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
|
for(int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
|
||||||
if (pQuest->ReqItemId[i] && pQuest->ReqItemCount[i] && !HasItemCount(pQuest->ReqItemId[i], pQuest->ReqItemCount[i]))
|
if (pQuest->ReqItemId[i] && pQuest->ReqItemCount[i] && !HasItemCount(pQuest->ReqItemId[i], pQuest->ReqItemCount[i]))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -13401,14 +13401,14 @@ bool Player::CanCompleteRepeatableQuest( Quest const *pQuest ) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::CanRewardQuest( Quest const *pQuest, bool msg ) const
|
bool Player::CanRewardQuest(Quest const *pQuest, bool msg) const
|
||||||
{
|
{
|
||||||
// not auto complete quest and not completed quest (only cheating case, then ignore without message)
|
// not auto complete quest and not completed quest (only cheating case, then ignore without message)
|
||||||
if (!pQuest->IsAutoComplete() && GetQuestStatus(pQuest->GetQuestId()) != QUEST_STATUS_COMPLETE)
|
if (!pQuest->IsAutoComplete() && GetQuestStatus(pQuest->GetQuestId()) != QUEST_STATUS_COMPLETE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// daily quest can't be rewarded (25 daily quest already completed)
|
// daily quest can't be rewarded (25 daily quest already completed)
|
||||||
if (!SatisfyQuestDay(pQuest,true) || !SatisfyQuestWeek(pQuest,true))
|
if (!SatisfyQuestDay(pQuest, true) || !SatisfyQuestWeek(pQuest, true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// rewarded and not repeatable quest (only cheating case, then ignore without message)
|
// rewarded and not repeatable quest (only cheating case, then ignore without message)
|
||||||
|
|
@ -13424,7 +13424,8 @@ bool Player::CanRewardQuest( Quest const *pQuest, bool msg ) const
|
||||||
GetItemCount(pQuest->ReqItemId[i]) < pQuest->ReqItemCount[i])
|
GetItemCount(pQuest->ReqItemId[i]) < pQuest->ReqItemCount[i])
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL, pQuest->ReqItemId[i]);
|
SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL, pQuest->ReqItemId[i]);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13437,7 +13438,7 @@ bool Player::CanRewardQuest( Quest const *pQuest, bool msg ) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::CanRewardQuest( Quest const *pQuest, uint32 reward, bool msg ) const
|
bool Player::CanRewardQuest(Quest const *pQuest, uint32 reward, bool msg) const
|
||||||
{
|
{
|
||||||
// prevent receive reward with quest items in bank or for not completed quest
|
// prevent receive reward with quest items in bank or for not completed quest
|
||||||
if (!CanRewardQuest(pQuest,msg))
|
if (!CanRewardQuest(pQuest,msg))
|
||||||
|
|
@ -13451,7 +13452,7 @@ bool Player::CanRewardQuest( Quest const *pQuest, uint32 reward, bool msg ) cons
|
||||||
uint8 res = CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewChoiceItemId[reward], pQuest->RewChoiceItemCount[reward] );
|
uint8 res = CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewChoiceItemId[reward], pQuest->RewChoiceItemCount[reward] );
|
||||||
if (res != EQUIP_ERR_OK)
|
if (res != EQUIP_ERR_OK)
|
||||||
{
|
{
|
||||||
SendEquipError( res, NULL, NULL, pQuest->RewChoiceItemId[reward] );
|
SendEquipError(res, NULL, NULL, pQuest->RewChoiceItemId[reward]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13467,7 +13468,7 @@ bool Player::CanRewardQuest( Quest const *pQuest, uint32 reward, bool msg ) cons
|
||||||
uint8 res = CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewItemId[i], pQuest->RewItemCount[i] );
|
uint8 res = CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewItemId[i], pQuest->RewItemCount[i] );
|
||||||
if (res != EQUIP_ERR_OK)
|
if (res != EQUIP_ERR_OK)
|
||||||
{
|
{
|
||||||
SendEquipError( res, NULL, NULL );
|
SendEquipError(res, NULL, NULL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13559,46 +13560,46 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver )
|
||||||
UpdateForQuestWorldObjects();
|
UpdateForQuestWorldObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::CompleteQuest( uint32 quest_id )
|
void Player::CompleteQuest(uint32 quest_id)
|
||||||
{
|
{
|
||||||
if( quest_id )
|
if (quest_id)
|
||||||
{
|
{
|
||||||
SetQuestStatus( quest_id, QUEST_STATUS_COMPLETE );
|
SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE);
|
||||||
|
|
||||||
uint16 log_slot = FindQuestSlot( quest_id );
|
uint16 log_slot = FindQuestSlot(quest_id);
|
||||||
if( log_slot < MAX_QUEST_LOG_SIZE)
|
if (log_slot < MAX_QUEST_LOG_SIZE)
|
||||||
SetQuestSlotState(log_slot,QUEST_STATE_COMPLETE);
|
SetQuestSlotState(log_slot, QUEST_STATE_COMPLETE);
|
||||||
|
|
||||||
if(Quest const* qInfo = sObjectMgr.GetQuestTemplate(quest_id))
|
if (Quest const* qInfo = sObjectMgr.GetQuestTemplate(quest_id))
|
||||||
{
|
{
|
||||||
if( qInfo->HasFlag(QUEST_FLAGS_AUTO_REWARDED) )
|
if (qInfo->HasFlag(QUEST_FLAGS_AUTO_REWARDED))
|
||||||
RewardQuest(qInfo,0,this,false);
|
RewardQuest(qInfo, 0, this, false);
|
||||||
else
|
else
|
||||||
SendQuestComplete( quest_id );
|
SendQuestComplete(quest_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::IncompleteQuest( uint32 quest_id )
|
void Player::IncompleteQuest(uint32 quest_id)
|
||||||
{
|
{
|
||||||
if( quest_id )
|
if (quest_id)
|
||||||
{
|
{
|
||||||
SetQuestStatus( quest_id, QUEST_STATUS_INCOMPLETE );
|
SetQuestStatus(quest_id, QUEST_STATUS_INCOMPLETE);
|
||||||
|
|
||||||
uint16 log_slot = FindQuestSlot( quest_id );
|
uint16 log_slot = FindQuestSlot( quest_id );
|
||||||
if( log_slot < MAX_QUEST_LOG_SIZE)
|
if (log_slot < MAX_QUEST_LOG_SIZE)
|
||||||
RemoveQuestSlotState(log_slot,QUEST_STATE_COMPLETE);
|
RemoveQuestSlotState(log_slot, QUEST_STATE_COMPLETE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver, bool announce )
|
void Player::RewardQuest(Quest const *pQuest, uint32 reward, Object* questGiver, bool announce)
|
||||||
{
|
{
|
||||||
uint32 quest_id = pQuest->GetQuestId();
|
uint32 quest_id = pQuest->GetQuestId();
|
||||||
|
|
||||||
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i )
|
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i )
|
||||||
{
|
{
|
||||||
if (pQuest->ReqItemId[i])
|
if (pQuest->ReqItemId[i])
|
||||||
DestroyItemCount( pQuest->ReqItemId[i], pQuest->ReqItemCount[i], true);
|
DestroyItemCount(pQuest->ReqItemId[i], pQuest->ReqItemCount[i], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveTimedQuest(quest_id);
|
RemoveTimedQuest(quest_id);
|
||||||
|
|
@ -13612,7 +13613,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
if (uint32 itemId = pQuest->RewChoiceItemId[reward])
|
if (uint32 itemId = pQuest->RewChoiceItemId[reward])
|
||||||
{
|
{
|
||||||
ItemPosCountVec dest;
|
ItemPosCountVec dest;
|
||||||
if (CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemId, pQuest->RewChoiceItemCount[reward] ) == EQUIP_ERR_OK)
|
if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, pQuest->RewChoiceItemCount[reward]) == EQUIP_ERR_OK)
|
||||||
{
|
{
|
||||||
Item* item = StoreNewItem( dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId));
|
Item* item = StoreNewItem( dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId));
|
||||||
SendNewItem(item, pQuest->RewChoiceItemCount[reward], true, false);
|
SendNewItem(item, pQuest->RewChoiceItemCount[reward], true, false);
|
||||||
|
|
@ -13627,7 +13628,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
if (uint32 itemId = pQuest->RewItemId[i])
|
if (uint32 itemId = pQuest->RewItemId[i])
|
||||||
{
|
{
|
||||||
ItemPosCountVec dest;
|
ItemPosCountVec dest;
|
||||||
if (CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemId, pQuest->RewItemCount[i] ) == EQUIP_ERR_OK)
|
if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, pQuest->RewItemCount[i]) == EQUIP_ERR_OK)
|
||||||
{
|
{
|
||||||
Item* item = StoreNewItem( dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId));
|
Item* item = StoreNewItem( dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId));
|
||||||
SendNewItem(item, pQuest->RewItemCount[i], true, false);
|
SendNewItem(item, pQuest->RewItemCount[i], true, false);
|
||||||
|
|
@ -13636,19 +13637,19 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RewardReputation( pQuest );
|
RewardReputation(pQuest);
|
||||||
|
|
||||||
uint16 log_slot = FindQuestSlot( quest_id );
|
uint16 log_slot = FindQuestSlot(quest_id);
|
||||||
if (log_slot < MAX_QUEST_LOG_SIZE)
|
if (log_slot < MAX_QUEST_LOG_SIZE)
|
||||||
SetQuestSlot(log_slot,0);
|
SetQuestSlot(log_slot,0);
|
||||||
|
|
||||||
QuestStatusData& q_status = mQuestStatus[quest_id];
|
QuestStatusData& q_status = mQuestStatus[quest_id];
|
||||||
|
|
||||||
// Not give XP in case already completed once repeatable quest
|
// Not give XP in case already completed once repeatable quest
|
||||||
uint32 XP = q_status.m_rewarded ? 0 : uint32(pQuest->XPValue( this )*sWorld.getConfig(CONFIG_FLOAT_RATE_XP_QUEST));
|
uint32 XP = q_status.m_rewarded ? 0 : uint32(pQuest->XPValue(this)*sWorld.getConfig(CONFIG_FLOAT_RATE_XP_QUEST));
|
||||||
|
|
||||||
if (getLevel() < sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
|
if (getLevel() < sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
|
||||||
GiveXP( XP , NULL );
|
GiveXP(XP , NULL);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32 money = uint32(pQuest->GetRewMoneyMaxLevel() * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY));
|
uint32 money = uint32(pQuest->GetRewMoneyMaxLevel() * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY));
|
||||||
|
|
@ -13659,7 +13660,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
// Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative
|
// Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative
|
||||||
if (pQuest->GetRewOrReqMoney())
|
if (pQuest->GetRewOrReqMoney())
|
||||||
{
|
{
|
||||||
ModifyMoney( pQuest->GetRewOrReqMoney() );
|
ModifyMoney(pQuest->GetRewOrReqMoney());
|
||||||
|
|
||||||
if (pQuest->GetRewOrReqMoney() > 0)
|
if (pQuest->GetRewOrReqMoney() > 0)
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, pQuest->GetRewOrReqMoney());
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, pQuest->GetRewOrReqMoney());
|
||||||
|
|
@ -13678,7 +13679,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
|
|
||||||
if (pQuest->GetBonusTalents())
|
if (pQuest->GetBonusTalents())
|
||||||
{
|
{
|
||||||
m_questRewardTalentCount+=pQuest->GetBonusTalents();
|
m_questRewardTalentCount += pQuest->GetBonusTalents();
|
||||||
InitTalentForLevel();
|
InitTalentForLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -13705,16 +13706,17 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
q_status.uState = QUEST_CHANGED;
|
q_status.uState = QUEST_CHANGED;
|
||||||
|
|
||||||
if (announce)
|
if (announce)
|
||||||
SendQuestReward( pQuest, XP, questGiver );
|
SendQuestReward(pQuest, XP, questGiver);
|
||||||
|
|
||||||
// cast spells after mark quest complete (some spells have quest completed state reqyurements in spell_area data)
|
// cast spells after mark quest complete (some spells have quest completed state reqyurements in spell_area data)
|
||||||
if (pQuest->GetRewSpellCast() > 0)
|
if (pQuest->GetRewSpellCast() > 0)
|
||||||
CastSpell( this, pQuest->GetRewSpellCast(), true);
|
CastSpell(this, pQuest->GetRewSpellCast(), true);
|
||||||
else if ( pQuest->GetRewSpell() > 0)
|
else if (pQuest->GetRewSpell() > 0)
|
||||||
CastSpell( this, pQuest->GetRewSpell(), true);
|
CastSpell(this, pQuest->GetRewSpell(), true);
|
||||||
|
|
||||||
if (pQuest->GetZoneOrSort() > 0)
|
if (pQuest->GetZoneOrSort() > 0)
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, pQuest->GetZoneOrSort());
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, pQuest->GetZoneOrSort());
|
||||||
|
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, pQuest->GetQuestId());
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, pQuest->GetQuestId());
|
||||||
|
|
||||||
|
|
@ -13723,26 +13725,26 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
|
|
||||||
// remove auras from spells with quest reward state limitations
|
// remove auras from spells with quest reward state limitations
|
||||||
SpellAreaForQuestMapBounds saEndBounds = sSpellMgr.GetSpellAreaForQuestEndMapBounds(quest_id);
|
SpellAreaForQuestMapBounds saEndBounds = sSpellMgr.GetSpellAreaForQuestEndMapBounds(quest_id);
|
||||||
if(saEndBounds.first != saEndBounds.second)
|
if (saEndBounds.first != saEndBounds.second)
|
||||||
{
|
{
|
||||||
GetZoneAndAreaId(zone,area);
|
GetZoneAndAreaId(zone,area);
|
||||||
|
|
||||||
for(SpellAreaForAreaMap::const_iterator itr = saEndBounds.first; itr != saEndBounds.second; ++itr)
|
for(SpellAreaForAreaMap::const_iterator itr = saEndBounds.first; itr != saEndBounds.second; ++itr)
|
||||||
if(!itr->second->IsFitToRequirements(this,zone,area))
|
if (!itr->second->IsFitToRequirements(this, zone, area))
|
||||||
RemoveAurasDueToSpell(itr->second->spellId);
|
RemoveAurasDueToSpell(itr->second->spellId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some spells applied at quest reward
|
// Some spells applied at quest reward
|
||||||
SpellAreaForQuestMapBounds saBounds = sSpellMgr.GetSpellAreaForQuestMapBounds(quest_id,false);
|
SpellAreaForQuestMapBounds saBounds = sSpellMgr.GetSpellAreaForQuestMapBounds(quest_id, false);
|
||||||
if(saBounds.first != saBounds.second)
|
if (saBounds.first != saBounds.second)
|
||||||
{
|
{
|
||||||
if(!zone || !area)
|
if (!zone || !area)
|
||||||
GetZoneAndAreaId(zone,area);
|
GetZoneAndAreaId(zone, area);
|
||||||
|
|
||||||
for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
|
for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
|
||||||
if(itr->second->autocast && itr->second->IsFitToRequirements(this,zone,area))
|
if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area))
|
||||||
if (!HasAura(itr->second->spellId, EFFECT_INDEX_0))
|
if (!HasAura(itr->second->spellId, EFFECT_INDEX_0))
|
||||||
CastSpell(this,itr->second->spellId,true);
|
CastSpell(this, itr->second->spellId, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -13794,18 +13796,20 @@ bool Player::SatisfyQuestSkill(Quest const* qInfo, bool msg) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::SatisfyQuestLevel( Quest const* qInfo, bool msg ) const
|
bool Player::SatisfyQuestLevel(Quest const* qInfo, bool msg) const
|
||||||
{
|
{
|
||||||
if (getLevel() < qInfo->GetMinLevel())
|
if (getLevel() < qInfo->GetMinLevel())
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ );
|
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::SatisfyQuestLog( bool msg ) const
|
bool Player::SatisfyQuestLog(bool msg) const
|
||||||
{
|
{
|
||||||
// exist free slot
|
// exist free slot
|
||||||
if (FindQuestSlot(0) < MAX_QUEST_LOG_SIZE)
|
if (FindQuestSlot(0) < MAX_QUEST_LOG_SIZE)
|
||||||
|
|
@ -13813,24 +13817,24 @@ bool Player::SatisfyQuestLog( bool msg ) const
|
||||||
|
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
WorldPacket data( SMSG_QUESTLOG_FULL, 0 );
|
WorldPacket data(SMSG_QUESTLOG_FULL, 0);
|
||||||
GetSession()->SendPacket( &data );
|
GetSession()->SendPacket(&data);
|
||||||
DEBUG_LOG( "WORLD: Sent SMSG_QUESTLOG_FULL" );
|
DEBUG_LOG("WORLD: Sent SMSG_QUESTLOG_FULL");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::SatisfyQuestPreviousQuest( Quest const* qInfo, bool msg ) const
|
bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) const
|
||||||
{
|
{
|
||||||
// No previous quest (might be first quest in a series)
|
// No previous quest (might be first quest in a series)
|
||||||
if (qInfo->prevQuests.empty())
|
if (qInfo->prevQuests.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for(Quest::PrevQuests::const_iterator iter = qInfo->prevQuests.begin(); iter != qInfo->prevQuests.end(); ++iter )
|
for(Quest::PrevQuests::const_iterator iter = qInfo->prevQuests.begin(); iter != qInfo->prevQuests.end(); ++iter)
|
||||||
{
|
{
|
||||||
uint32 prevId = abs(*iter);
|
uint32 prevId = abs(*iter);
|
||||||
|
|
||||||
QuestStatusMap::const_iterator i_prevstatus = mQuestStatus.find( prevId );
|
QuestStatusMap::const_iterator i_prevstatus = mQuestStatus.find(prevId);
|
||||||
Quest const* qPrevInfo = sObjectMgr.GetQuestTemplate(prevId);
|
Quest const* qPrevInfo = sObjectMgr.GetQuestTemplate(prevId);
|
||||||
|
|
||||||
if (qPrevInfo && i_prevstatus != mQuestStatus.end())
|
if (qPrevInfo && i_prevstatus != mQuestStatus.end())
|
||||||
|
|
@ -13856,13 +13860,14 @@ bool Player::SatisfyQuestPreviousQuest( Quest const* qInfo, bool msg ) const
|
||||||
if (exclude_Id == prevId)
|
if (exclude_Id == prevId)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QuestStatusMap::const_iterator i_exstatus = mQuestStatus.find( exclude_Id );
|
QuestStatusMap::const_iterator i_exstatus = mQuestStatus.find(exclude_Id);
|
||||||
|
|
||||||
// alternative quest from group also must be completed and rewarded(reported)
|
// alternative quest from group also must be completed and rewarded(reported)
|
||||||
if (i_exstatus == mQuestStatus.end() || !i_exstatus->second.m_rewarded)
|
if (i_exstatus == mQuestStatus.end() || !i_exstatus->second.m_rewarded)
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ );
|
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13893,7 +13898,8 @@ bool Player::SatisfyQuestPreviousQuest( Quest const* qInfo, bool msg ) const
|
||||||
if (!IsCurrentQuest(exclude_Id))
|
if (!IsCurrentQuest(exclude_Id))
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ );
|
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13905,7 +13911,7 @@ bool Player::SatisfyQuestPreviousQuest( Quest const* qInfo, bool msg ) const
|
||||||
// Has only positive prev. quests in non-rewarded state
|
// Has only positive prev. quests in non-rewarded state
|
||||||
// and negative prev. quests in non-active state
|
// and negative prev. quests in non-active state
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ );
|
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -13928,27 +13934,32 @@ bool Player::SatisfyQuestClass(Quest const* qInfo, bool msg) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::SatisfyQuestRace( Quest const* qInfo, bool msg ) const
|
bool Player::SatisfyQuestRace(Quest const* qInfo, bool msg) const
|
||||||
{
|
{
|
||||||
uint32 reqraces = qInfo->GetRequiredRaces();
|
uint32 reqraces = qInfo->GetRequiredRaces();
|
||||||
|
|
||||||
if (reqraces == 0)
|
if (reqraces == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if ((reqraces & getRaceMask()) == 0)
|
if ((reqraces & getRaceMask()) == 0)
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_QUEST_FAILED_WRONG_RACE );
|
SendCanTakeQuestResponse(INVALIDREASON_QUEST_FAILED_WRONG_RACE);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::SatisfyQuestReputation( Quest const* qInfo, bool msg ) const
|
bool Player::SatisfyQuestReputation(Quest const* qInfo, bool msg) const
|
||||||
{
|
{
|
||||||
uint32 fIdMin = qInfo->GetRequiredMinRepFaction(); //Min required rep
|
uint32 fIdMin = qInfo->GetRequiredMinRepFaction(); //Min required rep
|
||||||
if (fIdMin && GetReputationMgr().GetReputation(fIdMin) < qInfo->GetRequiredMinRepValue())
|
if (fIdMin && GetReputationMgr().GetReputation(fIdMin) < qInfo->GetRequiredMinRepValue())
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ );
|
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -13956,22 +13967,26 @@ bool Player::SatisfyQuestReputation( Quest const* qInfo, bool msg ) const
|
||||||
if (fIdMax && GetReputationMgr().GetReputation(fIdMax) >= qInfo->GetRequiredMaxRepValue())
|
if (fIdMax && GetReputationMgr().GetReputation(fIdMax) >= qInfo->GetRequiredMaxRepValue())
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ );
|
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::SatisfyQuestStatus( Quest const* qInfo, bool msg ) const
|
bool Player::SatisfyQuestStatus(Quest const* qInfo, bool msg) const
|
||||||
{
|
{
|
||||||
QuestStatusMap::const_iterator itr = mQuestStatus.find( qInfo->GetQuestId() );
|
QuestStatusMap::const_iterator itr = mQuestStatus.find(qInfo->GetQuestId());
|
||||||
|
|
||||||
if (itr != mQuestStatus.end() && itr->second.m_status != QUEST_STATUS_NONE)
|
if (itr != mQuestStatus.end() && itr->second.m_status != QUEST_STATUS_NONE)
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_QUEST_ALREADY_ON );
|
SendCanTakeQuestResponse(INVALIDREASON_QUEST_ALREADY_ON);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -13984,6 +13999,7 @@ bool Player::SatisfyQuestTimed(Quest const* qInfo, bool msg) const
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -13995,7 +14011,7 @@ bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg) const
|
||||||
|
|
||||||
ExclusiveQuestGroupsMapBounds bounds = sObjectMgr.GetExclusiveQuestGroupsMapBounds(qInfo->GetExclusiveGroup());
|
ExclusiveQuestGroupsMapBounds bounds = sObjectMgr.GetExclusiveQuestGroupsMapBounds(qInfo->GetExclusiveGroup());
|
||||||
|
|
||||||
MANGOS_ASSERT(bounds.first != bounds.second); // always must be found if qInfo->ExclusiveGroup != 0
|
MANGOS_ASSERT(bounds.first != bounds.second); // must always be found if qInfo->ExclusiveGroup != 0
|
||||||
|
|
||||||
for(ExclusiveQuestGroupsMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter)
|
for(ExclusiveQuestGroupsMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter)
|
||||||
{
|
{
|
||||||
|
|
@ -14009,37 +14025,41 @@ bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg) const
|
||||||
Quest const* Nquest = sObjectMgr.GetQuestTemplate(exclude_Id);
|
Quest const* Nquest = sObjectMgr.GetQuestTemplate(exclude_Id);
|
||||||
if (!SatisfyQuestDay(Nquest, false) || !SatisfyQuestWeek(Nquest, false))
|
if (!SatisfyQuestDay(Nquest, false) || !SatisfyQuestWeek(Nquest, false))
|
||||||
{
|
{
|
||||||
if( msg )
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ );
|
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestStatusMap::const_iterator i_exstatus = mQuestStatus.find( exclude_Id );
|
QuestStatusMap::const_iterator i_exstatus = mQuestStatus.find(exclude_Id);
|
||||||
|
|
||||||
// alternative quest already started or completed
|
// alternative quest already started or completed
|
||||||
if (i_exstatus != mQuestStatus.end()
|
if (i_exstatus != mQuestStatus.end() &&
|
||||||
&& (i_exstatus->second.m_status == QUEST_STATUS_COMPLETE || i_exstatus->second.m_status == QUEST_STATUS_INCOMPLETE))
|
(i_exstatus->second.m_status == QUEST_STATUS_COMPLETE || i_exstatus->second.m_status == QUEST_STATUS_INCOMPLETE))
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ );
|
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::SatisfyQuestNextChain( Quest const* qInfo, bool msg ) const
|
bool Player::SatisfyQuestNextChain(Quest const* qInfo, bool msg) const
|
||||||
{
|
{
|
||||||
if (!qInfo->GetNextQuestInChain())
|
if (!qInfo->GetNextQuestInChain())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// next quest in chain already started or completed
|
// next quest in chain already started or completed
|
||||||
QuestStatusMap::const_iterator itr = mQuestStatus.find( qInfo->GetNextQuestInChain() );
|
QuestStatusMap::const_iterator itr = mQuestStatus.find(qInfo->GetNextQuestInChain());
|
||||||
if (itr != mQuestStatus.end()
|
if (itr != mQuestStatus.end() &&
|
||||||
&& (itr->second.m_status == QUEST_STATUS_COMPLETE || itr->second.m_status == QUEST_STATUS_INCOMPLETE))
|
(itr->second.m_status == QUEST_STATUS_COMPLETE || itr->second.m_status == QUEST_STATUS_INCOMPLETE))
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ );
|
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -14049,13 +14069,13 @@ bool Player::SatisfyQuestNextChain( Quest const* qInfo, bool msg ) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::SatisfyQuestPrevChain( Quest const* qInfo, bool msg ) const
|
bool Player::SatisfyQuestPrevChain(Quest const* qInfo, bool msg) const
|
||||||
{
|
{
|
||||||
// No previous quest in chain
|
// No previous quest in chain
|
||||||
if (qInfo->prevChainQuests.empty())
|
if (qInfo->prevChainQuests.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for(Quest::PrevChainQuests::const_iterator iter = qInfo->prevChainQuests.begin(); iter != qInfo->prevChainQuests.end(); ++iter )
|
for(Quest::PrevChainQuests::const_iterator iter = qInfo->prevChainQuests.begin(); iter != qInfo->prevChainQuests.end(); ++iter)
|
||||||
{
|
{
|
||||||
uint32 prevId = *iter;
|
uint32 prevId = *iter;
|
||||||
|
|
||||||
|
|
@ -14063,7 +14083,8 @@ bool Player::SatisfyQuestPrevChain( Quest const* qInfo, bool msg ) const
|
||||||
if (IsCurrentQuest(prevId))
|
if (IsCurrentQuest(prevId))
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ );
|
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -14077,7 +14098,7 @@ bool Player::SatisfyQuestPrevChain( Quest const* qInfo, bool msg ) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::SatisfyQuestDay( Quest const* qInfo, bool msg ) const
|
bool Player::SatisfyQuestDay(Quest const* qInfo, bool msg) const
|
||||||
{
|
{
|
||||||
if (!qInfo->IsDaily())
|
if (!qInfo->IsDaily())
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -14096,14 +14117,15 @@ bool Player::SatisfyQuestDay( Quest const* qInfo, bool msg ) const
|
||||||
if (!have_slot)
|
if (!have_slot)
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
SendCanTakeQuestResponse( INVALIDREASON_DAILY_QUESTS_REMAINING );
|
SendCanTakeQuestResponse(INVALIDREASON_DAILY_QUESTS_REMAINING);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::SatisfyQuestWeek( Quest const* qInfo, bool msg ) const
|
bool Player::SatisfyQuestWeek(Quest const* qInfo, bool msg) const
|
||||||
{
|
{
|
||||||
if (!qInfo->IsWeekly() || m_weeklyquests.empty())
|
if (!qInfo->IsWeekly() || m_weeklyquests.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "10630"
|
#define REVISION_NR "10631"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue