diff --git a/zone/entity.h b/zone/entity.h index a1de10ae7..3f0800d24 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -539,7 +539,7 @@ public: inline const std::unordered_map &GetObjectList() { return object_list; } inline const std::unordered_map &GetDoorsList() { return door_list; } - std::unordered_map &GetCloseMobList(Mob *mob, float distance = 0); + std::unordered_map &GetCloseMobList(Mob *mob, float distance = 0.0f); void DepopAll(int NPCTypeID, bool StartSpawnTimer = true); diff --git a/zone/lua_entity_list.cpp b/zone/lua_entity_list.cpp index 0b9438fd3..1a334fc99 100644 --- a/zone/lua_entity_list.cpp +++ b/zone/lua_entity_list.cpp @@ -635,6 +635,62 @@ Lua_Bot Lua_EntityList::GetRandomBot(float x, float y, float z, float distance, return self->GetRandomBot(glm::vec3(x, y, z), distance, exclude_bot); } +Lua_Mob_List Lua_EntityList::GetCloseMobList(Lua_Mob mob) { + Lua_Safe_Call_Class(Lua_Mob_List); + + Lua_Mob_List ret; + + const auto& l = self->GetCloseMobList(mob); + + ret.entries.reserve(l.size()); + + for (const auto& e : l) { + ret.entries.emplace_back(Lua_Mob(e.second)); + } + + return ret; +} + +Lua_Mob_List Lua_EntityList::GetCloseMobList(Lua_Mob mob, float distance) { + Lua_Safe_Call_Class(Lua_Mob_List); + + Lua_Mob_List ret; + + const auto& l = self->GetCloseMobList(mob); + + ret.entries.reserve(l.size()); + + for (const auto& e : l) { + if (mob.CalculateDistance(e.second) <= distance) { + ret.entries.emplace_back(Lua_Mob(e.second)); + } + } + + return ret; +} + +Lua_Mob_List Lua_EntityList::GetCloseMobList(Lua_Mob mob, float distance, bool ignore_self) { + Lua_Safe_Call_Class(Lua_Mob_List); + + Lua_Mob_List ret; + + const auto& l = self->GetCloseMobList(mob); + + ret.entries.reserve(l.size()); + + for (const auto& e : l) { + if (ignore_self && e.second == mob) { + continue; + } + + if (mob.CalculateDistance(e.second) <= distance) { + ret.entries.emplace_back(Lua_Mob(e.second)); + } + } + + return ret; +} + luabind::scope lua_register_entity_list() { return luabind::class_("EntityList") .def(luabind::constructor<>()) @@ -665,6 +721,8 @@ luabind::scope lua_register_entity_list() { .def("GetClientByName", (Lua_Client(Lua_EntityList::*)(const char*))&Lua_EntityList::GetClientByName) .def("GetClientByWID", (Lua_Client(Lua_EntityList::*)(uint32))&Lua_EntityList::GetClientByWID) .def("GetClientList", (Lua_Client_List(Lua_EntityList::*)(void))&Lua_EntityList::GetClientList) + .def("GetCloseMobList", (Lua_Mob_List(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::GetCloseMobList) + .def("GetCloseMobList", (Lua_Mob_List(Lua_EntityList::*)(Lua_Mob,float))&Lua_EntityList::GetCloseMobList) .def("GetCorpseByID", (Lua_Corpse(Lua_EntityList::*)(int))&Lua_EntityList::GetCorpseByID) .def("GetCorpseByName", (Lua_Corpse(Lua_EntityList::*)(const char*))&Lua_EntityList::GetCorpseByName) .def("GetCorpseByOwner", (Lua_Corpse(Lua_EntityList::*)(Lua_Client))&Lua_EntityList::GetCorpseByOwner) diff --git a/zone/lua_entity_list.h b/zone/lua_entity_list.h index 11dac40a9..b20019ecb 100644 --- a/zone/lua_entity_list.h +++ b/zone/lua_entity_list.h @@ -139,6 +139,9 @@ public: void SignalAllBotsByOwnerName(std::string owner_name, int signal_id); void SignalBotByBotID(uint32 bot_id, int signal_id); void SignalBotByBotName(std::string bot_name, int signal_id); + Lua_Mob_List GetCloseMobList(Lua_Mob mob); + Lua_Mob_List GetCloseMobList(Lua_Mob mob, float distance); + Lua_Mob_List GetCloseMobList(Lua_Mob mob, float distance, bool ignore_self); }; #endif diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 121948e89..cba5c36e0 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -18,6 +18,10 @@ struct SpecialAbilities { }; +struct Lua_Mob_List { + std::vector entries; +}; + const char *Lua_Mob::GetName() { Lua_Safe_Call_String(); return self->GetName(); @@ -1265,6 +1269,11 @@ float Lua_Mob::CalculateDistance(double x, double y, double z) { return self->CalculateDistance(static_cast(x), static_cast(y), static_cast(z)); } +float Lua_Mob::CalculateDistance(Lua_Mob mob) { + Lua_Safe_Call_Real(); + return self->CalculateDistance(mob); +} + void Lua_Mob::SendTo(double x, double y, double z) { Lua_Safe_Call_Void(); self->SendTo(static_cast(x), static_cast(y), static_cast(z)); @@ -3050,6 +3059,62 @@ bool Lua_Mob::HasSpellEffect(int effect_id) { return self->HasSpellEffect(effect_id); } +Lua_Mob_List Lua_Mob::GetCloseMobList() { + Lua_Safe_Call_Class(Lua_Mob_List); + + Lua_Mob_List ret; + + const auto& l = entity_list.GetCloseMobList(self); + + ret.entries.reserve(l.size()); + + for (const auto& e : l) { + ret.entries.emplace_back(Lua_Mob(e.second)); + } + + return ret; +} + +Lua_Mob_List Lua_Mob::GetCloseMobList(float distance) { + Lua_Safe_Call_Class(Lua_Mob_List); + + Lua_Mob_List ret; + + const auto& l = entity_list.GetCloseMobList(self); + + ret.entries.reserve(l.size()); + + for (const auto& e : l) { + if (self->CalculateDistance(e.second) <= distance) { + ret.entries.emplace_back(Lua_Mob(e.second)); + } + } + + return ret; +} + +Lua_Mob_List Lua_Mob::GetCloseMobList(float distance, bool ignore_self) { + Lua_Safe_Call_Class(Lua_Mob_List); + + Lua_Mob_List ret; + + const auto& l = entity_list.GetCloseMobList(self); + + ret.entries.reserve(l.size()); + + for (const auto& e : l) { + if (ignore_self && e.second == self) { + continue; + } + + if (self->CalculateDistance(e.second) <= distance) { + ret.entries.emplace_back(Lua_Mob(e.second)); + } + } + + return ret; +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -3083,6 +3148,7 @@ luabind::scope lua_register_mob() { .def("BuffFadeBySlot", (void(Lua_Mob::*)(int,bool))&Lua_Mob::BuffFadeBySlot) .def("BuffFadeBySpellID", (void(Lua_Mob::*)(int))&Lua_Mob::BuffFadeBySpellID) .def("CalculateDistance", (float(Lua_Mob::*)(double,double,double))&Lua_Mob::CalculateDistance) + .def("CalculateDistance", (float(Lua_Mob::*)(Lua_Mob))&Lua_Mob::CalculateDistance) .def("CalculateHeadingToTarget", (double(Lua_Mob::*)(double,double))&Lua_Mob::CalculateHeadingToTarget) .def("CameraEffect", (void(Lua_Mob::*)(uint32,float))&Lua_Mob::CameraEffect) .def("CameraEffect", (void(Lua_Mob::*)(uint32,float,Lua_Client))&Lua_Mob::CameraEffect) @@ -3258,6 +3324,9 @@ luabind::scope lua_register_mob() { .def("GetClass", &Lua_Mob::GetClass) .def("GetClassName", &Lua_Mob::GetClassName) .def("GetCleanName", &Lua_Mob::GetCleanName) + .def("GetCloseMobList", (Lua_Mob_List(Lua_Mob::*)(void))&Lua_Mob::GetCloseMobList) + .def("GetCloseMobList", (Lua_Mob_List(Lua_Mob::*)(float))&Lua_Mob::GetCloseMobList) + .def("GetCloseMobList", (Lua_Mob_List(Lua_Mob::*)(float,bool))&Lua_Mob::GetCloseMobList) .def("GetCorruption", &Lua_Mob::GetCorruption) .def("GetDEX", &Lua_Mob::GetDEX) .def("GetDR", &Lua_Mob::GetDR) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 954717869..58b5c8361 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -12,6 +12,7 @@ class Lua_StatBonuses; class Lua_Bot; class Lua_NPC; class Lua_Client; +struct Lua_Mob_List; namespace luabind { struct scope; @@ -287,6 +288,7 @@ public: void NavigateTo(double x, double y, double z); void StopNavigation(); float CalculateDistance(double x, double y, double z); + float CalculateDistance(Lua_Mob mob); void SendTo(double x, double y, double z); void SendToFixZ(double x, double y, double z); void NPCSpecialAttacks(const char *parse, int perm); @@ -549,6 +551,9 @@ public: void StopTimer(const char* timer_name); luabind::object GetBuffSpellIDs(lua_State* L); bool HasSpellEffect(int effect_id); + Lua_Mob_List GetCloseMobList(); + Lua_Mob_List GetCloseMobList(float distance); + Lua_Mob_List GetCloseMobList(float distance, bool ignore_self); }; #endif diff --git a/zone/mob.h b/zone/mob.h index 6f27be3d0..9c0863876 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1203,6 +1203,7 @@ public: void RotateToRunning(float new_heading); void StopNavigation(); float CalculateDistance(float x, float y, float z); + float CalculateDistance(Mob* mob); float GetGroundZ(float new_x, float new_y, float z_offset=0.0); void SendTo(float new_x, float new_y, float new_z); void SendToFixZ(float new_x, float new_y, float new_z); diff --git a/zone/perl_entity.cpp b/zone/perl_entity.cpp index 2be7d2463..025f1d7d2 100644 --- a/zone/perl_entity.cpp +++ b/zone/perl_entity.cpp @@ -4,6 +4,7 @@ #include "embperl.h" #include "entity.h" +#include "mob.h" #include "../common/global_define.h" #include "../common/rulesys.h" #include "../common/say_link.h" @@ -610,6 +611,59 @@ Bot* Perl_EntityList_GetRandomBot(EntityList* self, float x, float y, float z, f return self->GetRandomBot(glm::vec3(x, y, z), distance, exclude_bot); } +perl::array Perl_EntityList_GetCloseMobList(EntityList* self, Mob* mob) +{ + perl::array result; + + const auto& l = self->GetCloseMobList(mob); + + result.reserve(l.size()); + + for (const auto& e : l) { + result.push_back(e.second); + } + + return result; +} + +perl::array Perl_EntityList_GetCloseMobList(EntityList* self, Mob* mob, float distance) +{ + perl::array result; + + const auto& l = self->GetCloseMobList(mob, distance); + + result.reserve(l.size()); + + for (const auto& e : l) { + if (mob->CalculateDistance(e.second) <= distance) { + result.push_back(e.second); + } + } + + return result; +} + +perl::array Perl_EntityList_GetCloseMobList(EntityList* self, Mob* mob, float distance, bool ignore_self) +{ + perl::array result; + + const auto& l = self->GetCloseMobList(mob, distance); + + result.reserve(l.size()); + + for (const auto& e : l) { + if (ignore_self && e.second == mob) { + continue; + } + + if (mob->CalculateDistance(e.second) <= distance) { + result.push_back(e.second); + } + } + + return result; +} + Spawn2* Perl_EntityList_GetSpawnByID(EntityList* self, uint32 spawn_id) { return self->GetSpawnByID(spawn_id); } @@ -657,6 +711,9 @@ void perl_register_entitylist() package.add("GetClientByName", &Perl_EntityList_GetClientByName); package.add("GetClientByWID", &Perl_EntityList_GetClientByWID); package.add("GetClientList", &Perl_EntityList_GetClientList); + package.add("GetCloseMobList", (perl::array(*)(EntityList*, Mob*))&Perl_EntityList_GetCloseMobList); + package.add("GetCloseMobList", (perl::array(*)(EntityList*, Mob*, float))&Perl_EntityList_GetCloseMobList); + package.add("GetCloseMobList", (perl::array(*)(EntityList*, Mob*, float, bool))&Perl_EntityList_GetCloseMobList); package.add("GetCorpseByID", &Perl_EntityList_GetCorpseByID); package.add("GetCorpseByName", &Perl_EntityList_GetCorpseByName); package.add("GetCorpseByOwner", &Perl_EntityList_GetCorpseByOwner); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index fda3d614b..6fd73609a 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -1374,6 +1374,11 @@ float Perl_Mob_CalculateDistance(Mob* self, float x, float y, float z) // @categ return self->CalculateDistance(x, y, z); } +float Perl_Mob_CalculateDistance(Mob* self, Mob* mob) // @categories Script Utility +{ + return self->CalculateDistance(mob); +} + void Perl_Mob_SendTo(Mob* self, float new_x, float new_y, float new_z) // @categories Script Utility { self->SendTo(new_x, new_y, new_z); @@ -3005,6 +3010,59 @@ bool Perl_Mob_HasSpellEffect(Mob* self, int effect_id) return self->HasSpellEffect(effect_id); } +perl::array Perl_Mob_GetCloseMobList(Mob* self) +{ + perl::array result; + + const auto& l = entity_list.GetCloseMobList(self); + + result.reserve(l.size()); + + for (const auto& e : l) { + result.push_back(e.second); + } + + return result; +} + +perl::array Perl_Mob_GetCloseMobList(Mob* self, float distance) +{ + perl::array result; + + const auto& l = entity_list.GetCloseMobList(self, distance); + + result.reserve(l.size()); + + for (const auto& e : l) { + if (self->CalculateDistance(e.second) <= distance) { + result.push_back(e.second); + } + } + + return result; +} + +perl::array Perl_Mob_GetCloseMobList(Mob* self, float distance, bool ignore_self) +{ + perl::array result; + + const auto& l = entity_list.GetCloseMobList(self, distance); + + result.reserve(l.size()); + + for (const auto& e : l) { + if (ignore_self && e.second == self) { + continue; + } + + if (self->CalculateDistance(e.second) <= distance) { + result.push_back(e.second); + } + } + + return result; +} + StatBonuses* Perl_Mob_GetAABonuses(Mob* self) { return self->GetAABonusesPtr(); @@ -3050,7 +3108,8 @@ void perl_register_mob() package.add("BuffFadeBySlot", (void(*)(Mob*, int))&Perl_Mob_BuffFadeBySlot); package.add("BuffFadeBySlot", (void(*)(Mob*, int, bool))&Perl_Mob_BuffFadeBySlot); package.add("BuffFadeBySpellID", &Perl_Mob_BuffFadeBySpellID); - package.add("CalculateDistance", &Perl_Mob_CalculateDistance); + package.add("CalculateDistance", (float(*)(Mob*, float, float, float))&Perl_Mob_CalculateDistance); + package.add("CalculateDistance", (float(*)(Mob*, Mob*))&Perl_Mob_CalculateDistance); package.add("CalculateHeadingToTarget", &Perl_Mob_CalculateHeadingToTarget); package.add("CameraEffect", (void(*)(Mob*, uint32))&Perl_Mob_CameraEffect); package.add("CameraEffect", (void(*)(Mob*, uint32, float))&Perl_Mob_CameraEffect); @@ -3211,6 +3270,9 @@ void perl_register_mob() package.add("GetClassLevelFactor", &Perl_Mob_GetClassLevelFactor); package.add("GetClassName", &Perl_Mob_GetClassName); package.add("GetCleanName", &Perl_Mob_GetCleanName); + package.add("GetCloseMobList", (perl::array(*)(Mob*))&Perl_Mob_GetCloseMobList); + package.add("GetCloseMobList", (perl::array(*)(Mob*, float))&Perl_Mob_GetCloseMobList); + package.add("GetCloseMobList", (perl::array(*)(Mob*, float, bool))&Perl_Mob_GetCloseMobList); package.add("GetCorruption", &Perl_Mob_GetCorruption); package.add("GetDefaultRaceSize", (float(*)(Mob*))&Perl_Mob_GetDefaultRaceSize); package.add("GetDefaultRaceSize", (float(*)(Mob*, int))&Perl_Mob_GetDefaultRaceSize); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 56e69d017..6eb96cbd2 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -592,7 +592,19 @@ void NPC::NextGuardPosition() { } float Mob::CalculateDistance(float x, float y, float z) { - return (float)sqrtf(((m_Position.x - x)*(m_Position.x - x)) + ((m_Position.y - y)*(m_Position.y - y)) + ((m_Position.z - z)*(m_Position.z - z))); + return sqrtf( + ((m_Position.x - x) * (m_Position.x - x)) + + ((m_Position.y - y) * (m_Position.y - y)) + + ((m_Position.z - z) * (m_Position.z - z)) + ); +} + +float Mob::CalculateDistance(Mob* mob) { + return sqrtf( + ((m_Position.x - mob->GetX()) * (m_Position.x - mob->GetX())) + + ((m_Position.y - mob->GetX()) * (m_Position.y - mob->GetY())) + + ((m_Position.z - mob->GetX()) * (m_Position.z - mob->GetZ())) + ); } void Mob::WalkTo(float x, float y, float z)