mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-25 01:41:29 +00:00
Merge branch 'shared_tasks' of github.com:EQEmu/Server into shared_tasks_service
This commit is contained in:
commit
0b26c80d8f
@ -1393,11 +1393,13 @@ sub fetch_latest_windows_binaries {
|
||||
}
|
||||
|
||||
sub fetch_latest_windows_binaries_bots {
|
||||
print "[Update] Fetching Latest Windows Binaries with Bots...\n";
|
||||
get_remote_file($install_repository_request_url . "master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1);
|
||||
print "[Update] Fetching Latest Windows Binaries (unstable) with Bots...\n";
|
||||
get_remote_file("https://ci.appveyor.com/api/projects/KimLS/server/artifacts/eqemu-x86-bots.zip", "updates_staged/eqemu-x86-bots.zip", 1);
|
||||
#::: old repository kept for reference until no issues reported
|
||||
#::: get_remote_file($install_repository_request_url . "master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1);
|
||||
print "[Update] Fetched Latest Windows Binaries with Bots...\n";
|
||||
print "[Update] Extracting...\n";
|
||||
unzip('updates_staged/master_windows_build_bots.zip', 'updates_staged/binaries/');
|
||||
unzip('updates_staged/eqemu-x86-bots.zip', 'updates_staged/binaries/');
|
||||
my @files;
|
||||
my $start_dir = "updates_staged/binaries";
|
||||
find(
|
||||
|
||||
@ -21,30 +21,30 @@ CREATE TABLE `task_replay_groups` (
|
||||
PRIMARY KEY(`id`)
|
||||
);
|
||||
CREATE TABLE `character_task_lockouts` (
|
||||
`charid` INT NOT NULL,
|
||||
`character_id` INT NOT NULL,
|
||||
`replay_group` INT NOT NULL,
|
||||
`original_id` INT NOT NULL,
|
||||
`timestamp` INT NOT NULL,
|
||||
PRIMARY KEY(`charid`, `replay_group`)
|
||||
PRIMARY KEY(`character_id`, `replay_group`)
|
||||
);
|
||||
CREATE TABLE `shared_task_state` (
|
||||
`id` INT NOT NULL,
|
||||
`taskid` INT NOT NULL,
|
||||
`acceptedtime` INT NOT NULL,
|
||||
`locked` TINYINT NOT NULL DEFAULT '0',
|
||||
`task_id` INT NOT NULL,
|
||||
`accepted_time` INT NOT NULL,
|
||||
`is_locked` TINYINT NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY(`id`)
|
||||
);
|
||||
CREATE TABLE `shared_task_activities` (
|
||||
`shared_id` INT NOT NULL,
|
||||
`shared_task_id` INT NOT NULL,
|
||||
`activity_id` INT NOT NULL,
|
||||
`done_count` INT NOT NULL,
|
||||
`completed` TINYINT,
|
||||
PRIMARY KEY(`shared_id`, `activity_id`)
|
||||
PRIMARY KEY(`shared_task_id`, `activity_id`)
|
||||
);
|
||||
CREATE TABLE `shared_task_members` (
|
||||
`shared_id` INT NOT NULL,
|
||||
`charid` INT NOT NULL,
|
||||
`name` VARCHAR(64) NOT NULL,
|
||||
`leader` TINYINT,
|
||||
PRIMARY KEY(`charid`)
|
||||
`shared_task_id` INT NOT NULL,
|
||||
`character_id` INT NOT NULL,
|
||||
`character_name` VARCHAR(64) NOT NULL,
|
||||
`is_leader` TINYINT DEFAULT 0,
|
||||
PRIMARY KEY(shared_task_id, character_id)
|
||||
);
|
||||
|
||||
@ -23,6 +23,7 @@ data_buckets
|
||||
db_str
|
||||
doors
|
||||
eqtime
|
||||
faction_base_data
|
||||
faction_list
|
||||
faction_list_mod
|
||||
fear_hints
|
||||
|
||||
@ -373,7 +373,7 @@ int ClientListEntry::GetTaskLockoutTimeLeft(int id) const
|
||||
[id](const TaskTimer &a) { return a.ID == id; });
|
||||
|
||||
if (it != m_task_replay_timers.end())
|
||||
return it->expires - Timer::GetCurrentTime();
|
||||
return it->expires - time(nullptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -384,7 +384,7 @@ int ClientListEntry::GetTaskLockoutTimeLeft(int id) const
|
||||
bool ClientListEntry::CleanExpiredTaskLockouts() const
|
||||
{
|
||||
std::string query =
|
||||
StringFormat("DELETE FROM `character_task_lockouts` WHERE `charid` = %i AND `timestamp` > %i", pcharid,
|
||||
StringFormat("DELETE FROM `character_task_lockouts` WHERE `character_id` = %i AND `timestamp` > %i", pcharid,
|
||||
Timer::GetCurrentTime());
|
||||
auto results = database.QueryDatabase(query);
|
||||
return results.Success();
|
||||
@ -397,7 +397,7 @@ bool ClientListEntry::LoadTaskLockouts()
|
||||
{
|
||||
CleanExpiredTaskLockouts();
|
||||
std::string query = StringFormat(
|
||||
"SELECT `replay_group`, `original_id`, `timestamp` FROM `character_task_lockouts` WHERE `charid` = %i",
|
||||
"SELECT `replay_group`, `original_id`, `timestamp` FROM `character_task_lockouts` WHERE `character_id` = %i",
|
||||
pcharid);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
|
||||
@ -82,7 +82,7 @@ void SharedTaskManager::HandleTaskRequest(ServerPacket *pack)
|
||||
}
|
||||
|
||||
auto &task = ret.first->second;
|
||||
task.AddMember(leader_name, cle_leader, true);
|
||||
task.AddMember(leader_name, cle_leader, cle_leader->CharID(), true);
|
||||
|
||||
if (players.empty()) {
|
||||
// send instant success to leader
|
||||
@ -133,7 +133,7 @@ void SharedTaskManager::HandleTaskRequest(ServerPacket *pack)
|
||||
|
||||
// check our lock out timer
|
||||
int expires = cle->GetTaskLockoutExpire(task_id);
|
||||
if ((expires - Timer::GetCurrentTime()) >= 0) {
|
||||
if ((expires - time(nullptr)) >= 0) {
|
||||
// failure TODO: appropriate message, we need to send the timestamp here
|
||||
auto pack = new ServerPacket(ServerOP_TaskReject, leader_name.size() + 1 + 8);
|
||||
pack->WriteUInt32(0); // string ID or just generic fail message
|
||||
@ -146,7 +146,7 @@ void SharedTaskManager::HandleTaskRequest(ServerPacket *pack)
|
||||
}
|
||||
|
||||
// we're good, add to task
|
||||
task.AddMember(name, cle);
|
||||
task.AddMember(name, cle, cle->CharID());
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,7 +374,7 @@ bool SharedTaskManager::LoadSharedTaskState()
|
||||
{
|
||||
// one may think we should clean up expired tasks, but we don't just in case world is booting back up after a crash
|
||||
// we will clean them up in the normal process loop so zones get told to clean up
|
||||
std::string query = "SELECT `id`, `taskid`, `acceptedtime`, `locked` FROM `shared_task_state`";
|
||||
std::string query = "SELECT `id`, `task_id`, `accepted_time`, `is_locked` FROM `shared_task_state`";
|
||||
auto results = database.QueryDatabase(query);
|
||||
|
||||
if (results.Success() && results.RowCount() > 0) {
|
||||
@ -389,14 +389,14 @@ bool SharedTaskManager::LoadSharedTaskState()
|
||||
}
|
||||
}
|
||||
|
||||
query = "SELECT `shared_id`, `charid`, `name`, `leader` FROM `shared_task_members` ORDER BY shared_id ASC";
|
||||
query = "SELECT `shared_task_id`, `character_id`, `character_name`, `is_leader` FROM `shared_task_members` ORDER BY shared_task_id ASC";
|
||||
results = database.QueryDatabase(query);
|
||||
if (results.Success() && results.RowCount() > 0) {
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
int task_id = atoi(row[0]);
|
||||
// hmm not sure best way to do this, fine for now
|
||||
if (tasks.count(task_id) == 1)
|
||||
tasks[task_id].AddMember(row[2], nullptr, atoi(row[3]) != 0);
|
||||
tasks[task_id].AddMember(row[2], nullptr, atoi(row[1]), atoi(row[3]) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -404,7 +404,7 @@ bool SharedTaskManager::LoadSharedTaskState()
|
||||
// But the crash case may actually dictate we should :P
|
||||
|
||||
// set next_id to highest used ID
|
||||
query = "SELECT MAX(id) FROM shared_task_state";
|
||||
query = "SELECT IFNULL(MAX(id), 0) FROM shared_task_state";
|
||||
results = database.QueryDatabase(query);
|
||||
if (results.Success() && results.RowCount() == 1) {
|
||||
auto row = results.begin();
|
||||
|
||||
@ -6,16 +6,21 @@
|
||||
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/global_tasks.h"
|
||||
#include "cliententry.h"
|
||||
|
||||
class ClientListEntry;
|
||||
|
||||
struct SharedTaskMember {
|
||||
std::string name;
|
||||
ClientListEntry *cle;
|
||||
int char_id;
|
||||
bool leader;
|
||||
// TODO: monster mission stuff
|
||||
SharedTaskMember() : cle(nullptr), leader(false) {}
|
||||
SharedTaskMember(std::string name, ClientListEntry *cle, bool leader) : name(name), cle(cle), leader(leader) {}
|
||||
SharedTaskMember() : cle(nullptr), char_id(0), leader(false) {}
|
||||
SharedTaskMember(std::string name, ClientListEntry *cle, int char_id, bool leader)
|
||||
: name(name), cle(cle), char_id(char_id), leader(leader)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class SharedTask {
|
||||
@ -24,11 +29,16 @@ public:
|
||||
SharedTask(int id, int task_id) : id(id), task_id(task_id), locked(false) {}
|
||||
~SharedTask() {}
|
||||
|
||||
void AddMember(std::string name, ClientListEntry *cle = nullptr, bool leader = false)
|
||||
void AddMember(std::string name, ClientListEntry *cle = nullptr, int char_id = 0, bool leader = false)
|
||||
{
|
||||
members.push_back({name, cle, leader});
|
||||
members.push_back({name, cle, char_id, leader});
|
||||
if (leader)
|
||||
leader_name = name;
|
||||
if (char_id == 0)
|
||||
return;
|
||||
auto it = std::find(char_ids.begin(), char_ids.end(), char_id);
|
||||
if (it == char_ids.end())
|
||||
char_ids.push_back(char_id);
|
||||
}
|
||||
void MemberLeftGame(ClientListEntry *cle);
|
||||
inline const std::string &GetLeaderName() const { return leader_name; }
|
||||
@ -59,6 +69,7 @@ private:
|
||||
bool locked;
|
||||
std::string leader_name;
|
||||
std::vector<SharedTaskMember> members;
|
||||
std::vector<int> char_ids; // every char id of someone to be locked out, different in case they leave/removed
|
||||
ClientTaskInformation task_state; // book keeping
|
||||
|
||||
friend class SharedTaskManager;
|
||||
|
||||
@ -1877,6 +1877,10 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk
|
||||
if (r)
|
||||
r->MemberZoned(this);
|
||||
|
||||
auto shared_task = GetSharedTask();
|
||||
if (shared_task)
|
||||
shared_task->MemberZoned(this);
|
||||
|
||||
dead_timer.Start(5000, true);
|
||||
m_pp.zone_id = m_pp.binds[0].zoneId;
|
||||
m_pp.zoneInstance = m_pp.binds[0].instance_id;
|
||||
|
||||
@ -439,6 +439,7 @@ NPCType *Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::st
|
||||
bot_npc_type->skip_global_loot = true;
|
||||
//bot_npc_type->rare_spawn = false;
|
||||
bot_npc_type->stuck_behavior = Ground;
|
||||
bot_npc_type->skip_auto_scale = true;
|
||||
|
||||
return bot_npc_type;
|
||||
}
|
||||
|
||||
@ -3396,6 +3396,11 @@ void Client::LinkDead()
|
||||
if(raid){
|
||||
raid->MemberZoned(this);
|
||||
}
|
||||
|
||||
auto shared_task = GetSharedTask();
|
||||
if (shared_task)
|
||||
shared_task->MemberZoned(this);
|
||||
|
||||
// save_timer.Start(2500);
|
||||
linkdead_timer.Start(RuleI(Zone,ClientLinkdeadMS));
|
||||
SendAppearancePacket(AT_Linkdead, 1);
|
||||
|
||||
@ -791,7 +791,9 @@ public:
|
||||
uint32 GetCharMaxLevelFromQGlobal();
|
||||
uint32 GetCharMaxLevelFromBucket();
|
||||
|
||||
inline bool IsStanding() const {return (playeraction == 0);}
|
||||
inline bool IsSitting() const {return (playeraction == 1);}
|
||||
inline bool IsCrouching() const {return (playeraction == 2);}
|
||||
inline bool IsBecomeNPC() const { return npcflag; }
|
||||
inline uint8 GetBecomeNPCLevel() const { return npclevel; }
|
||||
inline void SetBecomeNPC(bool flag) { npcflag = flag; }
|
||||
@ -1027,6 +1029,7 @@ public:
|
||||
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 AssignSharedTask(int TaskID, int NPCID, int id, int accepted_time, std::vector<std::string> &members) { if (taskstate) taskstate->AcceptNewSharedTask(this, TaskID, NPCID, id, accepted_time, members); }
|
||||
inline void AddToSharedTask(int TaskID) { if (taskstate) taskstate->AddToSharedTask(this, TaskID); }
|
||||
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 void FailTask(int TaskID) { if(taskstate) taskstate->FailTask(this, TaskID); }
|
||||
@ -1045,6 +1048,7 @@ public:
|
||||
inline int CompletedTasksInSet(int TaskSet) { return (taskstate ? taskstate->CompletedTasksInSet(TaskSet) :0); }
|
||||
inline int GetTaskLockoutExpire(int id) { return 0; } // stub
|
||||
inline int GetTaskLockoutTimeLeft(int id) { return 0; } // stub
|
||||
inline SharedTaskState *GetSharedTask() { return taskstate ? taskstate->GetSharedTask() : nullptr; }
|
||||
|
||||
inline const EQEmu::versions::ClientVersion ClientVersion() const { return m_ClientVersion; }
|
||||
inline const uint32 ClientVersionBit() const { return m_ClientVersionBit; }
|
||||
|
||||
@ -1799,7 +1799,7 @@ void Client::Handle_OP_AcceptNewSharedTask(const EQApplicationPacket *app)
|
||||
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);
|
||||
taskstate->RequestSharedTask(this, ant->task_id, ant->task_master_id);
|
||||
}
|
||||
|
||||
void Client::Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app)
|
||||
|
||||
@ -149,6 +149,9 @@ bool Client::Process() {
|
||||
{
|
||||
myraid->MemberZoned(this);
|
||||
}
|
||||
auto shared_task = GetSharedTask();
|
||||
if (shared_task)
|
||||
shared_task->MemberZoned(this);
|
||||
return(false);
|
||||
}
|
||||
|
||||
@ -171,6 +174,9 @@ bool Client::Process() {
|
||||
if (myraid) {
|
||||
myraid->MemberZoned(this);
|
||||
}
|
||||
auto shared_task = GetSharedTask();
|
||||
if (shared_task)
|
||||
shared_task->MemberZoned(this);
|
||||
return false; //delete client
|
||||
}
|
||||
|
||||
@ -653,6 +659,9 @@ bool Client::Process() {
|
||||
myraid->MemberZoned(this);
|
||||
}
|
||||
}
|
||||
auto shared_task = GetSharedTask();
|
||||
if (shared_task)
|
||||
shared_task->MemberZoned(this);
|
||||
OnDisconnect(false);
|
||||
return false;
|
||||
}
|
||||
@ -694,6 +703,10 @@ void Client::OnDisconnect(bool hard_disconnect) {
|
||||
if (MyRaid)
|
||||
MyRaid->MemberZoned(this);
|
||||
|
||||
auto shared_task = GetSharedTask();
|
||||
if (shared_task)
|
||||
shared_task->MemberZoned(this);
|
||||
|
||||
parse->EventPlayer(EVENT_DISCONNECT, this, "", 0);
|
||||
|
||||
/* QS: PlayerLogConnectDisconnect */
|
||||
@ -2101,6 +2114,10 @@ void Client::HandleRespawnFromHover(uint32 Option)
|
||||
if(r)
|
||||
r->MemberZoned(this);
|
||||
|
||||
auto shared_task = GetSharedTask();
|
||||
if (shared_task)
|
||||
shared_task->MemberZoned(this);
|
||||
|
||||
m_pp.zone_id = chosen->zone_id;
|
||||
m_pp.zoneInstance = chosen->instance_id;
|
||||
database.MoveCharacterToZone(CharacterID(), database.GetZoneName(chosen->zone_id));
|
||||
|
||||
@ -537,6 +537,9 @@ void EntityList::MobProcess()
|
||||
Log(Logs::General, Logs::Error, "About to delete a client still in a raid.");
|
||||
r->MemberZoned(mob->CastToClient());
|
||||
}
|
||||
auto shared_task = mob->CastToClient()->GetSharedTask();
|
||||
if (shared_task)
|
||||
shared_task->MemberZoned(mob);
|
||||
entity_list.RemoveClient(id);
|
||||
}
|
||||
|
||||
|
||||
@ -972,8 +972,8 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd
|
||||
safe_delete(outapp);
|
||||
}
|
||||
else {
|
||||
outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct));
|
||||
MoveItem_Struct* delitem = (MoveItem_Struct*)outapp->pBuffer;
|
||||
outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct));
|
||||
DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer;
|
||||
delitem->from_slot = slot_id;
|
||||
delitem->to_slot = 0xFFFFFFFF;
|
||||
delitem->number_in_stack = 0xFFFFFFFF;
|
||||
|
||||
@ -615,11 +615,21 @@ void Lua_Client::UntrainDiscAll(bool update_client) {
|
||||
self->UntrainDiscAll(update_client);
|
||||
}
|
||||
|
||||
bool Lua_Client::IsStanding() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsStanding();
|
||||
}
|
||||
|
||||
bool Lua_Client::IsSitting() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsSitting();
|
||||
}
|
||||
|
||||
bool Lua_Client::IsCrouching() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsCrouching();
|
||||
}
|
||||
|
||||
void Lua_Client::SetFeigned(bool v) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SetFeigned(v);
|
||||
@ -1621,7 +1631,9 @@ luabind::scope lua_register_client() {
|
||||
.def("UntrainDisc", (void(Lua_Client::*)(int,bool))&Lua_Client::UntrainDisc)
|
||||
.def("UntrainDiscAll", (void(Lua_Client::*)(void))&Lua_Client::UntrainDiscAll)
|
||||
.def("UntrainDiscAll", (void(Lua_Client::*)(bool))&Lua_Client::UntrainDiscAll)
|
||||
.def("IsStanding", (bool(Lua_Client::*)(void))&Lua_Client::IsStanding)
|
||||
.def("IsSitting", (bool(Lua_Client::*)(void))&Lua_Client::IsSitting)
|
||||
.def("IsCrouching", (bool(Lua_Client::*)(void))&Lua_Client::IsCrouching)
|
||||
.def("SetFeigned", (void(Lua_Client::*)(bool))&Lua_Client::SetFeigned)
|
||||
.def("GetFeigned", (bool(Lua_Client::*)(void))&Lua_Client::GetFeigned)
|
||||
.def("AutoSplitEnabled", (bool(Lua_Client::*)(void))&Lua_Client::AutoSplitEnabled)
|
||||
|
||||
@ -148,7 +148,9 @@ public:
|
||||
void UntrainDisc(int slot, bool update_client);
|
||||
void UntrainDiscAll();
|
||||
void UntrainDiscAll(bool update_client);
|
||||
bool IsStanding();
|
||||
bool IsSitting();
|
||||
bool IsCrouching();
|
||||
void SetFeigned(bool v);
|
||||
bool GetFeigned();
|
||||
bool AutoSplitEnabled();
|
||||
|
||||
@ -239,6 +239,7 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
|
||||
p_depop = false;
|
||||
loottable_id = npc_type_data->loottable_id;
|
||||
skip_global_loot = npc_type_data->skip_global_loot;
|
||||
skip_auto_scale = npc_type_data->skip_auto_scale;
|
||||
rare_spawn = npc_type_data->rare_spawn;
|
||||
no_target_hotkey = npc_type_data->no_target_hotkey;
|
||||
primary_faction = 0;
|
||||
|
||||
@ -468,6 +468,7 @@ public:
|
||||
|
||||
virtual int GetStuckBehavior() const { return NPCTypedata_ours ? NPCTypedata_ours->stuck_behavior : NPCTypedata->stuck_behavior; }
|
||||
|
||||
inline bool IsSkipAutoScale() const { return skip_auto_scale; }
|
||||
|
||||
protected:
|
||||
|
||||
@ -612,6 +613,7 @@ protected:
|
||||
private:
|
||||
uint32 loottable_id;
|
||||
bool skip_global_loot;
|
||||
bool skip_auto_scale;
|
||||
bool p_depop;
|
||||
};
|
||||
|
||||
|
||||
@ -26,6 +26,9 @@
|
||||
*/
|
||||
void NpcScaleManager::ScaleNPC(NPC * npc)
|
||||
{
|
||||
if (npc->IsSkipAutoScale())
|
||||
return;
|
||||
|
||||
int8 npc_type = GetNPCScalingType(npc);
|
||||
int npc_level = npc->GetLevel();
|
||||
bool is_auto_scaled = IsAutoScaled(npc);
|
||||
@ -621,4 +624,4 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically(NPC *&npc)
|
||||
auto results = database.QueryDatabase(query);
|
||||
|
||||
return results.Success();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2596,6 +2596,32 @@ XS(XS_Client_UntrainDiscAll) {
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Client_IsStanding); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Client_IsStanding)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Client::IsStanding(THIS)");
|
||||
{
|
||||
Client * THIS;
|
||||
bool RETVAL;
|
||||
|
||||
if (sv_derived_from(ST(0), "Client")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Client *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Client");
|
||||
if(THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->IsStanding();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Client_IsSitting); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Client_IsSitting) {
|
||||
dXSARGS;
|
||||
@ -2620,6 +2646,32 @@ XS(XS_Client_IsSitting) {
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Client_IsCrouching); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Client_IsCrouching)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Client::IsCrouching(THIS)");
|
||||
{
|
||||
Client * THIS;
|
||||
bool RETVAL;
|
||||
|
||||
if (sv_derived_from(ST(0), "Client")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Client *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Client");
|
||||
if(THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->IsCrouching();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Client_IsBecomeNPC); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Client_IsBecomeNPC) {
|
||||
dXSARGS;
|
||||
@ -6338,7 +6390,9 @@ XS(boot_Client) {
|
||||
newXSproto(strcpy(buf, "IsLD"), XS_Client_IsLD, file, "$");
|
||||
newXSproto(strcpy(buf, "IsMedding"), XS_Client_IsMedding, file, "$");
|
||||
newXSproto(strcpy(buf, "IsRaidGrouped"), XS_Client_IsRaidGrouped, file, "$");
|
||||
newXSproto(strcpy(buf, "IsStanding"), XS_Client_IsStanding, file, "$");
|
||||
newXSproto(strcpy(buf, "IsSitting"), XS_Client_IsSitting, file, "$");
|
||||
newXSproto(strcpy(buf, "IsCrouching"), XS_Client_IsCrouching, file, "$");
|
||||
newXSproto(strcpy(buf, "IsTaskActive"), XS_Client_IsTaskActive, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsTaskActivityActive"), XS_Client_IsTaskActivityActive, file, "$$$");
|
||||
newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$");
|
||||
|
||||
@ -3084,6 +3084,21 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, ClientTaskInf
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
// TODO: stub
|
||||
SharedTaskState *TaskManager::LoadSharedTask(int id)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SharedTaskState *TaskManager::GetSharedTask(int id)
|
||||
{
|
||||
auto it = SharedTasks.find(id);
|
||||
if (it == SharedTasks.end())
|
||||
return nullptr;
|
||||
|
||||
return &(it->second);
|
||||
}
|
||||
|
||||
bool ClientTaskState::IsTaskActivityCompleted(TaskType type, int index, int ActivityID)
|
||||
{
|
||||
switch (type) {
|
||||
@ -3387,10 +3402,13 @@ void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID, bool enfor
|
||||
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)
|
||||
/*
|
||||
* This function is a proxy for OP_AccetNewSharedTask since it has to fire to
|
||||
* world. We do a handful of checks on the leader, then build a packet with a
|
||||
* list of all the members in our group/raid if applicable. The verification for
|
||||
* the other members is done in world.
|
||||
*/
|
||||
void ClientTaskState::RequestSharedTask(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);
|
||||
@ -3550,11 +3568,47 @@ void ClientTaskState::AcceptNewSharedTask(Client *c, int TaskID, int NPCID, int
|
||||
worldserver.SendPacket(pack);
|
||||
delete pack;
|
||||
|
||||
ActiveSharedTask = task_state;
|
||||
|
||||
return;
|
||||
|
||||
// there are a few issues we need to solve with this
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when world sends ServerOP_TaskZoneCreated to trigger
|
||||
* members to join. If the task doesn't already exist, we need to load it from
|
||||
* the DB.
|
||||
*
|
||||
* This is also called in LoadClientTaskState() when they notice they have a
|
||||
* shared task they need to join. (Called from first OP_ZoneEntry)
|
||||
*/
|
||||
void ClientTaskState::AddToSharedTask(Client *c, int TaskID)
|
||||
{
|
||||
auto task = taskmanager->GetSharedTask(TaskID);
|
||||
if (!task)
|
||||
task = taskmanager->LoadSharedTask(TaskID);
|
||||
|
||||
if (!task) {// FUCK
|
||||
return;
|
||||
}
|
||||
|
||||
task->MemberEnterZone(c);
|
||||
|
||||
// send packets
|
||||
auto task_activity = task->GetActivity();
|
||||
taskmanager->SendSingleActiveTaskToClient(c, *task_activity, false, true);
|
||||
task->SendMembersList(c);
|
||||
|
||||
// So normally getting a task we would send EVENT_TASK_ACCEPTED here, but
|
||||
// this isn't an accept step. I guess we should add another event in case
|
||||
// they need the same thing TODO
|
||||
|
||||
ActiveSharedTask = task;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ClientTaskState::ProcessTaskProximities(Client *c, float X, float Y, float Z) {
|
||||
|
||||
float LastX = c->ProximityX();
|
||||
@ -3780,7 +3834,7 @@ void SharedTaskState::LockTask()
|
||||
void SharedTaskState::MemberZoned(Mob *player)
|
||||
{
|
||||
auto it = std::find_if(members.begin(), members.end(),
|
||||
[&player](const SharedTaskMember &a) { return a.name == player->GetName(); });
|
||||
[&player](const SharedTaskMember &a) { return a.entity == player; });
|
||||
|
||||
if (it == members.end()) // guess they weren't in this group, w/e
|
||||
return;
|
||||
|
||||
11
zone/tasks.h
11
zone/tasks.h
@ -146,8 +146,6 @@ public:
|
||||
int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID);
|
||||
int GetTaskStartTime(TaskType type, int index);
|
||||
void AcceptNewTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false);
|
||||
void AcceptNewSharedTask(Client *c, int TaskID, int NPCID, int id, int accepted_time, std::vector<std::string> &members);
|
||||
void PendSharedTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false);
|
||||
void FailTask(Client *c, int TaskID);
|
||||
int TaskTimeLeft(int TaskID);
|
||||
int IsTaskCompleted(int TaskID);
|
||||
@ -180,9 +178,15 @@ public:
|
||||
int ActiveTasksInSet(int TaskSetID);
|
||||
int CompletedTasksInSet(int TaskSetID);
|
||||
bool HasSlotForTask(TaskInformation *task);
|
||||
// shared task related functions
|
||||
void AcceptNewSharedTask(Client *c, int TaskID, int NPCID, int id, int accepted_time, std::vector<std::string> &members);
|
||||
void AddToSharedTask(Client *c, int TaskID);
|
||||
void RequestSharedTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false);
|
||||
|
||||
inline bool HasFreeTaskSlot() { return ActiveTask.TaskID == TASKSLOTEMPTY; }
|
||||
|
||||
inline SharedTaskState *GetSharedTask() { return ActiveSharedTask ; }
|
||||
|
||||
friend class TaskManager;
|
||||
|
||||
private:
|
||||
@ -266,8 +270,9 @@ public:
|
||||
bool IsTaskRepeatable(int TaskID);
|
||||
friend class ClientTaskState;
|
||||
|
||||
void LoadSharedTask(int id); // loads the shared task state
|
||||
SharedTaskState *LoadSharedTask(int id); // loads the shared task state
|
||||
SharedTaskState *CreateSharedTask(int id, int task_id);
|
||||
SharedTaskState *GetSharedTask(int id);
|
||||
|
||||
private:
|
||||
TaskGoalListManager GoalListManager;
|
||||
|
||||
@ -1991,6 +1991,17 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_TaskZoneCreated:
|
||||
{
|
||||
int task_id = pack->ReadUInt32();
|
||||
char name[64] = { 0 };
|
||||
pack->ReadString(name);
|
||||
|
||||
auto client = entity_list.GetClientByName(name);
|
||||
if (client)
|
||||
client->AddToSharedTask(task_id);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
std::cout << " Unknown ZSopcode:" << (int)pack->opcode;
|
||||
std::cout << " size:" << pack->size << std::endl;
|
||||
|
||||
@ -2675,6 +2675,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
|
||||
temp_npctype_data->rare_spawn = atoi(row[108]) != 0;
|
||||
temp_npctype_data->stuck_behavior = atoi(row[109]);
|
||||
temp_npctype_data->use_model = atoi(row[110]);
|
||||
temp_npctype_data->skip_auto_scale = false; // hardcoded here for now
|
||||
|
||||
// If NPC with duplicate NPC id already in table,
|
||||
// free item we attempted to add.
|
||||
@ -2877,6 +2878,8 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client
|
||||
tmpNPCType->scalerate = atoi(row[43]);
|
||||
tmpNPCType->spellscale = atoi(row[44]);
|
||||
tmpNPCType->healscale = atoi(row[45]);
|
||||
tmpNPCType->skip_global_loot = true;
|
||||
tmpNPCType->skip_auto_scale = true;
|
||||
|
||||
// If Merc with duplicate NPC id already in table,
|
||||
// free item we attempted to add.
|
||||
|
||||
@ -143,6 +143,7 @@ struct NPCType
|
||||
bool untargetable;
|
||||
bool skip_global_loot;
|
||||
bool rare_spawn;
|
||||
bool skip_auto_scale; // just so it doesn't mess up bots or mercs, probably should add to DB too just in case
|
||||
int8 stuck_behavior;
|
||||
uint16 use_model;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user