mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 12:41:30 +00:00
Bunch more work on fixing up DB and packets
This commit is contained in:
parent
1b8736188d
commit
0ea82b5d88
@ -61,6 +61,7 @@ SET(common_sources
|
||||
rdtsc.cpp
|
||||
rulesys.cpp
|
||||
say_link.cpp
|
||||
serialize_buffer.cpp
|
||||
serverinfo.cpp
|
||||
shareddb.cpp
|
||||
skills.cpp
|
||||
@ -192,6 +193,7 @@ SET(common_headers
|
||||
ruletypes.h
|
||||
say_link.h
|
||||
seperator.h
|
||||
serialize_buffer.h
|
||||
serverinfo.h
|
||||
servertalk.h
|
||||
shareddb.h
|
||||
|
||||
@ -63,6 +63,8 @@ public:
|
||||
void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); }
|
||||
void WriteDouble(double value) { *(double *)(pBuffer + _wpos) = value; _wpos += sizeof(double); }
|
||||
void WriteString(const char * str) { uint32 len = static_cast<uint32>(strlen(str)) + 1; memcpy(pBuffer + _wpos, str, len); _wpos += len; }
|
||||
// this is used in task system a lot, it is NOT null-termed
|
||||
void WriteLengthString(uint32 len, const char *str) { *(uint32 *)(pBuffer + _wpos) = len; _wpos += sizeof(uint32); memcpy(pBuffer + _wpos, str, len); _wpos += len; }
|
||||
void WriteData(const void *ptr, size_t n) { memcpy(pBuffer + _wpos, ptr, n); _wpos += n; }
|
||||
|
||||
uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; }
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
#include "base_packet.h"
|
||||
#include "platform.h"
|
||||
#include "serialize_buffer.h"
|
||||
#include <iostream>
|
||||
|
||||
#ifdef STATIC_OPCODE
|
||||
|
||||
23
common/serialize_buffer.cpp
Normal file
23
common/serialize_buffer.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "serialize_buffer.h"
|
||||
|
||||
void SerializeBuffer::Grow(size_t new_size)
|
||||
{
|
||||
assert(new_size > m_capacity);
|
||||
auto new_buffer = new unsigned char[new_size * 2];
|
||||
memset(new_buffer, 0, new_size * 2);
|
||||
|
||||
if (m_buffer)
|
||||
memcpy(new_buffer, m_buffer, m_capacity);
|
||||
m_capacity = new_size * 2;
|
||||
delete[] m_buffer;
|
||||
m_buffer = new_buffer;
|
||||
}
|
||||
|
||||
void SerializeBuffer::Reset()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
m_buffer = nullptr;
|
||||
m_capacity = 0;
|
||||
m_pos = 0;
|
||||
}
|
||||
|
||||
186
common/serialize_buffer.h
Normal file
186
common/serialize_buffer.h
Normal file
@ -0,0 +1,186 @@
|
||||
#ifndef SERIALIZE_BUFFER_H
|
||||
#define SERIALIZE_BUFFER_H
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class SerializeBuffer
|
||||
{
|
||||
public:
|
||||
SerializeBuffer() : m_buffer(nullptr), m_capacity(0), m_pos(0) {}
|
||||
|
||||
explicit SerializeBuffer(size_t size) : m_capacity(size), m_pos(0)
|
||||
{
|
||||
m_buffer = new unsigned char[size];
|
||||
memset(m_buffer, 0, size);
|
||||
}
|
||||
|
||||
SerializeBuffer(const SerializeBuffer &rhs)
|
||||
: m_buffer(new unsigned char[rhs.m_capacity]), m_capacity(rhs.m_capacity), m_pos(rhs.m_pos)
|
||||
{
|
||||
memcpy(m_buffer, rhs.m_buffer, rhs.m_capacity);
|
||||
}
|
||||
|
||||
SerializeBuffer &operator=(const SerializeBuffer &rhs)
|
||||
{
|
||||
if (this != &rhs) {
|
||||
delete[] m_buffer;
|
||||
m_buffer = new unsigned char[rhs.m_capacity];
|
||||
m_capacity = rhs.m_capacity;
|
||||
m_pos = rhs.m_pos;
|
||||
memcpy(m_buffer, rhs.m_buffer, m_capacity);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SerializeBuffer(SerializeBuffer &&rhs) : m_buffer(rhs.m_buffer), m_capacity(rhs.m_capacity), m_pos(rhs.m_pos)
|
||||
{
|
||||
rhs.m_buffer = nullptr;
|
||||
rhs.m_capacity = 0;
|
||||
rhs.m_pos = 0;
|
||||
}
|
||||
|
||||
SerializeBuffer &operator=(SerializeBuffer &&rhs)
|
||||
{
|
||||
if (this != &rhs) {
|
||||
delete[] m_buffer;
|
||||
|
||||
m_buffer = rhs.m_buffer;
|
||||
m_capacity = rhs.m_capacity;
|
||||
m_pos = rhs.m_pos;
|
||||
|
||||
rhs.m_buffer = nullptr;
|
||||
rhs.m_capacity = 0;
|
||||
rhs.m_pos = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~SerializeBuffer() { delete[] m_buffer; }
|
||||
|
||||
void WriteUInt8(uint8_t v)
|
||||
{
|
||||
if (m_pos + sizeof(uint8_t) > m_capacity)
|
||||
Grow(m_capacity + sizeof(uint8_t));
|
||||
*(uint8_t *)(m_buffer + m_pos) = v;
|
||||
m_pos += sizeof(uint8_t);
|
||||
}
|
||||
|
||||
void WriteUInt16(uint16_t v)
|
||||
{
|
||||
if (m_pos + sizeof(uint16_t) > m_capacity)
|
||||
Grow(m_capacity + sizeof(uint16_t));
|
||||
*(uint16_t *)(m_buffer + m_pos) = v;
|
||||
m_pos += sizeof(uint16_t);
|
||||
}
|
||||
|
||||
void WriteUInt32(uint32_t v)
|
||||
{
|
||||
if (m_pos + sizeof(uint32_t) > m_capacity)
|
||||
Grow(m_capacity + sizeof(uint32_t));
|
||||
*(uint32_t *)(m_buffer + m_pos) = v;
|
||||
m_pos += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
void WriteUInt64(uint64_t v)
|
||||
{
|
||||
if (m_pos + sizeof(uint64_t) > m_capacity)
|
||||
Grow(m_capacity + sizeof(uint64_t));
|
||||
*(uint64_t *)(m_buffer + m_pos) = v;
|
||||
m_pos += sizeof(uint64_t);
|
||||
}
|
||||
|
||||
void WriteInt8(int8_t v)
|
||||
{
|
||||
if (m_pos + sizeof(int8_t) > m_capacity)
|
||||
Grow(m_capacity + sizeof(int8_t));
|
||||
*(int8_t *)(m_buffer + m_pos) = v;
|
||||
m_pos += sizeof(int8_t);
|
||||
}
|
||||
|
||||
void WriteInt16(int16_t v)
|
||||
{
|
||||
if (m_pos + sizeof(int16_t) > m_capacity)
|
||||
Grow(m_capacity + sizeof(int16_t));
|
||||
*(int16_t *)(m_buffer + m_pos) = v;
|
||||
m_pos += sizeof(int16_t);
|
||||
}
|
||||
|
||||
void WriteInt32(int32_t v)
|
||||
{
|
||||
if (m_pos + sizeof(int32_t) > m_capacity)
|
||||
Grow(m_capacity + sizeof(int32_t));
|
||||
*(int32_t *)(m_buffer + m_pos) = v;
|
||||
m_pos += sizeof(int32_t);
|
||||
}
|
||||
|
||||
void WriteInt64(int64_t v)
|
||||
{
|
||||
if (m_pos + sizeof(int64_t) > m_capacity)
|
||||
Grow(m_capacity + sizeof(int64_t));
|
||||
*(int64_t *)(m_buffer + m_pos) = v;
|
||||
m_pos += sizeof(int64_t);
|
||||
}
|
||||
|
||||
void WriteFloat(float v)
|
||||
{
|
||||
if (m_pos + sizeof(float) > m_capacity)
|
||||
Grow(m_capacity + sizeof(float));
|
||||
*(float *)(m_buffer + m_pos) = v;
|
||||
m_pos += sizeof(float);
|
||||
}
|
||||
|
||||
void WriteDouble(double v)
|
||||
{
|
||||
if (m_pos + sizeof(double) > m_capacity)
|
||||
Grow(m_capacity + sizeof(double));
|
||||
*(double *)(m_buffer + m_pos) = v;
|
||||
m_pos += sizeof(double);
|
||||
}
|
||||
|
||||
void WriteString(const char *str)
|
||||
{
|
||||
assert(str != nullptr);
|
||||
auto len = strlen(str) + 1;
|
||||
if (m_pos + len > m_capacity)
|
||||
Grow(m_capacity + len);
|
||||
memcpy(m_buffer + m_pos, str, len);
|
||||
m_pos += len;
|
||||
}
|
||||
|
||||
void WriteString(const std::string &str)
|
||||
{
|
||||
auto len = str.length() + 1;
|
||||
if (m_pos + len > m_capacity)
|
||||
Grow(m_capacity + len);
|
||||
memcpy(m_buffer + m_pos, str.c_str(), len);
|
||||
m_pos += len;
|
||||
}
|
||||
|
||||
void WriteLengthString(uint32_t len, const char *str)
|
||||
{
|
||||
assert(str != nullptr);
|
||||
if (m_pos + len + sizeof(uint32_t) > m_capacity)
|
||||
Grow(m_capacity + len + sizeof(uint32_t));
|
||||
*(uint32_t *)(m_buffer + m_pos) = len;
|
||||
m_pos += sizeof(uint32_t);
|
||||
memcpy(m_buffer + m_pos, str, len);
|
||||
m_pos += len;
|
||||
}
|
||||
|
||||
size_t size() const { return m_pos; }
|
||||
size_t length() const { return size(); }
|
||||
size_t capacity() const { return m_capacity; }
|
||||
const unsigned char *buffer() const { return m_buffer; }
|
||||
|
||||
private:
|
||||
void Grow(size_t new_size);
|
||||
void Reset();
|
||||
unsigned char *m_buffer;
|
||||
size_t m_capacity;
|
||||
size_t m_pos;
|
||||
};
|
||||
|
||||
#endif /* !SERIALIZE_BUFFER_H */
|
||||
@ -3,3 +3,17 @@ ALTER TABLE `tasks` ADD `duration_code` TINYINT NOT NULL DEFAULT '0' AFTER `dura
|
||||
UPDATE `tasks` SET `type` = '2'; -- we were treating them all as quests
|
||||
ALTER TABLE `character_tasks` ADD `type` TINYINT NOT NULL DEFAULT '0' AFTER `slot`;
|
||||
UPDATE `character_tasks` SET `type` = '2'; -- we were treating them all as quests
|
||||
ALTER TABLE `activities` ADD `target_name` VARCHAR(64) NOT NULL DEFAULT '' AFTER `activitytype`;
|
||||
ALTER TABLE `activities` ADD `item_list` VARCHAR(128) NOT NULL DEFAULT '' AFTER `target_name`;
|
||||
ALTER TABLE `activities` ADD `skill_list` VARCHAR(64) NOT NULL DEFAULT '-1' AFTER `item_list`;
|
||||
ALTER TABLE `activities` ADD `spell_list` VARCHAR(64) NOT NULL DEFAULT '0' AFTER `skill_list`;
|
||||
ALTER TABLE `activities` ADD `description_override` VARCHAR(128) NOT NULL DEFAULT '' AFTER `spell_list`;
|
||||
ALTER TABLE `activities` ADD `zones` VARCHAR(64) NOT NULL DEFAULT '' AFTER `zoneid`;
|
||||
UPDATE `activities` SET `description_override` = `text3`;
|
||||
UPDATE `activities` SET `target_name` = `text1`;
|
||||
UPDATE `activities` SET `item_list` = `text2`;
|
||||
UPDATE `activities` SET `zones` = `zoneid`; -- should be safe for us ...
|
||||
ALTER TABLE `activities` DROP COLUMN `text1`;
|
||||
ALTER TABLE `activities` DROP COLUMN `text2`;
|
||||
ALTER TABLE `activities` DROP COLUMN `text3`;
|
||||
ALTER TABLE `activities` DROP COLUMN `zoneid`;
|
||||
|
||||
284
zone/tasks.cpp
284
zone/tasks.cpp
@ -172,21 +172,19 @@ bool TaskManager::LoadTasks(int singleTask)
|
||||
}
|
||||
|
||||
if (singleTask == 0)
|
||||
query = StringFormat("SELECT `taskid`, `step`, `activityid`, `activitytype`, "
|
||||
"`text1`, `text2`, `text3`, `goalid`, `goalmethod`, "
|
||||
"`goalcount`, `delivertonpc`, `zoneid`, `optional` "
|
||||
"FROM `activities` "
|
||||
"WHERE `taskid` < %i AND `activityid` < %i "
|
||||
"ORDER BY taskid, activityid ASC",
|
||||
MAXTASKS, MAXACTIVITIESPERTASK);
|
||||
query =
|
||||
StringFormat("SELECT `taskid`, `step`, `activityid`, `activitytype`, `target_name`, `item_list`, "
|
||||
"`skill_list`, `spell_list`, `description_override`, `goalid`, `goalmethod`, "
|
||||
"`goalcount`, `delivertonpc`, `zones`, `optional` FROM `activities` WHERE `taskid` < "
|
||||
"%i AND `activityid` < %i ORDER BY taskid, activityid ASC",
|
||||
MAXTASKS, MAXACTIVITIESPERTASK);
|
||||
else
|
||||
query = StringFormat("SELECT `taskid`, `step`, `activityid`, `activitytype`, "
|
||||
"`text1`, `text2`, `text3`, `goalid`, `goalmethod`, "
|
||||
"`goalcount`, `delivertonpc`, `zoneid`, `optional` "
|
||||
"FROM `activities` "
|
||||
"WHERE `taskid` = %i AND `activityid` < %i "
|
||||
"ORDER BY taskid, activityid ASC",
|
||||
singleTask, MAXACTIVITIESPERTASK);
|
||||
query =
|
||||
StringFormat("SELECT `taskid`, `step`, `activityid`, `activitytype`, `target_name`, `item_list`, "
|
||||
"`skill_list`, `spell_list`, `description_override`, `goalid`, `goalmethod`, "
|
||||
"`goalcount`, `delivertonpc`, `zones`, `optional` FROM `activities` WHERE `taskid` = "
|
||||
"%i AND `activityid` < %i ORDER BY taskid, activityid ASC",
|
||||
singleTask, MAXACTIVITIESPERTASK);
|
||||
results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
Log(Logs::General, Logs::Error, ERR_MYSQLERROR, results.ErrorMessage().c_str());
|
||||
@ -237,38 +235,42 @@ bool TaskManager::LoadTasks(int singleTask)
|
||||
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Type = atoi(row[3]);
|
||||
|
||||
if (row[4][0])
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Text1 = row[4];
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].target_name = row[4];
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].item_list = row[5];
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].skill_list = row[6];
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].skill_id = atoi(row[6]); // for older clients
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].spell_list = row[7];
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].spell_id = atoi(row[7]); // for older clients
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].desc_override = row[8];
|
||||
|
||||
if (row[5][0])
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Text2 = row[5];
|
||||
|
||||
if (row[6][0])
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Text3 = row[6];
|
||||
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalID = atoi(row[7]);
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalMethod = (TaskMethodType)atoi(row[8]);
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalCount = atoi(row[9]);
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].DeliverToNPC = atoi(row[10]);
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].ZoneID = atoi(row[11]);
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Optional = atoi(row[12]);
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalID = atoi(row[9]);
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalMethod = (TaskMethodType)atoi(row[10]);
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalCount = atoi(row[11]);
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].DeliverToNPC = atoi(row[12]);
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].zones = row[13];
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].ZoneID = atoi(row[13]); // for older clients
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Optional = atoi(row[14]);
|
||||
|
||||
Log(Logs::General, Logs::Tasks,
|
||||
"[GLOBALLOAD] Activity Slot %2i: ID %i for Task %5i. Type: %3i, GoalID: %8i, "
|
||||
"GoalMethod: %i, GoalCount: %3i, ZoneID:%3i",
|
||||
"GoalMethod: %i, GoalCount: %3i, Zones:%s",
|
||||
Tasks[taskID]->ActivityCount, activityID, taskID,
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Type,
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalID,
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalMethod,
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalCount,
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].ZoneID);
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].zones.c_str());
|
||||
|
||||
Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] Text1: %s",
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Text1.c_str());
|
||||
Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] Text2: %s",
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Text2.c_str());
|
||||
Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] Text3: %s",
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Text3.c_str());
|
||||
Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] target_name: %s",
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].target_name.c_str());
|
||||
Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] item_list: %s",
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].item_list.c_str());
|
||||
Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] skill_list: %s",
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].skill_list.c_str());
|
||||
Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] spell_list: %s",
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].spell_list.c_str());
|
||||
Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] description_override: %s",
|
||||
Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].desc_override.c_str());
|
||||
|
||||
Tasks[taskID]->ActivityCount++;
|
||||
}
|
||||
@ -1155,110 +1157,88 @@ void TaskManager::SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *Task
|
||||
|
||||
}
|
||||
|
||||
void TaskManager::SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *TaskList) {
|
||||
|
||||
void TaskManager::SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *TaskList)
|
||||
{
|
||||
Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSelector for %i Tasks", TaskCount);
|
||||
|
||||
int PlayerLevel = c->GetLevel();
|
||||
|
||||
// Check if any of the tasks exist
|
||||
for(int i=0; i<TaskCount; i++)
|
||||
{
|
||||
if(Tasks[TaskList[i]] != nullptr) break;
|
||||
}
|
||||
|
||||
int PacketLength = 12; // Header
|
||||
for (int i = 0; i < TaskCount; i++)
|
||||
if (Tasks[TaskList[i]] != nullptr)
|
||||
break;
|
||||
|
||||
int ValidTasks = 0;
|
||||
|
||||
char StartZone[10];
|
||||
|
||||
for(int i=0; i<TaskCount; i++) {
|
||||
|
||||
if(!AppropriateLevel(TaskList[i], PlayerLevel)) continue;
|
||||
|
||||
if(c->IsTaskActive(TaskList[i])) continue;
|
||||
|
||||
if(!IsTaskRepeatable(TaskList[i]) && c->IsTaskCompleted(TaskList[i])) continue;
|
||||
for (int i = 0; i < TaskCount; i++) {
|
||||
if (!AppropriateLevel(TaskList[i], PlayerLevel))
|
||||
continue;
|
||||
if (c->IsTaskActive(TaskList[i]))
|
||||
continue;
|
||||
if (!IsTaskRepeatable(TaskList[i]) && c->IsTaskCompleted(TaskList[i]))
|
||||
continue;
|
||||
|
||||
ValidTasks++;
|
||||
|
||||
PacketLength += 21; // Task Data - strings
|
||||
PacketLength += Tasks[TaskList[i]]->Title.size() + 1 +
|
||||
Tasks[TaskList[i]]->Description.size() + 1;
|
||||
|
||||
sprintf(StartZone, "%i", Tasks[TaskList[i]]->StartZone);
|
||||
/*
|
||||
PacketLength += strlen(Tasks[TaskList[i]]->Activity[ActivityID].Text1) + 1 +
|
||||
strlen(Tasks[TaskList[i]]->Activity[ActivityID].Text2) +
|
||||
strlen(Tasks[TaskList[i]]->Activity[ActivityID].Text3) + 1 +
|
||||
strlen(itoa(Tasks[TaskList[i]]->Activity[ActivityID].ZoneID)) + 1 +
|
||||
3 + 3 + 5; // Other strings (Hard set for now)
|
||||
*/
|
||||
PacketLength += 11 + 11 + 11 + 3 + 3 + (strlen(StartZone) * 2) + 2; // Other strings (Hard set for now)
|
||||
PacketLength += 28; // Activity Data - strings (Hard set for 1 activity per task for now)
|
||||
}
|
||||
|
||||
if(ValidTasks == 0) return;
|
||||
if (ValidTasks == 0)
|
||||
return;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_OpenNewTasksWindow, PacketLength);
|
||||
SerializeBuffer buf(50 * ValidTasks);
|
||||
|
||||
outapp->WriteUInt32(ValidTasks); // TaskCount
|
||||
outapp->WriteUInt32(2); // Type, valid values: 0-3. 0 = Task, 1 = Shared Task, 2 = Quest, 3 = ???
|
||||
buf.WriteUInt32(ValidTasks); // TaskCount
|
||||
buf.WriteUInt32(2); // Type, valid values: 0-3. 0 = Task, 1 = Shared Task, 2 = Quest, 3 = ??? -- should fix maybe some day, but we let more than 1 type through :P
|
||||
// so I guess an NPC can only offer one type of quests or we can only open a selection with one type :P (so quest call can tell us I guess)
|
||||
// this is also sent in OP_TaskDescription
|
||||
outapp->WriteUInt32(mob->GetID()); // TaskGiver
|
||||
buf.WriteUInt32(mob->GetID()); // TaskGiver
|
||||
|
||||
for(int i=0; i<TaskCount;i++) { // max 40
|
||||
for (int i = 0; i < TaskCount; i++) { // max 40
|
||||
if (!AppropriateLevel(TaskList[i], PlayerLevel))
|
||||
continue;
|
||||
if (c->IsTaskActive(TaskList[i]))
|
||||
continue;
|
||||
if (!IsTaskRepeatable(TaskList[i]) && c->IsTaskCompleted(TaskList[i]))
|
||||
continue;
|
||||
|
||||
if(!AppropriateLevel(TaskList[i], PlayerLevel)) continue;
|
||||
buf.WriteUInt32(TaskList[i]); // TaskID
|
||||
buf.WriteFloat(1.0f); // affects color, difficulty?
|
||||
buf.WriteUInt32(Tasks[TaskList[i]]->Duration);
|
||||
buf.WriteUInt32(static_cast<int>(Tasks[TaskList[i]]->dur_code)); // 1 = Short, 2 = Medium, 3 = Long, anything else Unlimited
|
||||
|
||||
if(c->IsTaskActive(TaskList[i])) continue;
|
||||
buf.WriteString(Tasks[TaskList[i]]->Title.c_str()); // max 64 with null
|
||||
buf.WriteString(Tasks[TaskList[i]]->Description.c_str()); // max 4000 with null
|
||||
|
||||
if(!IsTaskRepeatable(TaskList[i]) && c->IsTaskCompleted(TaskList[i])) continue;
|
||||
buf.WriteUInt8(0); // Has reward set flag
|
||||
buf.WriteUInt32(Tasks[TaskList[i]]->ActivityCount); // ActivityCount
|
||||
|
||||
outapp->WriteUInt32(TaskList[i]); // TaskID
|
||||
outapp->WriteFloat(1.0f); // affects color, difficulty?
|
||||
outapp->WriteUInt32(Tasks[TaskList[i]]->Duration);
|
||||
outapp->WriteUInt32(static_cast<int>(Tasks[TaskList[i]]->dur_code)); // 1 = Short, 2 = Medium, 3 = Long, anything else Unlimited
|
||||
for (int j = 0; j < Tasks[TaskList[i]]->ActivityCount; ++j) {
|
||||
buf.WriteUInt32(j); // ActivityNumber
|
||||
auto &activity = Tasks[TaskList[i]]->Activity[j];
|
||||
buf.WriteUInt32(activity.Type); // ActivityType
|
||||
buf.WriteUInt32(0); // solo, group, raid?
|
||||
buf.WriteString(activity.target_name); // max length 64, "target name" so like loot x foo from bar (this is bar)
|
||||
|
||||
outapp->WriteString(Tasks[TaskList[i]]->Title.c_str()); // max 64 with null
|
||||
outapp->WriteString(Tasks[TaskList[i]]->Description.c_str()); // max 4000 with null
|
||||
// this string is item names
|
||||
buf.WriteLengthString(activity.item_list.length(), activity.item_list.c_str());
|
||||
|
||||
outapp->WriteUInt8(0); // Has reward set flag
|
||||
outapp->WriteUInt32(1); // ActivityCount - Hard set to 1 for now
|
||||
buf.WriteUInt32(activity.GoalCount); // GoalCount
|
||||
|
||||
// Activity stuff below - Will need to iterate through each task
|
||||
// Currently hard set for testing
|
||||
// this string is skill IDs? probably one of the "use on" tasks
|
||||
buf.WriteLengthString(activity.skill_list.length(), activity.skill_list.c_str());
|
||||
|
||||
// this string is spell IDs? probably one of the "use on" tasks
|
||||
buf.WriteLengthString(activity.spell_list.length(), activity.spell_list.c_str());
|
||||
|
||||
sprintf(StartZone, "%i", Tasks[TaskList[i]]->StartZone);
|
||||
|
||||
outapp->WriteUInt32(0); // ActivityNumber
|
||||
outapp->WriteUInt32(1); // ActivityType
|
||||
outapp->WriteUInt32(0); // solo, group, raid?
|
||||
outapp->WriteString("Text1 Test"); // max length 64 -- affects what string ID it will use for the description, should be a name here?
|
||||
|
||||
// this string is item names
|
||||
outapp->WriteUInt32(11); // Text2Len
|
||||
outapp->WriteString("Text2 Test");
|
||||
|
||||
outapp->WriteUInt32(1); // GoalCount
|
||||
|
||||
// this string is skill IDs? probably one of the "use on" tasks
|
||||
outapp->WriteUInt32(3); // NumString1Len
|
||||
outapp->WriteString("-1");
|
||||
|
||||
// this string is spell IDs? probably one of the "use on" tasks
|
||||
outapp->WriteUInt32(3); // NumString2Len
|
||||
outapp->WriteString("-1");
|
||||
|
||||
//outapp->WriteString(itoa(Tasks[TaskList[i]]->Activity[ActivityID].ZoneID));
|
||||
outapp->WriteString(StartZone); // Zone number in ascii max length 64, can be multiple with separated by ;
|
||||
outapp->WriteString("Text3 Test"); // max length 128 -- overrides the automatic descriptions
|
||||
outapp->WriteString(StartZone); // Zone number in ascii max length 64, probably can be separated by ; too, haven't found it used
|
||||
//buf.WriteString(itoa(Tasks[TaskList[i]]->Activity[ActivityID].ZoneID));
|
||||
buf.WriteString(activity.zones); // Zone number in ascii max length 64, can be multiple with separated by ;
|
||||
buf.WriteString(activity.desc_override); // max length 128 -- overrides the automatic descriptions
|
||||
// this doesn't appear to be shown to the client at all and isn't the same as zones ... defaults to '0' though
|
||||
buf.WriteString(activity.zones); // Zone number in ascii max length 64, probably can be separated by ; too, haven't found it used
|
||||
}
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_OpenNewTasksWindow, buf.buffer(), buf.length());
|
||||
|
||||
c->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
@ -2609,12 +2589,12 @@ void TaskManager::SendTaskActivityLong(Client *c, int TaskID, int ActivityID, in
|
||||
tah->ActivityID = ActivityID;
|
||||
tah->unknown3 = 0x00000000;
|
||||
|
||||
// We send our 'internal' types as ActivityUse1. text3 should be set to the activity description, so it makes
|
||||
// We send our 'internal' types as ActivityCastOn. text3 should be set to the activity description, so it makes
|
||||
// no difference to the client. All activity updates will be done based on our interal activity types.
|
||||
if((Tasks[TaskID]->Activity[ActivityID].Type > 0) && Tasks[TaskID]->Activity[ActivityID].Type < 100)
|
||||
tah->ActivityType = Tasks[TaskID]->Activity[ActivityID].Type;
|
||||
else
|
||||
tah->ActivityType = ActivityUse1;
|
||||
tah->ActivityType = ActivityCastOn;
|
||||
|
||||
tah->Optional = Optional;
|
||||
tah->unknown5 = 0x00000000;
|
||||
@ -2667,77 +2647,59 @@ void TaskManager::SendTaskActivityLong(Client *c, int TaskID, int ActivityID, in
|
||||
}
|
||||
|
||||
// Used only by RoF+ Clients
|
||||
void TaskManager::SendTaskActivityNew(Client *c, int TaskID, int ActivityID, int ClientTaskIndex, bool Optional, bool TaskComplete) {
|
||||
void TaskManager::SendTaskActivityNew(Client *c, int TaskID, int ActivityID, int ClientTaskIndex, bool Optional, bool TaskComplete)
|
||||
{
|
||||
SerializeBuffer buf(100);
|
||||
|
||||
uint32 String2Len = 3;
|
||||
if(TaskComplete)
|
||||
String2Len = 4;
|
||||
buf.WriteUInt32(ClientTaskIndex); // TaskSequenceNumber
|
||||
buf.WriteUInt32(static_cast<uint32>(Tasks[TaskID]->type)); // task type
|
||||
buf.WriteUInt32(TaskID);
|
||||
buf.WriteUInt32(ActivityID);
|
||||
buf.WriteUInt32(0); // unknown3
|
||||
|
||||
long PacketLength = 29 + 4 + 8 + 4 + 4 + 5;
|
||||
PacketLength = PacketLength + Tasks[TaskID]->Activity[ActivityID].Text1.size() + 1 +
|
||||
Tasks[TaskID]->Activity[ActivityID].Text2.size() + 1 +
|
||||
Tasks[TaskID]->Activity[ActivityID].Text3.size() + 1 +
|
||||
((strlen(itoa(Tasks[TaskID]->Activity[ActivityID].ZoneID)) + 1) * 2) +
|
||||
3 + String2Len;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_TaskActivity, PacketLength);
|
||||
|
||||
outapp->WriteUInt32(ClientTaskIndex); // TaskSequenceNumber
|
||||
outapp->WriteUInt32(static_cast<uint32>(Tasks[TaskID]->type)); // task type
|
||||
outapp->WriteUInt32(TaskID);
|
||||
outapp->WriteUInt32(ActivityID);
|
||||
outapp->WriteUInt32(0); // unknown3
|
||||
|
||||
// We send our 'internal' types as ActivityUse1. text3 should be set to the activity description, so it makes
|
||||
// We send our 'internal' types as ActivityCastOn. text3 should be set to the activity description, so it makes
|
||||
// no difference to the client. All activity updates will be done based on our interal activity types.
|
||||
if((Tasks[TaskID]->Activity[ActivityID].Type > 0) && Tasks[TaskID]->Activity[ActivityID].Type < 100)
|
||||
outapp->WriteUInt32(Tasks[TaskID]->Activity[ActivityID].Type);
|
||||
buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].Type);
|
||||
else
|
||||
outapp->WriteUInt32(ActivityUse1);
|
||||
buf.WriteUInt32(ActivityCastOn); // w/e!
|
||||
|
||||
outapp->WriteUInt32(Optional);
|
||||
outapp->WriteUInt8(0); // unknown5
|
||||
buf.WriteUInt8(Optional);
|
||||
buf.WriteUInt32(0); // solo, group, raid
|
||||
|
||||
// One of these unknown fields maybe related to the 'Use On' activity types
|
||||
outapp->WriteString(Tasks[TaskID]->Activity[ActivityID].Text1.c_str());
|
||||
buf.WriteString(Tasks[TaskID]->Activity[ActivityID].target_name); // target name string
|
||||
|
||||
outapp->WriteUInt32(Tasks[TaskID]->Activity[ActivityID].Text2.length() + 1); // String Length - Add in null terminator
|
||||
outapp->WriteString(Tasks[TaskID]->Activity[ActivityID].Text2.c_str());
|
||||
buf.WriteLengthString(Tasks[TaskID]->Activity[ActivityID].item_list.length(), Tasks[TaskID]->Activity[ActivityID].item_list.c_str()); // item name list
|
||||
|
||||
// Goal Count
|
||||
if(Tasks[TaskID]->Activity[ActivityID].Type != ActivityGiveCash)
|
||||
outapp->WriteUInt32(Tasks[TaskID]->Activity[ActivityID].GoalCount);
|
||||
buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].GoalCount);
|
||||
else
|
||||
outapp->WriteUInt32(1); // GoalCount
|
||||
buf.WriteUInt32(1); // GoalCount
|
||||
|
||||
outapp->WriteUInt32(3); // String Length - Add in null terminator
|
||||
outapp->WriteString("-1");
|
||||
// skill ID list ; separated
|
||||
buf.WriteLengthString(Tasks[TaskID]->Activity[ActivityID].skill_list.length(), Tasks[TaskID]->Activity[ActivityID].skill_list.c_str());
|
||||
|
||||
if(!TaskComplete) {
|
||||
outapp->WriteUInt32(3); // String Length - Add in null terminator
|
||||
outapp->WriteString("-1");
|
||||
}
|
||||
else
|
||||
{
|
||||
outapp->WriteUInt32(4); // String Length - Add in null terminator
|
||||
outapp->WriteString("-54");
|
||||
}
|
||||
// spelll ID list ; separated -- unsure wtf we're doing here
|
||||
buf.WriteLengthString(Tasks[TaskID]->Activity[ActivityID].spell_list.length(), Tasks[TaskID]->Activity[ActivityID].spell_list.c_str());
|
||||
|
||||
outapp->WriteString(itoa(Tasks[TaskID]->Activity[ActivityID].ZoneID));
|
||||
outapp->WriteUInt32(0); // unknown7
|
||||
buf.WriteString(Tasks[TaskID]->Activity[ActivityID].zones);
|
||||
buf.WriteUInt32(0); // unknown7
|
||||
|
||||
outapp->WriteString(Tasks[TaskID]->Activity[ActivityID].Text3.c_str());
|
||||
buf.WriteString(Tasks[TaskID]->Activity[ActivityID].desc_override); // description override
|
||||
|
||||
if(Tasks[TaskID]->Activity[ActivityID].Type != ActivityGiveCash)
|
||||
outapp->WriteUInt32(c->GetTaskActivityDoneCount(ClientTaskIndex, ActivityID)); // DoneCount
|
||||
buf.WriteUInt32(c->GetTaskActivityDoneCount(ClientTaskIndex, ActivityID)); // DoneCount
|
||||
else
|
||||
// For internal activity types, DoneCount is either 1 if the activity is complete, 0 otherwise.
|
||||
outapp->WriteUInt32((c->GetTaskActivityDoneCount(ClientTaskIndex, ActivityID) >= Tasks[TaskID]->Activity[ActivityID].GoalCount));
|
||||
buf.WriteUInt32((c->GetTaskActivityDoneCount(ClientTaskIndex, ActivityID) >= Tasks[TaskID]->Activity[ActivityID].GoalCount));
|
||||
|
||||
outapp->WriteUInt8(1); // unknown9
|
||||
buf.WriteUInt8(1); // unknown9
|
||||
|
||||
outapp->WriteString(itoa(Tasks[TaskID]->Activity[ActivityID].ZoneID));
|
||||
buf.WriteString(Tasks[TaskID]->Activity[ActivityID].zones);
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_TaskActivity, buf.buffer(), buf.length());
|
||||
|
||||
c->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
10
zone/tasks.h
10
zone/tasks.h
@ -105,11 +105,19 @@ struct ActivityInformation {
|
||||
std::string Text1;
|
||||
std::string Text2;
|
||||
std::string Text3;
|
||||
std::string target_name; // name mob, location -- default empty
|
||||
std::string item_list; // likely defaults to empty
|
||||
std::string skill_list; // IDs ; separated -- default -1
|
||||
std::string spell_list; // IDs ; separated -- default 0
|
||||
std::string desc_override; // overrides auto generated description -- default empty
|
||||
int skill_id; // older clients, first id from above
|
||||
int spell_id; // older clients, first id from above
|
||||
int GoalID;
|
||||
TaskMethodType GoalMethod;
|
||||
int GoalCount;
|
||||
int DeliverToNPC;
|
||||
int ZoneID;
|
||||
std::string zones; // IDs ; searated, ZoneID is the first in this list for older clients -- default empty string
|
||||
bool Optional;
|
||||
};
|
||||
|
||||
@ -154,7 +162,7 @@ struct TaskInformation {
|
||||
typedef enum { ActivityHidden = 0, ActivityActive = 1, ActivityCompleted = 2 } ActivityState;
|
||||
|
||||
typedef enum { ActivityDeliver = 1, ActivityKill = 2, ActivityLoot = 3, ActivitySpeakWith = 4, ActivityExplore = 5,
|
||||
ActivityTradeSkill = 6, ActivityFish = 7, ActivityForage = 8, ActivityUse1 = 9, ActivityUse2 = 10,
|
||||
ActivityTradeSkill = 6, ActivityFish = 7, ActivityForage = 8, ActivityCastOn = 9, ActivitySkillOn = 10,
|
||||
ActivityTouch = 11, ActivityCollect = 13, ActivityGiveCash = 100 } ActivityType;
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user