mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 01:11: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;
|
||||
|
||||
// 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
|
||||
if (HasRaid() && !GetRaid()->IsRaidMember(GetBotOwner()->CastToClient())) {
|
||||
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;
|
||||
|
||||
} else if (bot_group) {
|
||||
bot_group->VerifyGroup();
|
||||
leash_owner = (bot_group->GetLeader() && bot_group->GetLeader()->IsClient() ? bot_group->GetLeader()->CastToClient() : bot_owner);
|
||||
|
||||
} 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();
|
||||
SetRaidGrouped(true);
|
||||
}
|
||||
else if (group = entity_list.GetGroupByMobName(GetName())) {
|
||||
group->VerifyGroup();
|
||||
SetGrouped(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3863,21 +3864,18 @@ bool Bot::RemoveBotFromGroup(Bot* bot, Group* group) {
|
||||
|
||||
bool Bot::AddBotToGroup(Bot* bot, Group* group) {
|
||||
bool Result = false;
|
||||
if (bot && group) {
|
||||
// Add bot to this group
|
||||
if (group->AddMember(bot)) {
|
||||
if (group->GetLeader()) {
|
||||
bot->SetFollowID(group->GetLeader()->GetID());
|
||||
// Need to send this only once when a group is formed with a bot so the client knows it is also the group leader
|
||||
if (group->GroupCount() == 2 && group->GetLeader()->IsClient()) {
|
||||
group->UpdateGroupAAs();
|
||||
Mob *TempLeader = group->GetLeader();
|
||||
group->SendUpdate(groupActUpdate, TempLeader);
|
||||
}
|
||||
if (bot && group && group->AddMember(bot)) {
|
||||
if (group->GetLeader()) {
|
||||
bot->SetFollowID(group->GetLeader()->GetID());
|
||||
// Need to send this only once when a group is formed with a bot so the client knows it is also the group leader
|
||||
if (group->GroupCount() == 2 && group->GetLeader()->IsClient()) {
|
||||
group->UpdateGroupAAs();
|
||||
Mob *TempLeader = group->GetLeader();
|
||||
group->SendUpdate(groupActUpdate, TempLeader);
|
||||
}
|
||||
group->VerifyGroup();
|
||||
Result = true;
|
||||
}
|
||||
group->VerifyGroup();
|
||||
Result = true;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
@ -6680,7 +6678,11 @@ void Bot::Camp(bool save_to_database) {
|
||||
Save();
|
||||
}
|
||||
|
||||
Depop();
|
||||
if (HasGroup() || HasRaid()) {
|
||||
Zone();
|
||||
} else {
|
||||
Depop();
|
||||
}
|
||||
}
|
||||
|
||||
void Bot::Zone() {
|
||||
@ -8582,24 +8584,34 @@ void Bot::SpawnBotGroupByName(Client* c, const std::string& botgroup_name, uint3
|
||||
return;
|
||||
}
|
||||
|
||||
if (!leader->Spawn(c)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Could not spawn bot-group leader {} for '{}'.",
|
||||
leader->GetName(),
|
||||
botgroup_name
|
||||
).c_str()
|
||||
);
|
||||
safe_delete(leader);
|
||||
return;
|
||||
if (!leader->spawned) {
|
||||
if (!leader->Spawn(c)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Could not spawn bot-group leader {} for '{}'.",
|
||||
leader->GetName(),
|
||||
botgroup_name
|
||||
).c_str()
|
||||
);
|
||||
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());
|
||||
|
||||
uint32 botgroup_id = 0;
|
||||
@ -8686,23 +8698,33 @@ void Bot::SpawnBotGroupByName(Client* c, const std::string& botgroup_name, uint3
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!member->Spawn(c)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Could not spawn bot '{}' (ID {}).",
|
||||
member->GetName(),
|
||||
member_iter
|
||||
).c_str()
|
||||
);
|
||||
safe_delete(member);
|
||||
return;
|
||||
if (!member->spawned) {
|
||||
if (!member->Spawn(c)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Could not spawn bot '{}' (ID {}).",
|
||||
member->GetName(),
|
||||
member_iter
|
||||
).c_str()
|
||||
);
|
||||
safe_delete(member);
|
||||
return;
|
||||
}
|
||||
|
||||
spawned_bot_count++;
|
||||
bot_class_spawned_count[member->GetClass() - 1]++;
|
||||
|
||||
if (group) {
|
||||
Bot::AddBotToGroup(member, group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spawned_bot_count++;
|
||||
bot_class_spawned_count[member->GetClass() - 1]++;
|
||||
|
||||
Bot::AddBotToGroup(member, g);
|
||||
if (group) {
|
||||
group->VerifyGroup();
|
||||
} else if (raid) {
|
||||
raid->VerifyRaid();
|
||||
}
|
||||
|
||||
c->Message(
|
||||
|
||||
@ -141,6 +141,7 @@ public:
|
||||
bool HasGroup() final { return GetGroup() != nullptr; }
|
||||
Raid* GetRaid() final { return entity_list.GetRaidByBot(this); }
|
||||
Group* GetGroup() final { return entity_list.GetGroupByMob(this); }
|
||||
Group* GetGroupByLeaderName() { return entity_list.GetGroupByLeaderName(GetName()); }
|
||||
|
||||
// Common, but informal "interfaces" with Client object
|
||||
uint32 CharacterID() const { return GetBotID(); }
|
||||
|
||||
@ -2119,6 +2119,18 @@ Group *EntityList::GetGroupByMob(Mob *mob)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
Mob* GetRandomMob(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Mob* exclude_mob = nullptr);
|
||||
Group* GetGroupByMob(Mob* mob);
|
||||
Group* GetGroupByMobName(const char* name);
|
||||
Group* GetGroupByBot(Bot* bot);
|
||||
bool IsInSameGroupOrRaidGroup(Client *client1, Client *client2);
|
||||
Group *GetGroupByClient(Client* client);
|
||||
|
||||
@ -547,11 +547,13 @@ bool Group::UpdatePlayer(Mob* update) {
|
||||
void Group::MemberZoned(Mob* removemob) {
|
||||
uint32 i;
|
||||
|
||||
if (removemob == nullptr)
|
||||
if (!removemob) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(removemob == GetLeader())
|
||||
if (removemob == GetLeader()) {
|
||||
SetLeader(nullptr);
|
||||
}
|
||||
|
||||
//should NOT clear the name, it is used for world communication.
|
||||
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);
|
||||
}
|
||||
|
||||
if(removemob->IsClient() && HasRole(removemob, RoleTank))
|
||||
if (removemob->IsClient() && HasRole(removemob, RoleTank)) {
|
||||
SetGroupTankTarget(0);
|
||||
}
|
||||
|
||||
if(removemob->IsClient() && HasRole(removemob, RolePuller))
|
||||
if (removemob->IsClient() && HasRole(removemob, RolePuller)) {
|
||||
SetGroupPullerTarget(0);
|
||||
}
|
||||
|
||||
if (removemob->IsClient() && removemob == mentoree)
|
||||
if (removemob->IsClient() && removemob == mentoree) {
|
||||
mentoree = nullptr;
|
||||
}
|
||||
|
||||
if (RuleB(Bots, Enabled)) {
|
||||
Bot::UpdateGroupCastingRoles(this);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user