[Commands] Convert NPC Spawn Methods to Repositories (#3956)

* [Commands] Convert NPC Spawn Methods to Repositories

# Notes
- Convert `AddNewNPCSpawnGroupCommand()`, `AddNPCTypes()`, `AddSpawnFromSpawnGroup()`, `CreateNewNPCCommand()`, `DeleteSpawnLeaveInNPCTypeTable()`, `DeleteSpawnRemoveFromNPCTypeTable()`, `NPCSpawnDB()`, and `UpdateNPCTypeAppearance()`.

* Regenerate.

* Cleanup.
This commit is contained in:
Alex King 2024-01-13 00:02:19 -05:00 committed by GitHub
parent 6968a70310
commit e182d685d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 309 additions and 248 deletions

View File

@ -16,6 +16,7 @@
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseSpawngroupRepository { class BaseSpawngroupRepository {
public: public:
struct Spawngroup { struct Spawngroup {

View File

@ -44,7 +44,32 @@ public:
*/ */
// Custom extended repository methods here // Custom extended repository methods here
static uint32 GetOpenIDInZoneRange(Database& db, uint32 zone_id)
{
const uint32 min_id = zone_id * 1000;
const uint32 max_id = min_id + 999;
auto results = db.QueryDatabase(
fmt::format(
"SELECT MAX({}) FROM `{}` WHERE `{}` BETWEEN {} AND {}",
PrimaryKey(),
TableName(),
PrimaryKey(),
min_id,
max_id
)
);
if (!results.Success() || !results.RowCount()) {
return 0;
}
auto row = results.begin();
const uint32 npc_id = row[0] ? Strings::ToUnsignedInt(row[0]) + 1 : 0;
return npc_id < max_id ? npc_id : 0;
}
}; };
#endif //EQEMU_NPC_TYPES_REPOSITORY_H #endif //EQEMU_NPC_TYPES_REPOSITORY_H

View File

@ -32,6 +32,11 @@
#include "../common/say_link.h" #include "../common/say_link.h"
#include "../common/data_verification.h" #include "../common/data_verification.h"
#include "../common/repositories/npc_types_repository.h"
#include "../common/repositories/spawngroup_repository.h"
#include "../common/repositories/spawn2_repository.h"
#include "../common/repositories/spawnentry_repository.h"
#include "client.h" #include "client.h"
#include "entity.h" #include "entity.h"
#include "npc.h" #include "npc.h"
@ -1459,96 +1464,80 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
} }
uint32 ZoneDatabase::CreateNewNPCCommand( uint32 ZoneDatabase::CreateNewNPCCommand(
const char *zone, const std::string& zone,
uint32 zone_version, uint32 instance_version,
Client *client, Client* c,
NPC *spawn, NPC* n,
uint32 extra uint32 extra
) )
{ {
uint32 npc_type_id = 0; auto e = NpcTypesRepository::NewEntity();
if (extra && client && client->GetZoneID()) { e.id = NpcTypesRepository::GetOpenIDInZoneRange(*this, c->GetZoneID());
// Set an npc_type ID within the standard range for the current zone if possible (zone_id * 1000) e.name = Strings::RemoveNumbers(n->GetName());
int starting_npc_id = client->GetZoneID() * 1000; e.level = n->GetLevel();
e.race = n->GetRace();
e.class_ = n->GetClass();
e.hp = n->GetMaxHP();
e.gender = n->GetGender();
e.texture = n->GetTexture();
e.helmtexture = n->GetHelmTexture();
e.size = n->GetSize();
e.loottable_id = n->GetLoottableID();
e.merchant_id = n->MerchantType;
e.runspeed = n->GetRunspeed();
e.prim_melee_type = static_cast<uint8_t>(EQ::skills::SkillHandtoHand);
e.sec_melee_type = static_cast<uint8_t>(EQ::skills::SkillHandtoHand);
std::string query = StringFormat( e = NpcTypesRepository::InsertOne(*this, e);
"SELECT MAX(id) FROM npc_types WHERE id >= %i AND id < %i",
starting_npc_id, if (!e.id) {
starting_npc_id + 1000 return false;
}
auto sg = SpawngroupRepository::NewEntity();
sg.name = fmt::format(
"{}-{}",
zone,
n->GetName()
); );
auto results = QueryDatabase(query); sg = SpawngroupRepository::InsertOne(*this, sg);
if (results.Success()) {
if (results.RowCount() != 0) {
auto row = results.begin();
npc_type_id = Strings::ToInt(row[0]) + 1;
// Prevent the npc_type id from exceeding the range for this zone
if (npc_type_id >= (starting_npc_id + 1000)) {
npc_type_id = 0;
}
}
else { // No npc_type IDs set in this range yet
npc_type_id = starting_npc_id;
}
}
}
char tmpstr[64]; if (!sg.id) {
EntityList::RemoveNumbers(strn0cpy(tmpstr, spawn->GetName(), sizeof(tmpstr)));
std::string query;
if (npc_type_id) {
query = StringFormat("INSERT INTO npc_types (id, name, level, race, class, hp, gender, "
"texture, helmtexture, size, loottable_id, merchant_id, face, "
"runspeed, prim_melee_type, sec_melee_type) "
"VALUES(%i, \"%s\" , %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %i, %i, %i)",
npc_type_id, tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(),
spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(),
spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(),
spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
npc_type_id = results.LastInsertedID();
} else {
query = StringFormat("INSERT INTO npc_types (name, level, race, class, hp, gender, "
"texture, helmtexture, size, loottable_id, merchant_id, face, "
"runspeed, prim_melee_type, sec_melee_type) "
"VALUES(\"%s\", %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %i, %i, %i)",
tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(),
spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(),
spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
npc_type_id = results.LastInsertedID();
}
query = StringFormat("INSERT INTO spawngroup (id, name) VALUES(%i, '%s-%s')", 0, zone, spawn->GetName());
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
uint32 spawngroupid = results.LastInsertedID();
spawn->SetSpawnGroupId(spawngroupid);
spawn->SetNPCTypeID(npc_type_id);
query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), 1200, spawn->GetHeading(),
spawngroupid);
results = QueryDatabase(query);
if (!results.Success()) {
return false; return false;
} }
query = StringFormat("INSERT INTO spawnentry (spawngroupID, npcID, chance) VALUES(%i, %i, %i)", spawngroupid, n->SetSpawnGroupId(sg.id);
npc_type_id, 100); n->SetNPCTypeID(e.id);
results = QueryDatabase(query);
if (!results.Success()) { auto s2 = Spawn2Repository::NewEntity();
s2.zone = zone;
s2.version = instance_version;
s2.x = n->GetX();
s2.y = n->GetY();
s2.z = n->GetZ();
s2.respawntime = 1200;
s2.heading = n->GetHeading();
s2.spawngroupID = sg.id;
s2 = Spawn2Repository::InsertOne(*this, s2);
if (!s2.id) {
return false;
}
auto se = SpawnentryRepository::NewEntity();
se.spawngroupID = sg.id;
se.npcID = e.id;
se.chance = 100;
se = SpawnentryRepository::InsertOne(*this, se);
if (!se.spawngroupID) {
return false; return false;
} }
@ -1556,227 +1545,273 @@ uint32 ZoneDatabase::CreateNewNPCCommand(
} }
uint32 ZoneDatabase::AddNewNPCSpawnGroupCommand( uint32 ZoneDatabase::AddNewNPCSpawnGroupCommand(
const char *zone, const std::string& zone,
uint32 zone_version, uint32 instance_version,
Client *client, Client* c,
NPC *spawn, NPC* n,
uint32 respawnTime uint32 in_respawn_time
) )
{ {
uint32 last_insert_id = 0; auto sg = SpawngroupRepository::InsertOne(
*this,
std::string query = fmt::format( SpawngroupRepository::Spawngroup{
"INSERT INTO spawngroup (name) VALUES('{}{}{}')", .name = fmt::format(
"{}_{}_{}",
zone, zone,
Strings::Escape(spawn->GetName()), Strings::Escape(n->GetName()),
Timer::GetCurrentTime() Timer::GetCurrentTime()
)
}
); );
auto results = QueryDatabase(query); if (!sg.id) {
if (!results.Success()) {
return 0;
}
last_insert_id = results.LastInsertedID();
uint32 respawntime = 0;
uint32 spawnid = 0;
if (respawnTime) {
respawntime = respawnTime;
}
else if (spawn->respawn2 && spawn->respawn2->RespawnTimer() != 0) {
respawntime = spawn->respawn2->RespawnTimer();
}
else {
respawntime = 1200;
}
query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), respawntime,
spawn->GetHeading(), last_insert_id);
results = QueryDatabase(query);
if (!results.Success()) {
return 0;
}
spawnid = results.LastInsertedID();
query = StringFormat("INSERT INTO spawnentry (spawngroupID, npcID, chance) VALUES(%i, %i, %i)", last_insert_id,
spawn->GetNPCTypeID(), 100);
results = QueryDatabase(query);
if (!results.Success()) {
return 0; return 0;
} }
return spawnid; uint32 respawn_time = 1200;
uint32 spawn_id = 0;
if (in_respawn_time) {
respawn_time = in_respawn_time;
} else if (n->respawn2 && n->respawn2->RespawnTimer()) {
respawn_time = n->respawn2->RespawnTimer();
}
auto s2 = Spawn2Repository::NewEntity();
s2.zone = zone;
s2.version = instance_version;
s2.x = n->GetX();
s2.y = n->GetY();
s2.z = n->GetZ();
s2.heading = n->GetHeading();
s2.respawntime = respawn_time;
s2.spawngroupID = sg.id;
s2 = Spawn2Repository::InsertOne(*this, s2);
if (!s2.id) {
return 0;
}
auto se = SpawnentryRepository::NewEntity();
se.spawngroupID = sg.id;
se.npcID = n->GetNPCTypeID();
se.chance = 100;
se = SpawnentryRepository::InsertOne(*this, se);
if (!se.spawngroupID) {
return 0;
}
return s2.id;
} }
uint32 ZoneDatabase::UpdateNPCTypeAppearance(Client *client, NPC *spawn) uint32 ZoneDatabase::UpdateNPCTypeAppearance(Client* c, NPC* n)
{ {
std::string query = auto e = NpcTypesRepository::FindOne(*this, n->GetNPCTypeID());
StringFormat("UPDATE npc_types SET name = '%s', level = '%i', race = '%i', class = '%i', "
"hp = '%i', gender = '%i', texture = '%i', helmtexture = '%i', size = '%i', " e.name = Strings::RemoveNumbers(n->GetName());
"loottable_id = '%i', merchant_id = '%i', face = '%i' " e.level = n->GetLevel();
"WHERE id = '%i'", e.race = n->GetRace();
spawn->GetName(), spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), e.class_ = n->GetClass();
spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), e.hp = n->GetMaxHP();
spawn->GetLoottableID(), spawn->MerchantType, spawn->GetLuclinFace(), spawn->GetNPCTypeID()); e.gender = n->GetGender();
auto results = QueryDatabase(query); e.texture = n->GetTexture();
return results.Success() == true ? 1 : 0; e.helmtexture = n->GetHelmTexture();
e.size = n->GetSize();
e.loottable_id = n->GetLoottableID();
e.merchant_id = n->MerchantType;
e.face = n->GetLuclinFace();
const int updated = NpcTypesRepository::UpdateOne(*this, e);
return updated;
} }
uint32 ZoneDatabase::DeleteSpawnLeaveInNPCTypeTable(const char *zone, Client *client, NPC *spawn) uint32 ZoneDatabase::DeleteSpawnLeaveInNPCTypeTable(const std::string& zone, Client* c, NPC* n)
{ {
uint32 id = 0; const auto& l = Spawn2Repository::GetWhere(
uint32 spawngroupID = 0; *this,
fmt::format(
"`zone` = '{}' AND `spawngroupID` = {}",
zone,
n->GetSpawnGroupId()
)
);
std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE " if (l.empty()) {
"zone='%s' AND spawngroupID=%i",
zone, spawn->GetSpawnGroupId());
auto results = QueryDatabase(query);
if (!results.Success())
return 0; return 0;
}
if (results.RowCount() == 0) auto e = l.front();
if (!Spawn2Repository::DeleteOne(*this, e.id)) {
return 0; return 0;
}
auto row = results.begin(); if (!SpawngroupRepository::DeleteOne(*this, e.spawngroupID)) {
if (row[0])
id = Strings::ToInt(row[0]);
if (row[1])
spawngroupID = Strings::ToInt(row[1]);
query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id);
results = QueryDatabase(query);
if (!results.Success())
return 0; return 0;
}
query = StringFormat("DELETE FROM spawngroup WHERE id = '%i'", spawngroupID); if (!SpawnentryRepository::DeleteOne(*this, e.spawngroupID)) {
results = QueryDatabase(query);
if (!results.Success())
return 0;
query = StringFormat("DELETE FROM spawnentry WHERE spawngroupID = '%i'", spawngroupID);
results = QueryDatabase(query);
if (!results.Success())
return 0; return 0;
}
return 1; return 1;
} }
uint32 ZoneDatabase::DeleteSpawnRemoveFromNPCTypeTable(const char *zone, uint32 zone_version, Client *client, uint32 ZoneDatabase::DeleteSpawnRemoveFromNPCTypeTable(
NPC *spawn) const std::string& zone,
uint32 instance_version,
Client* c,
NPC* n
)
{ {
uint32 id = 0; const auto& l = Spawn2Repository::GetWhere(
uint32 spawngroupID = 0; *this,
fmt::format(
"`zone` = '{}' AND (`version` = {} OR `version` = -1) AND `spawngroupID` = {}",
zone,
instance_version,
n->GetSpawnGroupId()
)
);
std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE zone = '%s' " if (l.empty()) {
"AND (version = %u OR version = -1) AND spawngroupID = %i",
zone, zone_version, spawn->GetSpawnGroupId());
auto results = QueryDatabase(query);
if (!results.Success())
return 0; return 0;
}
if (results.RowCount() == 0) auto e = l.front();
if (!Spawn2Repository::DeleteOne(*this, e.id)) {
return 0; return 0;
}
auto row = results.begin(); if (!SpawngroupRepository::DeleteOne(*this, e.spawngroupID)) {
if (row[0])
id = Strings::ToInt(row[0]);
if (row[1])
spawngroupID = Strings::ToInt(row[1]);
query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id);
results = QueryDatabase(query);
if (!results.Success())
return 0; return 0;
}
query = StringFormat("DELETE FROM spawngroup WHERE id = '%i'", spawngroupID); if (!SpawnentryRepository::DeleteOne(*this, e.spawngroupID)) {
results = QueryDatabase(query);
if (!results.Success())
return 0; return 0;
}
query = StringFormat("DELETE FROM spawnentry WHERE spawngroupID = '%i'", spawngroupID); if (!NpcTypesRepository::DeleteOne(*this, n->GetNPCTypeID())) {
results = QueryDatabase(query);
if (!results.Success())
return 0;
query = StringFormat("DELETE FROM npc_types WHERE id = '%i'", spawn->GetNPCTypeID());
results = QueryDatabase(query);
if (!results.Success())
return 0; return 0;
}
return 1; return 1;
} }
uint32 ZoneDatabase::AddSpawnFromSpawnGroup(const char *zone, uint32 zone_version, Client *client, NPC *spawn, uint32 ZoneDatabase::AddSpawnFromSpawnGroup(
uint32 spawnGroupID) const std::string& zone,
uint32 instance_version,
Client* c,
NPC* n,
uint32 spawngroup_id
)
{ {
uint32 last_insert_id = 0; auto e = Spawn2Repository::NewEntity();
std::string query =
StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) " e.zone = zone;
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)", e.version = instance_version;
zone, zone_version, client->GetX(), client->GetY(), client->GetZ(), 120, client->GetHeading(), e.x = c->GetX();
spawnGroupID); e.y = c->GetY();
auto results = QueryDatabase(query); e.z = c->GetZ();
if (!results.Success()) e.heading = c->GetHeading();
e.respawntime = 120;
e.spawngroupID = spawngroup_id;
e = Spawn2Repository::InsertOne(*this, e);
if (!e.id) {
return 0; return 0;
}
return 1; return 1;
} }
uint32 ZoneDatabase::AddNPCTypes(const char *zone, uint32 zone_version, Client *client, NPC *spawn, uint32 spawnGroupID) uint32 ZoneDatabase::AddNPCTypes(
const std::string& zone,
uint32 instance_version,
Client* c,
NPC* n,
uint32 spawngroup_id
)
{ {
uint32 npc_type_id; auto e = NpcTypesRepository::NewEntity();
char numberlessName[64];
EntityList::RemoveNumbers(strn0cpy(numberlessName, spawn->GetName(), sizeof(numberlessName))); e.name = Strings::RemoveNumbers(n->GetName());
std::string query = e.level = n->GetLevel();
StringFormat("INSERT INTO npc_types (name, level, race, class, hp, gender, " e.race = n->GetRace();
"texture, helmtexture, size, loottable_id, merchant_id, face, " e.class_ = n->GetClass();
"runspeed, prim_melee_type, sec_melee_type) " e.hp = n->GetMaxHP();
"VALUES(\"%s\", %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)", e.gender = n->GetGender();
numberlessName, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), e.texture = n->GetTexture();
spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), e.helmtexture = n->GetHelmTexture();
spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28); e.size = n->GetSize();
auto results = QueryDatabase(query); e.loottable_id = n->GetLoottableID();
if (!results.Success()) e.merchant_id = n->MerchantType;
e.face = n->GetLuclinFace();
e.runspeed = n->GetRunspeed();
e.prim_melee_type = static_cast<uint8_t>(EQ::skills::SkillHandtoHand);
e.sec_melee_type = static_cast<uint8_t>(EQ::skills::SkillHandtoHand);
e = NpcTypesRepository::InsertOne(*this, e);
if (!e.id) {
return 0; return 0;
npc_type_id = results.LastInsertedID(); }
if (client) if (c) {
client->Message(Chat::White, "%s npc_type ID %i created successfully!", numberlessName, npc_type_id); c->Message(
Chat::White,
fmt::format(
"NPC Created | ID: {} Name: {}",
e.id,
e.name
).c_str()
);
}
return 1; return 1;
} }
uint32 ZoneDatabase::NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn, uint32 extra) { uint32 ZoneDatabase::NPCSpawnDB(
uint8 command,
const std::string& zone,
uint32 instance_version,
Client *c,
NPC* n,
uint32 extra
)
{
switch (command) { switch (command) {
case NPCSpawnTypes::CreateNewSpawn: { // Create a new NPC and add all spawn related data case NPCSpawnTypes::CreateNewSpawn: {
return CreateNewNPCCommand(zone, zone_version, c, spawn, extra); return CreateNewNPCCommand(zone, instance_version, c, n, extra);
} }
case NPCSpawnTypes::AddNewSpawngroup: { // Add new spawn group and spawn point for an existing NPC Type ID case NPCSpawnTypes::AddNewSpawngroup: {
return AddNewNPCSpawnGroupCommand(zone, zone_version, c, spawn, extra); return AddNewNPCSpawnGroupCommand(zone, instance_version, c, n, extra);
} }
case NPCSpawnTypes::UpdateAppearance: { // Update npc_type appearance and other data on targeted spawn case NPCSpawnTypes::UpdateAppearance: {
return UpdateNPCTypeAppearance(c, spawn); return UpdateNPCTypeAppearance(c, n);
} }
case NPCSpawnTypes::RemoveSpawn: { // delete spawn from spawning, but leave in npc_types table case NPCSpawnTypes::RemoveSpawn: {
return DeleteSpawnLeaveInNPCTypeTable(zone, c, spawn); return DeleteSpawnLeaveInNPCTypeTable(zone, c, n);
} }
case NPCSpawnTypes::DeleteSpawn: { //delete spawn from DB (including npc_type) case NPCSpawnTypes::DeleteSpawn: {
return DeleteSpawnRemoveFromNPCTypeTable(zone, zone_version, c, spawn); return DeleteSpawnRemoveFromNPCTypeTable(zone, instance_version, c, n);
} }
case NPCSpawnTypes::AddSpawnFromSpawngroup: { // add a spawn from spawngroup case NPCSpawnTypes::AddSpawnFromSpawngroup: {
return AddSpawnFromSpawnGroup(zone, zone_version, c, spawn, extra); return AddSpawnFromSpawnGroup(zone, instance_version, c, n, extra);
} }
case NPCSpawnTypes::CreateNewNPC: { // add npc_type case NPCSpawnTypes::CreateNewNPC: {
return AddNPCTypes(zone, zone_version, c, spawn, extra); return AddNPCTypes(zone, instance_version, c, n, extra);
} }
} }
return false; return false;
} }

