mirror of
https://github.com/EQEmu/Server.git
synced 2026-03-10 14:22:26 +00:00
Shared Task WIP
This commit is contained in:
parent
d4e0e8aea2
commit
39544b4723
@ -6,6 +6,7 @@ N(OP_0x0347),
|
|||||||
N(OP_AAAction),
|
N(OP_AAAction),
|
||||||
N(OP_AAExpUpdate),
|
N(OP_AAExpUpdate),
|
||||||
N(OP_AcceptNewTask),
|
N(OP_AcceptNewTask),
|
||||||
|
N(OP_AcceptNewSharedTask),
|
||||||
N(OP_AckPacket),
|
N(OP_AckPacket),
|
||||||
N(OP_Action),
|
N(OP_Action),
|
||||||
N(OP_Action2),
|
N(OP_Action2),
|
||||||
|
|||||||
@ -3788,6 +3788,14 @@ struct AcceptNewTask_Struct {
|
|||||||
uint32 task_master_id; //entity ID
|
uint32 task_master_id; //entity ID
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AcceptNewSharedTask_Struct {
|
||||||
|
uint32 unknown00;
|
||||||
|
uint32 unknown04;
|
||||||
|
uint32 task_master_id;
|
||||||
|
uint32 task_id;
|
||||||
|
float unknown16;
|
||||||
|
};
|
||||||
|
|
||||||
//was all 0's from client, server replied with same op, all 0's
|
//was all 0's from client, server replied with same op, all 0's
|
||||||
struct CancelTask_Struct {
|
struct CancelTask_Struct {
|
||||||
uint32 SequenceNumber;
|
uint32 SequenceNumber;
|
||||||
|
|||||||
@ -187,6 +187,7 @@ public:
|
|||||||
const unsigned char *buffer() const { return m_buffer; }
|
const unsigned char *buffer() const { return m_buffer; }
|
||||||
|
|
||||||
friend class BasePacket;
|
friend class BasePacket;
|
||||||
|
friend class ServerPacket;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Grow(size_t new_size);
|
void Grow(size_t new_size);
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "../common/types.h"
|
#include "../common/types.h"
|
||||||
#include "../common/packet_functions.h"
|
#include "../common/packet_functions.h"
|
||||||
#include "../common/eq_packet_structs.h"
|
#include "../common/eq_packet_structs.h"
|
||||||
|
#include "../common/serialize_buffer.h"
|
||||||
#include "../net/packet.h"
|
#include "../net/packet.h"
|
||||||
#include <cereal/cereal.hpp>
|
#include <cereal/cereal.hpp>
|
||||||
#include <cereal/types/string.hpp>
|
#include <cereal/types/string.hpp>
|
||||||
@ -151,6 +152,12 @@
|
|||||||
#define ServerOP_LSRemoteAddr 0x1009
|
#define ServerOP_LSRemoteAddr 0x1009
|
||||||
#define ServerOP_LSAccountUpdate 0x100A
|
#define ServerOP_LSAccountUpdate 0x100A
|
||||||
|
|
||||||
|
#define ServerOP_TaskRequest 0x0300
|
||||||
|
#define ServerOP_TaskGrant 0x0301
|
||||||
|
#define ServerOP_TaskReject 0x0302
|
||||||
|
#define ServerOP_TaskAddPlayer 0x0303
|
||||||
|
#define ServerOP_TaskRemovePlayer 0x0304
|
||||||
|
|
||||||
#define ServerOP_EncapPacket 0x2007 // Packet within a packet
|
#define ServerOP_EncapPacket 0x2007 // Packet within a packet
|
||||||
#define ServerOP_WorldListUpdate 0x2008
|
#define ServerOP_WorldListUpdate 0x2008
|
||||||
#define ServerOP_WorldListRemove 0x2009
|
#define ServerOP_WorldListRemove 0x2009
|
||||||
@ -246,6 +253,19 @@ public:
|
|||||||
_rpos = 0;
|
_rpos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServerPacket(uint16 in_opcode, SerializeBuffer &buf)
|
||||||
|
{
|
||||||
|
compressed = false;
|
||||||
|
size = buf.m_pos;
|
||||||
|
buf.m_pos = 0;
|
||||||
|
opcode = in_opcode;
|
||||||
|
pBuffer = buf.m_buffer;
|
||||||
|
buf.m_buffer = 0;
|
||||||
|
buf.m_capacity = 0;
|
||||||
|
_wpos = 0;
|
||||||
|
_rpos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
ServerPacket* Copy() {
|
ServerPacket* Copy() {
|
||||||
if (this == 0) {
|
if (this == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -563,6 +563,7 @@ OP_TaskHistoryRequest=0x6cf6
|
|||||||
OP_TaskHistoryReply=0x25eb
|
OP_TaskHistoryReply=0x25eb
|
||||||
OP_DeclineAllTasks=0x0000
|
OP_DeclineAllTasks=0x0000
|
||||||
OP_TaskRequestTimer=0x4b76
|
OP_TaskRequestTimer=0x4b76
|
||||||
|
OP_AcceptNewSharedTask=0x3e5e
|
||||||
|
|
||||||
# Title opcodes
|
# Title opcodes
|
||||||
OP_NewTitlesAvailable=0x45d1
|
OP_NewTitlesAvailable=0x45d1
|
||||||
|
|||||||
@ -568,6 +568,7 @@ OP_TaskHistoryRequest=0x5f1c
|
|||||||
OP_TaskHistoryReply=0x3d05
|
OP_TaskHistoryReply=0x3d05
|
||||||
OP_DeclineAllTasks=0x0000
|
OP_DeclineAllTasks=0x0000
|
||||||
OP_TaskRequestTimer=0x7a48
|
OP_TaskRequestTimer=0x7a48
|
||||||
|
OP_AcceptNewSharedTask=0x6646
|
||||||
|
|
||||||
# Title opcodes
|
# Title opcodes
|
||||||
OP_NewTitlesAvailable=0x0d32
|
OP_NewTitlesAvailable=0x0d32
|
||||||
|
|||||||
@ -534,6 +534,7 @@ OP_TaskHistoryReply=0x3d2a # C
|
|||||||
OP_CancelTask=0x726b # C
|
OP_CancelTask=0x726b # C
|
||||||
OP_DeclineAllTasks=0x0000 #
|
OP_DeclineAllTasks=0x0000 #
|
||||||
OP_TaskRequestTimer=0x2e70
|
OP_TaskRequestTimer=0x2e70
|
||||||
|
OP_AcceptNewSharedTask=0x4751
|
||||||
|
|
||||||
|
|
||||||
OP_Shroud=0x6d1f
|
OP_Shroud=0x6d1f
|
||||||
|
|||||||
@ -510,6 +510,7 @@ OP_TaskRemovePlayer=0x516f
|
|||||||
OP_TaskPlayerList=0x0ad6
|
OP_TaskPlayerList=0x0ad6
|
||||||
OP_TaskQuit=0x2c8c
|
OP_TaskQuit=0x2c8c
|
||||||
OP_TaskRequestTimer=0x0b08
|
OP_TaskRequestTimer=0x0b08
|
||||||
|
OP_AcceptNewSharedTask=0x5bed
|
||||||
|
|
||||||
#Title opcodes
|
#Title opcodes
|
||||||
OP_NewTitlesAvailable=0x179c #
|
OP_NewTitlesAvailable=0x179c #
|
||||||
|
|||||||
@ -475,6 +475,7 @@ OP_TaskRemovePlayer=0x37b9
|
|||||||
OP_TaskPlayerList=0x3961
|
OP_TaskPlayerList=0x3961
|
||||||
OP_TaskQuit=0x35dd
|
OP_TaskQuit=0x35dd
|
||||||
OP_TaskRequestTimer=0x6a1d
|
OP_TaskRequestTimer=0x6a1d
|
||||||
|
OP_AcceptNewSharedTask=0x194d
|
||||||
#task complete related: 0x0000 (24 bytes), 0x0000 (8 bytes), 0x0000 (4 bytes)
|
#task complete related: 0x0000 (24 bytes), 0x0000 (8 bytes), 0x0000 (4 bytes)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -557,6 +557,7 @@ OP_TaskHistoryReply=0x4524 # C
|
|||||||
OP_CancelTask=0x3bf5 # C
|
OP_CancelTask=0x3bf5 # C
|
||||||
OP_DeclineAllTasks=0x0000 #
|
OP_DeclineAllTasks=0x0000 #
|
||||||
OP_TaskRequestTimer=0x719e
|
OP_TaskRequestTimer=0x719e
|
||||||
|
OP_AcceptNewSharedTask=0x6ded
|
||||||
|
|
||||||
# Title opcodes
|
# Title opcodes
|
||||||
OP_NewTitlesAvailable=0x4b49 # C
|
OP_NewTitlesAvailable=0x4b49 # C
|
||||||
|
|||||||
22
utils/sql/git/required/sharedtasks.sql
Normal file
22
utils/sql/git/required/sharedtasks.sql
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
ALTER TABLE `tasks` ADD `reward_points` INT NOT NULL DEFAULT '0' AFTER `rewardmethod`;
|
||||||
|
ALTER TABLE `tasks` ADD `reward_type` INT NOT NULL DEFAULT '0' AFTER `reward_points`;
|
||||||
|
ALTER TABLE `tasks` ADD `replay_group` INT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `min_players` INT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `max_players` INT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `task_lock_step` INT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `instance_zone_id` INT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `zone_version` INT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `zone_in_zone_id` INT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `zone_in_x` FLOAT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `zone_in_y` FLOAT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `zone_in_object_id` TINYINT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `dest_x` FLOAT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `dest_y` FLOAT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `dest_z` FLOAT NOT NULL DEFAULT '0';
|
||||||
|
ALTER TABLE `tasks` ADD `dest_h` FLOAT NOT NULL DEFAULT '0';
|
||||||
|
CREATE TABLE `task_replay_groups` (
|
||||||
|
`id` INT NOT NULL,
|
||||||
|
`duration` INT NOT NULL,
|
||||||
|
`name` VARCHAR(128) NOT NULL DEFAULT '',
|
||||||
|
PRIMARY KEY(`id`)
|
||||||
|
);
|
||||||
@ -229,6 +229,14 @@ struct ClientReward
|
|||||||
uint32 amount;
|
uint32 amount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PENDING_TASK_TIMEOUT 60000
|
||||||
|
struct PendingSharedTask {
|
||||||
|
int id;
|
||||||
|
int task_master_id;
|
||||||
|
Timer timeout; // so if we take a very long time to get messages back from world, we time out and fail
|
||||||
|
PendingSharedTask() : id(0), task_master_id(0) {}
|
||||||
|
};
|
||||||
|
|
||||||
class ClientFactory {
|
class ClientFactory {
|
||||||
public:
|
public:
|
||||||
Client *MakeClient(std::shared_ptr<EQStreamInterface> ieqs);
|
Client *MakeClient(std::shared_ptr<EQStreamInterface> ieqs);
|
||||||
@ -1020,8 +1028,8 @@ public:
|
|||||||
inline void UpdateTasksOnExplore(int ExploreID) { if(taskstate) taskstate->UpdateTasksOnExplore(this, ExploreID); }
|
inline void UpdateTasksOnExplore(int ExploreID) { if(taskstate) taskstate->UpdateTasksOnExplore(this, ExploreID); }
|
||||||
inline bool UpdateTasksOnSpeakWith(int NPCTypeID) { if(taskstate) return taskstate->UpdateTasksOnSpeakWith(this, NPCTypeID); else return false; }
|
inline bool UpdateTasksOnSpeakWith(int NPCTypeID) { if(taskstate) return taskstate->UpdateTasksOnSpeakWith(this, NPCTypeID); else return false; }
|
||||||
inline bool UpdateTasksOnDeliver(std::list<EQEmu::ItemInstance*>& Items, int Cash, int NPCTypeID) { if (taskstate) return taskstate->UpdateTasksOnDeliver(this, Items, Cash, NPCTypeID); else return false; }
|
inline bool UpdateTasksOnDeliver(std::list<EQEmu::ItemInstance*>& Items, int Cash, int NPCTypeID) { if (taskstate) return taskstate->UpdateTasksOnDeliver(this, Items, Cash, NPCTypeID); else return false; }
|
||||||
inline void TaskSetSelector(Mob *mob, int TaskSetID) { if(taskmanager) taskmanager->TaskSetSelector(this, taskstate, mob, TaskSetID); }
|
inline void TaskSetSelector(Mob *mob, int TaskSetID, bool shared = false) { if(taskmanager) taskmanager->TaskSetSelector(this, taskstate, mob, TaskSetID, shared); }
|
||||||
inline void TaskQuestSetSelector(Mob *mob, int count, int *tasks) { if(taskmanager) taskmanager->TaskQuestSetSelector(this, taskstate, mob, count, tasks); }
|
inline void TaskQuestSetSelector(Mob *mob, int count, int *tasks, bool shared = false) { if(taskmanager) taskmanager->TaskQuestSetSelector(this, taskstate, mob, count, tasks, shared); }
|
||||||
inline void EnableTask(int TaskCount, int *TaskList) { if(taskstate) taskstate->EnableTask(CharacterID(), TaskCount, TaskList); }
|
inline void EnableTask(int TaskCount, int *TaskList) { if(taskstate) taskstate->EnableTask(CharacterID(), TaskCount, TaskList); }
|
||||||
inline void DisableTask(int TaskCount, int *TaskList) { if(taskstate) taskstate->DisableTask(CharacterID(), TaskCount, TaskList); }
|
inline void DisableTask(int TaskCount, int *TaskList) { if(taskstate) taskstate->DisableTask(CharacterID(), TaskCount, TaskList); }
|
||||||
inline bool IsTaskEnabled(int TaskID) { return (taskstate ? taskstate->IsTaskEnabled(TaskID) : false); }
|
inline bool IsTaskEnabled(int TaskID) { return (taskstate ? taskstate->IsTaskEnabled(TaskID) : false); }
|
||||||
@ -1043,6 +1051,13 @@ public:
|
|||||||
inline int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID) { return (taskstate ? taskstate->GetTaskActivityDoneCountFromTaskID(TaskID, ActivityID) :0); }
|
inline int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID) { return (taskstate ? taskstate->GetTaskActivityDoneCountFromTaskID(TaskID, ActivityID) :0); }
|
||||||
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 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 int GetPendingTaskID() const { return pending_task.id; }
|
||||||
|
inline int GetPendingTaskMasterID() const { return pending_task.task_master_id; }
|
||||||
|
inline void StartPendingTimer() { pending_task.timeout.Start(PENDING_TASK_TIMEOUT); }
|
||||||
|
|
||||||
inline const EQEmu::versions::ClientVersion ClientVersion() const { return m_ClientVersion; }
|
inline const EQEmu::versions::ClientVersion ClientVersion() const { return m_ClientVersion; }
|
||||||
inline const uint32 ClientVersionBit() const { return m_ClientVersionBit; }
|
inline const uint32 ClientVersionBit() const { return m_ClientVersionBit; }
|
||||||
@ -1569,6 +1584,7 @@ private:
|
|||||||
std::set<uint32> zone_flags;
|
std::set<uint32> zone_flags;
|
||||||
|
|
||||||
ClientTaskState *taskstate;
|
ClientTaskState *taskstate;
|
||||||
|
PendingSharedTask pending_task;
|
||||||
int TotalSecondsPlayed;
|
int TotalSecondsPlayed;
|
||||||
|
|
||||||
//Anti Spam Stuff
|
//Anti Spam Stuff
|
||||||
|
|||||||
@ -114,6 +114,7 @@ void MapOpcodes()
|
|||||||
ConnectedOpcodes[OP_0x0193] = &Client::Handle_0x0193;
|
ConnectedOpcodes[OP_0x0193] = &Client::Handle_0x0193;
|
||||||
ConnectedOpcodes[OP_AAAction] = &Client::Handle_OP_AAAction;
|
ConnectedOpcodes[OP_AAAction] = &Client::Handle_OP_AAAction;
|
||||||
ConnectedOpcodes[OP_AcceptNewTask] = &Client::Handle_OP_AcceptNewTask;
|
ConnectedOpcodes[OP_AcceptNewTask] = &Client::Handle_OP_AcceptNewTask;
|
||||||
|
ConnectedOpcodes[OP_AcceptNewSharedTask] = &Client::Handle_OP_AcceptNewSharedTask;
|
||||||
ConnectedOpcodes[OP_AdventureInfoRequest] = &Client::Handle_OP_AdventureInfoRequest;
|
ConnectedOpcodes[OP_AdventureInfoRequest] = &Client::Handle_OP_AdventureInfoRequest;
|
||||||
ConnectedOpcodes[OP_AdventureLeaderboardRequest] = &Client::Handle_OP_AdventureLeaderboardRequest;
|
ConnectedOpcodes[OP_AdventureLeaderboardRequest] = &Client::Handle_OP_AdventureLeaderboardRequest;
|
||||||
ConnectedOpcodes[OP_AdventureMerchantPurchase] = &Client::Handle_OP_AdventureMerchantPurchase;
|
ConnectedOpcodes[OP_AdventureMerchantPurchase] = &Client::Handle_OP_AdventureMerchantPurchase;
|
||||||
@ -1840,6 +1841,20 @@ void Client::Handle_OP_AcceptNewTask(const EQApplicationPacket *app)
|
|||||||
taskstate->AcceptNewTask(this, ant->task_id, ant->task_master_id);
|
taskstate->AcceptNewTask(this, ant->task_id, ant->task_master_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_AcceptNewSharedTask(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
if (app->size != sizeof(AcceptNewSharedTask_Struct)) {
|
||||||
|
Log(Logs::General, Logs::None, "Size mismatch in OP_AcceptNewSharedTask expected %i got %i",
|
||||||
|
sizeof(AcceptNewSharedTask_Struct), app->size);
|
||||||
|
DumpPacket(app);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto *ant = (AcceptNewSharedTask_Struct*)app->pBuffer;
|
||||||
|
|
||||||
|
if (ant->task_id > 0 && RuleB(TaskSystem, EnableTaskSystem) && taskstate)
|
||||||
|
taskstate->PendSharedTask(this, ant->task_id, ant->task_master_id);
|
||||||
|
}
|
||||||
|
|
||||||
void Client::Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app)
|
void Client::Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app)
|
||||||
{
|
{
|
||||||
if (app->size < sizeof(EntityId_Struct))
|
if (app->size < sizeof(EntityId_Struct))
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
void Handle_0x01e7(const EQApplicationPacket *app);
|
void Handle_0x01e7(const EQApplicationPacket *app);
|
||||||
void Handle_OP_AAAction(const EQApplicationPacket *app);
|
void Handle_OP_AAAction(const EQApplicationPacket *app);
|
||||||
void Handle_OP_AcceptNewTask(const EQApplicationPacket *app);
|
void Handle_OP_AcceptNewTask(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_AcceptNewSharedTask(const EQApplicationPacket *app);
|
||||||
void Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app);
|
void Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app);
|
||||||
void Handle_OP_AdventureLeaderboardRequest(const EQApplicationPacket *app);
|
void Handle_OP_AdventureLeaderboardRequest(const EQApplicationPacket *app);
|
||||||
void Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app);
|
void Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app);
|
||||||
|
|||||||
@ -159,6 +159,12 @@ bool Client::Process() {
|
|||||||
if (TaskPeriodic_Timer.Check() && taskstate)
|
if (TaskPeriodic_Timer.Check() && taskstate)
|
||||||
taskstate->TaskPeriodicChecks(this);
|
taskstate->TaskPeriodicChecks(this);
|
||||||
|
|
||||||
|
if (pending_task.timeout.Check(false)) {
|
||||||
|
Message(13, "Shared task timed out.");
|
||||||
|
pending_task.id = 0;
|
||||||
|
pending_task.task_master_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (linkdead_timer.Check()) {
|
if (linkdead_timer.Check()) {
|
||||||
LeaveGroup();
|
LeaveGroup();
|
||||||
Save();
|
Save();
|
||||||
|
|||||||
@ -2048,6 +2048,23 @@ XS(XS__taskselector) {
|
|||||||
|
|
||||||
XSRETURN_EMPTY;
|
XSRETURN_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS__sharedtaskselector);
|
||||||
|
XS(XS__sharedtaskselector) {
|
||||||
|
dXSARGS;
|
||||||
|
if ((items >= 1) && (items <= MAXCHOOSERENTRIES)) {
|
||||||
|
int tasks[MAXCHOOSERENTRIES];
|
||||||
|
for (int i = 0; i < items; i++) {
|
||||||
|
tasks[i] = (int) SvIV(ST(i));
|
||||||
|
}
|
||||||
|
quest_manager.taskselector(items, tasks, true);
|
||||||
|
} else {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::sharedtaskselector(int task_id, 2, 3, 4, 5 [up to 40])");
|
||||||
|
}
|
||||||
|
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
XS(XS__task_setselector);
|
XS(XS__task_setselector);
|
||||||
XS(XS__task_setselector) {
|
XS(XS__task_setselector) {
|
||||||
dXSARGS;
|
dXSARGS;
|
||||||
@ -3770,6 +3787,7 @@ EXTERN_C XS(boot_quest) {
|
|||||||
newXS(strcpy(buf, "targlobal"), XS__targlobal, file);
|
newXS(strcpy(buf, "targlobal"), XS__targlobal, file);
|
||||||
newXS(strcpy(buf, "taskexploredarea"), XS__taskexploredarea, file);
|
newXS(strcpy(buf, "taskexploredarea"), XS__taskexploredarea, file);
|
||||||
newXS(strcpy(buf, "taskselector"), XS__taskselector, file);
|
newXS(strcpy(buf, "taskselector"), XS__taskselector, file);
|
||||||
|
newXS(strcpy(buf, "sharedtaskselector"), XS__sharedtaskselector, file);
|
||||||
newXS(strcpy(buf, "task_setselector"), XS__task_setselector, file);
|
newXS(strcpy(buf, "task_setselector"), XS__task_setselector, file);
|
||||||
newXS(strcpy(buf, "tasktimeleft"), XS__tasktimeleft, file);
|
newXS(strcpy(buf, "tasktimeleft"), XS__tasktimeleft, file);
|
||||||
newXS(strcpy(buf, "toggle_spawn_event"), XS__toggle_spawn_event, file);
|
newXS(strcpy(buf, "toggle_spawn_event"), XS__toggle_spawn_event, file);
|
||||||
|
|||||||
@ -581,6 +581,32 @@ void lua_task_selector(luabind::adl::object table) {
|
|||||||
quest_manager.taskselector(count, tasks);
|
quest_manager.taskselector(count, tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lua_task_selector(luabind::adl::object table, bool shared) {
|
||||||
|
if(luabind::type(table) != LUA_TTABLE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tasks[MAXCHOOSERENTRIES] = { 0 };
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for(int i = 1; i <= MAXCHOOSERENTRIES; ++i) {
|
||||||
|
auto cur = table[i];
|
||||||
|
int cur_value = 0;
|
||||||
|
if(luabind::type(cur) != LUA_TNIL) {
|
||||||
|
try {
|
||||||
|
cur_value = luabind::object_cast<int>(cur);
|
||||||
|
} catch(luabind::cast_failed) {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
count = i - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks[i - 1] = cur_value;
|
||||||
|
}
|
||||||
|
quest_manager.taskselector(count, tasks, shared);
|
||||||
|
}
|
||||||
|
|
||||||
void lua_task_set_selector(int task_set) {
|
void lua_task_set_selector(int task_set) {
|
||||||
quest_manager.tasksetselector(task_set);
|
quest_manager.tasksetselector(task_set);
|
||||||
}
|
}
|
||||||
@ -1630,7 +1656,8 @@ luabind::scope lua_register_general() {
|
|||||||
luabind::def("summon_all_player_corpses", &lua_summon_all_player_corpses),
|
luabind::def("summon_all_player_corpses", &lua_summon_all_player_corpses),
|
||||||
luabind::def("get_player_buried_corpse_count", &lua_get_player_buried_corpse_count),
|
luabind::def("get_player_buried_corpse_count", &lua_get_player_buried_corpse_count),
|
||||||
luabind::def("bury_player_corpse", &lua_bury_player_corpse),
|
luabind::def("bury_player_corpse", &lua_bury_player_corpse),
|
||||||
luabind::def("task_selector", &lua_task_selector),
|
luabind::def("task_selector", (void(*)(luabind::adl::object))&lua_task_selector),
|
||||||
|
luabind::def("task_selector", (void(*)(luabind::adl::object,bool))&lua_task_selector),
|
||||||
luabind::def("task_set_selector", &lua_task_set_selector),
|
luabind::def("task_set_selector", &lua_task_set_selector),
|
||||||
luabind::def("enable_task", &lua_enable_task),
|
luabind::def("enable_task", &lua_enable_task),
|
||||||
luabind::def("disable_task", &lua_disable_task),
|
luabind::def("disable_task", &lua_disable_task),
|
||||||
|
|||||||
@ -2146,10 +2146,10 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level
|
|||||||
|
|
||||||
#endif //BOTS
|
#endif //BOTS
|
||||||
|
|
||||||
void QuestManager::taskselector(int taskcount, int *tasks) {
|
void QuestManager::taskselector(int taskcount, int *tasks, bool shared) {
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && taskmanager)
|
if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && taskmanager)
|
||||||
initiator->TaskQuestSetSelector(owner, taskcount, tasks);
|
initiator->TaskQuestSetSelector(owner, taskcount, tasks, shared);
|
||||||
}
|
}
|
||||||
void QuestManager::enabletask(int taskcount, int *tasks) {
|
void QuestManager::enabletask(int taskcount, int *tasks) {
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
@ -2174,11 +2174,11 @@ bool QuestManager::istaskenabled(int taskid) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuestManager::tasksetselector(int tasksetid) {
|
void QuestManager::tasksetselector(int tasksetid, bool shared) {
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSetSelector called for task set %i", tasksetid);
|
Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSetSelector called for task set %i", tasksetid);
|
||||||
if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && taskmanager)
|
if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && taskmanager)
|
||||||
initiator->TaskSetSelector(owner, tasksetid);
|
initiator->TaskSetSelector(owner, tasksetid, shared);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QuestManager::istaskactive(int task) {
|
bool QuestManager::istaskactive(int task) {
|
||||||
|
|||||||
@ -188,8 +188,8 @@ public:
|
|||||||
void playerfeature(char *feature, int setting);
|
void playerfeature(char *feature, int setting);
|
||||||
void npcfeature(char *feature, int setting);
|
void npcfeature(char *feature, int setting);
|
||||||
void popup(const char *title, const char *text, uint32 popupid, uint32 buttons, uint32 Duration);
|
void popup(const char *title, const char *text, uint32 popupid, uint32 buttons, uint32 Duration);
|
||||||
void taskselector(int taskcount, int *tasks);
|
void taskselector(int taskcount, int *tasks, bool shared = false);
|
||||||
void tasksetselector(int tasksettid);
|
void tasksetselector(int tasksettid, bool shared = false);
|
||||||
void enabletask(int taskcount, int *tasks);
|
void enabletask(int taskcount, int *tasks);
|
||||||
void disabletask(int taskcount, int *tasks);
|
void disabletask(int taskcount, int *tasks);
|
||||||
bool istaskenabled(int taskid);
|
bool istaskenabled(int taskid);
|
||||||
|
|||||||
@ -359,6 +359,7 @@
|
|||||||
#define LDON_NO_LOCKPICK 7564 //You must have a lock pick in your inventory to do this.
|
#define LDON_NO_LOCKPICK 7564 //You must have a lock pick in your inventory to do this.
|
||||||
#define LDON_WAS_NOT_LOCKED 7565 //%1 was not locked.
|
#define LDON_WAS_NOT_LOCKED 7565 //%1 was not locked.
|
||||||
#define LDON_WAS_NOT_TRAPPED 7566 //%1 was not trapped
|
#define LDON_WAS_NOT_TRAPPED 7566 //%1 was not trapped
|
||||||
|
#define TASK_REJECT_LOCKEDOUT_ME 8017 //This task can not be assigned to you because you must wait %1d:%2h:%3m before you can do another task of this type.
|
||||||
#define GAIN_GROUP_LEADERSHIP_POINT 8585 //
|
#define GAIN_GROUP_LEADERSHIP_POINT 8585 //
|
||||||
#define GAIN_RAID_LEADERSHIP_POINT 8589 //
|
#define GAIN_RAID_LEADERSHIP_POINT 8589 //
|
||||||
#define MAX_GROUP_LEADERSHIP_POINTS 8584 //
|
#define MAX_GROUP_LEADERSHIP_POINTS 8584 //
|
||||||
@ -369,6 +370,15 @@
|
|||||||
#define GAIN_GROUP_LEADERSHIP_EXP 8788 //
|
#define GAIN_GROUP_LEADERSHIP_EXP 8788 //
|
||||||
#define GAIN_RAID_LEADERSHIP_EXP 8789 //
|
#define GAIN_RAID_LEADERSHIP_EXP 8789 //
|
||||||
#define BUFF_MINUTES_REMAINING 8799 //%1 (%2 minutes remaining)
|
#define BUFF_MINUTES_REMAINING 8799 //%1 (%2 minutes remaining)
|
||||||
|
#define TASK_REJECT_MAX_COUNT 8891 //You can not be assigned this shared task because your party exceeds the maximum allowed number of players.
|
||||||
|
#define TASK_REJECT_LEADER_REQ 8892 //You can not be assigned this shared task because the leader does not meet the shared task requirements.
|
||||||
|
#define TASK_REJECT_MIN_COUNT 8895 //You can not be assigned this shared task because your party does not contain the minimum required number of players.
|
||||||
|
#define TASK_REJECT_HAVE_ONE 8935 //You may not request a shared task because you already have one.
|
||||||
|
#define TASK_REJECT_RAID_HAVE_ONE 8936 //You may not request a shared task because someone in your raid, %1, already has one.
|
||||||
|
#define TASK_REJECT_GROUP_HAVE_ONE 8937 //You may not request a shared task because someone in your group, %1, already has one.
|
||||||
|
#define TASK_REJECT_LOCKEDOUT 8946 //You may not request this shared task because you must wait %1d:%2h:%3m before you can do another task of this type.
|
||||||
|
#define TASK_REJECT_LOCKEDOUT_OTHER 8947 //You may not request this shared task because %1 must wait %2d:%3h:%4m before they can do another task of this type.
|
||||||
|
#define SHARED_TASK_LOCK 8961 //Your shared task is now locked. You may no longer add or remove players.
|
||||||
#define NO_MORE_TRAPS 9002 //You have already placed your maximum number of traps.
|
#define NO_MORE_TRAPS 9002 //You have already placed your maximum number of traps.
|
||||||
#define FEAR_TOO_HIGH 9035 //Your target is too high of a level for your fear spell.
|
#define FEAR_TOO_HIGH 9035 //Your target is too high of a level for your fear spell.
|
||||||
#define SLOW_MOSTLY_SUCCESSFUL 9029 //Your spell was mostly successful.
|
#define SLOW_MOSTLY_SUCCESSFUL 9029 //Your spell was mostly successful.
|
||||||
|
|||||||
280
zone/tasks.cpp
280
zone/tasks.cpp
@ -30,16 +30,19 @@ Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
|||||||
#include "../common/rulesys.h"
|
#include "../common/rulesys.h"
|
||||||
#include "../common/string_util.h"
|
#include "../common/string_util.h"
|
||||||
#include "../common/say_link.h"
|
#include "../common/say_link.h"
|
||||||
|
#include "../common/data_verification.h"
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "entity.h"
|
#include "entity.h"
|
||||||
#include "mob.h"
|
#include "mob.h"
|
||||||
#include "string_ids.h"
|
#include "string_ids.h"
|
||||||
|
#include "worldserver.h"
|
||||||
|
|
||||||
#include "queryserv.h"
|
#include "queryserv.h"
|
||||||
#include "quest_parser_collection.h"
|
#include "quest_parser_collection.h"
|
||||||
|
|
||||||
extern QueryServ* QServ;
|
extern QueryServ* QServ;
|
||||||
|
extern WorldServer worldserver;
|
||||||
|
|
||||||
TaskManager::TaskManager() {
|
TaskManager::TaskManager() {
|
||||||
for(int i=0; i<MAXTASKS; i++)
|
for(int i=0; i<MAXTASKS; i++)
|
||||||
@ -116,15 +119,26 @@ bool TaskManager::LoadTasks(int singleTask)
|
|||||||
if (!LoadTaskSets())
|
if (!LoadTaskSets())
|
||||||
Log(Logs::Detail, Logs::Tasks, "TaskManager::LoadTasks LoadTaskSets failed");
|
Log(Logs::Detail, Logs::Tasks, "TaskManager::LoadTasks LoadTaskSets failed");
|
||||||
|
|
||||||
query = StringFormat("SELECT `id`, `type`, `duration`, `duration_code`, `title`, `description`, "
|
if (!LoadReplayGroups())
|
||||||
"`reward`, `rewardid`, `cashreward`, `xpreward`, `rewardmethod`, `faction_reward`,"
|
Log(Logs::Detail, Logs::Tasks, "TaskManager::LoadTasks LoadReplayGroups failed");
|
||||||
"`minlevel`, `maxlevel`, `repeatable`, `completion_emote` FROM `tasks` WHERE `id` < %i",
|
|
||||||
MAXTASKS);
|
query =
|
||||||
|
StringFormat("SELECT `id`, `type`, `duration`, `duration_code`, `title`, `description`, `reward`, "
|
||||||
|
"`rewardid`, `cashreward`, `xpreward`, `rewardmethod`, `faction_reward`, `minlevel`, "
|
||||||
|
"`maxlevel`, `repeatable`, `completion_emote`, `reward_points`, `reward_type`, "
|
||||||
|
"`replay_group`, `min_players`, `max_players`, `task_lock_step`, `instance_zone_id`, "
|
||||||
|
"`zone_version`, `zone_in_zone_id`, `zone_in_x`, `zone_in_y`, `zone_in_object_id`, "
|
||||||
|
"`dest_x`, `dest_y`, `dest_z`, `dest_h` FROM `tasks` WHERE `id` < %i",
|
||||||
|
MAXTASKS);
|
||||||
} else
|
} else
|
||||||
query = StringFormat("SELECT `id`, `type`, `duration`, `duration_code`, `title`, `description`, "
|
query =
|
||||||
"`reward`, `rewardid`, `cashreward`, `xpreward`, `rewardmethod`, `faction_reward`,"
|
StringFormat("SELECT `id`, `type`, `duration`, `duration_code`, `title`, `description`, `reward`, "
|
||||||
"`minlevel`, `maxlevel`, `repeatable`, `completion_emote` FROM `tasks` WHERE `id` = %i",
|
"`rewardid`, `cashreward`, `xpreward`, `rewardmethod`, `faction_reward`, `minlevel`, "
|
||||||
singleTask);
|
"`maxlevel`, `repeatable`, `completion_emote`, `reward_points`, `reward_type`, "
|
||||||
|
"`replay_group`, `min_players`, `max_players`, `task_lock_step`, `instance_zone_id`, "
|
||||||
|
"`zone_version`, `zone_in_zone_id`, `zone_in_x`, `zone_in_y`, `zone_in_object_id`, "
|
||||||
|
"`dest_x`, `dest_y`, `dest_z`, `dest_h` FROM `tasks` WHERE `id` = %i",
|
||||||
|
singleTask);
|
||||||
|
|
||||||
const char *ERR_MYSQLERROR = "[TASKS]Error in TaskManager::LoadTasks: %s";
|
const char *ERR_MYSQLERROR = "[TASKS]Error in TaskManager::LoadTasks: %s";
|
||||||
|
|
||||||
@ -160,6 +174,22 @@ bool TaskManager::LoadTasks(int singleTask)
|
|||||||
Tasks[taskID]->MaxLevel = atoi(row[13]);
|
Tasks[taskID]->MaxLevel = atoi(row[13]);
|
||||||
Tasks[taskID]->Repeatable = atoi(row[14]);
|
Tasks[taskID]->Repeatable = atoi(row[14]);
|
||||||
Tasks[taskID]->completion_emote = row[15];
|
Tasks[taskID]->completion_emote = row[15];
|
||||||
|
Tasks[taskID]->reward_points = atoi(row[16]);
|
||||||
|
Tasks[taskID]->reward_type = static_cast<PointType>(atoi(row[17]));
|
||||||
|
Tasks[taskID]->replay_group = atoi(row[18]);
|
||||||
|
Tasks[taskID]->min_players = atoi(row[19]);
|
||||||
|
Tasks[taskID]->max_players = atoi(row[20]);
|
||||||
|
Tasks[taskID]->task_lock_step = atoi(row[21]);
|
||||||
|
Tasks[taskID]->instance_zone_id = atoi(row[22]);
|
||||||
|
Tasks[taskID]->zone_version = atoi(row[23]);
|
||||||
|
Tasks[taskID]->zone_in_zone_id = atoi(row[24]);
|
||||||
|
Tasks[taskID]->zone_in_x = atof(row[25]);
|
||||||
|
Tasks[taskID]->zone_in_y = atof(row[26]);
|
||||||
|
Tasks[taskID]->zone_in_object_id = atoi(row[27]);
|
||||||
|
Tasks[taskID]->dest_x = atof(row[28]);
|
||||||
|
Tasks[taskID]->dest_y = atof(row[29]);
|
||||||
|
Tasks[taskID]->dest_z = atof(row[30]);
|
||||||
|
Tasks[taskID]->dest_h = atof(row[31]);
|
||||||
Tasks[taskID]->ActivityCount = 0;
|
Tasks[taskID]->ActivityCount = 0;
|
||||||
Tasks[taskID]->SequenceMode = ActivitiesSequential;
|
Tasks[taskID]->SequenceMode = ActivitiesSequential;
|
||||||
Tasks[taskID]->LastStep = 0;
|
Tasks[taskID]->LastStep = 0;
|
||||||
@ -281,6 +311,22 @@ bool TaskManager::LoadTasks(int singleTask)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TaskManager::LoadReplayGroups()
|
||||||
|
{
|
||||||
|
replay_groups.clear();
|
||||||
|
std::string query = "SELECT `id`, `name`, `duration` FROM `task_replay_groups` WHERE `id` > 0 ORDER BY `id` ASC";
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
replay_groups[atoi(row[0])] = {row[1], atoi(row[2])};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool TaskManager::SaveClientState(Client *c, ClientTaskState *state)
|
bool TaskManager::SaveClientState(Client *c, ClientTaskState *state)
|
||||||
{
|
{
|
||||||
// I am saving the slot in the ActiveTasks table, because unless a Task is cancelled/completed, the client
|
// I am saving the slot in the ActiveTasks table, because unless a Task is cancelled/completed, the client
|
||||||
@ -905,7 +951,7 @@ bool ClientTaskState::HasSlotForTask(TaskInformation *task)
|
|||||||
case TaskType::Task:
|
case TaskType::Task:
|
||||||
return ActiveTask.TaskID == TASKSLOTEMPTY;
|
return ActiveTask.TaskID == TASKSLOTEMPTY;
|
||||||
case TaskType::Shared:
|
case TaskType::Shared:
|
||||||
return false; // todo
|
return ActiveSharedTask == nullptr; // todo
|
||||||
case TaskType::Quest:
|
case TaskType::Quest:
|
||||||
for (int i = 0; i < MAXACTIVEQUESTS; ++i)
|
for (int i = 0; i < MAXACTIVEQUESTS; ++i)
|
||||||
if (ActiveQuests[i].TaskID == TASKSLOTEMPTY)
|
if (ActiveQuests[i].TaskID == TASKSLOTEMPTY)
|
||||||
@ -988,7 +1034,7 @@ int TaskManager::GetTaskMaxLevel(int TaskID)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID)
|
void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID, bool shared)
|
||||||
{
|
{
|
||||||
int TaskList[MAXCHOOSERENTRIES];
|
int TaskList[MAXCHOOSERENTRIES];
|
||||||
int TaskListIndex = 0;
|
int TaskListIndex = 0;
|
||||||
@ -1024,14 +1070,14 @@ void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, i
|
|||||||
// we aren't currently on another, and if it's enabled if not all_enabled
|
// we aren't currently on another, and if it's enabled if not all_enabled
|
||||||
if ((all_enabled || state->IsTaskEnabled(task)) && AppropriateLevel(task, PlayerLevel) &&
|
if ((all_enabled || state->IsTaskEnabled(task)) && AppropriateLevel(task, PlayerLevel) &&
|
||||||
!state->IsTaskActive(task) && state->HasSlotForTask(Tasks[task]) && // this slot checking is a bit silly, but we allow mixing of task types ...
|
!state->IsTaskActive(task) && state->HasSlotForTask(Tasks[task]) && // this slot checking is a bit silly, but we allow mixing of task types ...
|
||||||
(IsTaskRepeatable(task) || !state->IsTaskCompleted(task)))
|
(IsTaskRepeatable(task) || !state->IsTaskCompleted(task)) && (shared == (Tasks[task]->type == TaskType::Shared)))
|
||||||
TaskList[TaskListIndex++] = task;
|
TaskList[TaskListIndex++] = task;
|
||||||
|
|
||||||
++Iterator;
|
++Iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TaskListIndex > 0) {
|
if (TaskListIndex > 0) {
|
||||||
SendTaskSelector(c, mob, TaskListIndex, TaskList);
|
SendTaskSelector(c, mob, TaskListIndex, TaskList, shared);
|
||||||
} else {
|
} else {
|
||||||
mob->SayTo_StringID(c, CC_Yellow, MAX_ACTIVE_TASKS, c->GetName()); // check color, I think this might be only for (Shared) Tasks, w/e -- think should be yellow
|
mob->SayTo_StringID(c, CC_Yellow, MAX_ACTIVE_TASKS, c->GetName()); // check color, I think this might be only for (Shared) Tasks, w/e -- think should be yellow
|
||||||
}
|
}
|
||||||
@ -1041,7 +1087,7 @@ void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, i
|
|||||||
|
|
||||||
// unlike the non-Quest version of this function, it does not check enabled, that is assumed the responsibility of the quest to handle
|
// unlike the non-Quest version of this function, it does not check enabled, that is assumed the responsibility of the quest to handle
|
||||||
// we do however still want it to check the other stuff like level, active, room, etc
|
// we do however still want it to check the other stuff like level, active, room, etc
|
||||||
void TaskManager::TaskQuestSetSelector(Client *c, ClientTaskState *state, Mob *mob, int count, int *tasks)
|
void TaskManager::TaskQuestSetSelector(Client *c, ClientTaskState *state, Mob *mob, int count, int *tasks, bool shared)
|
||||||
{
|
{
|
||||||
int TaskList[MAXCHOOSERENTRIES];
|
int TaskList[MAXCHOOSERENTRIES];
|
||||||
int TaskListIndex = 0;
|
int TaskListIndex = 0;
|
||||||
@ -1058,12 +1104,12 @@ void TaskManager::TaskQuestSetSelector(Client *c, ClientTaskState *state, Mob *m
|
|||||||
// we aren't currently on another, and if it's enabled if not all_enabled
|
// we aren't currently on another, and if it's enabled if not all_enabled
|
||||||
if (AppropriateLevel(task, PlayerLevel) &&
|
if (AppropriateLevel(task, PlayerLevel) &&
|
||||||
!state->IsTaskActive(task) && state->HasSlotForTask(Tasks[task]) && // this slot checking is a bit silly, but we allow mixing of task types ...
|
!state->IsTaskActive(task) && state->HasSlotForTask(Tasks[task]) && // this slot checking is a bit silly, but we allow mixing of task types ...
|
||||||
(IsTaskRepeatable(task) || !state->IsTaskCompleted(task)))
|
(IsTaskRepeatable(task) || !state->IsTaskCompleted(task)) && (shared == (Tasks[task]->type == TaskType::Shared)))
|
||||||
TaskList[TaskListIndex++] = task;
|
TaskList[TaskListIndex++] = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TaskListIndex > 0) {
|
if (TaskListIndex > 0) {
|
||||||
SendTaskSelector(c, mob, TaskListIndex, TaskList);
|
SendTaskSelector(c, mob, TaskListIndex, TaskList, shared);
|
||||||
} else {
|
} else {
|
||||||
mob->SayTo_StringID(c, CC_Yellow, MAX_ACTIVE_TASKS, c->GetName()); // check color, I think this might be only for (Shared) Tasks, w/e -- think should be yellow
|
mob->SayTo_StringID(c, CC_Yellow, MAX_ACTIVE_TASKS, c->GetName()); // check color, I think this might be only for (Shared) Tasks, w/e -- think should be yellow
|
||||||
}
|
}
|
||||||
@ -1071,11 +1117,11 @@ void TaskManager::TaskQuestSetSelector(Client *c, ClientTaskState *state, Mob *m
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskManager::SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *TaskList) {
|
void TaskManager::SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *TaskList, bool shared) {
|
||||||
|
|
||||||
if (c->ClientVersion() >= EQEmu::versions::ClientVersion::RoF)
|
if (c->ClientVersion() >= EQEmu::versions::ClientVersion::RoF)
|
||||||
{
|
{
|
||||||
SendTaskSelectorNew(c, mob, TaskCount, TaskList);
|
SendTaskSelectorNew(c, mob, TaskCount, TaskList, shared);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Titanium OpCode: 0x5e7c
|
// Titanium OpCode: 0x5e7c
|
||||||
@ -1108,7 +1154,7 @@ void TaskManager::SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *Task
|
|||||||
|
|
||||||
|
|
||||||
buf.WriteUInt32(ValidTasks);
|
buf.WriteUInt32(ValidTasks);
|
||||||
buf.WriteUInt32(2); // task type, live doesn't let you send more than one type, but we do?
|
buf.WriteUInt32(shared ? static_cast<uint32>(TaskType::Shared) : static_cast<uint32>(TaskType::Quest)); // hack, we need to send only shared tasks when doing shared tasks since they use different reply ops
|
||||||
buf.WriteUInt32(mob->GetID());
|
buf.WriteUInt32(mob->GetID());
|
||||||
|
|
||||||
for (int i = 0; i < TaskCount; i++) {
|
for (int i = 0; i < TaskCount; i++) {
|
||||||
@ -1158,7 +1204,7 @@ 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, bool shared)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSelector for %i Tasks", TaskCount);
|
Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSelector for %i Tasks", TaskCount);
|
||||||
|
|
||||||
@ -1188,9 +1234,7 @@ void TaskManager::SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *T
|
|||||||
SerializeBuffer buf(50 * ValidTasks);
|
SerializeBuffer buf(50 * ValidTasks);
|
||||||
|
|
||||||
buf.WriteUInt32(ValidTasks); // TaskCount
|
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
|
buf.WriteUInt32(shared ? static_cast<uint32>(TaskType::Shared) : static_cast<uint32>(TaskType::Quest)); // hack, we need to send only shared tasks when doing shared tasks since they use different reply ops
|
||||||
// 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
|
|
||||||
buf.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
|
||||||
@ -1304,7 +1348,8 @@ ClientTaskState::ClientTaskState() {
|
|||||||
|
|
||||||
ActiveTask.slot = 0;
|
ActiveTask.slot = 0;
|
||||||
ActiveTask.TaskID = TASKSLOTEMPTY;
|
ActiveTask.TaskID = TASKSLOTEMPTY;
|
||||||
// TODO: shared task
|
|
||||||
|
ActiveSharedTask = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientTaskState::~ClientTaskState() {
|
ClientTaskState::~ClientTaskState() {
|
||||||
@ -3324,6 +3369,164 @@ void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID, bool enfor
|
|||||||
parse->EventNPC(EVENT_TASK_ACCEPTED, npc, c, buf.c_str(), 0);
|
parse->EventNPC(EVENT_TASK_ACCEPTED, npc, c, buf.c_str(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function will do a bunch of verification, then set up a pending state which will then send a request
|
||||||
|
// to world and send off requests to out of group zones to ask if they can join the task
|
||||||
|
// Once the we get all of the replies that pass, we will then assign the task
|
||||||
|
void ClientTaskState::PendSharedTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement)
|
||||||
|
{
|
||||||
|
if (!taskmanager || TaskID < 0 || TaskID >= MAXTASKS) {
|
||||||
|
c->Message(13, "Task system not functioning, or TaskID %i out of range.", TaskID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto task = taskmanager->Tasks[TaskID];
|
||||||
|
|
||||||
|
if (task == nullptr) {
|
||||||
|
c->Message(13, "Invalid TaskID %i", TaskID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task->type != TaskType::Shared) {
|
||||||
|
c->Message(13, "Trying to shared task a non shared task %i", TaskID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ActiveSharedTask != nullptr) {
|
||||||
|
c->Message_StringID(13, TASK_REJECT_HAVE_ONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enforce_level_requirement && !taskmanager->AppropriateLevel(TaskID, c->GetLevel())) {
|
||||||
|
c->Message(13, "You are outside the level range of this task.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!taskmanager->IsTaskRepeatable(TaskID) && IsTaskCompleted(TaskID))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (task->replay_group) {
|
||||||
|
auto expires = c->GetTaskLockoutExpire(task->replay_group);
|
||||||
|
if (expires) {
|
||||||
|
auto diff = expires - Timer::GetCurrentTime();
|
||||||
|
std::string days = std::to_string(diff / 86400);
|
||||||
|
diff = diff % 86400;
|
||||||
|
std::string hours = std::to_string(diff / 3600);
|
||||||
|
diff = diff % 3600;
|
||||||
|
std::string minutes = std::to_string(diff / 60);
|
||||||
|
c->Message_StringID(13, TASK_REJECT_LOCKEDOUT, days.c_str(), hours.c_str(), minutes.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we need to verify we meet min_player and max_players for raid/group
|
||||||
|
Group *group = nullptr;
|
||||||
|
Raid *raid = nullptr;
|
||||||
|
int player_count = 1; // 1 is just us!
|
||||||
|
if (c->IsGrouped()) {
|
||||||
|
group = c->GetGroup();
|
||||||
|
player_count = group->GroupCount();
|
||||||
|
} else if (c->IsRaidGrouped()) {
|
||||||
|
raid = c->GetRaid();
|
||||||
|
player_count = raid->RaidCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check task lockouts I guess it's simpler to require everyone to be in zone so we can verify lockouts ...
|
||||||
|
|
||||||
|
if (!EQEmu::ValueWithin(player_count, task->min_players, task->max_players)) {
|
||||||
|
if (player_count < task->min_players)
|
||||||
|
c->Message_StringID(13, TASK_REJECT_MIN_COUNT);
|
||||||
|
else
|
||||||
|
c->Message_StringID(13, TASK_REJECT_MAX_COUNT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
if (group) {
|
||||||
|
for (int i = 0; i < MAX_GROUP_MEMBERS; ++i) {
|
||||||
|
if (group->members[i] && group->members[i]->IsClient()) {
|
||||||
|
auto *client = group->members[i]->CastToClient();
|
||||||
|
auto *task_state = client->GetTaskState();
|
||||||
|
if (!task_state->HasSlotForTask(task)) {
|
||||||
|
task_failed = true;
|
||||||
|
c->Message_StringID(13, TASK_REJECT_GROUP_HAVE_ONE, c->GetName());
|
||||||
|
} else {
|
||||||
|
if (task->replay_group) {
|
||||||
|
auto expires = client->GetTaskLockoutExpire(task->replay_group);
|
||||||
|
if (expires) {
|
||||||
|
task_failed = true;
|
||||||
|
auto diff = expires - Timer::GetCurrentTime();
|
||||||
|
std::string days = std::to_string(diff / 86400);
|
||||||
|
diff = diff % 86400;
|
||||||
|
std::string hours = std::to_string(diff / 3600);
|
||||||
|
diff = diff % 3600;
|
||||||
|
std::string minutes = std::to_string(diff / 60);
|
||||||
|
c->Message_StringID(13, TASK_REJECT_LOCKEDOUT_OTHER,
|
||||||
|
client->GetName(), days.c_str(),
|
||||||
|
hours.c_str(), minutes.c_str());
|
||||||
|
client->Message_StringID(13, TASK_REJECT_LOCKEDOUT_ME,
|
||||||
|
days.c_str(), hours.c_str(),
|
||||||
|
minutes.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (group->members[i] == nullptr) { // out of zone
|
||||||
|
missing_players.push_back(group->membername[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (raid) {
|
||||||
|
for (int i = 0; i < MAX_RAID_MEMBERS; ++i) {
|
||||||
|
if (raid->members[i].member) {
|
||||||
|
auto *client = raid->members[i].member;
|
||||||
|
auto *task_state = client->GetTaskState();
|
||||||
|
if (!task_state->HasSlotForTask(task)) {
|
||||||
|
task_failed = true;
|
||||||
|
c->Message_StringID(13, TASK_REJECT_RAID_HAVE_ONE, c->GetName());
|
||||||
|
} else {
|
||||||
|
if (task->replay_group) {
|
||||||
|
auto expires = client->GetTaskLockoutExpire(task->replay_group);
|
||||||
|
if (expires) {
|
||||||
|
task_failed = true;
|
||||||
|
auto diff = expires - Timer::GetCurrentTime();
|
||||||
|
std::string days = std::to_string(diff / 86400);
|
||||||
|
diff = diff % 86400;
|
||||||
|
std::string hours = std::to_string(diff / 3600);
|
||||||
|
diff = diff % 3600;
|
||||||
|
std::string minutes = std::to_string(diff / 60);
|
||||||
|
c->Message_StringID(13, TASK_REJECT_LOCKEDOUT_OTHER,
|
||||||
|
client->GetName(), days.c_str(),
|
||||||
|
hours.c_str(), minutes.c_str());
|
||||||
|
client->Message_StringID(13, TASK_REJECT_LOCKEDOUT_ME,
|
||||||
|
days.c_str(), hours.c_str(),
|
||||||
|
minutes.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (raid->members[i].membername[0] != '\0') { // out of zone
|
||||||
|
missing_players.push_back(raid->members[i].membername);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task_failed) // we already yelled at them
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 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->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::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();
|
||||||
@ -3537,3 +3740,34 @@ int TaskProximityManager::CheckProximities(float X, float Y, float Z) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SharedTaskState::LockTask()
|
||||||
|
{
|
||||||
|
SetLocked(true);
|
||||||
|
|
||||||
|
for (auto & m : members)
|
||||||
|
if (m.entity != nullptr)
|
||||||
|
m.entity->Message_StringID(CC_Yellow, SHARED_TASK_LOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedTaskState::MemberZoned(Mob *player)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(members.begin(), members.end(),
|
||||||
|
[&player](const SharedTaskMember &a) { return a.name == player->GetName(); });
|
||||||
|
|
||||||
|
if (it == members.end()) // guess they weren't in this group, w/e
|
||||||
|
return;
|
||||||
|
|
||||||
|
it->entity = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedTaskState::MemberEnterZone(Mob *player)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(members.begin(), members.end(),
|
||||||
|
[&player](const SharedTaskMember &a) { return a.name == player->GetName(); });
|
||||||
|
|
||||||
|
if (it == members.end()) // guess they weren't in this group, w/e
|
||||||
|
return;
|
||||||
|
|
||||||
|
it->entity = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
87
zone/tasks.h
87
zone/tasks.h
@ -26,6 +26,8 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#define MAXTASKS 10000
|
#define MAXTASKS 10000
|
||||||
#define MAXTASKSETS 1000
|
#define MAXTASKSETS 1000
|
||||||
@ -141,6 +143,13 @@ enum class DurationCode {
|
|||||||
Long = 3
|
Long = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// need to capture more, shared are just Radiant/Ebon though
|
||||||
|
enum class PointType {
|
||||||
|
None = 0,
|
||||||
|
Radiant = 4,
|
||||||
|
Ebon = 5,
|
||||||
|
};
|
||||||
|
|
||||||
struct TaskInformation {
|
struct TaskInformation {
|
||||||
TaskType type;
|
TaskType type;
|
||||||
int Duration;
|
int Duration;
|
||||||
@ -155,12 +164,33 @@ struct TaskInformation {
|
|||||||
int XPReward;
|
int XPReward;
|
||||||
int faction_reward; // just a npc_faction_id
|
int faction_reward; // just a npc_faction_id
|
||||||
TaskMethodType RewardMethod;
|
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;
|
int ActivityCount;
|
||||||
SequenceType SequenceMode;
|
SequenceType SequenceMode;
|
||||||
int LastStep;
|
int LastStep;
|
||||||
short MinLevel;
|
short MinLevel;
|
||||||
short MaxLevel;
|
short MaxLevel;
|
||||||
bool Repeatable;
|
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];
|
ActivityInformation Activity[MAXACTIVITIESPERTASK];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -193,6 +223,35 @@ struct CompletedTaskInformation {
|
|||||||
bool ActivityDone[MAXACTIVITIESPERTASK];
|
bool ActivityDone[MAXACTIVITIESPERTASK];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SharedTaskMember {
|
||||||
|
std::string name;
|
||||||
|
Mob *entity; // needs to be managed
|
||||||
|
bool leader;
|
||||||
|
SharedTaskMember() : entity(nullptr), leader(false) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SharedTaskState {
|
||||||
|
public:
|
||||||
|
SharedTaskState() : locked(false) {}
|
||||||
|
// ~SharedTaskState();
|
||||||
|
|
||||||
|
inline const bool IsLocked() const { return locked; }
|
||||||
|
inline void SetLocked(bool v) { locked = v; }
|
||||||
|
void LockTask(); // notified clients (if they are etc)
|
||||||
|
|
||||||
|
void MemberZoned(Mob *player); // player left zone, update their pointer
|
||||||
|
void MemberEnterZone(Mob *player); // player entered zone, update their pointer
|
||||||
|
|
||||||
|
ClientTaskInformation *GetActivity() { return &activity; }
|
||||||
|
|
||||||
|
friend class TaskManager;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<SharedTaskMember> members;
|
||||||
|
ClientTaskInformation activity;
|
||||||
|
bool locked;
|
||||||
|
};
|
||||||
|
|
||||||
class ClientTaskState {
|
class ClientTaskState {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -206,6 +265,8 @@ public:
|
|||||||
int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID);
|
int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID);
|
||||||
int GetTaskStartTime(TaskType type, int index);
|
int GetTaskStartTime(TaskType type, int index);
|
||||||
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, bool enforce_level_requirement = false);
|
||||||
|
void PendSharedTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false);
|
||||||
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);
|
||||||
@ -255,6 +316,8 @@ private:
|
|||||||
info = &ActiveTask;
|
info = &ActiveTask;
|
||||||
break;
|
break;
|
||||||
case TaskType::Shared:
|
case TaskType::Shared:
|
||||||
|
if (index == 0 && ActiveSharedTask)
|
||||||
|
info = ActiveSharedTask->GetActivity();
|
||||||
break;
|
break;
|
||||||
case TaskType::Quest:
|
case TaskType::Quest:
|
||||||
if (index < MAXACTIVEQUESTS)
|
if (index < MAXACTIVEQUESTS)
|
||||||
@ -273,6 +336,7 @@ private:
|
|||||||
};
|
};
|
||||||
ClientTaskInformation ActiveTasks[MAXACTIVEQUESTS + 1];
|
ClientTaskInformation ActiveTasks[MAXACTIVEQUESTS + 1];
|
||||||
};
|
};
|
||||||
|
SharedTaskState *ActiveSharedTask; // pointer to our shared task managed by TaskManager
|
||||||
// Shared tasks should be limited to 1 as well
|
// Shared tasks should be limited to 1 as well
|
||||||
std::vector<int> EnabledTasks;
|
std::vector<int> EnabledTasks;
|
||||||
std::vector<CompletedTaskInformation> CompletedTasks;
|
std::vector<CompletedTaskInformation> CompletedTasks;
|
||||||
@ -280,6 +344,17 @@ 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 {
|
||||||
|
std::string name;
|
||||||
|
int duration;
|
||||||
|
};
|
||||||
|
|
||||||
class TaskManager {
|
class TaskManager {
|
||||||
|
|
||||||
@ -289,18 +364,19 @@ public:
|
|||||||
int GetActivityCount(int TaskID);
|
int GetActivityCount(int TaskID);
|
||||||
bool LoadSingleTask(int TaskID);
|
bool LoadSingleTask(int TaskID);
|
||||||
bool LoadTasks(int SingleTask=0);
|
bool LoadTasks(int SingleTask=0);
|
||||||
|
bool LoadReplayGroups();
|
||||||
void ReloadGoalLists();
|
void ReloadGoalLists();
|
||||||
inline void LoadProximities(int ZoneID) { ProximityManager.LoadProximities(ZoneID); }
|
inline void LoadProximities(int ZoneID) { ProximityManager.LoadProximities(ZoneID); }
|
||||||
bool LoadTaskSets();
|
bool LoadTaskSets();
|
||||||
bool LoadClientState(Client *c, ClientTaskState *state);
|
bool LoadClientState(Client *c, ClientTaskState *state);
|
||||||
bool SaveClientState(Client *c, ClientTaskState *state);
|
bool SaveClientState(Client *c, ClientTaskState *state);
|
||||||
void SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *TaskList);
|
void SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *TaskList, bool shared = false); // dumb hack cuz we do dumb things
|
||||||
void SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *TaskList);
|
void SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *TaskList, bool shared = false);
|
||||||
bool AppropriateLevel(int TaskID, int PlayerLevel);
|
bool AppropriateLevel(int TaskID, int PlayerLevel);
|
||||||
int GetTaskMinLevel(int TaskID);
|
int GetTaskMinLevel(int TaskID);
|
||||||
int GetTaskMaxLevel(int TaskID);
|
int GetTaskMaxLevel(int TaskID);
|
||||||
void TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID);
|
void TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID, bool shared = false);
|
||||||
void TaskQuestSetSelector(Client *c, ClientTaskState *state, Mob *mob, int count, int *tasks); // task list provided by QuestManager (perl/lua)
|
void TaskQuestSetSelector(Client *c, ClientTaskState *state, Mob *mob, int count, int *tasks, bool shared = false); // task list provided by QuestManager (perl/lua)
|
||||||
void SendActiveTasksToClient(Client *c, bool TaskComplete=false);
|
void SendActiveTasksToClient(Client *c, bool TaskComplete=false);
|
||||||
void SendSingleActiveTaskToClient(Client *c, ClientTaskInformation &task_info, bool TaskComplete, bool BringUpTaskJournal = false);
|
void SendSingleActiveTaskToClient(Client *c, ClientTaskInformation &task_info, bool TaskComplete, bool BringUpTaskJournal = false);
|
||||||
void SendTaskActivityShort(Client *c, int TaskID, int ActivityID, int ClientTaskIndex);
|
void SendTaskActivityShort(Client *c, int TaskID, int ActivityID, int ClientTaskIndex);
|
||||||
@ -316,6 +392,7 @@ public:
|
|||||||
bool IsTaskRepeatable(int TaskID);
|
bool IsTaskRepeatable(int TaskID);
|
||||||
friend class ClientTaskState;
|
friend class ClientTaskState;
|
||||||
|
|
||||||
|
void LoadSharedTask(int id); // loads the shared task state
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TaskGoalListManager GoalListManager;
|
TaskGoalListManager GoalListManager;
|
||||||
@ -323,6 +400,8 @@ private:
|
|||||||
TaskInformation* Tasks[MAXTASKS];
|
TaskInformation* Tasks[MAXTASKS];
|
||||||
std::vector<int> TaskSets[MAXTASKSETS];
|
std::vector<int> TaskSets[MAXTASKSETS];
|
||||||
void SendActiveTaskDescription(Client *c, int TaskID, ClientTaskInformation &task_info, int StartTime, int Duration, bool BringUpTaskJournal=false);
|
void SendActiveTaskDescription(Client *c, int TaskID, ClientTaskInformation &task_info, int StartTime, int Duration, bool BringUpTaskJournal=false);
|
||||||
|
std::unordered_map<int, SharedTaskState> SharedTasks;
|
||||||
|
std::map<int, TaskReplayGroups> replay_groups;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user