mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 22:01:30 +00:00
[Quest API] Add corpse->GetLootList() and npc->GetLootList() to Perl and Lua. (#1529)
* [Quest API] Add corpse->GetLootList() and npc->GetLootList() to Perl and Lua. - Add $corpse->GetLootList() to Perl. - Add $npc->GetLootList() to Perl. - Add corpse:GetLootList() to Lua. - Add npc:GetLootList() to Lua. Returns an array of item IDs for use with corpse and NPC methods such as HasItem(item_id), CountItem(item_id), and GetFirstSlotByItemID(item_id). * Categories. * Modify Lua to use classes.
This commit is contained in:
parent
97dcba70cf
commit
56b9b6f2c4
@ -1462,12 +1462,12 @@ bool Corpse::HasItem(uint32 item_id) {
|
|||||||
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
||||||
ServerLootItem_Struct* loot_item = *current_item;
|
ServerLootItem_Struct* loot_item = *current_item;
|
||||||
if (!loot_item) {
|
if (!loot_item) {
|
||||||
LogError("NPC::CountItem() - ItemList error, null item");
|
LogError("Corpse::HasItem() - ItemList error, null item");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) {
|
if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) {
|
||||||
LogError("NPC::CountItem() - Database error, invalid item");
|
LogError("Corpse::HasItem() - Database error, invalid item");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1487,12 +1487,12 @@ uint16 Corpse::CountItem(uint32 item_id) {
|
|||||||
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
||||||
ServerLootItem_Struct* loot_item = *current_item;
|
ServerLootItem_Struct* loot_item = *current_item;
|
||||||
if (!loot_item) {
|
if (!loot_item) {
|
||||||
LogError("NPC::CountItem() - ItemList error, null item");
|
LogError("Corpse::CountItem() - ItemList error, null item");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) {
|
if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) {
|
||||||
LogError("NPC::CountItem() - Database error, invalid item");
|
LogError("Corpse::CountItem() - Database error, invalid item");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1747,3 +1747,21 @@ bool Corpse::MovePlayerCorpseToNonInstance()
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<int> Corpse::GetLootList() {
|
||||||
|
std::vector<int> corpse_items;
|
||||||
|
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
||||||
|
ServerLootItem_Struct* loot_item = *current_item;
|
||||||
|
if (!loot_item) {
|
||||||
|
LogError("Corpse::GetLootList() - ItemList error, null item");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::find(corpse_items.begin(), corpse_items.end(), loot_item->item_id) != corpse_items.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
corpse_items.push_back(loot_item->item_id);
|
||||||
|
}
|
||||||
|
return corpse_items;
|
||||||
|
}
|
||||||
|
|||||||
@ -117,6 +117,7 @@ class Corpse : public Mob {
|
|||||||
uint16 CountItem(uint32 item_id);
|
uint16 CountItem(uint32 item_id);
|
||||||
uint32 GetItemIDBySlot(uint16 loot_slot);
|
uint32 GetItemIDBySlot(uint16 loot_slot);
|
||||||
uint16 GetFirstSlotByItemID(uint32 item_id);
|
uint16 GetFirstSlotByItemID(uint32 item_id);
|
||||||
|
std::vector<int> GetLootList();
|
||||||
void LootItem(Client* client, const EQApplicationPacket* app);
|
void LootItem(Client* client, const EQApplicationPacket* app);
|
||||||
void EndLoot(Client* client, const EQApplicationPacket* app);
|
void EndLoot(Client* client, const EQApplicationPacket* app);
|
||||||
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
|
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
|
||||||
|
|||||||
@ -2,11 +2,16 @@
|
|||||||
|
|
||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
#include <luabind/luabind.hpp>
|
#include <luabind/luabind.hpp>
|
||||||
|
#include <luabind/iterator_policy.hpp>
|
||||||
|
|
||||||
#include "corpse.h"
|
#include "corpse.h"
|
||||||
#include "lua_corpse.h"
|
#include "lua_corpse.h"
|
||||||
#include "lua_client.h"
|
#include "lua_client.h"
|
||||||
|
|
||||||
|
struct Lua_Corpse_Loot_List {
|
||||||
|
std::vector<uint32> entries;
|
||||||
|
};
|
||||||
|
|
||||||
uint32 Lua_Corpse::GetCharID() {
|
uint32 Lua_Corpse::GetCharID() {
|
||||||
Lua_Safe_Call_Int();
|
Lua_Safe_Call_Int();
|
||||||
return self->GetCharID();
|
return self->GetCharID();
|
||||||
@ -172,6 +177,18 @@ uint16 Lua_Corpse::GetFirstSlotByItemID(uint32 item_id) {
|
|||||||
return self->GetFirstSlotByItemID(item_id);
|
return self->GetFirstSlotByItemID(item_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lua_Corpse_Loot_List Lua_Corpse::GetLootList(lua_State* L) {
|
||||||
|
Lua_Safe_Call_Class(Lua_Corpse_Loot_List);
|
||||||
|
Lua_Corpse_Loot_List ret;
|
||||||
|
auto loot_list = self->GetLootList();
|
||||||
|
|
||||||
|
for (auto item_id : loot_list) {
|
||||||
|
ret.entries.push_back(item_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
luabind::scope lua_register_corpse() {
|
luabind::scope lua_register_corpse() {
|
||||||
return luabind::class_<Lua_Corpse, Lua_Mob>("Corpse")
|
return luabind::class_<Lua_Corpse, Lua_Mob>("Corpse")
|
||||||
.def(luabind::constructor<>())
|
.def(luabind::constructor<>())
|
||||||
@ -209,7 +226,13 @@ luabind::scope lua_register_corpse() {
|
|||||||
.def("HasItem", (bool(Lua_Corpse::*)(uint32))&Lua_Corpse::HasItem)
|
.def("HasItem", (bool(Lua_Corpse::*)(uint32))&Lua_Corpse::HasItem)
|
||||||
.def("CountItem", (uint16(Lua_Corpse::*)(uint32))&Lua_Corpse::CountItem)
|
.def("CountItem", (uint16(Lua_Corpse::*)(uint32))&Lua_Corpse::CountItem)
|
||||||
.def("GetItemIDBySlot", (uint32(Lua_Corpse::*)(uint16))&Lua_Corpse::GetItemIDBySlot)
|
.def("GetItemIDBySlot", (uint32(Lua_Corpse::*)(uint16))&Lua_Corpse::GetItemIDBySlot)
|
||||||
.def("GetFirstSlotByItemID", (uint16(Lua_Corpse::*)(uint32))&Lua_Corpse::GetFirstSlotByItemID);
|
.def("GetFirstSlotByItemID", (uint16(Lua_Corpse::*)(uint32))&Lua_Corpse::GetFirstSlotByItemID)
|
||||||
|
.def("GetLootList", (Lua_Corpse_Loot_List(Lua_Corpse::*)(lua_State* L))&Lua_Corpse::GetLootList);
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::scope lua_register_corpse_loot_list() {
|
||||||
|
return luabind::class_<Lua_Corpse_Loot_List>("CorpseLootList")
|
||||||
|
.def_readwrite("entries", &Lua_Corpse_Loot_List::entries, luabind::return_stl_iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -6,12 +6,14 @@
|
|||||||
|
|
||||||
class Corpse;
|
class Corpse;
|
||||||
class Lua_Client;
|
class Lua_Client;
|
||||||
|
struct Lua_Corpse_Loot_List;
|
||||||
|
|
||||||
namespace luabind {
|
namespace luabind {
|
||||||
struct scope;
|
struct scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
luabind::scope lua_register_corpse();
|
luabind::scope lua_register_corpse();
|
||||||
|
luabind::scope lua_register_corpse_loot_list();
|
||||||
|
|
||||||
class Lua_Corpse : public Lua_Mob
|
class Lua_Corpse : public Lua_Mob
|
||||||
{
|
{
|
||||||
@ -58,6 +60,7 @@ public:
|
|||||||
uint16 CountItem(uint32 item_id);
|
uint16 CountItem(uint32 item_id);
|
||||||
uint32 GetItemIDBySlot(uint16 loot_slot);
|
uint32 GetItemIDBySlot(uint16 loot_slot);
|
||||||
uint16 GetFirstSlotByItemID(uint32 item_id);
|
uint16 GetFirstSlotByItemID(uint32 item_id);
|
||||||
|
Lua_Corpse_Loot_List GetLootList(lua_State* L);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -2,11 +2,16 @@
|
|||||||
|
|
||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
#include <luabind/luabind.hpp>
|
#include <luabind/luabind.hpp>
|
||||||
|
#include <luabind/iterator_policy.hpp>
|
||||||
|
|
||||||
#include "npc.h"
|
#include "npc.h"
|
||||||
#include "lua_npc.h"
|
#include "lua_npc.h"
|
||||||
#include "lua_client.h"
|
#include "lua_client.h"
|
||||||
|
|
||||||
|
struct Lua_NPC_Loot_List {
|
||||||
|
std::vector<uint32> entries;
|
||||||
|
};
|
||||||
|
|
||||||
void Lua_NPC::Signal(int id) {
|
void Lua_NPC::Signal(int id) {
|
||||||
Lua_Safe_Call_Void();
|
Lua_Safe_Call_Void();
|
||||||
self->SignalNPC(id);
|
self->SignalNPC(id);
|
||||||
@ -618,6 +623,18 @@ float Lua_NPC::GetSpellScale()
|
|||||||
return self->GetSpellScale();
|
return self->GetSpellScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lua_NPC_Loot_List Lua_NPC::GetLootList(lua_State* L) {
|
||||||
|
Lua_Safe_Call_Class(Lua_NPC_Loot_List);
|
||||||
|
Lua_NPC_Loot_List ret;
|
||||||
|
auto loot_list = self->GetLootList();
|
||||||
|
|
||||||
|
for (auto item_id : loot_list) {
|
||||||
|
ret.entries.push_back(item_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
luabind::scope lua_register_npc() {
|
luabind::scope lua_register_npc() {
|
||||||
return luabind::class_<Lua_NPC, Lua_Mob>("NPC")
|
return luabind::class_<Lua_NPC, Lua_Mob>("NPC")
|
||||||
.def(luabind::constructor<>())
|
.def(luabind::constructor<>())
|
||||||
@ -740,7 +757,13 @@ luabind::scope lua_register_npc() {
|
|||||||
.def("GetItemIDBySlot", (uint32(Lua_NPC::*)(uint16))&Lua_NPC::GetItemIDBySlot)
|
.def("GetItemIDBySlot", (uint32(Lua_NPC::*)(uint16))&Lua_NPC::GetItemIDBySlot)
|
||||||
.def("GetFirstSlotByItemID", (uint16(Lua_NPC::*)(uint32))&Lua_NPC::GetFirstSlotByItemID)
|
.def("GetFirstSlotByItemID", (uint16(Lua_NPC::*)(uint32))&Lua_NPC::GetFirstSlotByItemID)
|
||||||
.def("GetHealScale", (float(Lua_NPC::*)(void))&Lua_NPC::GetHealScale)
|
.def("GetHealScale", (float(Lua_NPC::*)(void))&Lua_NPC::GetHealScale)
|
||||||
.def("GetSpellScale", (float(Lua_NPC::*)(void))&Lua_NPC::GetSpellScale);
|
.def("GetSpellScale", (float(Lua_NPC::*)(void))&Lua_NPC::GetSpellScale)
|
||||||
|
.def("GetLootList", (Lua_NPC_Loot_List(Lua_NPC::*)(lua_State* L))&Lua_NPC::GetLootList);
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::scope lua_register_npc_loot_list() {
|
||||||
|
return luabind::class_<Lua_NPC_Loot_List>("NPCLootList")
|
||||||
|
.def_readwrite("entries", &Lua_NPC_Loot_List::entries, luabind::return_stl_iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -8,12 +8,14 @@ class NPC;
|
|||||||
class Lua_Mob;
|
class Lua_Mob;
|
||||||
class Lua_NPC;
|
class Lua_NPC;
|
||||||
class Lua_Client;
|
class Lua_Client;
|
||||||
|
struct Lua_NPC_Loot_List;
|
||||||
|
|
||||||
namespace luabind {
|
namespace luabind {
|
||||||
struct scope;
|
struct scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
luabind::scope lua_register_npc();
|
luabind::scope lua_register_npc();
|
||||||
|
luabind::scope lua_register_npc_loot_list();
|
||||||
|
|
||||||
class Lua_NPC : public Lua_Mob
|
class Lua_NPC : public Lua_Mob
|
||||||
{
|
{
|
||||||
@ -146,6 +148,7 @@ public:
|
|||||||
uint16 GetFirstSlotByItemID(uint32 item_id);
|
uint16 GetFirstSlotByItemID(uint32 item_id);
|
||||||
float GetHealScale();
|
float GetHealScale();
|
||||||
float GetSpellScale();
|
float GetSpellScale();
|
||||||
|
Lua_NPC_Loot_List GetLootList(lua_State* L);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1121,6 +1121,8 @@ void LuaParser::MapFunctions(lua_State *L) {
|
|||||||
lua_register_object_list(),
|
lua_register_object_list(),
|
||||||
lua_register_door_list(),
|
lua_register_door_list(),
|
||||||
lua_register_spawn_list(),
|
lua_register_spawn_list(),
|
||||||
|
lua_register_corpse_loot_list(),
|
||||||
|
lua_register_npc_loot_list(),
|
||||||
lua_register_group(),
|
lua_register_group(),
|
||||||
lua_register_raid(),
|
lua_register_raid(),
|
||||||
lua_register_corpse(),
|
lua_register_corpse(),
|
||||||
|
|||||||
22
zone/npc.cpp
22
zone/npc.cpp
@ -682,12 +682,12 @@ bool NPC::HasItem(uint32 item_id) {
|
|||||||
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
||||||
ServerLootItem_Struct* loot_item = *current_item;
|
ServerLootItem_Struct* loot_item = *current_item;
|
||||||
if (!loot_item) {
|
if (!loot_item) {
|
||||||
LogError("NPC::CountItem() - ItemList error, null item");
|
LogError("NPC::HasItem() - ItemList error, null item");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) {
|
if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) {
|
||||||
LogError("NPC::CountItem() - Database error, invalid item");
|
LogError("NPC::HasItem() - Database error, invalid item");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3474,3 +3474,21 @@ bool NPC::IsGuard()
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<int> NPC::GetLootList() {
|
||||||
|
std::vector<int> npc_items;
|
||||||
|
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
||||||
|
ServerLootItem_Struct* loot_item = *current_item;
|
||||||
|
if (!loot_item) {
|
||||||
|
LogError("NPC::GetLootList() - ItemList error, null item");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::find(npc_items.begin(), npc_items.end(), loot_item->item_id) != npc_items.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
npc_items.push_back(loot_item->item_id);
|
||||||
|
}
|
||||||
|
return npc_items;
|
||||||
|
}
|
||||||
|
|||||||
@ -208,6 +208,7 @@ public:
|
|||||||
uint16 CountItem(uint32 item_id);
|
uint16 CountItem(uint32 item_id);
|
||||||
uint32 GetItemIDBySlot(uint16 loot_slot);
|
uint32 GetItemIDBySlot(uint16 loot_slot);
|
||||||
uint16 GetFirstSlotByItemID(uint32 item_id);
|
uint16 GetFirstSlotByItemID(uint32 item_id);
|
||||||
|
std::vector<int> GetLootList();
|
||||||
uint32 CountLoot();
|
uint32 CountLoot();
|
||||||
inline uint32 GetLoottableID() const { return loottable_id; }
|
inline uint32 GetLoottableID() const { return loottable_id; }
|
||||||
virtual void UpdateEquipmentLight();
|
virtual void UpdateEquipmentLight();
|
||||||
|
|||||||
@ -1846,6 +1846,29 @@ XS(XS_NPC_GetSpellScale) {
|
|||||||
XSRETURN(1);
|
XSRETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS_NPC_GetLootList);
|
||||||
|
XS(XS_NPC_GetLootList) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 1)
|
||||||
|
Perl_croak(aTHX_ "Usage: NPC::GetLootList(THIS)"); // @categories Script Utility
|
||||||
|
{
|
||||||
|
NPC *THIS;
|
||||||
|
VALIDATE_THIS_IS_NPC;
|
||||||
|
auto npc_items = THIS->GetLootList();
|
||||||
|
auto item_count = npc_items.size();
|
||||||
|
if (item_count > 0) {
|
||||||
|
EXTEND(sp, item_count);
|
||||||
|
for (int index = 0; index < item_count; ++index) {
|
||||||
|
ST(index) = sv_2mortal(newSVuv(npc_items[index]));
|
||||||
|
}
|
||||||
|
XSRETURN(item_count);
|
||||||
|
}
|
||||||
|
SV* return_value = &PL_sv_undef;
|
||||||
|
ST(0) = return_value;
|
||||||
|
XSRETURN(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
#endif
|
#endif
|
||||||
@ -1970,6 +1993,7 @@ XS(boot_NPC) {
|
|||||||
newXSproto(strcpy(buf, "GetFirstSlotByItemID"), XS_NPC_GetFirstSlotByItemID, file, "$$");
|
newXSproto(strcpy(buf, "GetFirstSlotByItemID"), XS_NPC_GetFirstSlotByItemID, file, "$$");
|
||||||
newXSproto(strcpy(buf, "GetHealScale"), XS_NPC_GetHealScale, file, "$");
|
newXSproto(strcpy(buf, "GetHealScale"), XS_NPC_GetHealScale, file, "$");
|
||||||
newXSproto(strcpy(buf, "GetSpellScale"), XS_NPC_GetSpellScale, file, "$");
|
newXSproto(strcpy(buf, "GetSpellScale"), XS_NPC_GetSpellScale, file, "$");
|
||||||
|
newXSproto(strcpy(buf, "GetLootList"), XS_NPC_GetLootList, file, "$");
|
||||||
XSRETURN_YES;
|
XSRETURN_YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -599,6 +599,29 @@ XS(XS_Corpse_GetFirstSlotByItemID) {
|
|||||||
XSRETURN(1);
|
XSRETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS_Corpse_GetLootList);
|
||||||
|
XS(XS_Corpse_GetLootList) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 1)
|
||||||
|
Perl_croak(aTHX_ "Usage: Corpse::GetLootList(THIS)"); // @categories Script Utility
|
||||||
|
{
|
||||||
|
Corpse *THIS;
|
||||||
|
VALIDATE_THIS_IS_CORPSE;
|
||||||
|
auto corpse_items = THIS->GetLootList();
|
||||||
|
auto item_count = corpse_items.size();
|
||||||
|
if (item_count > 0) {
|
||||||
|
EXTEND(sp, item_count);
|
||||||
|
for (int index = 0; index < item_count; ++index) {
|
||||||
|
ST(index) = sv_2mortal(newSVuv(corpse_items[index]));
|
||||||
|
}
|
||||||
|
XSRETURN(item_count);
|
||||||
|
}
|
||||||
|
SV* return_value = &PL_sv_undef;
|
||||||
|
ST(0) = return_value;
|
||||||
|
XSRETURN(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
#endif
|
#endif
|
||||||
@ -649,6 +672,7 @@ XS(boot_Corpse) {
|
|||||||
newXSproto(strcpy(buf, "CountItem"), XS_Corpse_CountItem, file, "$$");
|
newXSproto(strcpy(buf, "CountItem"), XS_Corpse_CountItem, file, "$$");
|
||||||
newXSproto(strcpy(buf, "GetItemIDBySlot"), XS_Corpse_GetItemIDBySlot, file, "$$");
|
newXSproto(strcpy(buf, "GetItemIDBySlot"), XS_Corpse_GetItemIDBySlot, file, "$$");
|
||||||
newXSproto(strcpy(buf, "GetFirstSlotByItemID"), XS_Corpse_GetFirstSlotByItemID, file, "$$");
|
newXSproto(strcpy(buf, "GetFirstSlotByItemID"), XS_Corpse_GetFirstSlotByItemID, file, "$$");
|
||||||
|
newXSproto(strcpy(buf, "GetLootList"), XS_Corpse_GetLootList, file, "$");
|
||||||
XSRETURN_YES;
|
XSRETURN_YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user