mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-19 20:41:33 +00:00
World should verify the full task to simplify things
This commit is contained in:
parent
358ce2ca94
commit
e1bb3301a5
@ -151,6 +151,7 @@ SET(common_headers
|
|||||||
fixed_memory_hash_set.h
|
fixed_memory_hash_set.h
|
||||||
fixed_memory_variable_hash_set.h
|
fixed_memory_variable_hash_set.h
|
||||||
global_define.h
|
global_define.h
|
||||||
|
global_tasks.h
|
||||||
guild_base.h
|
guild_base.h
|
||||||
guilds.h
|
guilds.h
|
||||||
inventory_profile.h
|
inventory_profile.h
|
||||||
|
|||||||
155
common/global_tasks.h
Normal file
155
common/global_tasks.h
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||||
|
|
||||||
|
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; version 2 of the License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
are required to give you total support for your newly bought product;
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
#ifndef GLOBAL_TASKS_H
|
||||||
|
#define GLOBAL_TASKS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
/* This file contains what is needed for both zone and world managers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAXTASKS 10000
|
||||||
|
#define MAXTASKSETS 1000
|
||||||
|
// The Client has a hard cap of 19 active quests, 29 in SoD+
|
||||||
|
#define MAXACTIVEQUESTS 19
|
||||||
|
// The Max Chooser (Task Selector entries) is capped at 40 in the Titanium Client.
|
||||||
|
#define MAXCHOOSERENTRIES 40
|
||||||
|
// The Client has a hard cap of 20 activities per task.
|
||||||
|
#define MAXACTIVITIESPERTASK 20
|
||||||
|
// This is used to determine if a client's active task slot is empty.
|
||||||
|
#define TASKSLOTEMPTY 0
|
||||||
|
|
||||||
|
// Command Codes for worldserver ServerOP_ReloadTasks
|
||||||
|
#define RELOADTASKS 0
|
||||||
|
#define RELOADTASKGOALLISTS 1
|
||||||
|
#define RELOADTASKPROXIMITIES 2
|
||||||
|
#define RELOADTASKSETS 3
|
||||||
|
|
||||||
|
// used for timer lockouts and /tasktimers
|
||||||
|
struct TaskTimer {
|
||||||
|
int ID; // ID used in task timer (replay group)
|
||||||
|
int original_id; // original ID of the task (book keeping)
|
||||||
|
int expires; // UNIX timestamp of when it expires, what happens with DLS? Fuck it.
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum { METHODSINGLEID = 0, METHODLIST = 1, METHODQUEST = 2 } TaskMethodType;
|
||||||
|
|
||||||
|
struct ActivityInformation {
|
||||||
|
int StepNumber;
|
||||||
|
int Type;
|
||||||
|
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;
|
||||||
|
std::vector<int> ZoneIDs;
|
||||||
|
std::string zones; // IDs ; searated, ZoneID is the first in this list for older clients -- default empty string
|
||||||
|
bool Optional;
|
||||||
|
|
||||||
|
inline bool CheckZone(int zone_id) {
|
||||||
|
if (ZoneIDs.empty())
|
||||||
|
return true;
|
||||||
|
return std::find(ZoneIDs.begin(), ZoneIDs.end(), zone_id) != ZoneIDs.end();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum { ActivitiesSequential = 0, ActivitiesStepped = 1 } SequenceType;
|
||||||
|
|
||||||
|
enum class TaskType {
|
||||||
|
Task = 0, // can have at max 1
|
||||||
|
Shared = 1, // can have at max 1
|
||||||
|
Quest = 2, // can have at max 19 or 29 depending on client
|
||||||
|
E = 3 // can have at max 19 or 29 depending on client, not present in live anymore
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class DurationCode {
|
||||||
|
None = 0,
|
||||||
|
Short = 1,
|
||||||
|
Medium = 2,
|
||||||
|
Long = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
// need to capture more, shared are just Radiant/Ebon though
|
||||||
|
enum class PointType {
|
||||||
|
None = 0,
|
||||||
|
Radiant = 4,
|
||||||
|
Ebon = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TaskInformation {
|
||||||
|
TaskType type;
|
||||||
|
int Duration;
|
||||||
|
DurationCode dur_code; // description for time investment for when Duration == 0
|
||||||
|
std::string Title; // max length 64
|
||||||
|
std::string Description; // max length 4000, 2048 on Tit
|
||||||
|
std::string Reward;
|
||||||
|
std::string item_link; // max length 128 older clients, item link gets own string
|
||||||
|
std::string completion_emote; // emote after completing task, yellow. Maybe should make more generic ... but yellow for now!
|
||||||
|
int RewardID;
|
||||||
|
int CashReward; // Expressed in copper
|
||||||
|
int XPReward;
|
||||||
|
int faction_reward; // just a npc_faction_id
|
||||||
|
TaskMethodType RewardMethod;
|
||||||
|
int reward_points; // DoN crystals for shared. Generic "points" for non-shared
|
||||||
|
PointType reward_type; // 4 for Radiant Crystals else Ebon crystals when shared task
|
||||||
|
int ActivityCount;
|
||||||
|
SequenceType SequenceMode;
|
||||||
|
int LastStep;
|
||||||
|
short MinLevel;
|
||||||
|
short MaxLevel;
|
||||||
|
bool Repeatable;
|
||||||
|
int replay_group; // ID of our replay timer group (0 means none)
|
||||||
|
int min_players; // shared tasks
|
||||||
|
int max_players;
|
||||||
|
int task_lock_step; // task locks after this step is completed
|
||||||
|
uint32 instance_zone_id; // instance shit
|
||||||
|
uint32 zone_version;
|
||||||
|
uint16 zone_in_zone_id;
|
||||||
|
float zone_in_x;
|
||||||
|
float zone_in_y;
|
||||||
|
uint16 zone_in_object_id;
|
||||||
|
float dest_x;
|
||||||
|
float dest_y;
|
||||||
|
float dest_z;
|
||||||
|
float dest_h;
|
||||||
|
/* int graveyard_zone_id;
|
||||||
|
float graveyard_x;
|
||||||
|
float graveyard_y;
|
||||||
|
float graveyard_z;
|
||||||
|
float graveyard_radius; */
|
||||||
|
ActivityInformation Activity[MAXACTIVITIESPERTASK];
|
||||||
|
};
|
||||||
|
|
||||||
|
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, ActivityCastOn = 9, ActivitySkillOn = 10,
|
||||||
|
ActivityTouch = 11, ActivityCollect = 13, ActivityGiveCash = 100 } ActivityType;
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !GLOBAL_TASKS_H */
|
||||||
@ -157,7 +157,6 @@
|
|||||||
#define ServerOP_TaskReject 0x0302
|
#define ServerOP_TaskReject 0x0302
|
||||||
#define ServerOP_TaskAddPlayer 0x0303
|
#define ServerOP_TaskAddPlayer 0x0303
|
||||||
#define ServerOP_TaskRemovePlayer 0x0304
|
#define ServerOP_TaskRemovePlayer 0x0304
|
||||||
#define ServerOP_TaskRequestReply 0x0305
|
|
||||||
|
|
||||||
#define ServerOP_EncapPacket 0x2007 // Packet within a packet
|
#define ServerOP_EncapPacket 0x2007 // Packet within a packet
|
||||||
#define ServerOP_WorldListUpdate 0x2008
|
#define ServerOP_WorldListUpdate 0x2008
|
||||||
|
|||||||
@ -25,6 +25,9 @@
|
|||||||
#include "world_config.h"
|
#include "world_config.h"
|
||||||
#include "../common/guilds.h"
|
#include "../common/guilds.h"
|
||||||
#include "../common/string_util.h"
|
#include "../common/string_util.h"
|
||||||
|
#include "shared_tasks.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
extern uint32 numplayers;
|
extern uint32 numplayers;
|
||||||
extern LoginServerList loginserverlist;
|
extern LoginServerList loginserverlist;
|
||||||
@ -50,6 +53,8 @@ ClientListEntry::ClientListEntry(uint32 in_id, uint32 iLSID, const char* iLoginN
|
|||||||
pLFGToLevel = 0;
|
pLFGToLevel = 0;
|
||||||
pLFGMatchFilter = false;
|
pLFGMatchFilter = false;
|
||||||
memset(pLFGComments, 0, 64);
|
memset(pLFGComments, 0, 64);
|
||||||
|
shared_task_id = 0;
|
||||||
|
m_shared_task = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin)
|
ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin)
|
||||||
@ -71,6 +76,8 @@ ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccNa
|
|||||||
pLFGToLevel = 0;
|
pLFGToLevel = 0;
|
||||||
pLFGMatchFilter = false;
|
pLFGMatchFilter = false;
|
||||||
memset(pLFGComments, 0, 64);
|
memset(pLFGComments, 0, 64);
|
||||||
|
shared_task_id = 0;
|
||||||
|
m_shared_task = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline)
|
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline)
|
||||||
@ -93,6 +100,8 @@ ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList
|
|||||||
pLFGToLevel = 0;
|
pLFGToLevel = 0;
|
||||||
pLFGMatchFilter = false;
|
pLFGMatchFilter = false;
|
||||||
memset(pLFGComments, 0, 64);
|
memset(pLFGComments, 0, 64);
|
||||||
|
shared_task_id = 0;
|
||||||
|
m_shared_task = nullptr;
|
||||||
|
|
||||||
if (iOnline >= CLE_Status_Zoning)
|
if (iOnline >= CLE_Status_Zoning)
|
||||||
Update(iZS, scl, iOnline);
|
Update(iZS, scl, iOnline);
|
||||||
@ -105,6 +114,8 @@ ClientListEntry::~ClientListEntry() {
|
|||||||
Camp(); // updates zoneserver's numplayers
|
Camp(); // updates zoneserver's numplayers
|
||||||
client_list.RemoveCLEReferances(this);
|
client_list.RemoveCLEReferances(this);
|
||||||
}
|
}
|
||||||
|
if (m_shared_task != nullptr)
|
||||||
|
m_shared_task->MemberLeftGame(this);
|
||||||
for (auto &elem : tell_queue)
|
for (auto &elem : tell_queue)
|
||||||
safe_delete_array(elem);
|
safe_delete_array(elem);
|
||||||
tell_queue.clear();
|
tell_queue.clear();
|
||||||
@ -248,6 +259,10 @@ void ClientListEntry::ClearVars(bool iAll) {
|
|||||||
pLFG = 0;
|
pLFG = 0;
|
||||||
gm = 0;
|
gm = 0;
|
||||||
pClientVersion = 0;
|
pClientVersion = 0;
|
||||||
|
shared_task_id = 0;
|
||||||
|
if (m_shared_task != nullptr)
|
||||||
|
m_shared_task->MemberLeftGame(this);
|
||||||
|
m_shared_task = nullptr;
|
||||||
for (auto &elem : tell_queue)
|
for (auto &elem : tell_queue)
|
||||||
safe_delete_array(elem);
|
safe_delete_array(elem);
|
||||||
tell_queue.clear();
|
tell_queue.clear();
|
||||||
@ -331,3 +346,34 @@ void ClientListEntry::ProcessTellQueue()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns expire timestamp
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ClientListEntry::GetTaskLockoutExpire(int id) const
|
||||||
|
{
|
||||||
|
auto it = std::find_if(m_task_replay_timers.begin(), m_task_replay_timers.end(),
|
||||||
|
[id](const TaskTimer &a) { return a.ID == id; });
|
||||||
|
|
||||||
|
if (it != m_task_replay_timers.end())
|
||||||
|
return it->expires;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns seconds until expires
|
||||||
|
* returns <= 0 if expired
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ClientListEntry::GetTaskLockoutTimeLeft(int id) const
|
||||||
|
{
|
||||||
|
auto it = std::find_if(m_task_replay_timers.begin(), m_task_replay_timers.end(),
|
||||||
|
[id](const TaskTimer &a) { return a.ID == id; });
|
||||||
|
|
||||||
|
if (it != m_task_replay_timers.end())
|
||||||
|
return it->expires - Timer::GetCurrentTime();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
//#include "../common/eq_packet_structs.h"
|
//#include "../common/eq_packet_structs.h"
|
||||||
#include "../common/servertalk.h"
|
#include "../common/servertalk.h"
|
||||||
#include "../common/rulesys.h"
|
#include "../common/rulesys.h"
|
||||||
|
#include "../common/global_tasks.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
@ -18,6 +19,7 @@
|
|||||||
|
|
||||||
class ZoneServer;
|
class ZoneServer;
|
||||||
struct ServerClientList_Struct;
|
struct ServerClientList_Struct;
|
||||||
|
class SharedTask;
|
||||||
|
|
||||||
class ClientListEntry {
|
class ClientListEntry {
|
||||||
public:
|
public:
|
||||||
@ -88,6 +90,12 @@ public:
|
|||||||
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
|
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
|
||||||
void ProcessTellQueue();
|
void ProcessTellQueue();
|
||||||
|
|
||||||
|
// shared task stuff
|
||||||
|
int GetTaskLockoutExpire(int id) const;
|
||||||
|
int GetTaskLockoutTimeLeft(int id) const;
|
||||||
|
inline int GetCurrentSharedTaskID() const { return shared_task_id; }
|
||||||
|
inline void SetCurrentSharedTaskID(int in) { shared_task_id = in; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ClearVars(bool iAll = false);
|
void ClearVars(bool iAll = false);
|
||||||
|
|
||||||
@ -129,6 +137,13 @@ private:
|
|||||||
bool pLFGMatchFilter;
|
bool pLFGMatchFilter;
|
||||||
char pLFGComments[64];
|
char pLFGComments[64];
|
||||||
|
|
||||||
|
// shared task stuff
|
||||||
|
// stub for now
|
||||||
|
int shared_task_id; // ID in the TaskManager
|
||||||
|
SharedTask *m_shared_task; // just for quick reference so we can tell it to clean up our pointer
|
||||||
|
|
||||||
|
std::vector<TaskTimer> m_task_replay_timers;
|
||||||
|
|
||||||
// Tell Queue -- really a vector :D
|
// Tell Queue -- really a vector :D
|
||||||
std::vector<ServerChannelMessage_Struct *> tell_queue;
|
std::vector<ServerChannelMessage_Struct *> tell_queue;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
#include "cliententry.h"
|
#include "cliententry.h"
|
||||||
#include "zonelist.h"
|
#include "zonelist.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
extern ClientList client_list;
|
extern ClientList client_list;
|
||||||
extern ZSList zoneserver_list;
|
extern ZSList zoneserver_list;
|
||||||
|
|
||||||
@ -15,11 +17,25 @@ void SharedTaskManager::HandleTaskRequest(ServerPacket *pack)
|
|||||||
int task_id = pack->ReadUInt32();
|
int task_id = pack->ReadUInt32();
|
||||||
pack->ReadString(tmp_str);
|
pack->ReadString(tmp_str);
|
||||||
std::string leader_name = tmp_str;
|
std::string leader_name = tmp_str;
|
||||||
int missing_count = pack->ReadUInt32();
|
int player_count = pack->ReadUInt32();
|
||||||
std::vector<std::string> missing_players;
|
std::vector<std::string> players;
|
||||||
for (int i = 0; i < missing_count; ++i) {
|
for (int i = 0; i < player_count; ++i) {
|
||||||
pack->ReadString(tmp_str);
|
pack->ReadString(tmp_str);
|
||||||
missing_players.push_back(tmp_str);
|
players.push_back(tmp_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the task exist, we only load shared tasks in world, so we know the type is correct if found
|
||||||
|
auto it = task_information.find(task_id);
|
||||||
|
if (it == task_information.end()) { // not loaded! bad id or not shared task
|
||||||
|
auto pc = client_list.FindCharacter(leader_name.c_str());
|
||||||
|
if (pc) {
|
||||||
|
auto pack = new ServerPacket(ServerOP_TaskReject, leader_name.size() + 1 + 4);
|
||||||
|
pack->WriteUInt32(0); // string ID or just generic fail message
|
||||||
|
pack->WriteString(leader_name.c_str());
|
||||||
|
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
||||||
|
safe_delete(pack);
|
||||||
|
} // oh well
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int id = GetNextID();
|
int id = GetNextID();
|
||||||
@ -33,85 +49,46 @@ void SharedTaskManager::HandleTaskRequest(ServerPacket *pack)
|
|||||||
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
} // oh well
|
} // oh well
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cle = client_list.FindCharacter(leader_name.c_str());
|
||||||
|
if (cle == nullptr) {// something went wrong
|
||||||
|
tasks.erase(ret.first);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &task = ret.first->second;
|
auto &task = ret.first->second;
|
||||||
task.AddMember(leader_name, true);
|
task.AddMember(leader_name, cle, true);
|
||||||
|
|
||||||
if (missing_players.empty()) {
|
if (players.empty()) {
|
||||||
// send instant success to leader
|
// send instant success to leader
|
||||||
auto pc = client_list.FindCharacter(leader_name.c_str());
|
SerializeBuffer buf(10);
|
||||||
if (pc) {
|
buf.WriteInt32(id); // task's ID
|
||||||
SerializeBuffer buf(10);
|
buf.WriteString(leader_name); // leader's name
|
||||||
buf.WriteInt32(id); // task's ID
|
|
||||||
buf.WriteString(leader_name); // leader's name
|
|
||||||
|
|
||||||
auto pack = new ServerPacket(ServerOP_TaskGrant, buf);
|
auto pack = new ServerPacket(ServerOP_TaskGrant, buf);
|
||||||
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
zoneserver_list.SendPacket(cle->zone(), cle->instance(), pack);
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
} else { // well fuck
|
|
||||||
tasks.erase(ret.first);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
task.SetMissingCount(missing_count);
|
for (auto &&name : players) {
|
||||||
for (auto &&name : missing_players) {
|
|
||||||
// look up CLEs by name, tell them we need to know if they can be added
|
// look up CLEs by name, tell them we need to know if they can be added
|
||||||
auto pc = client_list.FindCharacter(name.c_str());
|
cle = client_list.FindCharacter(name.c_str());
|
||||||
if (pc) {
|
if (cle) {
|
||||||
SerializeBuffer buf(10);
|
// make sure we don't have a shared task already
|
||||||
buf.WriteInt32(id);
|
|
||||||
buf.WriteInt32(task_id);
|
|
||||||
buf.WriteString(name);
|
|
||||||
|
|
||||||
auto pack = new ServerPacket(ServerOP_TaskRequest, buf);
|
// make sure our level is right
|
||||||
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
|
||||||
safe_delete(pack);
|
// check our lock out timer
|
||||||
} else { // asked for a toon we couldn't find ABORT!
|
|
||||||
auto pc = client_list.FindCharacter(leader_name.c_str());
|
// we're good, add to task
|
||||||
if (pc) {
|
task.AddMember(name, cle);
|
||||||
auto pack = new ServerPacket(ServerOP_TaskReject, leader_name.size() + 1 + 4);
|
|
||||||
pack->WriteUInt32(0); // string ID or just generic fail message
|
|
||||||
pack->WriteString(leader_name.c_str());
|
|
||||||
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
|
||||||
safe_delete(pack);
|
|
||||||
} // oh well
|
|
||||||
tasks.erase(ret.first);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedTaskManager::HandleTaskRequestReply(ServerPacket *pack)
|
|
||||||
{
|
|
||||||
if (!pack)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int id = pack->ReadUInt32();
|
|
||||||
|
|
||||||
char name[64] = { 0 };
|
|
||||||
pack->ReadString(name);
|
|
||||||
|
|
||||||
int status = pack->ReadUInt32();
|
|
||||||
|
|
||||||
auto it = tasks.find(id);
|
|
||||||
if (it == tasks.end()) {
|
|
||||||
// task already errored and no longer existed, we can ignore
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &task = it->second;
|
|
||||||
|
|
||||||
if (status != TASKJOINOOZ_CAN) {
|
|
||||||
// TODO: forward to leader
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!task.DecrementMissingCount())
|
|
||||||
tasks.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is called once during boot of world
|
* This is called once during boot of world
|
||||||
* We need to load next_id, clean up expired tasks (?), and populate the map
|
* We need to load next_id, clean up expired tasks (?), and populate the map
|
||||||
@ -138,23 +115,19 @@ int SharedTaskManager::GetNextID()
|
|||||||
return next_id;
|
return next_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SharedTask::DecrementMissingCount()
|
/*
|
||||||
{
|
* When a player leaves world they will tell us to clean up their pointer
|
||||||
--missing_count;
|
* This is NOT leaving the shared task, just crashed or something
|
||||||
if (missing_count == 0) {
|
*/
|
||||||
auto pc = client_list.FindCharacter(leader_name.c_str());
|
|
||||||
if (pc) {
|
|
||||||
SerializeBuffer buf(10);
|
|
||||||
buf.WriteInt32(id); // task's ID
|
|
||||||
buf.WriteString(leader_name); // leader's name
|
|
||||||
|
|
||||||
auto pack = new ServerPacket(ServerOP_TaskGrant, buf);
|
void SharedTask::MemberLeftGame(ClientListEntry *cle)
|
||||||
zoneserver_list.SendPacket(pc->zone(), pc->instance(), pack);
|
{
|
||||||
safe_delete(pack);
|
auto it = std::find_if(members.begin(), members.end(), [cle](SharedTaskMember &m) { return m.cle == cle; });
|
||||||
} else {
|
|
||||||
return false; // error, please clean us up
|
// ahh okay ...
|
||||||
}
|
if (it == members.end())
|
||||||
}
|
return;
|
||||||
return true;
|
|
||||||
|
it->cle = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,29 +5,36 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "../common/servertalk.h"
|
#include "../common/servertalk.h"
|
||||||
|
#include "../common/global_tasks.h"
|
||||||
|
|
||||||
|
class ClientListEntry;
|
||||||
|
|
||||||
struct SharedTaskMember {
|
struct SharedTaskMember {
|
||||||
std::string name;
|
std::string name;
|
||||||
|
ClientListEntry *cle;
|
||||||
bool leader;
|
bool leader;
|
||||||
SharedTaskMember() : leader(false) {}
|
SharedTaskMember() : leader(false), cle(nullptr) {}
|
||||||
SharedTaskMember(std::string name, bool leader) : name(name), leader(leader) {}
|
SharedTaskMember(std::string name, ClientListEntry *cle, bool leader) : name(name), cle(cle), leader(leader) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SharedTask {
|
class SharedTask {
|
||||||
public:
|
public:
|
||||||
SharedTask() : id(0), task_id(0), missing_count(0) {}
|
SharedTask() : id(0), task_id(0) {}
|
||||||
SharedTask(int id, int task_id) : id(id), task_id(task_id), missing_count(0) {}
|
SharedTask(int id, int task_id) : id(id), task_id(task_id) {}
|
||||||
~SharedTask() {}
|
~SharedTask() {}
|
||||||
|
|
||||||
void AddMember(std::string name, bool leader = false) { members.push_back({name, leader}); if (leader) leader_name = name; }
|
void AddMember(std::string name, ClientListEntry *cle = nullptr, bool leader = false)
|
||||||
inline void SetMissingCount(int in) { missing_count = in; }
|
{
|
||||||
bool DecrementMissingCount(); // if we failed, tell who called us to clean us up basically
|
members.push_back({name, cle, leader});
|
||||||
|
if (leader)
|
||||||
|
leader_name = name;
|
||||||
|
}
|
||||||
|
void MemberLeftGame(ClientListEntry *cle);
|
||||||
const std::string &GetLeaderName() const { return leader_name; }
|
const std::string &GetLeaderName() const { return leader_name; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int id; // id we have in our map
|
int id; // id we have in our map
|
||||||
int task_id; // ID of the task we're on
|
int task_id; // ID of the task we're on
|
||||||
int missing_count; // other toons waiting to verify (out of zone, etc)
|
|
||||||
std::string leader_name;
|
std::string leader_name;
|
||||||
std::vector<SharedTaskMember> members;
|
std::vector<SharedTaskMember> members;
|
||||||
};
|
};
|
||||||
@ -38,15 +45,16 @@ public:
|
|||||||
~SharedTaskManager() {}
|
~SharedTaskManager() {}
|
||||||
|
|
||||||
bool LoadSharedTaskState();
|
bool LoadSharedTaskState();
|
||||||
|
bool LoadSharedTasks();
|
||||||
|
|
||||||
// IPC packet processing
|
// IPC packet processing
|
||||||
void HandleTaskRequest(ServerPacket *pack);
|
void HandleTaskRequest(ServerPacket *pack);
|
||||||
void HandleTaskRequestReply(ServerPacket *pack);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int GetNextID();
|
int GetNextID();
|
||||||
int next_id;
|
int next_id;
|
||||||
std::unordered_map<int, SharedTask> tasks;
|
std::unordered_map<int, SharedTask> tasks; // current active shared task states
|
||||||
|
std::unordered_map<int, TaskInformation> task_information; // task info shit
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* !SHARED_TASKS_H */
|
#endif /* !SHARED_TASKS_H */
|
||||||
|
|||||||
@ -1356,11 +1356,6 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
|||||||
shared_tasks.HandleTaskRequest(pack);
|
shared_tasks.HandleTaskRequest(pack);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ServerOP_TaskRequestReply:
|
|
||||||
{
|
|
||||||
shared_tasks.HandleTaskRequestReply(pack);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::World_Server, "Unknown ServerOPcode from zone 0x%04x, size %d", pack->opcode, pack->size);
|
Log(Logs::Detail, Logs::World_Server, "Unknown ServerOPcode from zone 0x%04x, size %d", pack->opcode, pack->size);
|
||||||
|
|||||||
@ -1036,7 +1036,6 @@ public:
|
|||||||
inline void ProcessTaskProximities(float X, float Y, float Z) { if(taskstate) taskstate->ProcessTaskProximities(this, X, Y, Z); }
|
inline void ProcessTaskProximities(float X, float Y, float Z) { if(taskstate) taskstate->ProcessTaskProximities(this, X, Y, Z); }
|
||||||
inline void AssignTask(int TaskID, int NPCID, bool enforce_level_requirement = false) { if (taskstate) taskstate->AcceptNewTask(this, TaskID, NPCID, enforce_level_requirement); }
|
inline void AssignTask(int TaskID, int NPCID, bool enforce_level_requirement = false) { if (taskstate) taskstate->AcceptNewTask(this, TaskID, NPCID, enforce_level_requirement); }
|
||||||
inline void AssignSharedTask(int TaskID, int NPCID, int id) { if (taskstate) taskstate->AcceptNewSharedTask(this, TaskID, NPCID, id); }
|
inline void AssignSharedTask(int TaskID, int NPCID, int id) { if (taskstate) taskstate->AcceptNewSharedTask(this, TaskID, NPCID, id); }
|
||||||
inline void HandleCanJoinSharedTask(int TaskID, int id) { if (taskstate) taskstate->HandleCanJoinSharedTask(this, TaskID, id); }
|
|
||||||
inline int ActiveSpeakTask(int NPCID) { if(taskstate) return taskstate->ActiveSpeakTask(NPCID); else return 0; }
|
inline int ActiveSpeakTask(int NPCID) { if(taskstate) return taskstate->ActiveSpeakTask(NPCID); else return 0; }
|
||||||
inline int ActiveSpeakActivity(int NPCID, int TaskID) { if(taskstate) return taskstate->ActiveSpeakActivity(NPCID, TaskID); else return 0; }
|
inline int ActiveSpeakActivity(int NPCID, int TaskID) { if(taskstate) return taskstate->ActiveSpeakActivity(NPCID, TaskID); else return 0; }
|
||||||
inline void FailTask(int TaskID) { if(taskstate) taskstate->FailTask(this, TaskID); }
|
inline void FailTask(int TaskID) { if(taskstate) taskstate->FailTask(this, TaskID); }
|
||||||
@ -1054,6 +1053,7 @@ public:
|
|||||||
inline int ActiveTasksInSet(int TaskSet) { return (taskstate ? taskstate->ActiveTasksInSet(TaskSet) :0); }
|
inline int ActiveTasksInSet(int TaskSet) { return (taskstate ? taskstate->ActiveTasksInSet(TaskSet) :0); }
|
||||||
inline int CompletedTasksInSet(int TaskSet) { return (taskstate ? taskstate->CompletedTasksInSet(TaskSet) :0); }
|
inline int CompletedTasksInSet(int TaskSet) { return (taskstate ? taskstate->CompletedTasksInSet(TaskSet) :0); }
|
||||||
inline int GetTaskLockoutExpire(int id) { return 0; } // stub
|
inline int GetTaskLockoutExpire(int id) { return 0; } // stub
|
||||||
|
inline int GetTaskLockoutTimeLeft(int id) { return 0; } // stub
|
||||||
|
|
||||||
inline void SetPendingTask(int id, int task_master_id) { pending_task.id = id; pending_task.task_master_id = task_master_id; }
|
inline void SetPendingTask(int id, int task_master_id) { pending_task.id = id; pending_task.task_master_id = task_master_id; }
|
||||||
inline bool HasPendingTask() const { return pending_task.id != 0; }
|
inline bool HasPendingTask() const { return pending_task.id != 0; }
|
||||||
|
|||||||
156
zone/tasks.cpp
156
zone/tasks.cpp
@ -3405,14 +3405,13 @@ void ClientTaskState::PendSharedTask(Client *c, int TaskID, int NPCID, bool enfo
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (task->replay_group) {
|
if (task->replay_group) {
|
||||||
auto expires = c->GetTaskLockoutExpire(task->replay_group);
|
auto expires = c->GetTaskLockoutTimeLeft(task->replay_group);
|
||||||
if (expires) {
|
if (expires > 0) {
|
||||||
auto diff = expires - Timer::GetCurrentTime();
|
std::string days = std::to_string(expires / 86400);
|
||||||
std::string days = std::to_string(diff / 86400);
|
expires = expires % 86400;
|
||||||
diff = diff % 86400;
|
std::string hours = std::to_string(expires / 3600);
|
||||||
std::string hours = std::to_string(diff / 3600);
|
expires = expires % 3600;
|
||||||
diff = diff % 3600;
|
std::string minutes = std::to_string(expires / 60);
|
||||||
std::string minutes = std::to_string(diff / 60);
|
|
||||||
c->Message_StringID(13, TASK_REJECT_LOCKEDOUT, days.c_str(), hours.c_str(), minutes.c_str());
|
c->Message_StringID(13, TASK_REJECT_LOCKEDOUT, days.c_str(), hours.c_str(), minutes.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3440,6 +3439,37 @@ void ClientTaskState::PendSharedTask(Client *c, int TaskID, int NPCID, bool enfo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// okay, we verified a few things on the requestor, now we need to fire off to world to do the rest
|
||||||
|
SerializeBuffer buf(25 + 10 * player_count);
|
||||||
|
buf.WriteInt32(TaskID); // Task ID
|
||||||
|
buf.WriteString(c->GetName()); // leader name
|
||||||
|
buf.WriteInt32(player_count - 1); // count, not leader
|
||||||
|
if (group) {
|
||||||
|
for (int i = 0; i < MAX_GROUP_MEMBERS; ++i) {
|
||||||
|
if (group->members[i] == c) // skipping requestor
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// TODO: mercs/bots
|
||||||
|
if (group->members[i] != nullptr && group->members[i]->IsClient())
|
||||||
|
buf.WriteString(group->membername[i]);
|
||||||
|
}
|
||||||
|
} else if (raid) {
|
||||||
|
for (int i = 0; i < MAX_RAID_MEMBERS; ++i) {
|
||||||
|
if (raid->members[i].member == c) // skipping requestor
|
||||||
|
continue;
|
||||||
|
// TODO: bots if they ever can live in a raid
|
||||||
|
if (raid->members[i].membername[0] != '\0')
|
||||||
|
buf.WriteString(raid->members[i].membername);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pack = new ServerPacket(ServerOP_TaskRequest, buf);
|
||||||
|
worldserver.SendPacket(pack);
|
||||||
|
delete pack;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
std::vector<std::string> missing_players; // names of players not in this zone so we can put the checks off to world
|
std::vector<std::string> missing_players; // names of players not in this zone so we can put the checks off to world
|
||||||
bool task_failed = false;
|
bool task_failed = false;
|
||||||
if (group) {
|
if (group) {
|
||||||
@ -3458,15 +3488,14 @@ void ClientTaskState::PendSharedTask(Client *c, int TaskID, int NPCID, bool enfo
|
|||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (task->replay_group) {
|
if (task->replay_group) {
|
||||||
auto expires = client->GetTaskLockoutExpire(task->replay_group);
|
auto expires = client->GetTaskLockoutTimeLeft(task->replay_group);
|
||||||
if (expires) {
|
if (expires > 0) {
|
||||||
task_failed = true;
|
task_failed = true;
|
||||||
auto diff = expires - Timer::GetCurrentTime();
|
std::string days = std::to_string(expires / 86400);
|
||||||
std::string days = std::to_string(diff / 86400);
|
expires = expires % 86400;
|
||||||
diff = diff % 86400;
|
std::string hours = std::to_string(expires / 3600);
|
||||||
std::string hours = std::to_string(diff / 3600);
|
expires = expires % 3600;
|
||||||
diff = diff % 3600;
|
std::string minutes = std::to_string(expires / 60);
|
||||||
std::string minutes = std::to_string(diff / 60);
|
|
||||||
c->Message_StringID(13, TASK_REJECT_LOCKEDOUT_OTHER,
|
c->Message_StringID(13, TASK_REJECT_LOCKEDOUT_OTHER,
|
||||||
client->GetName(), days.c_str(),
|
client->GetName(), days.c_str(),
|
||||||
hours.c_str(), minutes.c_str());
|
hours.c_str(), minutes.c_str());
|
||||||
@ -3497,15 +3526,14 @@ void ClientTaskState::PendSharedTask(Client *c, int TaskID, int NPCID, bool enfo
|
|||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (task->replay_group) {
|
if (task->replay_group) {
|
||||||
auto expires = client->GetTaskLockoutExpire(task->replay_group);
|
auto expires = client->GetTaskLockoutTimeLeft(task->replay_group);
|
||||||
if (expires) {
|
if (expires > 0) {
|
||||||
task_failed = true;
|
task_failed = true;
|
||||||
auto diff = expires - Timer::GetCurrentTime();
|
std::string days = std::to_string(expires / 86400);
|
||||||
std::string days = std::to_string(diff / 86400);
|
expires = expires % 86400;
|
||||||
diff = diff % 86400;
|
std::string hours = std::to_string(expires / 3600);
|
||||||
std::string hours = std::to_string(diff / 3600);
|
expires = expires % 3600;
|
||||||
diff = diff % 3600;
|
std::string minutes = std::to_string(expires / 60);
|
||||||
std::string minutes = std::to_string(diff / 60);
|
|
||||||
c->Message_StringID(13, TASK_REJECT_LOCKEDOUT_OTHER,
|
c->Message_StringID(13, TASK_REJECT_LOCKEDOUT_OTHER,
|
||||||
client->GetName(), days.c_str(),
|
client->GetName(), days.c_str(),
|
||||||
hours.c_str(), minutes.c_str());
|
hours.c_str(), minutes.c_str());
|
||||||
@ -3530,17 +3558,8 @@ void ClientTaskState::PendSharedTask(Client *c, int TaskID, int NPCID, bool enfo
|
|||||||
// so we've verified all the clients we can and didn't fail, time to pend and yell at world
|
// so we've verified all the clients we can and didn't fail, time to pend and yell at world
|
||||||
c->SetPendingTask(TaskID, NPCID);
|
c->SetPendingTask(TaskID, NPCID);
|
||||||
c->StartPendingTimer(); // in case something goes wrong and takes ages, we time out
|
c->StartPendingTimer(); // in case something goes wrong and takes ages, we time out
|
||||||
|
*/
|
||||||
|
|
||||||
SerializeBuffer buf(25 + 10 * missing_players.size());
|
|
||||||
buf.WriteInt32(TaskID); // Task ID
|
|
||||||
buf.WriteString(c->GetName()); // leader name
|
|
||||||
buf.WriteInt32(missing_players.size()); // count
|
|
||||||
for (auto && name : missing_players)
|
|
||||||
buf.WriteString(name);
|
|
||||||
|
|
||||||
auto pack = new ServerPacket(ServerOP_TaskRequest, buf);
|
|
||||||
worldserver.SendPacket(pack);
|
|
||||||
delete pack;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientTaskState::AcceptNewSharedTask(Client *c, int TaskID, int NPCID, int id)
|
void ClientTaskState::AcceptNewSharedTask(Client *c, int TaskID, int NPCID, int id)
|
||||||
@ -3548,75 +3567,6 @@ void ClientTaskState::AcceptNewSharedTask(Client *c, int TaskID, int NPCID, int
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientTaskState::HandleCanJoinSharedTask(Client *c, int TaskID, int id)
|
|
||||||
{
|
|
||||||
if (!c)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SerializeBuffer buf(15);
|
|
||||||
buf.WriteInt32(id);
|
|
||||||
buf.WriteString(c->GetName());
|
|
||||||
|
|
||||||
if (!taskmanager || TaskID < 0 || TaskID >= MAXTASKS) {
|
|
||||||
buf.WriteInt32(TASKJOINOOZ_NOTASK);
|
|
||||||
auto pack = new ServerPacket(ServerOP_TaskRequestReply, buf);
|
|
||||||
worldserver.SendPacket(pack);
|
|
||||||
delete pack;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto task = taskmanager->Tasks[TaskID];
|
|
||||||
|
|
||||||
if (task == nullptr) {
|
|
||||||
buf.WriteInt32(TASKJOINOOZ_NOTASK);
|
|
||||||
auto pack = new ServerPacket(ServerOP_TaskRequestReply, buf);
|
|
||||||
worldserver.SendPacket(pack);
|
|
||||||
delete pack;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (task->type != TaskType::Shared) {
|
|
||||||
buf.WriteInt32(TASKJOINOOZ_NOTASK);
|
|
||||||
auto pack = new ServerPacket(ServerOP_TaskRequestReply, buf);
|
|
||||||
worldserver.SendPacket(pack);
|
|
||||||
delete pack;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ActiveSharedTask != nullptr) {
|
|
||||||
buf.WriteInt32(TASKJOINOOZ_HAVEONE);
|
|
||||||
auto pack = new ServerPacket(ServerOP_TaskRequestReply, buf);
|
|
||||||
worldserver.SendPacket(pack);
|
|
||||||
delete pack;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!taskmanager->AppropriateLevel(TaskID, c->GetLevel())) {
|
|
||||||
buf.WriteInt32(TASKJOINOOZ_LEVEL);
|
|
||||||
auto pack = new ServerPacket(ServerOP_TaskRequestReply, buf);
|
|
||||||
worldserver.SendPacket(pack);
|
|
||||||
delete pack;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (task->replay_group) {
|
|
||||||
auto expires = c->GetTaskLockoutExpire(task->replay_group);
|
|
||||||
if (expires) {
|
|
||||||
buf.WriteInt32(TASKJOINOOZ_TIMER);
|
|
||||||
buf.WriteInt32(expires);
|
|
||||||
auto pack = new ServerPacket(ServerOP_TaskRequestReply, buf);
|
|
||||||
worldserver.SendPacket(pack);
|
|
||||||
delete pack;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.WriteInt32(TASKJOINOOZ_CAN);
|
|
||||||
auto pack = new ServerPacket(ServerOP_TaskRequestReply, buf);
|
|
||||||
worldserver.SendPacket(pack);
|
|
||||||
delete pack;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientTaskState::ProcessTaskProximities(Client *c, float X, float Y, float Z) {
|
void ClientTaskState::ProcessTaskProximities(Client *c, float X, float Y, float Z) {
|
||||||
|
|
||||||
float LastX = c->ProximityX();
|
float LastX = c->ProximityX();
|
||||||
|
|||||||
127
zone/tasks.h
127
zone/tasks.h
@ -21,6 +21,7 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
|
|||||||
#define TASKS_H
|
#define TASKS_H
|
||||||
|
|
||||||
#include "../common/types.h"
|
#include "../common/types.h"
|
||||||
|
#include "../common/global_tasks.h"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -29,24 +30,6 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#define MAXTASKS 10000
|
|
||||||
#define MAXTASKSETS 1000
|
|
||||||
// The Client has a hard cap of 19 active quests, 29 in SoD+
|
|
||||||
#define MAXACTIVEQUESTS 19
|
|
||||||
// The Max Chooser (Task Selector entries) is capped at 40 in the Titanium Client.
|
|
||||||
#define MAXCHOOSERENTRIES 40
|
|
||||||
// The Client has a hard cap of 20 activities per task.
|
|
||||||
#define MAXACTIVITIESPERTASK 20
|
|
||||||
// This is used to determine if a client's active task slot is empty.
|
|
||||||
#define TASKSLOTEMPTY 0
|
|
||||||
|
|
||||||
// Command Codes for worldserver ServerOP_ReloadTasks
|
|
||||||
//
|
|
||||||
#define RELOADTASKS 0
|
|
||||||
#define RELOADTASKGOALLISTS 1
|
|
||||||
#define RELOADTASKPROXIMITIES 2
|
|
||||||
#define RELOADTASKSETS 3
|
|
||||||
|
|
||||||
class Client;
|
class Client;
|
||||||
class Mob;
|
class Mob;
|
||||||
|
|
||||||
@ -100,106 +83,6 @@ private:
|
|||||||
std::vector<TaskProximity> TaskProximities;
|
std::vector<TaskProximity> TaskProximities;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum { METHODSINGLEID = 0, METHODLIST = 1, METHODQUEST = 2 } TaskMethodType;
|
|
||||||
|
|
||||||
struct ActivityInformation {
|
|
||||||
int StepNumber;
|
|
||||||
int Type;
|
|
||||||
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;
|
|
||||||
std::vector<int> ZoneIDs;
|
|
||||||
std::string zones; // IDs ; searated, ZoneID is the first in this list for older clients -- default empty string
|
|
||||||
bool Optional;
|
|
||||||
|
|
||||||
inline bool CheckZone(int zone_id) {
|
|
||||||
if (ZoneIDs.empty())
|
|
||||||
return true;
|
|
||||||
return std::find(ZoneIDs.begin(), ZoneIDs.end(), zone_id) != ZoneIDs.end();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum { ActivitiesSequential = 0, ActivitiesStepped = 1 } SequenceType;
|
|
||||||
|
|
||||||
enum class TaskType {
|
|
||||||
Task = 0, // can have at max 1
|
|
||||||
Shared = 1, // can have at max 1
|
|
||||||
Quest = 2, // can have at max 19 or 29 depending on client
|
|
||||||
E = 3 // can have at max 19 or 29 depending on client, not present in live anymore
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class DurationCode {
|
|
||||||
None = 0,
|
|
||||||
Short = 1,
|
|
||||||
Medium = 2,
|
|
||||||
Long = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
// need to capture more, shared are just Radiant/Ebon though
|
|
||||||
enum class PointType {
|
|
||||||
None = 0,
|
|
||||||
Radiant = 4,
|
|
||||||
Ebon = 5,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TaskInformation {
|
|
||||||
TaskType type;
|
|
||||||
int Duration;
|
|
||||||
DurationCode dur_code; // description for time investment for when Duration == 0
|
|
||||||
std::string Title; // max length 64
|
|
||||||
std::string Description; // max length 4000, 2048 on Tit
|
|
||||||
std::string Reward;
|
|
||||||
std::string item_link; // max length 128 older clients, item link gets own string
|
|
||||||
std::string completion_emote; // emote after completing task, yellow. Maybe should make more generic ... but yellow for now!
|
|
||||||
int RewardID;
|
|
||||||
int CashReward; // Expressed in copper
|
|
||||||
int XPReward;
|
|
||||||
int faction_reward; // just a npc_faction_id
|
|
||||||
TaskMethodType RewardMethod;
|
|
||||||
int reward_points; // DoN crystals for shared. Generic "points" for non-shared
|
|
||||||
PointType reward_type; // 4 for Radiant Crystals else Ebon crystals when shared task
|
|
||||||
int ActivityCount;
|
|
||||||
SequenceType SequenceMode;
|
|
||||||
int LastStep;
|
|
||||||
short MinLevel;
|
|
||||||
short MaxLevel;
|
|
||||||
bool Repeatable;
|
|
||||||
int replay_group; // ID of our replay timer group (0 means none)
|
|
||||||
int min_players; // shared tasks
|
|
||||||
int max_players;
|
|
||||||
int task_lock_step; // task locks after this step is completed
|
|
||||||
uint32 instance_zone_id; // instance shit
|
|
||||||
uint32 zone_version;
|
|
||||||
uint16 zone_in_zone_id;
|
|
||||||
float zone_in_x;
|
|
||||||
float zone_in_y;
|
|
||||||
uint16 zone_in_object_id;
|
|
||||||
float dest_x;
|
|
||||||
float dest_y;
|
|
||||||
float dest_z;
|
|
||||||
float dest_h;
|
|
||||||
/* int graveyard_zone_id;
|
|
||||||
float graveyard_x;
|
|
||||||
float graveyard_y;
|
|
||||||
float graveyard_z;
|
|
||||||
float graveyard_radius; */
|
|
||||||
ActivityInformation Activity[MAXACTIVITIESPERTASK];
|
|
||||||
};
|
|
||||||
|
|
||||||
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, ActivityCastOn = 9, ActivitySkillOn = 10,
|
|
||||||
ActivityTouch = 11, ActivityCollect = 13, ActivityGiveCash = 100 } ActivityType;
|
|
||||||
|
|
||||||
|
|
||||||
struct ClientActivityInformation {
|
struct ClientActivityInformation {
|
||||||
int ActivityID;
|
int ActivityID;
|
||||||
@ -267,7 +150,6 @@ public:
|
|||||||
void AcceptNewTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false);
|
void AcceptNewTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false);
|
||||||
void AcceptNewSharedTask(Client *c, int TaskID, int NPCID, int id);
|
void AcceptNewSharedTask(Client *c, int TaskID, int NPCID, int id);
|
||||||
void PendSharedTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false);
|
void PendSharedTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false);
|
||||||
void HandleCanJoinSharedTask(Client *c, int TaskID, int id);
|
|
||||||
void FailTask(Client *c, int TaskID);
|
void FailTask(Client *c, int TaskID);
|
||||||
int TaskTimeLeft(int TaskID);
|
int TaskTimeLeft(int TaskID);
|
||||||
int IsTaskCompleted(int TaskID);
|
int IsTaskCompleted(int TaskID);
|
||||||
@ -345,13 +227,6 @@ private:
|
|||||||
bool CheckedTouchActivities;
|
bool CheckedTouchActivities;
|
||||||
};
|
};
|
||||||
|
|
||||||
// used for timer lockouts and /tasktimers
|
|
||||||
struct TaskTimer {
|
|
||||||
int ID; // ID used in task timer
|
|
||||||
int original_id; // original ID of the task
|
|
||||||
int expires; // UNIX timestamp of when it expires, what happens with DLS? Fuck it.
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TaskReplayGroups {
|
struct TaskReplayGroups {
|
||||||
std::string name;
|
std::string name;
|
||||||
int duration;
|
int duration;
|
||||||
|
|||||||
@ -1954,6 +1954,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
|||||||
}
|
}
|
||||||
case ServerOP_TaskReject:
|
case ServerOP_TaskReject:
|
||||||
{
|
{
|
||||||
|
// this will be reworked to not use the pend shit, we will depend on hoping successive requests just get thrown out
|
||||||
int message = pack->ReadUInt32();
|
int message = pack->ReadUInt32();
|
||||||
char name[64] = { 0 };
|
char name[64] = { 0 };
|
||||||
pack->ReadString(name);
|
pack->ReadString(name);
|
||||||
@ -1968,18 +1969,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ServerOP_TaskRequest:
|
|
||||||
{
|
|
||||||
int id = pack->ReadUInt32(); // we need the ID when reply to world so we know which shared task we're going to
|
|
||||||
int task_id = pack->ReadUInt32();
|
|
||||||
char name[64] = { 0 };
|
|
||||||
pack->ReadString(name);
|
|
||||||
auto client = entity_list.GetClientByName(name);
|
|
||||||
if (client) {
|
|
||||||
client->HandleCanJoinSharedTask(task_id, id);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
default: {
|
||||||
std::cout << " Unknown ZSopcode:" << (int)pack->opcode;
|
std::cout << " Unknown ZSopcode:" << (int)pack->opcode;
|
||||||
std::cout << " size:" << pack->size << std::endl;
|
std::cout << " size:" << pack->size << std::endl;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user