View File

@ -551,14 +551,14 @@ public:
/* NPCs */ /* NPCs */
uint32 NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn = 0, uint32 extra = 0); // 0 = Create 1 = Add; 2 = Update; 3 = Remove; 4 = Delete uint32 NPCSpawnDB(uint8 command, const std::string& zone, uint32 instance_version, Client *c, NPC* n = 0, uint32 extra = 0); // 0 = Create 1 = Add; 2 = Update; 3 = Remove; 4 = Delete
uint32 CreateNewNPCCommand(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 extra); uint32 CreateNewNPCCommand(const std::string& zone, uint32 instance_version, Client* c, NPC* n, uint32 extra);
uint32 AddNewNPCSpawnGroupCommand(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 respawnTime); uint32 AddNewNPCSpawnGroupCommand(const std::string& zone, uint32 instance_version, Client* c, NPC* n, uint32 in_respawn_time);
uint32 DeleteSpawnLeaveInNPCTypeTable(const char* zone, Client *client, NPC* spawn); uint32 DeleteSpawnLeaveInNPCTypeTable(const std::string& zone, Client* c, NPC* n);
uint32 DeleteSpawnRemoveFromNPCTypeTable(const char* zone, uint32 zone_version, Client *client, NPC* spawn); uint32 DeleteSpawnRemoveFromNPCTypeTable(const std::string& zone, uint32 instance_version, Client* c, NPC* n);
uint32 AddSpawnFromSpawnGroup(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 spawnGroupID); uint32 AddSpawnFromSpawnGroup(const std::string& zone, uint32 instance_version, Client* c, NPC* n, uint32 spawngroup_id);
uint32 AddNPCTypes(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 spawnGroupID); uint32 AddNPCTypes(const std::string& zone, uint32 instance_version, Client* c, NPC* n, uint32 spawngroup_id);
uint32 UpdateNPCTypeAppearance(Client *client, NPC* spawn); uint32 UpdateNPCTypeAppearance(Client* c, NPC* n);
bool SetSpecialAttkFlag(uint8 id, const char* flag); bool SetSpecialAttkFlag(uint8 id, const char* flag);
bool GetPetEntry(const std::string& pet_type, PetRecord* r); bool GetPetEntry(const std::string& pet_type, PetRecord* r);
bool GetPoweredPetEntry(const std::string& pet_type, int16 pet_power, PetRecord* r); bool GetPoweredPetEntry(const std::string& pet_type, int16 pet_power, PetRecord* r);