mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 05:21:29 +00:00
[Crash] Fix dangling Group member pointers for Bots. (#3134)
* [Crash] Fix dangling Group member pointers for Bots. * fixes for edge cases
This commit is contained in:
parent
4fe44f4cb6
commit
fe2dcb6544
126
zone/bot.cpp
126
zone/bot.cpp
@ -425,11 +425,6 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
|||||||
|
|
||||||
cur_end = max_end;
|
cur_end = max_end;
|
||||||
|
|
||||||
// Safety Check to confirm we have a valid group
|
|
||||||
if (HasGroup() && !GetGroup()->IsGroupMember(GetBotOwner())) {
|
|
||||||
Bot::RemoveBotFromGroup(this, GetGroup());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Safety Check to confirm we have a valid raid
|
// Safety Check to confirm we have a valid raid
|
||||||
if (HasRaid() && !GetRaid()->IsRaidMember(GetBotOwner()->CastToClient())) {
|
if (HasRaid() && !GetRaid()->IsRaidMember(GetBotOwner()->CastToClient())) {
|
||||||
Bot::RemoveBotFromRaid(this);
|
Bot::RemoveBotFromRaid(this);
|
||||||
@ -3111,7 +3106,6 @@ Client* Bot::SetLeashOwner(Client* bot_owner, Group* bot_group, Raid* raid, uint
|
|||||||
raid->GetGroupLeader(r_group)->CastToClient() : bot_owner;
|
raid->GetGroupLeader(r_group)->CastToClient() : bot_owner;
|
||||||
|
|
||||||
} else if (bot_group) {
|
} else if (bot_group) {
|
||||||
bot_group->VerifyGroup();
|
|
||||||
leash_owner = (bot_group->GetLeader() && bot_group->GetLeader()->IsClient() ? bot_group->GetLeader()->CastToClient() : bot_owner);
|
leash_owner = (bot_group->GetLeader() && bot_group->GetLeader()->IsClient() ? bot_group->GetLeader()->CastToClient() : bot_owner);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -3321,11 +3315,18 @@ bool Bot::Spawn(Client* botCharacterOwner) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Raid* raid = entity_list.GetRaidByBotName(GetName()))
|
Raid* raid = nullptr;
|
||||||
{
|
Group* group = nullptr;
|
||||||
|
|
||||||
|
if (raid = entity_list.GetRaidByBotName(GetName())) {
|
||||||
raid->VerifyRaid();
|
raid->VerifyRaid();
|
||||||
SetRaidGrouped(true);
|
SetRaidGrouped(true);
|
||||||
}
|
}
|
||||||
|
else if (group = entity_list.GetGroupByMobName(GetName())) {
|
||||||
|
group->VerifyGroup();
|
||||||
|
SetGrouped(true);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3863,21 +3864,18 @@ bool Bot::RemoveBotFromGroup(Bot* bot, Group* group) {
|
|||||||
|
|
||||||
bool Bot::AddBotToGroup(Bot* bot, Group* group) {
|
bool Bot::AddBotToGroup(Bot* bot, Group* group) {
|
||||||
bool Result = false;
|
bool Result = false;
|
||||||
if (bot && group) {
|
if (bot && group && group->AddMember(bot)) {
|
||||||
// Add bot to this group
|
if (group->GetLeader()) {
|
||||||
if (group->AddMember(bot)) {
|
bot->SetFollowID(group->GetLeader()->GetID());
|
||||||
if (group->GetLeader()) {
|
// Need to send this only once when a group is formed with a bot so the client knows it is also the group leader
|
||||||
bot->SetFollowID(group->GetLeader()->GetID());
|
if (group->GroupCount() == 2 && group->GetLeader()->IsClient()) {
|
||||||
// Need to send this only once when a group is formed with a bot so the client knows it is also the group leader
|
group->UpdateGroupAAs();
|
||||||
if (group->GroupCount() == 2 && group->GetLeader()->IsClient()) {
|
Mob *TempLeader = group->GetLeader();
|
||||||
group->UpdateGroupAAs();
|
group->SendUpdate(groupActUpdate, TempLeader);
|
||||||
Mob *TempLeader = group->GetLeader();
|
|
||||||
group->SendUpdate(groupActUpdate, TempLeader);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
group->VerifyGroup();
|
|
||||||
Result = true;
|
|
||||||
}
|
}
|
||||||
|
group->VerifyGroup();
|
||||||
|
Result = true;
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -6680,7 +6678,11 @@ void Bot::Camp(bool save_to_database) {
|
|||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
Depop();
|
if (HasGroup() || HasRaid()) {
|
||||||
|
Zone();
|
||||||
|
} else {
|
||||||
|
Depop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::Zone() {
|
void Bot::Zone() {
|
||||||
@ -8582,24 +8584,34 @@ void Bot::SpawnBotGroupByName(Client* c, const std::string& botgroup_name, uint3
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!leader->Spawn(c)) {
|
if (!leader->spawned) {
|
||||||
c->Message(
|
if (!leader->Spawn(c)) {
|
||||||
Chat::White,
|
c->Message(
|
||||||
fmt::format(
|
Chat::White,
|
||||||
"Could not spawn bot-group leader {} for '{}'.",
|
fmt::format(
|
||||||
leader->GetName(),
|
"Could not spawn bot-group leader {} for '{}'.",
|
||||||
botgroup_name
|
leader->GetName(),
|
||||||
).c_str()
|
botgroup_name
|
||||||
);
|
).c_str()
|
||||||
safe_delete(leader);
|
);
|
||||||
return;
|
safe_delete(leader);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* g = new Group(leader);
|
auto group = leader->GetGroupByLeaderName();
|
||||||
|
auto raid = leader->GetRaid();
|
||||||
|
|
||||||
|
if (!raid && group) {
|
||||||
|
group->SetLeader(leader);
|
||||||
|
}
|
||||||
|
else if (!raid) {
|
||||||
|
group = new Group(leader);
|
||||||
|
entity_list.AddGroup(group);
|
||||||
|
database.SetGroupID(leader->GetCleanName(), group->GetID(), leader->GetBotID());
|
||||||
|
database.SetGroupLeaderName(group->GetID(), leader->GetCleanName());
|
||||||
|
}
|
||||||
|
|
||||||
entity_list.AddGroup(g);
|
|
||||||
database.SetGroupID(leader->GetCleanName(), g->GetID(), leader->GetBotID());
|
|
||||||
database.SetGroupLeaderName(g->GetID(), leader->GetCleanName());
|
|
||||||
leader->SetFollowID(c->GetID());
|
leader->SetFollowID(c->GetID());
|
||||||
|
|
||||||
uint32 botgroup_id = 0;
|
uint32 botgroup_id = 0;
|
||||||
@ -8686,23 +8698,33 @@ void Bot::SpawnBotGroupByName(Client* c, const std::string& botgroup_name, uint3
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!member->Spawn(c)) {
|
if (!member->spawned) {
|
||||||
c->Message(
|
if (!member->Spawn(c)) {
|
||||||
Chat::White,
|
c->Message(
|
||||||
fmt::format(
|
Chat::White,
|
||||||
"Could not spawn bot '{}' (ID {}).",
|
fmt::format(
|
||||||
member->GetName(),
|
"Could not spawn bot '{}' (ID {}).",
|
||||||
member_iter
|
member->GetName(),
|
||||||
).c_str()
|
member_iter
|
||||||
);
|
).c_str()
|
||||||
safe_delete(member);
|
);
|
||||||
return;
|
safe_delete(member);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spawned_bot_count++;
|
||||||
|
bot_class_spawned_count[member->GetClass() - 1]++;
|
||||||
|
|
||||||
|
if (group) {
|
||||||
|
Bot::AddBotToGroup(member, group);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spawned_bot_count++;
|
if (group) {
|
||||||
bot_class_spawned_count[member->GetClass() - 1]++;
|
group->VerifyGroup();
|
||||||
|
} else if (raid) {
|
||||||
Bot::AddBotToGroup(member, g);
|
raid->VerifyRaid();
|
||||||
}
|
}
|
||||||
|
|
||||||
c->Message(
|
c->Message(
|
||||||
|
|||||||
@ -141,6 +141,7 @@ public:
|
|||||||
bool HasGroup() final { return GetGroup() != nullptr; }
|
bool HasGroup() final { return GetGroup() != nullptr; }
|
||||||
Raid* GetRaid() final { return entity_list.GetRaidByBot(this); }
|
Raid* GetRaid() final { return entity_list.GetRaidByBot(this); }
|
||||||
Group* GetGroup() final { return entity_list.GetGroupByMob(this); }
|
Group* GetGroup() final { return entity_list.GetGroupByMob(this); }
|
||||||
|
Group* GetGroupByLeaderName() { return entity_list.GetGroupByLeaderName(GetName()); }
|
||||||
|
|
||||||
// Common, but informal "interfaces" with Client object
|
// Common, but informal "interfaces" with Client object
|
||||||
uint32 CharacterID() const { return GetBotID(); }
|
uint32 CharacterID() const { return GetBotID(); }
|
||||||
|
|||||||
@ -2119,6 +2119,18 @@ Group *EntityList::GetGroupByMob(Mob *mob)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Group *EntityList::GetGroupByMobName(const char* name)
|
||||||
|
{
|
||||||
|
for (const auto& g : group_list) {
|
||||||
|
for (const auto& m : g->membername) {
|
||||||
|
if (strcmp(m, name) == 0) {
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Group *EntityList::GetGroupByLeaderName(const char *leader)
|
Group *EntityList::GetGroupByLeaderName(const char *leader)
|
||||||
{
|
{
|
||||||
std::list<Group *>::iterator iterator;
|
std::list<Group *>::iterator iterator;
|
||||||
|
|||||||
@ -193,6 +193,7 @@ public:
|
|||||||
NPC* GetRandomNPC(const glm::vec3& location = glm::vec3(0.f), float distance = 0, NPC* exclude_npc = nullptr);
|
NPC* GetRandomNPC(const glm::vec3& location = glm::vec3(0.f), float distance = 0, NPC* exclude_npc = nullptr);
|
||||||
Mob* GetRandomMob(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Mob* exclude_mob = nullptr);
|
Mob* GetRandomMob(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Mob* exclude_mob = nullptr);
|
||||||
Group* GetGroupByMob(Mob* mob);
|
Group* GetGroupByMob(Mob* mob);
|
||||||
|
Group* GetGroupByMobName(const char* name);
|
||||||
Group* GetGroupByBot(Bot* bot);
|
Group* GetGroupByBot(Bot* bot);
|
||||||
bool IsInSameGroupOrRaidGroup(Client *client1, Client *client2);
|
bool IsInSameGroupOrRaidGroup(Client *client1, Client *client2);
|
||||||
Group *GetGroupByClient(Client* client);
|
Group *GetGroupByClient(Client* client);
|
||||||
|
|||||||
@ -547,11 +547,13 @@ bool Group::UpdatePlayer(Mob* update) {
|
|||||||
void Group::MemberZoned(Mob* removemob) {
|
void Group::MemberZoned(Mob* removemob) {
|
||||||
uint32 i;
|
uint32 i;
|
||||||
|
|
||||||
if (removemob == nullptr)
|
if (!removemob) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(removemob == GetLeader())
|
if (removemob == GetLeader()) {
|
||||||
SetLeader(nullptr);
|
SetLeader(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
//should NOT clear the name, it is used for world communication.
|
//should NOT clear the name, it is used for world communication.
|
||||||
for (auto & m : members) {
|
for (auto & m : members) {
|
||||||
@ -560,17 +562,21 @@ void Group::MemberZoned(Mob* removemob) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(removemob->IsClient() && HasRole(removemob, RoleAssist))
|
if (removemob->IsClient() && HasRole(removemob, RoleAssist)) {
|
||||||
SetGroupAssistTarget(0);
|
SetGroupAssistTarget(0);
|
||||||
|
}
|
||||||
|
|
||||||
if(removemob->IsClient() && HasRole(removemob, RoleTank))
|
if (removemob->IsClient() && HasRole(removemob, RoleTank)) {
|
||||||
SetGroupTankTarget(0);
|
SetGroupTankTarget(0);
|
||||||
|
}
|
||||||
|
|
||||||
if(removemob->IsClient() && HasRole(removemob, RolePuller))
|
if (removemob->IsClient() && HasRole(removemob, RolePuller)) {
|
||||||
SetGroupPullerTarget(0);
|
SetGroupPullerTarget(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (removemob->IsClient() && removemob == mentoree)
|
if (removemob->IsClient() && removemob == mentoree) {
|
||||||
mentoree = nullptr;
|
mentoree = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (RuleB(Bots, Enabled)) {
|
if (RuleB(Bots, Enabled)) {
|
||||||
Bot::UpdateGroupCastingRoles(this);
|
Bot::UpdateGroupCastingRoles(this);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user