Core/Quests: Implement quests that require PlayerSlain. Closes #169
This commit is contained in:
@@ -805,6 +805,7 @@ CREATE TABLE `character_queststatus` (
|
||||
`itemcount2` smallint(5) unsigned NOT NULL DEFAULT '0',
|
||||
`itemcount3` smallint(5) unsigned NOT NULL DEFAULT '0',
|
||||
`itemcount4` smallint(5) unsigned NOT NULL DEFAULT '0',
|
||||
`playercount` smallint(5) unsigned NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`guid`,`quest`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `character_queststatus` ADD `playercount` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0';
|
||||
@@ -539,8 +539,13 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
|
||||
{
|
||||
// 4. Reward player.
|
||||
if (!_isBattleGround)
|
||||
{
|
||||
// 4.1. Give honor (player must be alive and not on BG).
|
||||
_RewardHonor(player);
|
||||
// 4.1.1 Send player killcredit for quests with PlayerSlain
|
||||
if (_victim->GetTypeId() == TYPEID_PLAYER)
|
||||
player->KilledPlayerCredit();
|
||||
}
|
||||
// Give XP only in PvE or in battlegrounds.
|
||||
// Give reputation and kill credit only in PvE.
|
||||
if (!_isPvP || _isBattleGround)
|
||||
@@ -14610,6 +14615,10 @@ bool Player::CanCompleteQuest(uint32 quest_id)
|
||||
}
|
||||
}
|
||||
|
||||
if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL))
|
||||
if (qInfo->GetPlayersSlain() != 0 && q_status.m_playercount < qInfo->GetPlayersSlain())
|
||||
return false;
|
||||
|
||||
if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT) && !q_status.m_explored)
|
||||
return false;
|
||||
|
||||
@@ -14753,6 +14762,9 @@ void Player::AddQuest(Quest const *pQuest, Object *questGiver)
|
||||
questStatusData.m_creatureOrGOcount[i] = 0;
|
||||
}
|
||||
|
||||
if (pQuest->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL))
|
||||
questStatusData.m_playercount = 0;
|
||||
|
||||
GiveQuestSourceItem(pQuest);
|
||||
AdjustQuestReqItemCount(pQuest, questStatusData);
|
||||
|
||||
@@ -15816,6 +15828,46 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid)
|
||||
}
|
||||
}
|
||||
|
||||
void Player::KilledPlayerCredit()
|
||||
{
|
||||
uint16 addkillcount = 1;
|
||||
|
||||
for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i)
|
||||
{
|
||||
uint32 questid = GetQuestSlotQuestId(i);
|
||||
if (!questid)
|
||||
continue;
|
||||
|
||||
Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid);
|
||||
if (!qInfo)
|
||||
continue;
|
||||
// just if !ingroup || !noraidgroup || raidgroup
|
||||
QuestStatusData& q_status = m_QuestStatus[questid];
|
||||
if (q_status.m_status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid()))
|
||||
{
|
||||
if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL))
|
||||
{
|
||||
uint32 reqkill = qInfo->GetPlayersSlain();
|
||||
uint16 curkill = q_status.m_playercount;
|
||||
|
||||
if (curkill < reqkill)
|
||||
{
|
||||
q_status.m_playercount = curkill + addkillcount;
|
||||
|
||||
m_QuestStatusSave[questid] = true;
|
||||
|
||||
SendQuestUpdateAddPlayer(qInfo, curkill, addkillcount);
|
||||
}
|
||||
|
||||
if (CanCompleteQuest(questid))
|
||||
CompleteQuest(questid);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id)
|
||||
{
|
||||
bool isCreature = IS_CRE_OR_VEH_GUID(guid);
|
||||
@@ -16231,6 +16283,22 @@ void Player::SendQuestUpdateAddCreatureOrGo(Quest const* pQuest, uint64 guid, ui
|
||||
SetQuestSlotCounter(log_slot, creatureOrGO_idx, GetQuestSlotCounter(log_slot, creatureOrGO_idx)+add_count);
|
||||
}
|
||||
|
||||
void Player::SendQuestUpdateAddPlayer(Quest const* pQuest, uint16 old_count, uint16 add_count)
|
||||
{
|
||||
ASSERT(old_count + add_count < 65536 && "player count store in 16 bits");
|
||||
|
||||
WorldPacket data(SMSG_QUESTUPDATE_ADD_PVP_KILL, (3*4));
|
||||
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTUPDATE_ADD_PVP_KILL");
|
||||
data << uint32(pQuest->GetQuestId());
|
||||
data << uint32(old_count + add_count);
|
||||
data << uint32(pQuest->GetPlayersSlain());
|
||||
GetSession()->SendPacket(&data);
|
||||
|
||||
uint16 log_slot = FindQuestSlot(pQuest->GetQuestId());
|
||||
if (log_slot < MAX_QUEST_LOG_SIZE)
|
||||
SetQuestSlotCounter(log_slot, QUEST_PVP_KILL_SLOT, GetQuestSlotCounter(log_slot, QUEST_PVP_KILL_SLOT) + add_count);
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/*** LOAD SYSTEM ***/
|
||||
/*********************************************************/
|
||||
@@ -17574,8 +17642,8 @@ void Player::_LoadQuestStatus(PreparedQueryResult result)
|
||||
|
||||
//// 0 1 2 3 4 5 6 7 8 9 10
|
||||
//QueryResult *result = CharacterDatabase.PQuery("SELECT quest, status, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, itemcount1, itemcount2, itemcount3,
|
||||
// 11
|
||||
// itemcount4 FROM character_queststatus WHERE guid = '%u'", GetGUIDLow());
|
||||
// 11 12
|
||||
// itemcount4, playercount FROM character_queststatus WHERE guid = '%u'", GetGUIDLow());
|
||||
|
||||
if (result)
|
||||
{
|
||||
@@ -17624,6 +17692,7 @@ void Player::_LoadQuestStatus(PreparedQueryResult result)
|
||||
questStatusData.m_itemcount[1] = fields[9].GetUInt16();
|
||||
questStatusData.m_itemcount[2] = fields[10].GetUInt16();
|
||||
questStatusData.m_itemcount[3] = fields[11].GetUInt16();
|
||||
questStatusData.m_playercount = fields[12].GetUInt16();
|
||||
|
||||
// add to quest log
|
||||
if (slot < MAX_QUEST_LOG_SIZE && questStatusData.m_status != QUEST_STATUS_NONE)
|
||||
@@ -17639,6 +17708,9 @@ void Player::_LoadQuestStatus(PreparedQueryResult result)
|
||||
if (questStatusData.m_creatureOrGOcount[idx])
|
||||
SetQuestSlotCounter(slot, idx, questStatusData.m_creatureOrGOcount[idx]);
|
||||
|
||||
if (questStatusData.m_playercount)
|
||||
SetQuestSlotCounter(slot, QUEST_PVP_KILL_SLOT, questStatusData.m_playercount);
|
||||
|
||||
++slot;
|
||||
}
|
||||
|
||||
@@ -18676,11 +18748,9 @@ void Player::_SaveQuestStatus(SQLTransaction& trans)
|
||||
{
|
||||
statusItr = m_QuestStatus.find(saveItr->first);
|
||||
if (statusItr != m_QuestStatus.end() && (keepAbandoned || statusItr->second.m_status != QUEST_STATUS_NONE))
|
||||
{
|
||||
trans->PAppend("REPLACE INTO character_queststatus (guid, quest, status, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, itemcount1, itemcount2, itemcount3, itemcount4) "
|
||||
"VALUES ('%u', '%u', '%u', '%u', '" UI64FMTD "', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')",
|
||||
GetGUIDLow(), statusItr->first, statusItr->second.m_status, statusItr->second.m_explored, uint64(statusItr->second.m_timer / IN_MILLISECONDS+ sWorld->GetGameTime()), statusItr->second.m_creatureOrGOcount[0], statusItr->second.m_creatureOrGOcount[1], statusItr->second.m_creatureOrGOcount[2], statusItr->second.m_creatureOrGOcount[3], statusItr->second.m_itemcount[0], statusItr->second.m_itemcount[1], statusItr->second.m_itemcount[2], statusItr->second.m_itemcount[3]);
|
||||
}
|
||||
trans->PAppend("REPLACE INTO character_queststatus (guid, quest, status, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, itemcount1, itemcount2, itemcount3, itemcount4, playercount) "
|
||||
"VALUES ('%u', '%u', '%u', '%u', '" UI64FMTD "', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')",
|
||||
GetGUIDLow(), statusItr->first, statusItr->second.m_status, statusItr->second.m_explored, uint64(statusItr->second.m_timer / IN_MILLISECONDS+ sWorld->GetGameTime()), statusItr->second.m_creatureOrGOcount[0], statusItr->second.m_creatureOrGOcount[1], statusItr->second.m_creatureOrGOcount[2], statusItr->second.m_creatureOrGOcount[3], statusItr->second.m_itemcount[0], statusItr->second.m_itemcount[1], statusItr->second.m_itemcount[2], statusItr->second.m_itemcount[3], statusItr->second.m_playercount);
|
||||
}
|
||||
else
|
||||
trans->PAppend("DELETE FROM character_queststatus WHERE guid = %u AND quest = %u", GetGUIDLow(), saveItr->first);
|
||||
|
||||
@@ -1462,6 +1462,7 @@ class Player : public Unit, public GridObject<Player>
|
||||
void ItemRemovedQuestCheck(uint32 entry, uint32 count);
|
||||
void KilledMonster(CreatureTemplate const* cInfo, uint64 guid);
|
||||
void KilledMonsterCredit(uint32 entry, uint64 guid);
|
||||
void KilledPlayerCredit();
|
||||
void CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id);
|
||||
void TalkedToCreature(uint32 entry, uint64 guid);
|
||||
void MoneyChanged(uint32 value);
|
||||
@@ -1481,6 +1482,7 @@ class Player : public Unit, public GridObject<Player>
|
||||
void SendPushToPartyResponse(Player *pPlayer, uint32 msg);
|
||||
void SendQuestUpdateAddItem(Quest const* pQuest, uint32 item_idx, uint16 count);
|
||||
void SendQuestUpdateAddCreatureOrGo(Quest const* pQuest, uint64 guid, uint32 creatureOrGO_idx, uint16 old_count, uint16 add_count);
|
||||
void SendQuestUpdateAddPlayer(Quest const* pQuest, uint16 old_count, uint16 add_count);
|
||||
|
||||
uint64 GetDivider() { return m_divider; }
|
||||
void SetDivider(uint64 guid) { m_divider = guid; }
|
||||
|
||||
@@ -4336,6 +4336,8 @@ void ObjectMgr::LoadQuests()
|
||||
mExclusiveQuestGroups.insert(std::pair<int32, uint32>(qinfo->ExclusiveGroup, qinfo->GetQuestId()));
|
||||
if (qinfo->LimitTime)
|
||||
qinfo->SetFlag(QUEST_TRINITY_FLAGS_TIMED);
|
||||
if (qinfo->PlayersSlain)
|
||||
qinfo->SetFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL);
|
||||
}
|
||||
|
||||
// check QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE
|
||||
|
||||
@@ -40,6 +40,7 @@ class ObjectMgr;
|
||||
#define QUEST_DEPLINK_COUNT 10
|
||||
#define QUEST_REPUTATIONS_COUNT 5
|
||||
#define QUEST_EMOTE_COUNT 4
|
||||
#define QUEST_PVP_KILL_SLOT 0
|
||||
|
||||
enum QuestFailedReasons
|
||||
{
|
||||
@@ -157,6 +158,7 @@ enum __QuestFlags
|
||||
QUEST_TRINITY_FLAGS_SPEAKTO = 0x08000000, // Internal flag computed only
|
||||
QUEST_TRINITY_FLAGS_KILL_OR_CAST = 0x10000000, // Internal flag computed only
|
||||
QUEST_TRINITY_FLAGS_TIMED = 0x20000000, // Internal flag computed only
|
||||
QUEST_TRINITY_FLAGS_PLAYER_KILL = 0x40000000, // Internal flag computed only
|
||||
};
|
||||
|
||||
struct QuestLocale
|
||||
@@ -355,7 +357,7 @@ class Quest
|
||||
|
||||
struct QuestStatusData
|
||||
{
|
||||
QuestStatusData(): m_status(QUEST_STATUS_NONE), m_explored(false), m_timer(0)
|
||||
QuestStatusData(): m_status(QUEST_STATUS_NONE), m_explored(false), m_timer(0), m_playercount(0)
|
||||
{
|
||||
memset(m_itemcount, 0, QUEST_ITEM_OBJECTIVES_COUNT * sizeof(uint16));
|
||||
memset(m_creatureOrGOcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint16));
|
||||
@@ -366,5 +368,6 @@ struct QuestStatusData
|
||||
uint32 m_timer;
|
||||
uint16 m_itemcount[QUEST_ITEM_OBJECTIVES_COUNT];
|
||||
uint16 m_creatureOrGOcount[QUEST_OBJECTIVES_COUNT];
|
||||
uint16 m_playercount;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -49,7 +49,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
"base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges FROM character_aura WHERE guid = ?", CONNECTION_ASYNC)
|
||||
PREPARE_STATEMENT(CHAR_LOAD_PLAYER_SPELLS, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?", CONNECTION_ASYNC)
|
||||
PREPARE_STATEMENT(CHAR_LOAD_PLAYER_QUESTSTATUS, "SELECT quest, status, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, "
|
||||
"itemcount1, itemcount2, itemcount3, itemcount4 FROM character_queststatus WHERE guid = ?", CONNECTION_ASYNC)
|
||||
"itemcount1, itemcount2, itemcount3, itemcount4, playercount FROM character_queststatus WHERE guid = ?", CONNECTION_ASYNC)
|
||||
PREPARE_STATEMENT(CHAR_LOAD_PLAYER_DAILYQUESTSTATUS, "SELECT quest, time FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC)
|
||||
PREPARE_STATEMENT(CHAR_LOAD_PLAYER_WEKLYQUESTSTATUS, "SELECT quest FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC)
|
||||
PREPARE_STATEMENT(CHAR_LOAD_PLAYER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?", CONNECTION_ASYNC)
|
||||
|
||||
Reference in New Issue
Block a user