mirror of
https://github.com/EQEmu/Server.git
synced 2026-02-16 08:42:25 +00:00
The requestor should at least be able to see the new shared task and get
a member list There are still a few issues that need to be solved this way. We could try searching for the members in zone (by name ...) or we could just fire off to world and world will have to send a special full serialization so the new zone could load the state. Or at this point we could just assume that we have saved the state to the DB (which hasn't been coded yet) and any out of zone members will have to depend on loading it up from the DB.
This commit is contained in:
parent
977c3ca3dc
commit
c5bf71f221
@ -462,6 +462,7 @@ N(OP_SetServerFilter),
|
||||
N(OP_SetStartCity),
|
||||
N(OP_SetTitle),
|
||||
N(OP_SetTitleReply),
|
||||
N(OP_SharedTaskMemberList),
|
||||
N(OP_Shielding),
|
||||
N(OP_ShopDelItem),
|
||||
N(OP_ShopEnd),
|
||||
|
||||
@ -3698,6 +3698,7 @@ struct TaskMemberList_Struct {
|
||||
/*12*/ char list_pointer[0];
|
||||
/* list is of the form:
|
||||
char member_name[1] //null terminated string
|
||||
uint32 monster_mission; // class chosen
|
||||
uint8 task_leader //boolean flag
|
||||
*/
|
||||
};
|
||||
|
||||
@ -564,6 +564,7 @@ OP_TaskHistoryReply=0x25eb
|
||||
OP_DeclineAllTasks=0x0000
|
||||
OP_TaskRequestTimer=0x4b76
|
||||
OP_AcceptNewSharedTask=0x3e5e
|
||||
OP_SharedTaskMemberList=0x4ddb
|
||||
|
||||
# Title opcodes
|
||||
OP_NewTitlesAvailable=0x45d1
|
||||
|
||||
@ -569,6 +569,7 @@ OP_TaskHistoryReply=0x3d05
|
||||
OP_DeclineAllTasks=0x0000
|
||||
OP_TaskRequestTimer=0x7a48
|
||||
OP_AcceptNewSharedTask=0x6646
|
||||
OP_SharedTaskMemberList=0x1e7d
|
||||
|
||||
# Title opcodes
|
||||
OP_NewTitlesAvailable=0x0d32
|
||||
|
||||
@ -535,6 +535,7 @@ OP_CancelTask=0x726b # C
|
||||
OP_DeclineAllTasks=0x0000 #
|
||||
OP_TaskRequestTimer=0x2e70
|
||||
OP_AcceptNewSharedTask=0x4751
|
||||
OP_SharedTaskMemberList=0x55f4
|
||||
|
||||
|
||||
OP_Shroud=0x6d1f
|
||||
|
||||
@ -500,7 +500,7 @@ OP_TaskHistoryRequest=0x3035 #
|
||||
OP_TaskHistoryReply=0x3A60 #
|
||||
OP_CancelTask=0x4db6 #Xinu or 0x2c8c or 0x4db6
|
||||
OP_DeclineAllTasks=0x0000 #not sure, 12 bytes
|
||||
OP_TaskMemberList=0x3713
|
||||
#OP_TaskMemberList=0x3713
|
||||
OP_TaskMemberInvite=0x3cde
|
||||
OP_TaskMemberInviteResponse=0x6cab
|
||||
OP_TaskMemberChange=0x354a
|
||||
@ -511,6 +511,7 @@ OP_TaskPlayerList=0x0ad6
|
||||
OP_TaskQuit=0x2c8c
|
||||
OP_TaskRequestTimer=0x0b08
|
||||
OP_AcceptNewSharedTask=0x5bed
|
||||
OP_SharedTaskMemberList=0x3713
|
||||
|
||||
#Title opcodes
|
||||
OP_NewTitlesAvailable=0x179c #
|
||||
|
||||
@ -458,7 +458,7 @@ OP_TaskActivityComplete=0x54eb
|
||||
OP_CompletedTasks=0x76a2 # ShowEQ 10/27/05
|
||||
OP_TaskDescription=0x5ef7 # ShowEQ 10/27/05
|
||||
OP_TaskActivity=0x682d # ShowEQ 10/27/05
|
||||
OP_TaskMemberList=0x722f #not sure
|
||||
#OP_TaskMemberList=0x722f #not sure
|
||||
OP_OpenNewTasksWindow=0x5e7c #combined with OP_AvaliableTask I think
|
||||
OP_AvaliableTask=0x0000
|
||||
OP_AcceptNewTask=0x207f
|
||||
@ -476,6 +476,7 @@ OP_TaskPlayerList=0x3961
|
||||
OP_TaskQuit=0x35dd
|
||||
OP_TaskRequestTimer=0x6a1d
|
||||
OP_AcceptNewSharedTask=0x194d
|
||||
OP_SharedTaskMemberList=0x722f
|
||||
#task complete related: 0x0000 (24 bytes), 0x0000 (8 bytes), 0x0000 (4 bytes)
|
||||
|
||||
|
||||
|
||||
@ -558,6 +558,7 @@ OP_CancelTask=0x3bf5 # C
|
||||
OP_DeclineAllTasks=0x0000 #
|
||||
OP_TaskRequestTimer=0x719e
|
||||
OP_AcceptNewSharedTask=0x6ded
|
||||
OP_SharedTaskMemberList=0x584e
|
||||
|
||||
# Title opcodes
|
||||
OP_NewTitlesAvailable=0x4b49 # C
|
||||
|
||||
@ -433,6 +433,7 @@ void SharedTask::MemberLeftGame(ClientListEntry *cle)
|
||||
* Serializes Members into the SerializeBuffer
|
||||
* Starts with count then followed by names null-termed
|
||||
* In the future this will include monster mission shit
|
||||
* This should probably send the SharedMember struct or something more like it, fine for now
|
||||
*/
|
||||
void SharedTask::SerializeMembers(SerializeBuffer &buf, bool include_leader) const
|
||||
{
|
||||
|
||||
189
zone/tasks.cpp
189
zone/tasks.cpp
@ -2451,6 +2451,15 @@ bool TaskManager::IsTaskRepeatable(int TaskID) {
|
||||
return Task->Repeatable;
|
||||
}
|
||||
|
||||
SharedTaskState *TaskManager::CreateSharedTask(int id, int task_id)
|
||||
{
|
||||
auto ret = SharedTasks.insert({id, {id, task_id}});
|
||||
if (!ret.second) // hmm was already created
|
||||
return nullptr;
|
||||
|
||||
return &(ret.first->second);
|
||||
}
|
||||
|
||||
bool ClientTaskState::TaskOutOfTime(TaskType type, int Index)
|
||||
{
|
||||
// Returns true if the Task in the specified slot has a time limit that has been exceeded.
|
||||
@ -3267,10 +3276,8 @@ void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID, bool enfor
|
||||
if (ActiveTask.TaskID != TASKSLOTEMPTY)
|
||||
max_tasks = true;
|
||||
break;
|
||||
case TaskType::Shared: // TODO: shared tasks
|
||||
// if (something)
|
||||
max_tasks = true;
|
||||
break;
|
||||
case TaskType::Shared: // shared tasks shouldn't call this function. should we log?
|
||||
return;
|
||||
case TaskType::Quest:
|
||||
if (ActiveTaskCount == MAXACTIVEQUESTS)
|
||||
max_tasks = true;
|
||||
@ -3312,9 +3319,8 @@ void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID, bool enfor
|
||||
case TaskType::Task:
|
||||
active_slot = &ActiveTask;
|
||||
break;
|
||||
case TaskType::Shared: // TODO: shared
|
||||
active_slot = nullptr;
|
||||
break;
|
||||
case TaskType::Shared: // shared aren't done here, should have returned already :P
|
||||
return;
|
||||
case TaskType::Quest:
|
||||
for (int i = 0; i < MAXACTIVEQUESTS; i++) {
|
||||
Log(Logs::General, Logs::Tasks,
|
||||
@ -3467,103 +3473,66 @@ void ClientTaskState::PendSharedTask(Client *c, int TaskID, int NPCID, bool enfo
|
||||
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
|
||||
bool task_failed = false;
|
||||
if (group) {
|
||||
for (int i = 0; i < MAX_GROUP_MEMBERS; ++i) {
|
||||
if (group->members[i] == c)
|
||||
continue;
|
||||
|
||||
c->PendingTaskAddMember(group->membername[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());
|
||||
break;
|
||||
} else {
|
||||
if (task->replay_group) {
|
||||
auto expires = client->GetTaskLockoutTimeLeft(task->replay_group);
|
||||
if (expires > 0) {
|
||||
task_failed = true;
|
||||
std::string days = std::to_string(expires / 86400);
|
||||
expires = expires % 86400;
|
||||
std::string hours = std::to_string(expires / 3600);
|
||||
expires = expires % 3600;
|
||||
std::string minutes = std::to_string(expires / 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());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} 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 == c)
|
||||
continue;
|
||||
|
||||
c->PendingTaskAddMember(raid->members[i].membername);
|
||||
|
||||
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());
|
||||
break;
|
||||
} else {
|
||||
if (task->replay_group) {
|
||||
auto expires = client->GetTaskLockoutTimeLeft(task->replay_group);
|
||||
if (expires > 0) {
|
||||
task_failed = true;
|
||||
std::string days = std::to_string(expires / 86400);
|
||||
expires = expires % 86400;
|
||||
std::string hours = std::to_string(expires / 3600);
|
||||
expires = expires % 3600;
|
||||
std::string minutes = std::to_string(expires / 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());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} 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
|
||||
c->ResetPendingTask();
|
||||
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
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void ClientTaskState::AcceptNewSharedTask(Client *c, int TaskID, int NPCID, int id, std::vector<std::string> &members)
|
||||
{
|
||||
// all of this data should have been verified already
|
||||
// first we need to create the new SharedTaskState
|
||||
auto task_state = taskmanager->CreateSharedTask(id, TaskID);
|
||||
if (!task_state) {
|
||||
// TODO: something failed, tell world
|
||||
return;
|
||||
}
|
||||
|
||||
// we need to init the activity now
|
||||
auto task_activity = task_state->GetActivity();
|
||||
|
||||
task_activity->TaskID = TaskID;
|
||||
task_activity->AcceptedTime = time(nullptr);
|
||||
task_activity->Updated = true;
|
||||
task_activity->CurrentStep = -1;
|
||||
|
||||
for (int i = 0; i < taskmanager->Tasks[TaskID]->ActivityCount; i++) {
|
||||
task_activity->Activity[i].ActivityID = i;
|
||||
task_activity->Activity[i].DoneCount = 0;
|
||||
task_activity->Activity[i].State = ActivityHidden;
|
||||
task_activity->Activity[i].Updated = true;
|
||||
}
|
||||
|
||||
// TODO: figure out packet order
|
||||
// unsure if we unlock now packet wise, just copying normal tasks for now
|
||||
UnlockActivities(c->CharacterID(), *task_activity);
|
||||
|
||||
taskmanager->SendSingleActiveTaskToClient(c, *task_activity, false, true);
|
||||
c->Message(0, "You have been assigned the task '%s'.", taskmanager->Tasks[TaskID]->Title.c_str());
|
||||
|
||||
// send member list of just leader
|
||||
task_state->AddMember(c->GetName(), c, true);
|
||||
task_state->SendMembersList(c);
|
||||
|
||||
// send compass shit
|
||||
|
||||
// add everyone else and send that
|
||||
// we could try to find these members so they could know about it ... but ahh not sure :P
|
||||
for (auto &m : members)
|
||||
task_state->AddMember(m);
|
||||
|
||||
task_state->SendMembersList(c);
|
||||
|
||||
std::string buf = std::to_string(TaskID);
|
||||
NPC *npc = entity_list.GetID(NPCID)->CastToNPC();
|
||||
if(!npc) {
|
||||
c->Message(clientMessageYellow, "Task Giver ID is %i", NPCID);
|
||||
c->Message(clientMessageError, "Unable to find NPC to send EVENT_TASKACCEPTED to. Report this bug.");
|
||||
// TODO: ahh do we wanna do this? clean up world at least
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: save state
|
||||
parse->EventNPC(EVENT_TASK_ACCEPTED, npc, c, buf.c_str(), 0);
|
||||
// TODO: We need to tell world we are successful so we can tell all the other clients
|
||||
// there are a few issues we need to solve with this
|
||||
}
|
||||
|
||||
void ClientTaskState::ProcessTaskProximities(Client *c, float X, float Y, float Z) {
|
||||
@ -3810,3 +3779,25 @@ void SharedTaskState::MemberEnterZone(Mob *player)
|
||||
it->entity = player;
|
||||
}
|
||||
|
||||
void SharedTaskState::SendMembersList(Client *to) const
|
||||
{
|
||||
if (!to)
|
||||
return;
|
||||
|
||||
SerializeBuffer buf(sizeof(TaskMemberList_Struct) + 15 * members.size());
|
||||
buf.WriteInt32(0); // unknown ids
|
||||
buf.WriteInt32(0);
|
||||
buf.WriteInt32(members.size());
|
||||
|
||||
for (auto &&m : members) {
|
||||
buf.WriteString(m.name);
|
||||
buf.WriteInt32(0); // monster mission shit
|
||||
buf.WriteInt8(m.leader);
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_SharedTaskMemberList, buf);
|
||||
|
||||
to->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
|
||||
15
zone/tasks.h
15
zone/tasks.h
@ -95,11 +95,13 @@ struct SharedTaskMember {
|
||||
Mob *entity; // needs to be managed
|
||||
bool leader;
|
||||
SharedTaskMember() : entity(nullptr), leader(false) {}
|
||||
SharedTaskMember(std::string name, Mob *entity, bool leader) : name(name), entity(entity), leader(leader) {}
|
||||
};
|
||||
|
||||
class SharedTaskState {
|
||||
public:
|
||||
SharedTaskState() : locked(false) {}
|
||||
SharedTaskState(int id, int task_id) : id(id), task_id(task_id), locked(false) { }
|
||||
// ~SharedTaskState();
|
||||
|
||||
inline const bool IsLocked() const { return locked; }
|
||||
@ -109,12 +111,24 @@ public:
|
||||
void MemberZoned(Mob *player); // player left zone, update their pointer
|
||||
void MemberEnterZone(Mob *player); // player entered zone, update their pointer
|
||||
|
||||
void AddMember(std::string name, Mob *entity = nullptr, bool leader = false)
|
||||
{
|
||||
members.push_back({name, entity, leader});
|
||||
if (leader)
|
||||
leader_name = name;
|
||||
}
|
||||
|
||||
void SendMembersList(Client *to) const;
|
||||
|
||||
ClientTaskInformation *GetActivity() { return &activity; }
|
||||
|
||||
friend class TaskManager;
|
||||
|
||||
private:
|
||||
int id;
|
||||
int task_id;
|
||||
std::vector<SharedTaskMember> members;
|
||||
std::string leader_name;
|
||||
ClientTaskInformation activity;
|
||||
bool locked;
|
||||
};
|
||||
@ -253,6 +267,7 @@ public:
|
||||
friend class ClientTaskState;
|
||||
|
||||
void LoadSharedTask(int id); // loads the shared task state
|
||||
SharedTaskState *CreateSharedTask(int id, int task_id);
|
||||
|
||||
private:
|
||||
TaskGoalListManager GoalListManager;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user