diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index a7ce4dd85..74f6bd05e 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -149,7 +149,7 @@ Mob* HateList::GetDamageTopOnHateList(Mob* hater) return current; } -Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed, EntityFilterType entity_type) { +Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed, EntityFilterType filter_type) { Mob* close_entity = nullptr; float close_distance = 99999.9f; float this_distance; @@ -163,7 +163,7 @@ Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed, EntityFilte continue; } - switch (entity_type) { + switch (filter_type) { case EntityFilterType::Bots: if (!e->entity_on_hatelist->IsBot()) { continue; @@ -589,47 +589,39 @@ Mob *HateList::GetMobWithMostHateOnList(bool skip_mezzed){ } -Mob *HateList::GetRandomMobOnHateList(bool skip_mezzed) +Mob *HateList::GetRandomMobOnHateList(EntityFilterType filter_type) { - int count = list.size(); - if (count <= 0) //If we don't have any entries it'll crash getting a random 0, -1 position. - return nullptr; - - if (count == 1) //No need to do all that extra work if we only have one hate entry - { - if (*list.begin() && (!skip_mezzed || !(*list.begin())->entity_on_hatelist->IsMezzed())) // Just in case tHateEntry is invalidated somehow... - return (*list.begin())->entity_on_hatelist; + const auto &l = GetFilteredHateList(filter_type); + int count = l.size(); + if (count <= 0) { // If we don't have any entries it'll crash getting a random 0, -1 position. return nullptr; } - if (skip_mezzed) { - - for (auto iter : list) { - if (iter->entity_on_hatelist->IsMezzed()) { - --count; + if (count == 1) { // No need to do all that extra work if we only have one hate entry + auto c = *l.begin(); + if (c) { + Mob *m = c->entity_on_hatelist; + if (!m) { + return nullptr; } + + return m; } - if (count <= 0) { - return nullptr; - } + + return nullptr; } - int random = zone->random.Int(0, count - 1); - int counter = 0; + auto r = l.begin(); + int random_index = rand() % count; - for (auto iter : list) { + std::advance(r, random_index); - if (skip_mezzed && iter->entity_on_hatelist->IsMezzed()) { - continue; - } - if (counter < random) { + auto e = *r; - ++counter; - continue; - } - - return iter->entity_on_hatelist; + Mob *m = e->entity_on_hatelist; + if (m) { + return m; } return nullptr; @@ -877,153 +869,6 @@ void HateList::RemoveStaleEntries(int time_ms, float dist) } } -Bot* HateList::GetRandomBotOnHateList(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. - return nullptr; - } - - if (count == 1) { //No need to do all that extra work if we only have one hate entry - if (*list.begin() && (*list.begin())->entity_on_hatelist->IsBot() && (!skip_mezzed || !(*list.begin())->entity_on_hatelist->IsMezzed())) { - return (*list.begin())->entity_on_hatelist->CastToBot(); - } - return nullptr; - } - - if (skip_mezzed) { - for (auto iter : list) { - if (iter->entity_on_hatelist->IsMezzed()) { - --count; - } - } - - if (count <= 0) { - return nullptr; - } - } - - int random = zone->random.Int(0, count - 1); - int counter = 0; - - for (auto iter : list) { - if (!iter->entity_on_hatelist->IsBot()) { - continue; - } - - if (skip_mezzed && iter->entity_on_hatelist->IsMezzed()) { - continue; - } - - if (counter < random) { - ++counter; - continue; - } - - return iter->entity_on_hatelist->CastToBot(); - } - - return nullptr; -} - -Client* HateList::GetRandomClientOnHateList(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. - return nullptr; - } - - if (count == 1) { //No need to do all that extra work if we only have one hate entry - if (*list.begin() && (*list.begin())->entity_on_hatelist->IsClient() && (!skip_mezzed || !(*list.begin())->entity_on_hatelist->IsMezzed())) { - return (*list.begin())->entity_on_hatelist->CastToClient(); - } - return nullptr; - } - - if (skip_mezzed) { - for (auto iter : list) { - if (iter->entity_on_hatelist->IsMezzed()) { - --count; - } - } - - if (count <= 0) { - return nullptr; - } - } - - int random = zone->random.Int(0, count - 1); - int counter = 0; - - for (auto iter : list) { - if (!iter->entity_on_hatelist->IsClient()) { - continue; - } - - if (skip_mezzed && iter->entity_on_hatelist->IsMezzed()) { - continue; - } - - if (counter < random) { - ++counter; - continue; - } - - return iter->entity_on_hatelist->CastToClient(); - } - - return nullptr; -} - -NPC* HateList::GetRandomNPCOnHateList(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. - return nullptr; - } - - if (count == 1) { //No need to do all that extra work if we only have one hate entry - if (*list.begin() && (*list.begin())->entity_on_hatelist->IsNPC() && (!skip_mezzed || !(*list.begin())->entity_on_hatelist->IsMezzed())) { - return (*list.begin())->entity_on_hatelist->CastToNPC(); - } - return nullptr; - } - - if (skip_mezzed) { - for (auto iter : list) { - if (iter->entity_on_hatelist->IsMezzed()) { - --count; - } - } - - if (count <= 0) { - return nullptr; - } - } - - int random = zone->random.Int(0, count - 1); - int counter = 0; - - for (auto iter : list) { - if (!iter->entity_on_hatelist->IsNPC()) { - continue; - } - - if (skip_mezzed && iter->entity_on_hatelist->IsMezzed()) { - continue; - } - - if (counter < random) { - ++counter; - continue; - } - - return iter->entity_on_hatelist->CastToNPC(); - } - - return nullptr; -} - void HateList::DamageHateList(int64 damage, uint32 distance, EntityFilterType filter_type, bool is_percentage) { if (damage <= 0) { diff --git a/zone/hate_list.h b/zone/hate_list.h index 199c8307b..1e52ce190 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -41,17 +41,13 @@ public: HateList(); ~HateList(); - Mob *GetClosestEntOnHateList(Mob *hater, bool skip_mezzed = false, EntityFilterType entity_type = EntityFilterType::All); + Mob *GetClosestEntOnHateList(Mob *hater, bool skip_mezzed = false, EntityFilterType filter_type = EntityFilterType::All); Mob *GetDamageTopOnHateList(Mob *hater); // didn't add 'skip_mezzed' due to calls being in ::Death() - Mob *GetMobWithMostHateOnList(Mob *center, Mob *skip = nullptr, bool skip_mezzed = false, EntityFilterType entity_type = EntityFilterType::All); - Mob *GetRandomMobOnHateList(bool skip_mezzed = false); + Mob *GetMobWithMostHateOnList(Mob *center, Mob *skip = nullptr, bool skip_mezzed = false, EntityFilterType filter_type = EntityFilterType::All); + Mob *GetRandomMobOnHateList(EntityFilterType filter_type = EntityFilterType::All); 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); - NPC *GetRandomNPCOnHateList(bool skip_mezzed = false); - bool IsEntOnHateList(Mob *mob); bool IsHateListEmpty(); bool RemoveEntFromHateList(Mob *ent); diff --git a/zone/mob.h b/zone/mob.h index f06a2955f..783e9fafd 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -754,10 +754,10 @@ public: 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.GetRandomMobOnHateList();} - Client* GetHateRandomClient() { return hate_list.GetRandomClientOnHateList(); } - NPC* GetHateRandomNPC() { return hate_list.GetRandomNPCOnHateList(); } - Bot* GetHateRandomBot() { return hate_list.GetRandomBotOnHateList(); } + Mob* GetHateRandom() { return hate_list.GetRandomMobOnHateList(); } + Bot* GetHateRandomBot() { return hate_list.GetRandomMobOnHateList(EntityFilterType::Bots)->CastToBot(); } + Client* GetHateRandomClient() { return hate_list.GetRandomMobOnHateList(EntityFilterType::Clients)->CastToClient(); } + NPC* GetHateRandomNPC() { return hate_list.GetRandomMobOnHateList(EntityFilterType::NPCs)->CastToNPC(); } 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(); }