648 lines
27 KiB
C#
648 lines
27 KiB
C#
/*
|
|
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
using Framework.Constants;
|
|
using Game.BattleGrounds;
|
|
using Game.Entities;
|
|
using Game.Groups;
|
|
using Game.Network;
|
|
using Game.Network.Packets;
|
|
|
|
namespace Game
|
|
{
|
|
public partial class WorldSession
|
|
{
|
|
[WorldPacketHandler(ClientOpcodes.QuestGiverStatusQuery, Processing = PacketProcessing.Inplace)]
|
|
void HandleQuestgiverStatusQuery(QuestGiverStatusQuery packet)
|
|
{
|
|
QuestGiverStatus questStatus = QuestGiverStatus.None;
|
|
|
|
var questgiver = Global.ObjAccessor.GetObjectByTypeMask(GetPlayer(), packet.QuestGiverGUID, TypeMask.Unit | TypeMask.GameObject);
|
|
if (!questgiver)
|
|
{
|
|
Log.outInfo(LogFilter.Network, "Error in CMSG_QUESTGIVER_STATUS_QUERY, called for non-existing questgiver {0}", packet.QuestGiverGUID.ToString());
|
|
return;
|
|
}
|
|
|
|
switch (questgiver.GetTypeId())
|
|
{
|
|
case TypeId.Unit:
|
|
if (!questgiver.ToCreature().IsHostileTo(GetPlayer()))// do not show quest status to enemies
|
|
questStatus = GetPlayer().GetQuestDialogStatus(questgiver);
|
|
break;
|
|
case TypeId.GameObject:
|
|
questStatus = GetPlayer().GetQuestDialogStatus(questgiver);
|
|
break;
|
|
default:
|
|
Log.outError(LogFilter.Network, "QuestGiver called for unexpected type {0}", questgiver.GetTypeId());
|
|
break;
|
|
}
|
|
|
|
//inform client about status of quest
|
|
GetPlayer().PlayerTalkClass.SendQuestGiverStatus(questStatus, packet.QuestGiverGUID);
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.QuestGiverHello)]
|
|
void HandleQuestgiverHello(QuestGiverHello packet)
|
|
{
|
|
Creature creature = GetPlayer().GetNPCIfCanInteractWith(packet.QuestGiverGUID, NPCFlags.QuestGiver);
|
|
if (creature == null)
|
|
{
|
|
Log.outDebug(LogFilter.Network, "WORLD: HandleQuestgiverHello - {0} not found or you can't interact with him.", packet.QuestGiverGUID.ToString());
|
|
return;
|
|
}
|
|
|
|
// remove fake death
|
|
if (GetPlayer().HasUnitState(UnitState.Died))
|
|
GetPlayer().RemoveAurasByType(AuraType.FeignDeath);
|
|
// Stop the npc if moving
|
|
creature.StopMoving();
|
|
|
|
if (Global.ScriptMgr.OnGossipHello(GetPlayer(), creature))
|
|
return;
|
|
|
|
GetPlayer().PrepareGossipMenu(creature, creature.GetCreatureTemplate().GossipMenuId, true);
|
|
GetPlayer().SendPreparedGossip(creature);
|
|
|
|
creature.GetAI().sGossipHello(GetPlayer());
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.QuestGiverAcceptQuest)]
|
|
void HandleQuestgiverAcceptQuest(QuestGiverAcceptQuest packet)
|
|
{
|
|
WorldObject obj;
|
|
if (!packet.QuestGiverGUID.IsPlayer())
|
|
obj = Global.ObjAccessor.GetObjectByTypeMask(_player, packet.QuestGiverGUID, TypeMask.Unit | TypeMask.GameObject | TypeMask.Item);
|
|
else
|
|
obj = Global.ObjAccessor.FindPlayer(packet.QuestGiverGUID);
|
|
|
|
var CLOSE_GOSSIP_CLEAR_DIVIDER = new System.Action(() =>
|
|
{
|
|
GetPlayer().PlayerTalkClass.SendCloseGossip();
|
|
GetPlayer().SetDivider(ObjectGuid.Empty);
|
|
});
|
|
|
|
// no or incorrect quest giver
|
|
if (obj == null)
|
|
{
|
|
CLOSE_GOSSIP_CLEAR_DIVIDER();
|
|
return;
|
|
}
|
|
|
|
Player playerQuestObject = obj.ToPlayer();
|
|
if (playerQuestObject)
|
|
{
|
|
if ((_player.GetDivider().IsEmpty() && _player.GetDivider() != packet.QuestGiverGUID) || !playerQuestObject.CanShareQuest(packet.QuestID))
|
|
{
|
|
CLOSE_GOSSIP_CLEAR_DIVIDER();
|
|
return;
|
|
}
|
|
if (!_player.IsInSameRaidWith(playerQuestObject))
|
|
{
|
|
CLOSE_GOSSIP_CLEAR_DIVIDER();
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!obj.hasQuest(packet.QuestID))
|
|
{
|
|
CLOSE_GOSSIP_CLEAR_DIVIDER();
|
|
return;
|
|
}
|
|
}
|
|
|
|
// some kind of WPE protection
|
|
if (!_player.CanInteractWithQuestGiver(obj))
|
|
{
|
|
CLOSE_GOSSIP_CLEAR_DIVIDER();
|
|
return;
|
|
}
|
|
|
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID);
|
|
if (quest != null)
|
|
{
|
|
// prevent cheating
|
|
if (!GetPlayer().CanTakeQuest(quest, true))
|
|
{
|
|
CLOSE_GOSSIP_CLEAR_DIVIDER();
|
|
return;
|
|
}
|
|
|
|
if (!_player.GetDivider().IsEmpty())
|
|
{
|
|
Player player = Global.ObjAccessor.FindPlayer(_player.GetDivider());
|
|
if (player != null)
|
|
{
|
|
player.SendPushToPartyResponse(_player, QuestPushReason.Accepted);
|
|
_player.SetDivider(ObjectGuid.Empty);
|
|
}
|
|
}
|
|
|
|
if (_player.CanAddQuest(quest, true))
|
|
{
|
|
_player.AddQuestAndCheckCompletion(quest, obj);
|
|
|
|
if (quest.HasFlag(QuestFlags.PartyAccept))
|
|
{
|
|
var group = _player.GetGroup();
|
|
if (group)
|
|
{
|
|
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next())
|
|
{
|
|
Player player = refe.GetSource();
|
|
|
|
if (!player || player == _player) // not self
|
|
continue;
|
|
|
|
if (player.CanTakeQuest(quest, true))
|
|
{
|
|
player.SetDivider(_player.GetGUID());
|
|
|
|
//need confirmation that any gossip window will close
|
|
player.PlayerTalkClass.SendCloseGossip();
|
|
|
|
_player.SendQuestConfirmAccept(quest, player);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_player.PlayerTalkClass.SendCloseGossip();
|
|
|
|
if (quest.SourceSpellID > 0)
|
|
_player.CastSpell(_player, quest.SourceSpellID, true);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
CLOSE_GOSSIP_CLEAR_DIVIDER();
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.QuestGiverQueryQuest)]
|
|
void HandleQuestgiverQueryQuest(QuestGiverQueryQuest packet)
|
|
{
|
|
// Verify that the guid is valid and is a questgiver or involved in the requested quest
|
|
var obj = Global.ObjAccessor.GetObjectByTypeMask(GetPlayer(), packet.QuestGiverGUID, (TypeMask.Unit | TypeMask.GameObject | TypeMask.Item));
|
|
if (!obj || (!obj.hasQuest(packet.QuestID) && !obj.hasInvolvedQuest(packet.QuestID)))
|
|
{
|
|
GetPlayer().PlayerTalkClass.SendCloseGossip();
|
|
return;
|
|
}
|
|
|
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID);
|
|
if (quest != null)
|
|
{
|
|
if (!GetPlayer().CanTakeQuest(quest, true))
|
|
return;
|
|
|
|
if (quest.IsAutoAccept() && GetPlayer().CanAddQuest(quest, true))
|
|
GetPlayer().AddQuestAndCheckCompletion(quest, obj);
|
|
|
|
if (quest.IsAutoComplete())
|
|
GetPlayer().PlayerTalkClass.SendQuestGiverRequestItems(quest, obj.GetGUID(), GetPlayer().CanCompleteQuest(quest.Id), true);
|
|
else
|
|
GetPlayer().PlayerTalkClass.SendQuestGiverQuestDetails(quest, obj.GetGUID(), true, false);
|
|
}
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.QueryQuestInfo)]
|
|
void HandleQuestQuery(QueryQuestInfo packet)
|
|
{
|
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID);
|
|
if (quest != null)
|
|
_player.PlayerTalkClass.SendQuestQueryResponse(quest);
|
|
else
|
|
{
|
|
QueryQuestInfoResponse response = new QueryQuestInfoResponse();
|
|
response.QuestID = packet.QuestID;
|
|
SendPacket(response);
|
|
}
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.QuestGiverChooseReward)]
|
|
void HandleQuestgiverChooseReward(QuestGiverChooseReward packet)
|
|
{
|
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID);
|
|
if (quest == null)
|
|
return;
|
|
|
|
// This is Real Item Entry, not slot id as pre 5.x
|
|
if (packet.ItemChoiceID != 0)
|
|
{
|
|
ItemTemplate rewardProto = Global.ObjectMgr.GetItemTemplate(packet.ItemChoiceID);
|
|
if (rewardProto == null)
|
|
{
|
|
Log.outError(LogFilter.Network, "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player {0} ({1}) tried to get invalid reward item (Item Entry: {2}) for quest {3} (possible packet-hacking detected)", GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), packet.ItemChoiceID, packet.QuestID);
|
|
return;
|
|
}
|
|
|
|
bool itemValid = false;
|
|
for (uint i = 0; i < quest.GetRewChoiceItemsCount(); ++i)
|
|
{
|
|
if (quest.RewardChoiceItemId[i] != 0 && quest.RewardChoiceItemId[i] == packet.ItemChoiceID)
|
|
{
|
|
itemValid = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!itemValid && quest.PackageID != 0)
|
|
{
|
|
var questPackageItems = Global.DB2Mgr.GetQuestPackageItems(quest.PackageID);
|
|
if (questPackageItems != null)
|
|
{
|
|
foreach (var questPackageItem in questPackageItems)
|
|
{
|
|
if (questPackageItem.ItemID != packet.ItemChoiceID)
|
|
continue;
|
|
|
|
if (_player.CanSelectQuestPackageItem(questPackageItem))
|
|
{
|
|
itemValid = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!itemValid)
|
|
{
|
|
var questPackageItems1 = Global.DB2Mgr.GetQuestPackageItemsFallback(quest.PackageID);
|
|
if (questPackageItems1 != null)
|
|
{
|
|
foreach (var questPackageItem in questPackageItems1)
|
|
{
|
|
if (questPackageItem.ItemID != packet.ItemChoiceID)
|
|
continue;
|
|
|
|
itemValid = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!itemValid)
|
|
{
|
|
Log.outError(LogFilter.Network, "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player {0} ({1}) tried to get reward item (Item Entry: {2}) wich is not a reward for quest {3} (possible packet-hacking detected)", GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), packet.ItemChoiceID, packet.QuestID);
|
|
return;
|
|
}
|
|
}
|
|
|
|
WorldObject obj = GetPlayer();
|
|
if (!quest.HasFlag(QuestFlags.AutoComplete))
|
|
{
|
|
obj = Global.ObjAccessor.GetObjectByTypeMask(GetPlayer(), packet.QuestGiverGUID, TypeMask.Unit | TypeMask.GameObject);
|
|
if (!obj || !obj.hasInvolvedQuest(packet.QuestID))
|
|
return;
|
|
|
|
// some kind of WPE protection
|
|
if (!GetPlayer().CanInteractWithQuestGiver(obj))
|
|
return;
|
|
}
|
|
|
|
if ((!GetPlayer().CanSeeStartQuest(quest) && GetPlayer().GetQuestStatus(packet.QuestID) == QuestStatus.None) ||
|
|
(GetPlayer().GetQuestStatus(packet.QuestID) != QuestStatus.Complete && !quest.IsAutoComplete()))
|
|
{
|
|
Log.outError(LogFilter.Network, "Error in QuestStatus.Complete: player {0} ({1}) tried to complete quest {2}, but is not allowed to do so (possible packet-hacking or high latency)",
|
|
GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), packet.QuestID);
|
|
return;
|
|
}
|
|
|
|
if (GetPlayer().CanRewardQuest(quest, packet.ItemChoiceID, true))
|
|
{
|
|
GetPlayer().RewardQuest(quest, packet.ItemChoiceID, obj);
|
|
|
|
switch (obj.GetTypeId())
|
|
{
|
|
case TypeId.Unit:
|
|
case TypeId.Player:
|
|
{
|
|
//For AutoSubmition was added plr case there as it almost same exclute AI script cases.
|
|
Creature creatureQGiver = obj.ToCreature();
|
|
if (!creatureQGiver || !Global.ScriptMgr.OnQuestReward(GetPlayer(), creatureQGiver, quest, packet.ItemChoiceID))
|
|
{
|
|
// Send next quest
|
|
Quest nextQuest = GetPlayer().GetNextQuest(packet.QuestGiverGUID, quest);
|
|
if (nextQuest != null)
|
|
{
|
|
// Only send the quest to the player if the conditions are met
|
|
if (GetPlayer().CanTakeQuest(nextQuest, false))
|
|
{
|
|
if (nextQuest.IsAutoAccept() && GetPlayer().CanAddQuest(nextQuest, true))
|
|
GetPlayer().AddQuestAndCheckCompletion(nextQuest, obj);
|
|
|
|
GetPlayer().PlayerTalkClass.SendQuestGiverQuestDetails(nextQuest, packet.QuestGiverGUID, true, false);
|
|
}
|
|
}
|
|
|
|
if (creatureQGiver)
|
|
creatureQGiver.GetAI().sQuestReward(GetPlayer(), quest, packet.ItemChoiceID);
|
|
}
|
|
break;
|
|
}
|
|
case TypeId.GameObject:
|
|
GameObject questGiver = obj.ToGameObject();
|
|
if (!Global.ScriptMgr.OnQuestReward(GetPlayer(), questGiver, quest, packet.ItemChoiceID))
|
|
{
|
|
// Send next quest
|
|
Quest nextQuest = GetPlayer().GetNextQuest(packet.QuestGiverGUID, quest);
|
|
if (nextQuest != null)
|
|
{
|
|
// Only send the quest to the player if the conditions are met
|
|
if (GetPlayer().CanTakeQuest(nextQuest, false))
|
|
{
|
|
if (nextQuest.IsAutoAccept() && GetPlayer().CanAddQuest(nextQuest, true))
|
|
GetPlayer().AddQuestAndCheckCompletion(nextQuest, obj);
|
|
|
|
GetPlayer().PlayerTalkClass.SendQuestGiverQuestDetails(nextQuest, packet.QuestGiverGUID, true, false);
|
|
}
|
|
}
|
|
|
|
questGiver.GetAI().QuestReward(GetPlayer(), quest, packet.ItemChoiceID);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
GetPlayer().PlayerTalkClass.SendQuestGiverOfferReward(quest, packet.QuestGiverGUID, true);
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.QuestGiverRequestReward)]
|
|
void HandleQuestgiverRequestReward(QuestGiverRequestReward packet)
|
|
{
|
|
WorldObject obj = Global.ObjAccessor.GetObjectByTypeMask(GetPlayer(), packet.QuestGiverGUID, TypeMask.Unit | TypeMask.GameObject);
|
|
if (obj == null || !obj.hasInvolvedQuest(packet.QuestID))
|
|
return;
|
|
|
|
// some kind of WPE protection
|
|
if (!GetPlayer().CanInteractWithQuestGiver(obj))
|
|
return;
|
|
|
|
if (GetPlayer().CanCompleteQuest(packet.QuestID))
|
|
GetPlayer().CompleteQuest(packet.QuestID);
|
|
|
|
if (GetPlayer().GetQuestStatus(packet.QuestID) != QuestStatus.Complete)
|
|
return;
|
|
|
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID);
|
|
if (quest != null)
|
|
GetPlayer().PlayerTalkClass.SendQuestGiverOfferReward(quest, packet.QuestGiverGUID, true);
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.QuestLogRemoveQuest)]
|
|
void HandleQuestLogRemoveQuest(QuestLogRemoveQuest packet)
|
|
{
|
|
if (packet.Entry < SharedConst.MaxQuestLogSize)
|
|
{
|
|
uint questId = GetPlayer().GetQuestSlotQuestId(packet.Entry);
|
|
if (questId != 0)
|
|
{
|
|
if (!GetPlayer().TakeQuestSourceItem(questId, true))
|
|
return; // can't un-equip some items, reject quest cancel
|
|
|
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(questId);
|
|
if (quest != null)
|
|
{
|
|
if (quest.HasSpecialFlag(QuestSpecialFlags.Timed))
|
|
GetPlayer().RemoveTimedQuest(questId);
|
|
|
|
if (quest.HasFlag(QuestFlags.Pvp))
|
|
{
|
|
GetPlayer().pvpInfo.IsHostile = GetPlayer().pvpInfo.IsInHostileArea || GetPlayer().HasPvPForcingQuest();
|
|
GetPlayer().UpdatePvPState();
|
|
}
|
|
}
|
|
|
|
GetPlayer().TakeQuestSourceItem(questId, true); // remove quest src item from player
|
|
GetPlayer().AbandonQuest(questId); // remove all quest items player received before abandoning quest. Note, this does not remove normal drop items that happen to be quest requirements.
|
|
GetPlayer().RemoveActiveQuest(questId);
|
|
GetPlayer().RemoveCriteriaTimer(CriteriaTimedTypes.Quest, questId);
|
|
|
|
Log.outInfo(LogFilter.Network, "Player {0} abandoned quest {1}", GetPlayer().GetGUID().ToString(), questId);
|
|
|
|
Global.ScriptMgr.OnQuestStatusChange(_player, questId);
|
|
}
|
|
|
|
GetPlayer().SetQuestSlot(packet.Entry, 0);
|
|
|
|
GetPlayer().UpdateCriteria(CriteriaTypes.QuestAbandoned, 1);
|
|
}
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.QuestConfirmAccept)]
|
|
void HandleQuestConfirmAccept(QuestConfirmAccept packet)
|
|
{
|
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID);
|
|
if (quest != null)
|
|
{
|
|
if (!quest.HasFlag(QuestFlags.PartyAccept))
|
|
return;
|
|
|
|
Player originalPlayer = Global.ObjAccessor.FindPlayer(GetPlayer().GetDivider());
|
|
if (originalPlayer == null)
|
|
return;
|
|
|
|
if (!GetPlayer().IsInSameRaidWith(originalPlayer))
|
|
return;
|
|
|
|
if (!!originalPlayer.IsActiveQuest(packet.QuestID))
|
|
return;
|
|
|
|
if (!GetPlayer().CanTakeQuest(quest, true))
|
|
return;
|
|
|
|
if (GetPlayer().CanAddQuest(quest, true))
|
|
{
|
|
GetPlayer().AddQuestAndCheckCompletion(quest, null); // NULL, this prevent DB script from duplicate running
|
|
|
|
if (quest.SourceSpellID > 0)
|
|
_player.CastSpell(_player, quest.SourceSpellID, true);
|
|
}
|
|
}
|
|
|
|
GetPlayer().SetDivider(ObjectGuid.Empty);
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.QuestGiverCompleteQuest)]
|
|
void HandleQuestgiverCompleteQuest(QuestGiverCompleteQuest packet)
|
|
{
|
|
bool autoCompleteMode = packet.FromScript; // 0 - standart complete quest mode with npc, 1 - auto-complete mode
|
|
|
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID);
|
|
if (quest == null)
|
|
return;
|
|
|
|
if (autoCompleteMode && !quest.HasFlag(QuestFlags.AutoComplete))
|
|
return;
|
|
|
|
WorldObject obj;
|
|
if (autoCompleteMode)
|
|
obj = GetPlayer();
|
|
else
|
|
obj = Global.ObjAccessor.GetObjectByTypeMask(GetPlayer(), packet.QuestGiverGUID, TypeMask.Unit | TypeMask.GameObject);
|
|
|
|
if (!obj)
|
|
return;
|
|
|
|
if (!autoCompleteMode)
|
|
{
|
|
if (!obj.hasInvolvedQuest(packet.QuestID))
|
|
return;
|
|
|
|
// some kind of WPE protection
|
|
if (!GetPlayer().CanInteractWithQuestGiver(obj))
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// Do not allow completing quests on other players.
|
|
if (packet.QuestGiverGUID != GetPlayer().GetGUID())
|
|
return;
|
|
}
|
|
|
|
if (!GetPlayer().CanSeeStartQuest(quest) && GetPlayer().GetQuestStatus(packet.QuestID) == QuestStatus.None)
|
|
{
|
|
Log.outError(LogFilter.Network, "Possible hacking attempt: Player {0} ({1}) tried to complete quest [entry: {2}] without being in possession of the quest!",
|
|
GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), packet.QuestID);
|
|
return;
|
|
}
|
|
Battleground bg = GetPlayer().GetBattleground();
|
|
if (bg)
|
|
bg.HandleQuestComplete(packet.QuestID, GetPlayer());
|
|
|
|
if (GetPlayer().GetQuestStatus(packet.QuestID) != QuestStatus.Complete)
|
|
{
|
|
if (quest.IsRepeatable())
|
|
GetPlayer().PlayerTalkClass.SendQuestGiverRequestItems(quest, packet.QuestGiverGUID, GetPlayer().CanCompleteRepeatableQuest(quest), false);
|
|
else
|
|
GetPlayer().PlayerTalkClass.SendQuestGiverRequestItems(quest, packet.QuestGiverGUID, GetPlayer().CanRewardQuest(quest, false), false);
|
|
}
|
|
else
|
|
{
|
|
if (quest.HasSpecialFlag(QuestSpecialFlags.Deliver)) // some items required
|
|
GetPlayer().PlayerTalkClass.SendQuestGiverRequestItems(quest, packet.QuestGiverGUID, GetPlayer().CanRewardQuest(quest, false), false);
|
|
else // no items required
|
|
GetPlayer().PlayerTalkClass.SendQuestGiverOfferReward(quest, packet.QuestGiverGUID, true);
|
|
}
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.PushQuestToParty)]
|
|
void HandlePushQuestToParty(PushQuestToParty packet)
|
|
{
|
|
if (!GetPlayer().CanShareQuest(packet.QuestID))
|
|
return;
|
|
|
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID);
|
|
if (quest == null)
|
|
return;
|
|
|
|
Player sender = GetPlayer();
|
|
|
|
Group group = sender.GetGroup();
|
|
if (!group)
|
|
return;
|
|
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next())
|
|
{
|
|
Player receiver = refe.GetSource();
|
|
|
|
if (!receiver || receiver == sender)
|
|
continue;
|
|
|
|
if (!receiver.SatisfyQuestStatus(quest, false))
|
|
{
|
|
sender.SendPushToPartyResponse(receiver, QuestPushReason.OnQuest);
|
|
continue;
|
|
}
|
|
|
|
if (receiver.GetQuestStatus(packet.QuestID) == QuestStatus.Complete)
|
|
{
|
|
sender.SendPushToPartyResponse(receiver, QuestPushReason.AlreadyDone);
|
|
continue;
|
|
}
|
|
|
|
if (!receiver.CanTakeQuest(quest, false))
|
|
{
|
|
sender.SendPushToPartyResponse(receiver, QuestPushReason.Invalid);
|
|
continue;
|
|
}
|
|
|
|
if (!receiver.SatisfyQuestLog(false))
|
|
{
|
|
sender.SendPushToPartyResponse(receiver, QuestPushReason.LogFull);
|
|
continue;
|
|
}
|
|
|
|
if (!receiver.GetDivider().IsEmpty())
|
|
{
|
|
sender.SendPushToPartyResponse(receiver, QuestPushReason.Busy);
|
|
continue;
|
|
}
|
|
|
|
sender.SendPushToPartyResponse(receiver, QuestPushReason.Success);
|
|
|
|
if (quest.IsAutoAccept() && receiver.CanAddQuest(quest, true) && receiver.CanTakeQuest(quest, true))
|
|
receiver.AddQuestAndCheckCompletion(quest, sender);
|
|
|
|
if ((quest.IsAutoComplete() && quest.IsRepeatable() && !quest.IsDailyOrWeekly()) || quest.HasFlag(QuestFlags.AutoComplete))
|
|
receiver.PlayerTalkClass.SendQuestGiverRequestItems(quest, sender.GetGUID(), receiver.CanCompleteRepeatableQuest(quest), true);
|
|
else
|
|
{
|
|
receiver.SetDivider(sender.GetGUID());
|
|
receiver.PlayerTalkClass.SendQuestGiverQuestDetails(quest, receiver.GetGUID(), true, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.QuestPushResult)]
|
|
void HandleQuestPushResult(QuestPushResult packet)
|
|
{
|
|
if (!GetPlayer().GetDivider().IsEmpty())
|
|
{
|
|
if (_player.GetDivider() == packet.SenderGUID)
|
|
{
|
|
Player player = Global.ObjAccessor.FindPlayer(_player.GetDivider());
|
|
if (player)
|
|
player.SendPushToPartyResponse(_player, packet.Result);
|
|
}
|
|
|
|
_player.SetDivider(ObjectGuid.Empty);
|
|
}
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.QuestGiverStatusMultipleQuery)]
|
|
void HandleQuestgiverStatusMultipleQuery(QuestGiverStatusMultipleQuery packet)
|
|
{
|
|
_player.SendQuestGiverStatusMultiple();
|
|
}
|
|
|
|
[WorldPacketHandler(ClientOpcodes.RequestWorldQuestUpdate)]
|
|
void HandleRequestWorldQuestUpdate(RequestWorldQuestUpdate packet)
|
|
{
|
|
WorldQuestUpdate response = new WorldQuestUpdate();
|
|
|
|
/// @todo: 7.x Has to be implemented
|
|
//response.WorldQuestUpdates.push_back(WorldPackets::Quest::WorldQuestUpdateInfo(lastUpdate, questID, timer, variableID, value));
|
|
|
|
SendPacket(response);
|
|
}
|
|
}
|
|
}
|