diff --git a/zone/bot.cpp b/zone/bot.cpp index 5da47b482..139431a24 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2902,12 +2902,12 @@ void Bot::AcquireBotTarget(Group* bot_group, Raid* raid, Client* leash_owner, fl } } else { // This will keep bots on target for now..but, future updates will allow for rooting/stunning - if (auto escaping = hate_list.GetEscapingEntOnHateList(leash_owner, leash_distance)) { + if (auto escaping = hate_list.GetEscapingMobOnHateList(leash_owner, leash_distance)) { SetTarget(escaping); } if (!GetTarget()) { - auto most_hate = hate_list.GetEntWithMostHateOnList(this, nullptr, true); + auto most_hate = hate_list.GetMobWithMostHateOnList(this, nullptr, true); if (most_hate) { SetTarget(most_hate); } diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index b8f202132..a7ce4dd85 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -344,191 +344,215 @@ int HateList::GetHateRatio(Mob *top, Mob *other) // skip is used to ignore a certain mob on the list // Currently used for getting 2nd on list for aggro meter -Mob *HateList::GetEntWithMostHateOnList(Mob *center, Mob *skip, bool skip_mezzed) +Mob *HateList::GetMobWithMostHateOnList( + Mob *center, + Mob *skip, + bool skip_mezzed, + EntityFilterType filter_type +) { - // hack fix for zone shutdown crashes on some servers - if (!zone->IsLoaded()) + if (!zone->IsLoaded()) { // hack fix for zone shutdown crashes on some servers return nullptr; + } - Mob* top_hate = nullptr; - int64 hate = -1; + Mob *top_hate = nullptr; + int64 hate = -1; - if (center == nullptr) + if (!center) { return nullptr; + } - if (RuleB(Aggro, SmartAggroList)){ - Mob* top_client_type_in_range = nullptr; + if (RuleB(Aggro, SmartAggroList)) { + Mob *top_client_type_in_range = nullptr; int64 hate_client_type_in_range = -1; - int skipped_count = 0; + int skipped_count = 0; auto iterator = list.begin(); - while (iterator != list.end()) - { - struct_HateList *cur = (*iterator); - int16 aggro_mod = 0; + while (iterator != list.end()) { + struct_HateList *cur = (*iterator); + int16 aggro_mod = 0; - if (!cur){ + if (!cur) { ++iterator; continue; } - if (!cur->entity_on_hatelist){ + Mob *m = cur->entity_on_hatelist; + + if (!m) { ++iterator; continue; } - if (cur->entity_on_hatelist == skip) { + if (m == skip) { ++iterator; continue; } - if (skip_mezzed && cur->entity_on_hatelist->IsMezzed()) { + if (skip_mezzed && m->IsMezzed()) { ++iterator; continue; } - if (cur->entity_on_hatelist->Sanctuary()) { - if (hate == -1) - { - top_hate = cur->entity_on_hatelist; - hate = 1; + if ( + (filter_type == EntityFilterType::Bots && !m->IsBot()) || + (filter_type == EntityFilterType::Clients && !m->IsClient()) || + (filter_type == EntityFilterType::NPCs && !m->IsNPC()) + ) { + ++iterator; + continue; + } + + if (m->Sanctuary()) { + if (hate == -1) { + top_hate = m; + hate = 1; } + ++iterator; continue; } - if (cur->entity_on_hatelist->DivineAura() || cur->entity_on_hatelist->IsMezzed() || cur->entity_on_hatelist->IsFeared()){ - if (hate == -1) - { - top_hate = cur->entity_on_hatelist; - hate = 0; + if (m->DivineAura() || m->IsMezzed() || m->IsFeared()) { + if (hate == -1) { + top_hate = m; + hate = 0; } + ++iterator; continue; } int64 current_hate = cur->stored_hate_amount; - if (cur->entity_on_hatelist->IsClient() || cur->entity_on_hatelist->IsBot()){ - if (cur->entity_on_hatelist->IsClient() && cur->entity_on_hatelist->CastToClient()->IsSitting()){ + if (m->IsOfClientBot()) { + if (m->IsClient() && m->CastToClient()->IsSitting()) { aggro_mod += RuleI(Aggro, SittingAggroMod); } - if (center){ - if (center->GetTarget() == cur->entity_on_hatelist) + if (center) { + if (center->GetTarget() == m) { aggro_mod += RuleI(Aggro, CurrentTargetAggroMod); - if (RuleI(Aggro, MeleeRangeAggroMod) != 0) - { - if (center->CombatRange(cur->entity_on_hatelist)){ + } + + if (RuleI(Aggro, MeleeRangeAggroMod) != 0) { + if (center->CombatRange(m)) { aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); - if (current_hate > hate_client_type_in_range || cur->is_entity_frenzy){ + if (current_hate > hate_client_type_in_range || cur->is_entity_frenzy) { hate_client_type_in_range = current_hate; - top_client_type_in_range = cur->entity_on_hatelist; + top_client_type_in_range = m; } } } } - - } - else{ - if (center){ - if (center->GetTarget() == cur->entity_on_hatelist) + } else { + if (center) { + if (center->GetTarget() == m) { aggro_mod += RuleI(Aggro, CurrentTargetAggroMod); - if (RuleI(Aggro, MeleeRangeAggroMod) != 0) - { - if (center->CombatRange(cur->entity_on_hatelist)){ + } + + if (RuleI(Aggro, MeleeRangeAggroMod) != 0) { + if (center->CombatRange(m)) { aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); } } } } - if (cur->entity_on_hatelist->GetMaxHP() != 0 && ((cur->entity_on_hatelist->GetHP() * 100 / cur->entity_on_hatelist->GetMaxHP()) < 20)){ + if (m->GetMaxHP() != 0 && ((m->GetHP() * 100 / m->GetMaxHP()) < 20)) { aggro_mod += RuleI(Aggro, CriticallyWoundedAggroMod); } - if (aggro_mod){ + if (aggro_mod) { current_hate += (current_hate * aggro_mod / 100); } - if (current_hate > hate || cur->is_entity_frenzy){ - hate = current_hate; - top_hate = cur->entity_on_hatelist; + if (current_hate > hate || cur->is_entity_frenzy) { + hate = current_hate; + top_hate = m; } ++iterator; } - if (top_client_type_in_range != nullptr && top_hate != nullptr) { - bool isTopClientType = top_hate->IsClient(); - if (!isTopClientType) { + if (top_client_type_in_range && top_hate) { + bool is_top_client_type = top_hate->IsClient(); + if (!is_top_client_type) { if (top_hate->IsBot()) { - isTopClientType = true; + is_top_client_type = true; top_client_type_in_range = top_hate; } } - if (!isTopClientType) { + if (!is_top_client_type) { if (top_hate->IsMerc()) { - isTopClientType = true; + is_top_client_type = true; top_client_type_in_range = top_hate; } } - if (!isTopClientType) { - if (top_hate->GetSpecialAbility(ALLOW_TO_TANK)){ - isTopClientType = true; + if (!is_top_client_type) { + if (top_hate->GetSpecialAbility(ALLOW_TO_TANK)) { + is_top_client_type = true; top_client_type_in_range = top_hate; } } - if (!isTopClientType) + if (!is_top_client_type) { return top_client_type_in_range ? top_client_type_in_range : nullptr; + } return top_hate ? top_hate : nullptr; - } - else { - if (top_hate == nullptr && skipped_count > 0) { + } else { + if (!top_hate && skipped_count > 0) { return center->GetTarget() ? center->GetTarget() : nullptr; } + return top_hate ? top_hate : nullptr; } - } - else{ - auto iterator = list.begin(); - int skipped_count = 0; - while (iterator != list.end()) - { + } else { + auto iterator = list.begin(); + int skipped_count = 0; + while (iterator != list.end()) { struct_HateList *cur = (*iterator); if (cur) { - if (cur->entity_on_hatelist == skip) { + Mob *m = cur->entity_on_hatelist; + + if (!m) { ++iterator; continue; } - if (skip_mezzed && cur->entity_on_hatelist->IsMezzed()) { + if (m == skip) { ++iterator; continue; } - if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy)) - { - top_hate = cur->entity_on_hatelist; - hate = cur->stored_hate_amount; + if (skip_mezzed && m->IsMezzed()) { + ++iterator; + continue; + } + + if ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy) { + top_hate = m; + hate = cur->stored_hate_amount; } } ++iterator; } - if (top_hate == nullptr && skipped_count > 0) { + + if (!top_hate && skipped_count > 0) { return center->GetTarget() ? center->GetTarget() : nullptr; } + return top_hate ? top_hate : nullptr; } + return nullptr; } -Mob *HateList::GetEntWithMostHateOnList(bool skip_mezzed){ +Mob *HateList::GetMobWithMostHateOnList(bool skip_mezzed){ Mob* top = nullptr; int64 hate = -1; @@ -539,7 +563,7 @@ Mob *HateList::GetEntWithMostHateOnList(bool skip_mezzed){ if (cur) { LogHateDetail( - "Looping GetEntWithMostHateOnList1 [{}] cur [{}] hate [{}] calc [{}]", + "Looping GetMobWithMostHateOnList1 [{}] cur [{}] hate [{}] calc [{}]", cur->entity_on_hatelist->GetMobDescription(), cur->stored_hate_amount, hate, @@ -549,7 +573,7 @@ Mob *HateList::GetEntWithMostHateOnList(bool skip_mezzed){ if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate)) { LogHateDetail( - "Looping GetEntWithMostHateOnList2 [{}]", + "Looping GetMobWithMostHateOnList2 [{}]", cur->entity_on_hatelist->GetMobDescription() ); @@ -565,7 +589,7 @@ Mob *HateList::GetEntWithMostHateOnList(bool skip_mezzed){ } -Mob *HateList::GetRandomEntOnHateList(bool skip_mezzed) +Mob *HateList::GetRandomMobOnHateList(bool skip_mezzed) { int count = list.size(); if (count <= 0) //If we don't have any entries it'll crash getting a random 0, -1 position. @@ -611,7 +635,7 @@ Mob *HateList::GetRandomEntOnHateList(bool skip_mezzed) return nullptr; } -Mob *HateList::GetEscapingEntOnHateList(Mob *center, float range, bool first) { +Mob *HateList::GetEscapingMobOnHateList(Mob *center, float range, bool first) { // function is still in design stage if (!center) diff --git a/zone/hate_list.h b/zone/hate_list.h index 531671168..199c8307b 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -43,10 +43,10 @@ public: Mob *GetClosestEntOnHateList(Mob *hater, bool skip_mezzed = false, EntityFilterType entity_type = EntityFilterType::All); Mob *GetDamageTopOnHateList(Mob *hater); // didn't add 'skip_mezzed' due to calls being in ::Death() - Mob *GetEntWithMostHateOnList(Mob *center, Mob *skip = nullptr, bool skip_mezzed = false); - Mob *GetRandomEntOnHateList(bool skip_mezzed = false); - Mob *GetEntWithMostHateOnList(bool skip_mezzed = false); - Mob *GetEscapingEntOnHateList(Mob *center, float range = 0.0f, bool first = false); + Mob *GetMobWithMostHateOnList(Mob *center, Mob *skip = nullptr, bool skip_mezzed = false, EntityFilterType entity_type = EntityFilterType::All); + Mob *GetRandomMobOnHateList(bool skip_mezzed = false); + Mob *GetMobWithMostHateOnList(bool skip_mezzed = false); + Mob *GetEscapingMobOnHateList(Mob *center, float range = 0.0f, bool first = false); Bot* GetRandomBotOnHateList(bool skip_mezzed = false); Client *GetRandomClientOnHateList(bool skip_mezzed = false); diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 17d4a90e0..94d4cbfd8 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1015,6 +1015,21 @@ Lua_Mob Lua_Mob::GetHateTop() { return Lua_Mob(self->GetHateTop()); } +Lua_Bot Lua_Mob::GetHateTopBot() { + Lua_Safe_Call_Class(Lua_Bot); + return Lua_Bot(self->GetHateTopBot()); +} + +Lua_Client Lua_Mob::GetHateTopClient() { + Lua_Safe_Call_Class(Lua_Client); + return Lua_Client(self->GetHateTopClient()); +} + +Lua_NPC Lua_Mob::GetHateTopNPC() { + Lua_Safe_Call_Class(Lua_NPC); + return Lua_NPC(self->GetHateTopNPC()); +} + Lua_Mob Lua_Mob::GetHateDamageTop(Lua_Mob other) { Lua_Safe_Call_Class(Lua_Mob); return Lua_Mob(self->GetHateDamageTop(other)); @@ -3456,6 +3471,9 @@ luabind::scope lua_register_mob() { .def("GetHateRandomClient", (Lua_Client(Lua_Mob::*)(void))&Lua_Mob::GetHateRandomClient) .def("GetHateRandomNPC", (Lua_NPC(Lua_Mob::*)(void))&Lua_Mob::GetHateRandomNPC) .def("GetHateTop", (Lua_Mob(Lua_Mob::*)(void))&Lua_Mob::GetHateTop) + .def("GetHateTopBot", (Lua_Bot(Lua_Mob::*)(void))&Lua_Mob::GetHateTopBot) + .def("GetHateTopClient", (Lua_Client(Lua_Mob::*)(void))&Lua_Mob::GetHateTopClient) + .def("GetHateTopNPC", (Lua_NPC(Lua_Mob::*)(void))&Lua_Mob::GetHateTopNPC) .def("GetHeading", &Lua_Mob::GetHeading) .def("GetHelmTexture", &Lua_Mob::GetHelmTexture) .def("GetHerosForgeModel", (int32(Lua_Mob::*)(uint8))&Lua_Mob::GetHerosForgeModel) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 784328533..c8bbffeb7 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -225,6 +225,9 @@ public: Lua_HateList GetHateListByDistance(); Lua_HateList GetHateListByDistance(uint32 distance); Lua_Mob GetHateTop(); + Lua_Bot GetHateTopBot(); + Lua_Client GetHateTopClient(); + Lua_NPC GetHateTopNPC(); Lua_Mob GetHateDamageTop(Lua_Mob other); Lua_Mob GetHateRandom(); Lua_Bot GetHateRandomBot(); diff --git a/zone/mob.cpp b/zone/mob.cpp index ca0f8ff83..f951961c5 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4883,7 +4883,7 @@ bool Mob::RemoveFromHateList(Mob* mob) } if(GetTarget() == mob) { - SetTarget(hate_list.GetEntWithMostHateOnList(this)); + SetTarget(hate_list.GetMobWithMostHateOnList(this)); } return bFound; diff --git a/zone/mob.h b/zone/mob.h index 1088cb7ed..8287de96a 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -748,14 +748,17 @@ public: int64 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHateAmount(tmob,is_dam);} int64 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHateAmount(tmob, true);} int GetHateRatio(Mob *first, Mob *with) { return hate_list.GetHateRatio(first, with); } - Mob* GetHateTop() { return hate_list.GetEntWithMostHateOnList(this);} - Mob* GetSecondaryHate(Mob *skip) { return hate_list.GetEntWithMostHateOnList(this, skip); } + Mob* GetHateTop() { return hate_list.GetMobWithMostHateOnList(this);} + Bot* GetHateTopBot() { return hate_list.GetMobWithMostHateOnList(this, nullptr, false, EntityFilterType::Bots)->CastToBot();} + Client* GetHateTopClient() { return hate_list.GetMobWithMostHateOnList(this, nullptr, false, EntityFilterType::Clients)->CastToClient();} + NPC* GetHateTopNPC() { return hate_list.GetMobWithMostHateOnList(this, nullptr, false, EntityFilterType::NPCs)->CastToNPC();} + Mob* GetSecondaryHate(Mob *skip) { return hate_list.GetMobWithMostHateOnList(this, skip); } Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);} - Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();} + Mob* GetHateRandom() { return hate_list.GetRandomMobOnHateList();} Client* GetHateRandomClient() { return hate_list.GetRandomClientOnHateList(); } NPC* GetHateRandomNPC() { return hate_list.GetRandomNPCOnHateList(); } Bot* GetHateRandomBot() { return hate_list.GetRandomBotOnHateList(); } - Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();} + Mob* GetHateMost() { return hate_list.GetMobWithMostHateOnList();} Mob* GetHateClosest(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed); } Bot* GetHateClosestBot(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::Bots)->CastToBot(); } Client* GetHateClosestClient(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::Clients)->CastToClient(); } diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 10d44a6cb..b09e617b5 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -769,7 +769,7 @@ void Client::AI_Process() { if(AI_target_check_timer->Check()) { - SetTarget(hate_list.GetEntWithMostHateOnList(this)); + SetTarget(hate_list.GetMobWithMostHateOnList(this)); } } @@ -1073,12 +1073,12 @@ void Mob::AI_Process() { if (IsFocused()) { if (!target) { - SetTarget(hate_list.GetEntWithMostHateOnList(this)); + SetTarget(hate_list.GetMobWithMostHateOnList(this)); } } else { if (!ImprovedTaunt()) - SetTarget(hate_list.GetEntWithMostHateOnList(this)); + SetTarget(hate_list.GetMobWithMostHateOnList(this)); } } diff --git a/zone/npc.cpp b/zone/npc.cpp index 5a0900295..028a6dc7f 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1058,7 +1058,7 @@ bool NPC::Process() NPCAssistCap() < RuleI(Combat, NPCAssistCap)) { // Some cases like flash of light used for aggro haven't set target if (!GetTarget()) { - SetTarget(hate_list.GetEntWithMostHateOnList(this)); + SetTarget(hate_list.GetMobWithMostHateOnList(this)); } AIYellForHelp(this, GetTarget()); if (NPCAssistCap() > 0 && !assist_cap_timer.Enabled()) diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 7af1aeedb..d28383bf8 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -1344,6 +1344,21 @@ Mob* Perl_Mob_GetHateTop(Mob* self) // @categories Hate and Aggro return self->GetHateTop(); } +Bot* Perl_Mob_GetHateTopBot(Mob* self) // @categories Hate and Aggro +{ + return self->GetHateTopBot(); +} + +Client* Perl_Mob_GetHateTopClient(Mob* self) // @categories Hate and Aggro +{ + return self->GetHateTopClient(); +} + +NPC* Perl_Mob_GetHateTopNPC(Mob* self) // @categories Hate and Aggro +{ + return self->GetHateTopNPC(); +} + Mob* Perl_Mob_GetHateDamageTop(Mob* self, Mob* other) // @categories Hate and Aggro { return self->GetHateDamageTop(other); @@ -3581,6 +3596,9 @@ void perl_register_mob() package.add("GetHateRandomClient", &Perl_Mob_GetHateRandomClient); package.add("GetHateRandomNPC", &Perl_Mob_GetHateRandomNPC); package.add("GetHateTop", &Perl_Mob_GetHateTop); + package.add("GetHateTopBot", &Perl_Mob_GetHateTopBot); + package.add("GetHateTopClient", &Perl_Mob_GetHateTopClient); + package.add("GetHateTopNPC", &Perl_Mob_GetHateTopNPC); package.add("GetHeading", &Perl_Mob_GetHeading); package.add("GetHelmTexture", &Perl_Mob_GetHelmTexture); package.add("GetHerosForgeModel", &Perl_Mob_GetHerosForgeModel);