From 0d02fadb600ee457387d8eb4d8b06d75b292633d Mon Sep 17 00:00:00 2001 From: Kinglykrab <89047260+Kinglykrab@users.noreply.github.com> Date: Thu, 17 Feb 2022 08:57:02 -0500 Subject: [PATCH] [Quest API] Add GetRandomMob() and GetRandomNPC() to Perl/Lua. (#2006) - Add $entity_list->GetRandomMob(x, y, z, distance, exclude_mob) to Perl. - Add $entity_list->GetRandomNPC(x, y, z, distance, exclude_npc) to Perl. - Add eq.get_entity_list():GetRandomMob(x, y, z, distance, exclude_mob) to Lua. - Add eq.get_entity_list():GetRandomNPC(x, y, z, distance, exclude_npc) to Lua. --- zone/entity.cpp | 61 ++++++++++++++++++++++++++----- zone/entity.h | 4 ++- zone/lua_entity_list.cpp | 32 ++++++++++++++--- zone/lua_entity_list.h | 8 +++-- zone/perl_entity.cpp | 78 +++++++++++++++++++++++++++++++++++----- 5 files changed, 159 insertions(+), 24 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index 0aa2aba78..b35aa0897 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1867,19 +1867,64 @@ Client *EntityList::GetClientByLSID(uint32 iLSID) return nullptr; } -Client *EntityList::GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient) +Client *EntityList::GetRandomClient(const glm::vec3& location, float distance, Client *exclude_client) { - std::vector ClientsInRange; + std::vector clients_in_range; + for (const auto& client : client_list) { + if ( + client.second != exclude_client && + DistanceSquared(static_cast(client.second->GetPosition()), location) <= distance + ) { + clients_in_range.push_back(client.second); + } + } - for (auto it = client_list.begin();it != client_list.end(); ++it) - if ((it->second != ExcludeClient) && (DistanceSquared(static_cast(it->second->GetPosition()), location) <= Distance)) - ClientsInRange.push_back(it->second); - - if (ClientsInRange.empty()) + if (clients_in_range.empty()) { return nullptr; + } - return ClientsInRange[zone->random.Int(0, ClientsInRange.size() - 1)]; + return clients_in_range[zone->random.Int(0, clients_in_range.size() - 1)]; +} + +NPC* EntityList::GetRandomNPC(const glm::vec3& location, float distance, NPC* exclude_npc) +{ + std::vector npcs_in_range; + + for (const auto& npc : npc_list) { + if ( + npc.second != exclude_npc && + DistanceSquared(static_cast(npc.second->GetPosition()), location) <= distance + ) { + npcs_in_range.push_back(npc.second); + } + } + + if (npcs_in_range.empty()) { + return nullptr; + } + + return npcs_in_range[zone->random.Int(0, npcs_in_range.size() - 1)]; +} + +Mob* EntityList::GetRandomMob(const glm::vec3& location, float distance, Mob* exclude_mob) +{ + std::vector mobs_in_range; + + for (const auto& mob : mob_list) { + if ( + mob.second != exclude_mob && + DistanceSquared(static_cast(mob.second->GetPosition()), location) <= distance + ) { + mobs_in_range.push_back(mob.second); + } + } + + if (mobs_in_range.empty()) { + return nullptr; + } + + return mobs_in_range[zone->random.Int(0, mobs_in_range.size() - 1)]; } Corpse *EntityList::GetCorpseByOwner(Client *client) diff --git a/zone/entity.h b/zone/entity.h index bc44cb2c7..8d711ef42 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -189,7 +189,9 @@ public: Client *GetClientByWID(uint32 iWID); Client *GetClientByLSID(uint32 iLSID); Client *GetClient(uint32 ip, uint16 port); - Client *GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient = nullptr); + Client* GetRandomClient(const glm::vec3& location, float distance, Client* exclude_client = nullptr); + NPC* GetRandomNPC(const glm::vec3& location, float distance, NPC* exclude_npc = nullptr); + Mob* GetRandomMob(const glm::vec3& location, float distance, Mob* exclude_mob = nullptr); Group *GetGroupByMob(Mob* mob); Group *GetGroupByClient(Client* client); Group *GetGroupByID(uint32 id); diff --git a/zone/lua_entity_list.cpp b/zone/lua_entity_list.cpp index 9ee08ecbf..8c3ad1458 100644 --- a/zone/lua_entity_list.cpp +++ b/zone/lua_entity_list.cpp @@ -322,14 +322,14 @@ void Lua_EntityList::MessageGroup(Lua_Mob who, bool skip_close, uint32 type, con self->MessageGroup(who, skip_close, type, message); } -Lua_Client Lua_EntityList::GetRandomClient(float x, float y, float z, float dist) { +Lua_Client Lua_EntityList::GetRandomClient(float x, float y, float z, float distance) { Lua_Safe_Call_Class(Lua_Client); - return self->GetRandomClient(glm::vec3(x, y, z), dist); + return self->GetRandomClient(glm::vec3(x, y, z), distance); } -Lua_Client Lua_EntityList::GetRandomClient(float x, float y, float z, float dist, Lua_Client exclude) { +Lua_Client Lua_EntityList::GetRandomClient(float x, float y, float z, float distance, Lua_Client exclude_client) { Lua_Safe_Call_Class(Lua_Client); - return self->GetRandomClient(glm::vec3(x, y, z), dist, exclude); + return self->GetRandomClient(glm::vec3(x, y, z), distance, exclude_client); } Lua_Mob_List Lua_EntityList::GetMobList() { @@ -480,6 +480,26 @@ void Lua_EntityList::ChannelMessage(Lua_Mob from, int channel_num, int language, self->ChannelMessage(from, channel_num, language, message); } +Lua_Mob Lua_EntityList::GetRandomMob(float x, float y, float z, float distance) { + Lua_Safe_Call_Class(Lua_Mob); + return self->GetRandomMob(glm::vec3(x, y, z), distance); +} + +Lua_Mob Lua_EntityList::GetRandomMob(float x, float y, float z, float distance, Lua_Mob exclude_mob) { + Lua_Safe_Call_Class(Lua_Mob); + return self->GetRandomMob(glm::vec3(x, y, z), distance, exclude_mob); +} + +Lua_NPC Lua_EntityList::GetRandomNPC(float x, float y, float z, float distance) { + Lua_Safe_Call_Class(Lua_NPC); + return self->GetRandomNPC(glm::vec3(x, y, z), distance); +} + +Lua_NPC Lua_EntityList::GetRandomNPC(float x, float y, float z, float distance, Lua_NPC exclude_npc) { + Lua_Safe_Call_Class(Lua_NPC); + return self->GetRandomNPC(glm::vec3(x, y, z), distance, exclude_npc); +} + luabind::scope lua_register_entity_list() { return luabind::class_("EntityList") .def(luabind::constructor<>()) @@ -534,6 +554,10 @@ luabind::scope lua_register_entity_list() { .def("GetRaidByID", (Lua_Raid(Lua_EntityList::*)(int))&Lua_EntityList::GetRaidByID) .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float, float, float, float))&Lua_EntityList::GetRandomClient) .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float, float, float, float, Lua_Client))&Lua_EntityList::GetRandomClient) + .def("GetRandomMob", (Lua_Mob(Lua_EntityList::*)(float,float,float,float))&Lua_EntityList::GetRandomMob) + .def("GetRandomMob", (Lua_Mob(Lua_EntityList::*)(float,float,float,float,Lua_Mob))&Lua_EntityList::GetRandomMob) + .def("GetRandomNPC", (Lua_NPC(Lua_EntityList::*)(float,float,float,float))&Lua_EntityList::GetRandomNPC) + .def("GetRandomNPC", (Lua_NPC(Lua_EntityList::*)(float,float,float,float,Lua_NPC))&Lua_EntityList::GetRandomNPC) .def("GetShuffledClientList", (Lua_Client_List(Lua_EntityList::*)(void))&Lua_EntityList::GetShuffledClientList) .def("GetSpawnByID", (Lua_Spawn(Lua_EntityList::*)(uint32))&Lua_EntityList::GetSpawnByID) .def("GetSpawnList", (Lua_Spawn_List(Lua_EntityList::*)(void))&Lua_EntityList::GetSpawnList) diff --git a/zone/lua_entity_list.h b/zone/lua_entity_list.h index ba67971dd..0e5f32a4d 100644 --- a/zone/lua_entity_list.h +++ b/zone/lua_entity_list.h @@ -108,8 +108,12 @@ public: void RemoveFromHateLists(Lua_Mob who); void RemoveFromHateLists(Lua_Mob who, bool set_to_one); void MessageGroup(Lua_Mob who, bool skip_close, uint32 type, const char *message); - Lua_Client GetRandomClient(float x, float y, float z, float dist); - Lua_Client GetRandomClient(float x, float y, float z, float dist, Lua_Client exclude); + Lua_Client GetRandomClient(float x, float y, float z, float distance); + Lua_Client GetRandomClient(float x, float y, float z, float distance, Lua_Client exclude_client); + Lua_Mob GetRandomMob(float x, float y, float z, float distance); + Lua_Mob GetRandomMob(float x, float y, float z, float distance, Lua_Mob exclude_mob); + Lua_NPC GetRandomNPC(float x, float y, float z, float distance); + Lua_NPC GetRandomNPC(float x, float y, float z, float distance, Lua_NPC exclude_npc); Lua_Mob_List GetMobList(); Lua_Client_List GetClientList(); Lua_Client_List GetShuffledClientList(); diff --git a/zone/perl_entity.cpp b/zone/perl_entity.cpp index 7dddf791b..a4e6f60bc 100644 --- a/zone/perl_entity.cpp +++ b/zone/perl_entity.cpp @@ -1215,24 +1215,26 @@ XS(XS_EntityList_MessageGroup) { XS(XS_EntityList_GetRandomClient); /* prototype to pass -Wmissing-prototypes */ XS(XS_EntityList_GetRandomClient) { dXSARGS; - if ((items < 5) || (items > 6)) + if (items < 5 || items > 6) Perl_croak(aTHX_ "Usage: EntityList::GetRandomClient(THIS, float x, float y, float z, float distance, [Client* exclude_client = nullptr])"); // @categories Account and Character, Script Utility { EntityList *THIS; - Client *RETVAL, *c = nullptr; - float x = (float) SvNV(ST(1)); - float y = (float) SvNV(ST(2)); - float z = (float) SvNV(ST(3)); - float d = (float) SvNV(ST(4)); + Client *RETVAL, *exclude_client = nullptr; + float x = (float) SvNV(ST(1)); + float y = (float) SvNV(ST(2)); + float z = (float) SvNV(ST(3)); + float distance = (float) SvNV(ST(4)); VALIDATE_THIS_IS_ENTITY; + if (items == 6) { if (sv_derived_from(ST(5), "Client")) { IV tmp = SvIV((SV *) SvRV(ST(5))); - c = INT2PTR(Client *, tmp); + exclude_client = INT2PTR(Client *, tmp); } } - RETVAL = entity_list.GetRandomClient(glm::vec3(x, y, z), d * d, c); - ST(0) = sv_newmortal(); + + RETVAL = entity_list.GetRandomClient(glm::vec3(x, y, z), (distance * distance), exclude_client); + ST(0) = sv_newmortal(); sv_setref_pv(ST(0), "Client", (void *) RETVAL); } XSRETURN(1); @@ -1460,6 +1462,62 @@ XS(XS_EntityList_SignalAllClients) { XSRETURN_EMPTY; } +XS(XS_EntityList_GetRandomMob); /* prototype to pass -Wmissing-prototypes */ +XS(XS_EntityList_GetRandomMob) { + dXSARGS; + if (items < 5 || items > 6) + Perl_croak(aTHX_ "Usage: EntityList::GetRandomMob(THIS, float x, float y, float z, float distance, [Mob* exclude_mob = nullptr])"); // @categories Account and Character, Script Utility + { + EntityList *THIS; + Mob *RETVAL, *exclude_mob = nullptr; + float x = (float) SvNV(ST(1)); + float y = (float) SvNV(ST(2)); + float z = (float) SvNV(ST(3)); + float distance = (float) SvNV(ST(4)); + VALIDATE_THIS_IS_ENTITY; + + if (items == 6) { + if (sv_derived_from(ST(5), "Mob")) { + IV tmp = SvIV((SV *) SvRV(ST(5))); + exclude_mob = INT2PTR(Mob*, tmp); + } + } + + RETVAL = entity_list.GetRandomMob(glm::vec3(x, y, z), (distance * distance), exclude_mob); + ST(0) = sv_newmortal(); + sv_setref_pv(ST(0), "Mob", (void *) RETVAL); + } + XSRETURN(1); +} + +XS(XS_EntityList_GetRandomNPC); /* prototype to pass -Wmissing-prototypes */ +XS(XS_EntityList_GetRandomNPC) { + dXSARGS; + if (items < 5 || items > 6) + Perl_croak(aTHX_ "Usage: EntityList::GetRandomNPC(THIS, float x, float y, float z, float distance, [NPC* exclude_npc = nullptr])"); // @categories Account and Character, Script Utility + { + EntityList *THIS; + NPC *RETVAL, *exclude_npc = nullptr; + float x = (float) SvNV(ST(1)); + float y = (float) SvNV(ST(2)); + float z = (float) SvNV(ST(3)); + float distance = (float) SvNV(ST(4)); + VALIDATE_THIS_IS_ENTITY; + + if (items == 6) { + if (sv_derived_from(ST(5), "NPC")) { + IV tmp = SvIV((SV *) SvRV(ST(5))); + exclude_npc = INT2PTR(NPC*, tmp); + } + } + + RETVAL = entity_list.GetRandomNPC(glm::vec3(x, y, z), (distance * distance), exclude_npc); + ST(0) = sv_newmortal(); + sv_setref_pv(ST(0), "NPC", (void *) RETVAL); + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -1524,6 +1582,8 @@ XS(boot_EntityList) { newXSproto(strcpy(buf, "GetRaidByClient"), XS_EntityList_GetRaidByClient, file, "$$"); newXSproto(strcpy(buf, "GetRaidByID"), XS_EntityList_GetRaidByID, file, "$$"); newXSproto(strcpy(buf, "GetRandomClient"), XS_EntityList_GetRandomClient, file, "$$$$$;$"); + newXSproto(strcpy(buf, "GetRandomMob"), XS_EntityList_GetRandomMob, file, "$$$$$;$"); + newXSproto(strcpy(buf, "GetRandomNPC"), XS_EntityList_GetRandomNPC, file, "$$$$$;$"); newXSproto(strcpy(buf, "HalveAggro"), XS_EntityList_HalveAggro, file, "$$"); newXSproto(strcpy(buf, "IsMobSpawnedByNpcTypeID"), XS_EntityList_IsMobSpawnedByNpcTypeID, file, "$$"); newXSproto(strcpy(buf, "MakeNameUnique"), XS_EntityList_MakeNameUnique, file, "$$");