This commit is contained in:
neckkola
2022-05-17 22:31:04 -03:00
24 changed files with 3783 additions and 525 deletions
+2 -2
View File
@@ -54,5 +54,5 @@ bin/
/Win32
/x64
/client_files/**/CMakeFiles/
.idea
submodules/libuv
.idea
+15
View File
@@ -0,0 +1,15 @@
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": ""
}
]
}
@@ -28,6 +28,9 @@ public:
int isgroupleader;
int israidleader;
int islooter;
#ifdef BOTS
int isbot;
#endif
};
static std::string PrimaryKey()
@@ -47,6 +50,9 @@ public:
"isgroupleader",
"israidleader",
"islooter",
#ifdef BOTS
"isbot",
#endif
};
}
@@ -111,6 +117,9 @@ public:
entry.isgroupleader = 0;
entry.israidleader = 0;
entry.islooter = 0;
#ifdef BOTS
entry.isbot = 0;
#endif
return entry;
}
@@ -154,7 +163,10 @@ public:
entry.name = row[5] ? row[5] : "";
entry.isgroupleader = atoi(row[6]);
entry.israidleader = atoi(row[7]);
entry.islooter = atoi(row[8]);
entry.islooter = atoi(row[8]);
#ifdef BOTS
entry.isbot = atoi(row[9]);
#endif
return entry;
}
@@ -197,6 +209,9 @@ public:
update_values.push_back(columns[6] + " = " + std::to_string(raid_members_entry.isgroupleader));
update_values.push_back(columns[7] + " = " + std::to_string(raid_members_entry.israidleader));
update_values.push_back(columns[8] + " = " + std::to_string(raid_members_entry.islooter));
#ifdef BOTS
update_values.push_back(columns[9] + " = " + std::to_string(raid_members_entry.isbot));
#endif
auto results = db.QueryDatabase(
fmt::format(
@@ -227,7 +242,9 @@ public:
insert_values.push_back(std::to_string(raid_members_entry.isgroupleader));
insert_values.push_back(std::to_string(raid_members_entry.israidleader));
insert_values.push_back(std::to_string(raid_members_entry.islooter));
#ifdef BOTS
insert_values.push_back(std::to_string(raid_members_entry.isbot));
#endif
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
@@ -265,7 +282,9 @@ public:
insert_values.push_back(std::to_string(raid_members_entry.isgroupleader));
insert_values.push_back(std::to_string(raid_members_entry.israidleader));
insert_values.push_back(std::to_string(raid_members_entry.islooter));
#ifdef BOTS
insert_values.push_back(std::to_string(raid_members_entry.isbot));
#endif
insert_chunks.push_back("(" + implode(",", insert_values) + ")");
}
@@ -307,7 +326,9 @@ public:
entry.isgroupleader = atoi(row[6]);
entry.israidleader = atoi(row[7]);
entry.islooter = atoi(row[8]);
#ifdef BOTS
entry.isbot = atoi(row[9]);
#endif
all_entries.push_back(entry);
}
@@ -340,7 +361,9 @@ public:
entry.isgroupleader = atoi(row[6]);
entry.israidleader = atoi(row[7]);
entry.islooter = atoi(row[8]);
#ifdef BOTS
entry.isbot = atoi(row[9]);
#endif
all_entries.push_back(entry);
}
+3
View File
@@ -622,10 +622,13 @@ RULE_REAL(Bots, LeashDistance, 562500.0f, "Distance a bot is allowed to travel f
RULE_BOOL(Bots, AllowApplyPoisonCommand, true, "Allows the use of the bot command 'applypoison'")
RULE_BOOL(Bots, AllowApplyPotionCommand, true, "Allows the use of the bot command 'applypotion'")
RULE_BOOL(Bots, RestrictApplyPotionToRogue, true, "Restricts the bot command 'applypotion' to rogue-usable potions (i.e., poisons)")
RULE_BOOL(Bots, DisplayHealDamage, false, "Enables the display of bot heal damage to the bot owner client")
RULE_BOOL(Bots, DisplaySpellDamage, false, "Enables the display of bot spell damage to the bot owner client")
RULE_BOOL(Bots, OldRaceRezEffects, false, "Older clients had ID 757 for races with high starting STR, but it doesn't seem used anymore")
RULE_BOOL(Bots, ResurrectionSickness, true, "Use Resurrection Sickness based on Resurrection spell cast, set to false to disable Resurrection Sickness.")
RULE_INT(Bots, OldResurrectionSicknessSpell, 757, "757 is Default Old Resurrection Sickness Spell")
RULE_INT(Bots, ResurrectionSicknessSpell, 756, "756 is Default Resurrection Sickness Spell")
RULE_CATEGORY_END()
#endif
+3
View File
@@ -57,6 +57,9 @@ typedef const char Const_char; //for perl XS
#define safe_delete(d) if(d) { delete d; d=nullptr; }
#define safe_delete_array(d) if(d) { delete[] d; d=nullptr; }
//#define safe_delete(d)(_RPTF0(_CRT_WARN,"Testing delete function\n"));
//#define safe_delete(d) if(d) { }
//#define safe_delete_array(d) if(d) { }
#define L32(i) ((uint32) i)
#define H32(i) ((uint32) (i >> 32))
#define L16(i) ((uint16) i)
@@ -27,6 +27,7 @@
9026|2019_09_09_bots_owner_options_rework.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'option_type'|empty|
9027|2020_03_30_bots_view_update.sql|SELECT * FROM db_version WHERE bots_version >= 9027|empty|
9028|2021_06_04_bot_create_combinations.sql|SHOW TABLES LIKE 'bot_create_combinations'|empty|
9029|2022_02_08_bots_raid_members.sql|SELECT * FROM db_version WHERE bots_version >= 9028|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not
@@ -0,0 +1 @@
ALTER TABLE `raid_members` ADD COLUMN `isbot` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '';
+1
View File
@@ -11,6 +11,7 @@ SET(zone_sources
beacon.cpp
bonuses.cpp
bot.cpp
bot_raid.cpp
bot_command.cpp
bot_database.cpp
botspellsai.cpp
+17 -2
View File
@@ -35,6 +35,7 @@
#include "../common/global_define.h"
#include "guild_mgr.h"
#include "worldserver.h"
#include "raids.h"
#include <sstream>
@@ -151,8 +152,8 @@ public:
ExtraAttackOptions *opts = nullptr);
virtual bool HasRaid() { return (GetRaid() ? true : false); }
virtual bool HasGroup() { return (GetGroup() ? true : false); }
virtual Raid* GetRaid() { return entity_list.GetRaidByMob(this); }
virtual Group* GetGroup() { return entity_list.GetGroupByMob(this); }
virtual Raid* GetRaid() { return entity_list.GetRaidByMob(this); } // GetRaidByMob(this);
virtual Group* GetGroup() { return entity_list.GetGroupByMob(this); } // GetGroupByMob;
// Common, but informal "interfaces" with Client object
uint32 CharacterID() { return GetBotID(); } // Just returns the Bot Id
@@ -375,6 +376,15 @@ public:
static bool CheckDisciplineRecastTimers(Bot *caster, int timer_index);
static uint32 GetDisciplineRemainingTime(Bot *caster, int timer_index);
//Raid methods
void PetAIProcess_Raid();
void AI_Process_Raid();
bool AICastSpell_Raid(Mob* tar, uint8 iChance, uint32 iSpellTypes);
static void ProcessRaidInvite(Bot* invitee, Client* invitor);
static void ProcessRaidInvite(Client* invitee, Client* invitor);
uint8 GetNumberNeedingHealedInRaidGroup(uint8 hpr, bool includePets);
inline void SetDirtyAutoHaters() { m_dirtyautohaters = true; }
static std::list<BotSpell> GetBotSpellsForSpellEffect(Bot* botCaster, int spellEffect);
static std::list<BotSpell> GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, int spellEffect, SpellTargetType targetType);
static std::list<BotSpell> GetBotSpellsBySpellType(Bot* botCaster, uint32 spellType);
@@ -610,6 +620,9 @@ public:
int32 GetBaseDR() { return _baseDR; }
int32 GetBaseCorrup() { return _baseCorrup; }
//Raid additions
Raid* p_raid_instance;
protected:
virtual void PetAIProcess();
virtual void BotMeditate(bool isSitting);
@@ -674,6 +687,7 @@ private:
Timer m_auto_defend_timer;
//Timer m_combat_jitter_timer;
//bool m_combat_jitter_flag;
bool m_dirtyautohaters;
bool m_guard_flag;
bool m_hold_flag;
bool m_attack_flag;
@@ -740,6 +754,7 @@ private:
public:
static uint8 spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND];
};
#endif // BOTS
+2630
View File
File diff suppressed because it is too large Load Diff
+47
View File
@@ -0,0 +1,47 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef BOT_RAID_H
#define BOT_RAID_H
#ifdef BOTS
#include "bot_structs.h"
#include "mob.h"
#include "client.h"
#include "pets.h"
#include "heal_rotation.h"
#include "groups.h"
#include "corpse.h"
#include "zonedb.h"
#include "zone_store.h"
#include "string_ids.h"
#include "../common/misc_functions.h"
#include "../common/global_define.h"
#include "guild_mgr.h"
#include "worldserver.h"
#include <sstream>
extern WorldServer worldserver;
//void Bot::PetAIProcess_Raid();
#endif // BOTS
#endif // BOT_RAID_H
+8 -1
View File
@@ -3,7 +3,7 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
the Free Software Foundation; version 2 ogroupf the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
@@ -31,6 +31,13 @@
bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) {
// Bot AI
Raid* raid = entity_list.GetRaidByBotName(this->GetName());
if (raid) {
return AICastSpell_Raid(tar, iChance, iSpellTypes);
//return true;
}
if (!tar) {
return false;
}
+5 -4
View File
@@ -807,9 +807,10 @@ void Client::QueuePacket(const EQApplicationPacket* app, bool ack_req, CLIENT_CO
// todo: save packets for later use
AddPacket(app, ack_req);
}
else
if(eqs)
eqs->QueuePacket(app, ack_req);
else if (eqs)
{
eqs->QueuePacket(app, ack_req);
}
}
void Client::FastQueuePacket(EQApplicationPacket** app, bool ack_req, CLIENT_CONN_STATUS required_state) {
@@ -820,7 +821,7 @@ void Client::FastQueuePacket(EQApplicationPacket** app, bool ack_req, CLIENT_CON
return;
}
else {
if(eqs)
if(eqs)
eqs->FastQueuePacket((EQApplicationPacket **)app, ack_req);
else if (app && (*app))
delete *app;
+695 -485
View File
File diff suppressed because it is too large Load Diff
+47 -3
View File
@@ -2137,17 +2137,17 @@ Raid *EntityList::GetRaidByID(uint32 id)
return nullptr;
}
Raid *EntityList::GetRaidByClient(Client* client)
Raid* EntityList::GetRaidByClient(Client* client)
{
if (client->p_raid_instance) {
return client->p_raid_instance;
}
std::list<Raid *>::iterator iterator;
std::list<Raid*>::iterator iterator;
iterator = raid_list.begin();
while (iterator != raid_list.end()) {
for (auto &member : (*iterator)->members) {
for (auto& member : (*iterator)->members) {
if (member.member) {
if (member.member == client) {
client->p_raid_instance = *iterator;
@@ -2161,6 +2161,50 @@ Raid *EntityList::GetRaidByClient(Client* client)
return nullptr;
}
#ifdef BOTS
Raid* EntityList::GetRaidByBotName(const char* name)
{
std::list<Raid*>::iterator iterator;
iterator = raid_list.begin();
while (iterator != raid_list.end()) {
for (auto& member : (*iterator)->members) {
if (member.membername) {
if (strcmp(member.membername, name) == 0) {
//client->p_raid_instance = *iterator;
return *iterator;
}
}
}
++iterator;
}
return nullptr;
}
#endif
#ifdef BOTS
Raid* EntityList::GetRaidByBot(Bot* bot)
{
std::list<Raid*>::iterator iterator;
iterator = raid_list.begin();
while (iterator != raid_list.end()) {
for (auto& member : (*iterator)->members) {
if (member.member && member.member->CastToBot() == bot) {
bot->p_raid_instance = *iterator;
return *iterator;
}
}
++iterator;
}
return nullptr;
}
#endif
Raid *EntityList::GetRaidByMob(Mob *mob)
{
+4
View File
@@ -200,6 +200,10 @@ public:
Raid *GetRaidByClient(Client* client);
Raid *GetRaidByID(uint32 id);
Raid *GetRaidByLeaderName(const char *leader);
#ifdef BOTS
Raid* GetRaidByBotName(const char* name);
Raid* GetRaidByBot(Bot* bot);
#endif
Corpse *GetCorpseByOwner(Client* client);
Corpse *GetCorpseByOwnerWithinRange(Client* client, Mob* center, int range);
+4
View File
@@ -1097,7 +1097,11 @@ void Raid::SplitExp(uint32 exp, Mob* other) {
return;
for (unsigned int x = 0; x < MAX_RAID_MEMBERS; x++) {
#ifdef BOTS
if (members[x].member != nullptr && !members[x].IsBot) // If Group Member is Client
#else
if (members[x].member != nullptr) // If Group Member is Client
#endif
{
Client *cmember = members[x].member;
// add exp + exp cap
+57 -3
View File
@@ -248,10 +248,24 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
uint32 i = 0;
for (i = 0; i < MAX_GROUP_MEMBERS; ++i)
{
if(!strcasecmp(membername[i], NewMemberName))
#ifdef BOTSS
if (newmember->IsBot() && !newmember->HasGroup() && !strcasecmp(membername[i], NewMemberName)) // Mitch
{
//Bot::RemoveBotFromGroup(newmember->CastToBot(), members[0]->GetGroup());
//Group::DelMember(newmember);
memset(membername[i], 0, 64);
members[i] = nullptr;
}
else if (!strcasecmp(membername[i], NewMemberName))
{
return false;
}
#else
if (!strcasecmp(membername[i], NewMemberName))
{
return false;
}
#endif
}
// Put them in the group
@@ -1140,7 +1154,13 @@ void Group::TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float
}
bool Group::LearnMembers() {
std::string query = StringFormat("SELECT name FROM group_id WHERE groupid = %lu", (unsigned long)GetID());
//std::string query = StringFormat("SELECT name FROM group_id WHERE groupid = %lu", (unsigned long)GetID());
std::string query = StringFormat("SELECT name FROM group_id "
"WHERE group_id.groupid = %lu AND group_id.name NOT "
"IN(SELECT group_leaders.leadername FROM group_leaders WHERE gid = %lu)"
, (unsigned long)GetID()
, (unsigned long)GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
return false;
@@ -1155,7 +1175,7 @@ bool Group::LearnMembers() {
return false;
}
int memberIndex = 0;
int memberIndex = 1; //starts at 1 becasuse leader [0] is done specifically
for(auto row = results.begin(); row != results.end(); ++row) {
if(!row[0])
continue;
@@ -1165,7 +1185,24 @@ bool Group::LearnMembers() {
memberIndex++;
}
// for leader only [0] /Mitch
query = StringFormat("SELECT leadername FROM group_leaders WHERE group_leaders.gid = %lu", (unsigned long)GetID());
auto results2 = database.QueryDatabase(query);
if (!results2.Success())
return false;
if (results2.RowCount() == 0) {
LogError(
"Error getting group leader for group [{}]: [{}]",
(unsigned long)GetID(),
results2.ErrorMessage().c_str()
);
return false;
}
auto row2 = results2.begin();
members[0] = nullptr;
strn0cpy(membername[0], row2[0], 64);
return true;
}
@@ -1176,6 +1213,22 @@ void Group::VerifyGroup() {
Only called every once in a while (on member re-join for now).
*/
// To do
// Reset the membername array to match the group_id database records?
// When doing this manually, it seem to have resolved the issue.
// Only want to do this when the database Name does not match the array
// Could this be done from the LearnGroup method?
// reset the members and membername array for this group
// Mitch
for (int i = 0; i < MAX_GROUP_MEMBERS; i++) {
members[i] = nullptr;
memset(membername[i],'\0',64);
//membername[i][0] == '\0');
}
// repopulate the membername array from the database to ensure the local zone instance has accurate information
Group::LearnMembers();
uint32 i;
for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
if (membername[i][0] == '\0') {
@@ -1196,6 +1249,7 @@ void Group::VerifyGroup() {
continue;
}
if(them != nullptr && members[i] != them) { //our pointer is out of date... not so good.
#if EQDEBUG >= 5
LogDebug("Member of group [{}] named [{}] had an out of date pointer!!", (unsigned long)GetID(), membername[i]);
+2 -1
View File
@@ -88,6 +88,7 @@ volatile bool RunLoops = true;
#endif
extern volatile bool is_zone_loaded;
extern bool Critical = false;
EntityList entity_list;
WorldServer worldserver;
@@ -578,7 +579,7 @@ int main(int argc, char** argv) {
EQ::Timer process_timer(loop_fn);
process_timer.Start(32, true);
EQ::EventLoop::Get().Run();
entity_list.Clear();
+1 -1
View File
@@ -3987,7 +3987,7 @@ void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::O
const char *Mob::GetCleanName()
{
if (!strlen(clean_name)) {
if (!strlen(clean_name)) {
CleanMobName(GetName(), clean_name);
}
+199 -17
View File
@@ -24,6 +24,7 @@
#include "groups.h"
#include "mob.h"
#include "raids.h"
#include "bot.h"
#include "worldserver.h"
@@ -95,13 +96,22 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo
if(!c)
return;
#ifdef BOTS
std::string query = StringFormat("INSERT INTO raid_members SET raidid = %lu, charid = %lu, "
"groupid = %lu, _class = %d, level = %d, name = '%s', "
"isgroupleader = %d, israidleader = %d, islooter = %d",
"isgroupleader = %d, israidleader = %d, islooter = %d, isbot = 0",
(unsigned long)GetID(), (unsigned long)c->CharacterID(),
(unsigned long)group, c->GetClass(), c->GetLevel(),
c->GetName(), groupleader, rleader, looter);
auto results = database.QueryDatabase(query);
#else
std::string query = StringFormat("INSERT INTO raid_members SET raidid = %lu, charid = %lu, "
"groupid = %lu, _class = %d, level = %d, name = '%s', "
"isgroupleader = %d, israidleader = %d, islooter = %d",
(unsigned long)GetID(), (unsigned long)c->CharacterID(),
(unsigned long)group, c->GetClass(), c->GetLevel(),
c->GetName(), groupleader, rleader, looter);
#endif
auto results = database.QueryDatabase(query);
if(!results.Success()) {
LogError("Error inserting into raid members: [{}]", results.ErrorMessage().c_str());
@@ -109,6 +119,14 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo
LearnMembers();
VerifyRaid();
#ifdef BOTS
if (rleader) {
database.SetRaidGroupLeaderInfo(group, GetID());
UpdateRaidAAs();
}
else
#endif
if (rleader) {
database.SetRaidGroupLeaderInfo(RAID_GROUPLESS, GetID());
UpdateRaidAAs();
@@ -163,12 +181,65 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo
safe_delete(pack);
}
#ifdef BOTS
void Raid::AddBot(Bot* b, uint32 group, bool rleader, bool groupleader, bool looter) {
if (!b)
return;
std::string query = StringFormat("INSERT INTO raid_members SET raidid = %lu, charid = %lu, "
"groupid = %lu, _class = %d, level = %d, name = '%s', "
"isgroupleader = %d, israidleader = %d, islooter = %d, isbot = 1",
(unsigned long)GetID(), (unsigned long)b->GetBotID(),
(unsigned long)group, b->GetClass(), b->GetLevel(),
b->GetName(), groupleader, rleader, looter);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogError("Error inserting into raid members: [{}]", results.ErrorMessage().c_str());
}
LearnMembers();
VerifyRaid();
if (group < 12) //Jan22
GroupUpdate(group); //Jan22
else // get raid AAs, GroupUpdate will handles it otherwise Jan 22
SendGroupLeadershipAA(b->GetOwner()->CastToClient(), RAID_GROUPLESS); //Is this needed for bots? Jan 22
SendRaidAddAll(b->GetName());
b->SetRaidGrouped(true);
b->p_raid_instance = this;
auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct));
ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer;
rga->rid = GetID();
strn0cpy(rga->playername, b->GetName(), 64);
rga->zoneid = zone->GetZoneID();
rga->instance_id = zone->GetInstanceID();
worldserver.SendPacket(pack);
safe_delete(pack);
}
#endif
void Raid::RemoveMember(const char *characterName)
{
std::string query = StringFormat("DELETE FROM raid_members where name='%s'", characterName);
auto results = database.QueryDatabase(query);
Client *client = entity_list.GetClientByName(characterName);
#ifdef BOTS
Bot* bot = entity_list.GetBotByBotName(characterName);
if (bot) {
bot->SetFollowID(bot->GetOwner()->CastToClient()->GetID());
bot->SetGrouped(false);
bot->SetTarget(nullptr);
bot->SetRaidGrouped(false);
}
#endif
disbandCheck = true;
SendRaidRemoveAll(characterName);
SendRaidDisband(client);
@@ -983,12 +1054,12 @@ void Raid::SendRaidAdd(const char *who, Client *to)
void Raid::SendRaidAddAll(const char *who)
{
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
for (int x = 0; x < MAX_RAID_MEMBERS; x++)
{
if(strcmp(members[x].membername, who) == 0)
if (strcmp(members[x].membername, who) == 0 )
{
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidAddMember_Struct));
RaidAddMember_Struct *ram = (RaidAddMember_Struct*)outapp->pBuffer;
RaidAddMember_Struct* ram = (RaidAddMember_Struct*)outapp->pBuffer;
ram->raidGen.action = raidAdd;
ram->raidGen.parameter = members[x].GroupNumber;
strcpy(ram->raidGen.leader_name, members[x].membername);
@@ -999,6 +1070,7 @@ void Raid::SendRaidAddAll(const char *who)
QueuePacket(outapp);
safe_delete(outapp);
return;
}
}
}
@@ -1111,11 +1183,16 @@ void Raid::SendBulkRaid(Client *to)
if(!to)
return;
#ifdef BOTS
if (members[GetPlayerIndex(to)].IsBot)
return;
#endif
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
{
if(strlen(members[x].membername) > 0 && (strcmp(members[x].membername, to->GetName()) != 0)) //don't send ourself
if(members[x].member && strlen(members[x].membername) > 0 && (strcmp(members[x].membername, to->GetName()) != 0)) //don't send ourself
{
SendRaidAdd(members[x].membername, to);
SendRaidAdd(members[x].membername, to);
}
}
}
@@ -1124,7 +1201,11 @@ void Raid::QueuePacket(const EQApplicationPacket *app, bool ack_req)
{
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
{
#ifdef BOTS
if(members[x].member && !members[x].IsBot)
#else
if(members[x].member)
#endif
{
members[x].member->QueuePacket(app, ack_req);
}
@@ -1133,6 +1214,12 @@ void Raid::QueuePacket(const EQApplicationPacket *app, bool ack_req)
void Raid::SendMakeLeaderPacket(const char *who) //30
{
#ifdef BOTS
if (entity_list.GetBotByBotName(who) && members[GetPlayerIndex(who)].IsBot)
return;
#endif
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct));
RaidLeadershipUpdate_Struct *rg = (RaidLeadershipUpdate_Struct*)outapp->pBuffer;
rg->action = raidMakeLeader;
@@ -1148,6 +1235,11 @@ void Raid::SendMakeLeaderPacketTo(const char *who, Client *to)
if(!to)
return;
#ifdef BOTS
if (members[GetPlayerIndex(who)].IsBot)
return;
#endif
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct));
RaidLeadershipUpdate_Struct *rg = (RaidLeadershipUpdate_Struct*)outapp->pBuffer;
rg->action = raidMakeLeader;
@@ -1178,6 +1270,11 @@ void Raid::SendGroupUpdate(Client *to)
if(!to)
return;
#ifdef BOTS
if (members[GetPlayerIndex(to)].IsBot)
return;
#endif
auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate2_Struct));
GroupUpdate2_Struct* gu = (GroupUpdate2_Struct*)outapp->pBuffer;
gu->action = groupActUpdate;
@@ -1224,7 +1321,7 @@ void Raid::GroupUpdate(uint32 gid, bool initial)
{
if(strlen(members[x].membername) > 0){
if(members[x].GroupNumber == gid){
if(members[x].member) {
if (members[x].member) {
SendGroupUpdate(members[x].member);
SendGroupLeadershipAA(members[x].member, gid);
}
@@ -1366,6 +1463,11 @@ void Raid::SendRaidMOTDToWorld()
void Raid::SendGroupLeadershipAA(Client *c, uint32 gid)
{
#ifdef BOTS
if (members[GetPlayerIndex(c)].IsBot)
return;
#endif
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct));
RaidLeadershipUpdate_Struct *rlaa = (RaidLeadershipUpdate_Struct *)outapp->pBuffer;
rlaa->action = raidSetLeaderAbilities;
@@ -1381,17 +1483,26 @@ void Raid::SendGroupLeadershipAA(Client *c, uint32 gid)
void Raid::SendGroupLeadershipAA(uint32 gid)
{
for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++)
#ifdef BOTS
if (members[i].member && members[i].GroupNumber == gid && !members[i].IsBot)
#else
if (members[i].member && members[i].GroupNumber == gid)
#endif
SendGroupLeadershipAA(members[i].member, gid);
}
void Raid::SendAllRaidLeadershipAA()
{
for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++)
#ifdef BOTS
if (members[i].member && !members[i].IsBot)
#else
if (members[i].member)
SendGroupLeadershipAA(members[i].member, members[i].GroupNumber);
#endif
SendGroupLeadershipAA(members[i].member, members[i].GroupNumber);
}
void Raid::LockRaid(bool lockFlag)
{
std::string query = StringFormat("UPDATE raid_details SET locked = %d WHERE raidid = %lu",
@@ -1457,11 +1568,18 @@ bool Raid::LearnMembers()
{
memset(members, 0, (sizeof(RaidMember)*MAX_RAID_MEMBERS));
#ifdef BOTS
std::string query = StringFormat("SELECT name, groupid, _class, level, "
"isgroupleader, israidleader, islooter "
"isgroupleader, israidleader, islooter, isbot "
"FROM raid_members WHERE raidid = %lu",
(unsigned long)GetID());
auto results = database.QueryDatabase(query);
#else
std::string query = StringFormat("SELECT name, groupid, _class, level, "
"isgroupleader, israidleader, islooter "
"FROM raid_members WHERE raidid = %lu",
(unsigned long)GetID());
#endif
auto results = database.QueryDatabase(query);
if (!results.Success())
return false;
@@ -1489,7 +1607,10 @@ bool Raid::LearnMembers()
members[index].IsGroupLeader = atoi(row[4]);
members[index].IsRaidLeader = atoi(row[5]);
members[index].IsLooter = atoi(row[6]);
++index;
#ifdef BOTS
members[index].IsBot = atoi(row[7]);
#endif
++index;
}
return true;
@@ -1504,14 +1625,32 @@ void Raid::VerifyRaid()
}
else{
Client *c = entity_list.GetClientByName(members[x].membername);
#ifdef BOTS
Bot* b = entity_list.GetBotByBotName(members[x].membername);
#endif
if(c){
members[x].member = c;
#ifdef BOTS
members[x].IsBot = false;
#endif
}
else{
#ifdef BOTS
else if(b){
//Raid requires client* we are forcing it here to be a BOT. Care is needed here as any client function that
//does not exist within the Bot Class will likely corrupt memory for the member object. Good practice to test the IsBot
//attribute before calling a client function or casting to client.
members[x].member = b->CastToClient();
members[x].IsBot = true; //Used to identify those members who are Bots
}
#endif
else {
members[x].member = nullptr;
#ifdef BOTS
members[x].IsBot = false;
#endif
}
}
if(members[x].IsRaidLeader){
if(members[x].IsRaidLeader){
if(strlen(members[x].membername) > 0){
SetLeader(members[x].member);
strn0cpy(leadername, members[x].membername, 64);
@@ -1561,7 +1700,11 @@ void Raid::SendHPManaEndPacketsTo(Client *client)
EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct));
for(int x = 0; x < MAX_RAID_MEMBERS; x++) {
if(members[x].member) {
#ifdef BOTS
if(members[x].member && !members[x].IsBot) {
#else
if (members[x].member) {
#endif
if((members[x].member != client) && (members[x].GroupNumber == group_id)) {
members[x].member->CreateHPPacket(&hp_packet);
@@ -1603,7 +1746,11 @@ void Raid::SendHPManaEndPacketsFrom(Mob *mob)
mob->CreateHPPacket(&hpapp);
for(int x = 0; x < MAX_RAID_MEMBERS; x++) {
if(members[x].member) {
#ifdef BOTS
if(members[x].member && !members[x].IsBot) {
#else
if (members[x].member) {
#endif
if(!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) {
members[x].member->QueuePacket(&hpapp, false);
if (members[x].member->ClientVersion() >= EQ::versions::ClientVersion::SoD) {
@@ -1636,7 +1783,11 @@ void Raid::SendManaPacketFrom(Mob *mob)
EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct));
for (int x = 0; x < MAX_RAID_MEMBERS; x++) {
#ifdef BOTS
if (members[x].member && !members[x].IsBot) {
#else
if (members[x].member) {
#endif
if (!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) {
if (members[x].member->ClientVersion() >= EQ::versions::ClientVersion::SoD) {
outapp.SetOpcode(OP_MobManaUpdate);
@@ -1663,7 +1814,11 @@ void Raid::SendEndurancePacketFrom(Mob *mob)
EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct));
for (int x = 0; x < MAX_RAID_MEMBERS; x++) {
#ifdef BTOS
if (members[x].member && !members[x].IsBot) {
#else
if (members[x].member) {
#endif
if (!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) {
if (members[x].member->ClientVersion() >= EQ::versions::ClientVersion::SoD) {
outapp.SetOpcode(OP_MobEnduranceUpdate);
@@ -1770,9 +1925,18 @@ void Raid::CheckGroupMentor(uint32 group_id, Client *c)
void Raid::SetDirtyAutoHaters()
{
for (int i = 0; i < MAX_RAID_MEMBERS; ++i)
#ifdef BOTS
if (members[i].member && members[i].IsBot)
{
members[i].member->CastToBot()->SetDirtyAutoHaters();
}
else if (members[i].member && !members[i].IsBot)
#else
if (members[i].member)
#endif
{
members[i].member->SetDirtyAutoHaters();
}
}
void Raid::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required /*= true*/, bool ignore_sender /*= true*/, float distance /*= 0*/, bool group_only /*= true*/) {
@@ -1791,6 +1955,10 @@ void Raid::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_re
if (!members[i].member->IsClient())
continue;
#ifdef BOTS
if (members[i].IsBot)
continue;
#endif
if (ignore_sender && members[i].member == sender)
continue;
@@ -1853,3 +2021,17 @@ bool Raid::DoesAnyMemberHaveExpeditionLockout(
return Expedition::HasLockoutByCharacterName(raid_member.membername, expedition_name, event_name);
});
}
#ifdef BOTS
Mob* Raid::GetRaidMainAssistOneByName(const char* name)
{
Raid* raid = entity_list.GetRaidByBotName(name);
std::vector<RaidMember> raid_members = raid->GetMembers();
for (RaidMember iter : raid_members)
{
if (iter.IsRaidMainAssistOne)
return iter.member->CastToMob();
}
return nullptr;
}
#endif
+11
View File
@@ -88,6 +88,10 @@ struct RaidMember{
bool IsGroupLeader;
bool IsRaidLeader;
bool IsLooter;
#ifdef BOTS
bool IsBot = false;
bool IsRaidMainAssistOne = false;
#endif
};
struct GroupMentor {
@@ -112,6 +116,11 @@ public:
bool IsRaid() { return true; }
void AddMember(Client *c, uint32 group = 0xFFFFFFFF, bool rleader=false, bool groupleader=false, bool looter=false);
#ifdef BOTS
void AddBot(Bot* b, uint32 group = 0xFFFFFFFF, bool rleader=false, bool groupleader=false, bool looter=false);
void RaidBotGroupSay(Bot* b, uint8 language, uint8 lang_skill, const char* msg, ...); //Not yet implemented
Mob* GetRaidMainAssistOneByName(const char* name);
#endif
void RemoveMember(const char *c);
void DisbandRaid();
void MoveMember(const char *name, uint32 newGroup);
@@ -121,6 +130,7 @@ public:
bool IsGroupLeader(const char *who);
bool IsRaidMember(const char *name);
void UpdateLevel(const char *name, int newLevel);
uint32 GetFreeGroup();
uint8 GroupCount(uint32 gid);
@@ -241,6 +251,7 @@ public:
bool DoesAnyMemberHaveExpeditionLockout(const std::string& expedition_name, const std::string& event_name, int max_check_count = 0);
std::vector<RaidMember> GetMembers() const;
std::vector<RaidMember> GetRaidGroupMembers(uint32 gid);
RaidMember members[MAX_RAID_MEMBERS];
char leadername[64];
+1 -1
View File
@@ -154,7 +154,7 @@ bool Spawn2::Process() {
return true;
}
if (timer.Check()) {
if (timer.Check() && zone->spawn2_timer.Enabled()) {
timer.Disable();
LogSpawns("Spawn2 [{}]: Timer has triggered", spawn2_id);
+1
View File
@@ -1742,6 +1742,7 @@ bool Zone::Depop(bool StartSpawnTimer) {
itr = npctable.begin();
delete itr->second;
itr->second = nullptr;
npctable.erase(itr);
}