/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* 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
* 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 .
*
*/
#include "StdAfx.h"
//Pakcet Building
/////////////////
WorldPacket* BuildQuestQueryResponse(Quest *qst)
{
// 2048 bytes should be more than enough. The fields cost ~200 bytes.
// better to allocate more at startup than have to realloc the buffer later on.
WorldPacket *data = new WorldPacket(SMSG_QUEST_QUERY_RESPONSE, 2048);
*data << uint32(qst->id); // Quest ID
*data << uint32(2); // Unknown, always seems to be 2
*data << uint32(qst->max_level); // Quest level
if(qst->quest_sort > 0)
*data << uint32(qst->quest_sort); // Negative if pointing to a sort.
else
*data << uint32(qst->zone_id); // Positive if pointing to a zone.
*data << uint32(qst->type); // Info ID / Type
*data << uint32(qst->required_rep_faction); // Faction ID
*data << uint32(qst->required_rep_value); // Faction Amount
*data << uint32(0); // Unknown (always 0)
*data << uint32(0); // Unknown (always 0)
*data << uint32(0); // Unknown (always 0) was added for dirty fix remove this
*data << uint32(qst->next_quest_id); // Next Quest ID
*data << uint32(qst->reward_money); // Copper reward
// disabled for dirty fix remove this *data << uint32(qst->reward_xp_as_money); // Copper given instead of XP
*data << uint32(qst->required_money); // Required Money
*data << uint32(qst->reward_spell); // Spell added to spellbook upon completion
*data << uint32(qst->effect_on_player); // Spell casted on player upon completion
*data << uint32(qst->srcitem); // Item given at the start of a quest (srcitem)
*data << uint32(qst->quest_flags); // Quest Flags
// (loop 4 times)
for(uint32 i = 0; i < 4; ++i)
{
*data << qst->reward_item[i]; // Forced Reward Item [i]
*data << qst->reward_itemcount[i]; // Forced Reward Item Count [i]
}
// (loop 6 times)
for(uint32 i = 0; i < 6; ++i)
{
*data << qst->reward_choiceitem[i]; // Choice Reward Item [i]
*data << qst->reward_choiceitemcount[i]; // Choice Reward Item Count [i]
}
*data << qst->point_mapid; // Unknown
*data << qst->point_x; // Unknown
*data << qst->point_y; // Unknown
*data << qst->point_opt; // Unknown
*data << qst->title; // Title / name of quest
*data << qst->objectives; // Objectives / description
*data << qst->details; // Details
*data << qst->endtext; // Subdescription
// (loop 4 times)
for(uint32 i = 0; i < 4; ++i)
{
*data << qst->required_mob[i]; // Kill mob entry ID [i]
*data << qst->required_mobcount[i]; // Kill mob count [i]
*data << qst->required_item[i]; // Collect item [i]
*data << qst->required_itemcount[i]; // Collect item count [i]
}
*data << qst->objectivetexts[0]; // Objective 1 - Used as text if mob not set
*data << qst->objectivetexts[1]; // Objective 2 - Used as text if mob not set
*data << qst->objectivetexts[2]; // Objective 3 - Used as text if mob not set
*data << qst->objectivetexts[3]; // Objective 4 - Used as text if mob not set
return data;
}
/*****************
* QuestLogEntry *
*****************/
QuestLogEntry::QuestLogEntry()
{
mInitialized = false;
m_quest = NULL;
mDirty = false;
m_slot = -1;
_questScript = NULL;
completed=0;
}
void QuestLogEntry::Init(Quest* quest, Player* plr, uint32 slot)
{
ASSERT(quest);
ASSERT(plr);
m_quest = quest;
m_plr = plr;
m_slot = slot;
// update slot
plr->SetQuestLogSlot(this, slot);
mDirty = true;
memset(m_mobcount, 0, 4*4);
memset(m_explored_areas, 0, 4*4);
if(m_quest->time)
m_time_left = m_quest->time * 1000;
else
m_time_left = 0;
LoadScript();
CALL_QUESTSCRIPT_EVENT(this, OnQuestStart)(plr);
}
void QuestLogEntry::SaveToDB()
{
ASSERT(m_slot != -1);
if(!mDirty)
return;
CharacterDatabase.Execute("DELETE FROM questlog WHERE player_guid=%u AND quest_id=%u", m_plr->GetGUIDLow(), m_quest->id);
std::stringstream ss;
ss << "INSERT INTO questlog (player_guid, quest_id, slot, time_left, explored_area1, explored_area2, explored_area3, explored_area4, mob_kill1, mob_kill2, mob_kill3, mob_kill4) VALUES(";
ss << m_plr->GetGUIDLow() << "," << m_quest->id << "," << m_slot << "," << m_time_left;
for(int i = 0; i < 4; ++i)
ss << "," << m_explored_areas[i];
for(int i = 0; i < 4; ++i)
ss << "," << m_mobcount[i];
ss << ")";
CharacterDatabase.Execute(ss.str().c_str());
}
bool QuestLogEntry::LoadFromDB(Field *fields)
{
// index,playerguid,questid,timeleft,area0,area1,area2,area3,kill0,kill1,kill2,kill3
int f = 4;
ASSERT(m_plr && m_quest);
m_time_left = fields[f].GetUInt32(); f++;
for(int i = 0; i < 4; ++i)
{
m_explored_areas[i] = fields[f].GetUInt32(); f++;
CALL_QUESTSCRIPT_EVENT(this, OnExploreArea)(m_explored_areas[i], m_plr);
}
for(int i = 0; i < 4; ++i)
{
m_mobcount[i] = fields[f].GetUInt32(); f++;
if(GetQuest()->required_mobtype[i] == QUEST_MOB_TYPE_CREATURE)
CALL_QUESTSCRIPT_EVENT(this, OnCreatureKill)(GetQuest()->required_mob[i], m_plr);
else
CALL_QUESTSCRIPT_EVENT(this, OnGameObjectActivate)(GetQuest()->required_mob[i], m_plr);
}
mDirty = false;
return true;
}
bool QuestLogEntry::CanBeFinished()
{
uint32 i;
for(i = 0; i < 4; ++i)
{
if(m_quest->required_mob[i])
{
if(m_mobcount[i] < m_quest->required_mobcount[i])
{
return false;
}
}
}
for(i = 0; i < 4; ++i)
{
if(m_quest->required_item[i])
{
if(m_plr->GetItemInterface()->GetItemCount(m_quest->required_item[i]) < m_quest->required_itemcount[i])
{
return false;
}
}
}
for(i = 0; i < 4; ++i)
{
if(m_quest->required_triggers[i])
{
if(m_explored_areas[i] == 0)
return false;
}
}
return true;
}
void QuestLogEntry::SubtractTime(uint32 value)
{
if(this->m_time_left <=value)
m_time_left = 0;
else
m_time_left-=value;
}
void QuestLogEntry::SetMobCount(uint32 i, uint32 count)
{
ASSERT(i<4);
m_mobcount[i] = count;
mDirty = true;
}
void QuestLogEntry::SetTrigger(uint32 i)
{
ASSERT(i<4);
m_explored_areas[i] = 1;
mDirty = true;
}
void QuestLogEntry::SetSlot(int32 i)
{
ASSERT(i!=-1);
m_slot = i;
}
void QuestLogEntry::Finish()
{
uint32 base = GetBaseField(m_slot);
m_plr->SetUInt32Value(base + 0, 0);
m_plr->SetUInt32Value(base + 1, 0);
m_plr->SetUInt32Value(base + 2, 0);
// clear from player log
m_plr->SetQuestLogSlot(NULL, m_slot);
m_plr->PushToRemovedQuests(m_quest->id);
// delete ourselves
delete this;
}
void QuestLogEntry::UpdatePlayerFields()
{
if(!m_plr)
return;
uint32 base = GetBaseField(m_slot);
m_plr->SetUInt32Value(base + 0, m_quest->id);
// next field is kills and shit like that
uint32 field1 = 0;
int i;
// explored areas
if(m_quest->count_requiredtriggers)
{
uint32 count = 0;
for(i = 0; i < 4; ++i)
{
if(m_quest->required_triggers[i])
{
if(m_explored_areas[i] == 1)
{
count++;
}
}
}
if(count == m_quest->count_requiredtriggers)
{
field1 |= 0x01000000;
}
}
// mob hunting
if(m_quest->count_required_mob)
{
uint8 cnt;
for(int i = 0; i < 4; ++i)
{
if(m_quest->required_mob[i] && m_mobcount[i] > 0)
{
// 1 << (offset * 6)
cnt = m_mobcount[i];
field1 |= (cnt << (i*6));
}
}
}
m_plr->SetUInt32Value(base + 1, field1);
m_plr->SetUInt32Value(base + 2, m_time_left);
}
void QuestLogEntry::SendQuestComplete()
{
WorldPacket data(4);
data.SetOpcode(SMSG_QUESTUPDATE_COMPLETE);
data << m_quest->id;
m_plr->GetSession()->SendPacket(&data);
CALL_QUESTSCRIPT_EVENT(this, OnQuestComplete)(m_plr);
}
void QuestLogEntry::SendUpdateAddKill(uint32 i)
{
sQuestMgr.SendQuestUpdateAddKill(m_plr, m_quest->id, m_quest->required_mob[i], m_mobcount[i], m_quest->required_mobcount[i], 0);
}
void QuestLogEntry::LoadScript()
{
//_questScript = sScriptMgr.CreateQuestScriptClassForEntry(GetQuest()->id, this);
}
void QuestLogEntry::CallScriptUpdate()
{
ASSERT(_questScript);
_questScript->EventUpdate();
}
QuestLogEntry::~QuestLogEntry()
{
//sEventMgr.RemoveEvents(this);
if(_questScript != 0)
_questScript->Destroy();
}