From 2e0ed82986e2a837496bd666df965086b05f2a41 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Mon, 29 Jan 2024 00:37:34 -0500 Subject: [PATCH] [Grids] Convert Grid/Grid Entries to Repositories (#4011) * [Grids] Convert Grid/Grid Entries to Repositories - Convert `AddWaypoint()`, `AddWaypointForSpawn()`, `DeleteWaypoint()`, `GetHighestWaypoint()`, `GetRandomWaypointFromGrid()`, `GridExistsInZone()`, and `ModifyGrid()` to repositories. * Update grid.cpp * Update questmgr.cpp * Update waypoints.cpp * Update waypoints.cpp --- common/repositories/grid_entries_repository.h | 42 ++ common/repositories/grid_repository.h | 21 + common/repositories/spawn2_repository.h | 28 ++ zone/gm_commands/grid.cpp | 190 +++++---- zone/gm_commands/wp.cpp | 4 +- zone/gm_commands/wpadd.cpp | 2 +- zone/questmgr.cpp | 59 +-- zone/questmgr.h | 2 +- zone/spawn2.cpp | 2 +- zone/waypoints.cpp | 375 ++++++++---------- zone/zonedb.h | 20 +- 11 files changed, 418 insertions(+), 327 deletions(-) diff --git a/common/repositories/grid_entries_repository.h b/common/repositories/grid_entries_repository.h index 7a9712d64..8be3c6ae0 100644 --- a/common/repositories/grid_entries_repository.h +++ b/common/repositories/grid_entries_repository.h @@ -76,6 +76,48 @@ public: return grid_entries; } + static int GetHighestWaypoint(Database& db, uint32 zone_id, uint32 grid_id) + { + auto results = db.QueryDatabase( + fmt::format( + SQL( + SELECT COALESCE(MAX(`number`), 0) FROM `{}` + WHERE `zoneid` = {} AND `gridid` = {} + ), + TableName(), + zone_id, + grid_id + ) + ); + + if (!results.Success() || !results.RowCount()) { + return 0; + } + + auto row = results.begin(); + + return Strings::ToInt(row[0]); + } + + static int GetNextWaypoint(Database& db, uint32 zone_id, uint32 grid_id) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT MAX(`number`) FROM `{}` WHERE `zoneid` = {} AND `gridid` = {}", + TableName(), + zone_id, + grid_id + ) + ); + + if (!results.Success() || !results.RowCount()) { + return 1; + } + + auto row = results.begin(); + + return Strings::ToInt(row[0]) + 1; + } }; #endif //EQEMU_GRID_ENTRIES_REPOSITORY_H diff --git a/common/repositories/grid_repository.h b/common/repositories/grid_repository.h index df6968209..afdc07f75 100644 --- a/common/repositories/grid_repository.h +++ b/common/repositories/grid_repository.h @@ -71,6 +71,27 @@ public: return grids; } + static int GetHighestGrid(Database& db, uint32 zone_id) + { + auto results = db.QueryDatabase( + fmt::format( + SQL( + SELECT COALESCE(MAX(`id`), 0) FROM `{}` + WHERE `zoneid` = {} + ), + TableName(), + zone_id + ) + ); + + if (!results.Success() || !results.RowCount()) { + return 0; + } + + auto row = results.begin(); + + return Strings::ToInt(row[0]); + } }; #endif //EQEMU_GRID_REPOSITORY_H diff --git a/common/repositories/spawn2_repository.h b/common/repositories/spawn2_repository.h index 5b2dabcaa..8fc53ad1d 100644 --- a/common/repositories/spawn2_repository.h +++ b/common/repositories/spawn2_repository.h @@ -44,7 +44,35 @@ public: */ // Custom extended repository methods here + static uint32 GetPathGridBySpawn2ID(Database& db, uint32 spawn2_id) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT `pathgrid` FROM `{}` WHERE `id` = {}", + TableName(), + spawn2_id + ) + ); + if (!results.Success() || !results.RowCount()) { + return 0; + } + + auto row = results.begin(); + + return Strings::ToUnsignedInt(row[0]); + } + + static void SetPathGridBySpawn2ID(Database& db, uint32 spawn2_id, uint32 grid_id) + { + auto results = db.QueryDatabase( + fmt::format( + "UPDATE `spawn2` SET `pathgrid` = {} WHERE `id` = {}", + grid_id, + spawn2_id + ) + ); + } }; #endif //EQEMU_SPAWN2_REPOSITORY_H diff --git a/zone/gm_commands/grid.cpp b/zone/gm_commands/grid.cpp index 3a346807e..b8a7e7d3d 100755 --- a/zone/gm_commands/grid.cpp +++ b/zone/gm_commands/grid.cpp @@ -1,82 +1,138 @@ #include "../client.h" +#include "../../common/repositories/grid_entries_repository.h" void command_grid(Client *c, const Seperator *sep) { - auto command_type = sep->arg[1]; - auto zone_id = zone->GetZoneID(); - if (strcasecmp("max", command_type) == 0) { - c->Message( - Chat::White, - fmt::format( - "Highest grid ID in this zone is {}.", - content_db.GetHighestGrid(zone_id) - ).c_str() - ); + const uint16 arguments = sep->argnum; + + if (!arguments) { + c->Message(Chat::White, "Usage: #grid add [Grid ID] [Wander Type] [Pause Type] - Add a grid with the specified wander and pause type"); + c->Message(Chat::White, "Usage: #grid delete [Grid ID] - Delete a grid"); + c->Message(Chat::White, "Usage: #grid hide - Hides waypoint nodes from targeted NPC's grid"); + c->Message(Chat::White, "Usage: #grid max - Displays the highest grid ID used in this zone (for add)"); + c->Message(Chat::White, "Usage: #grid show - Displays waypoint nodes for targeted NPC's grid"); + return; } - else if (strcasecmp("add", command_type) == 0) { - auto grid_id = Strings::ToInt(sep->arg[2]); - auto wander_type = Strings::ToInt(sep->arg[3]); - auto pause_type = Strings::ToInt(sep->arg[4]); - if (!content_db.GridExistsInZone(zone_id, grid_id)) { - content_db.ModifyGrid(c, false, grid_id, wander_type, pause_type, zone_id); + + const bool is_add = !strcasecmp(sep->arg[1], "add"); + const bool is_delete = !strcasecmp(sep->arg[1], "delete"); + const bool is_hide = !strcasecmp(sep->arg[1], "hide"); + const bool is_max = !strcasecmp(sep->arg[1], "max"); + const bool is_show = !strcasecmp(sep->arg[1], "show"); + + if (!is_add && !is_delete && !is_hide && !is_max && !is_show) { + c->Message(Chat::White, "Usage: #grid add [Grid ID] [Wander Type] [Pause Type] - Add a grid with the specified wander and pause type"); + c->Message(Chat::White, "Usage: #grid delete [Grid ID] - Delete a grid"); + c->Message(Chat::White, "Usage: #grid hide - Hides waypoint nodes from targeted NPC's grid"); + c->Message(Chat::White, "Usage: #grid max - Displays the highest grid ID used in this zone (for add)"); + c->Message(Chat::White, "Usage: #grid show - Displays waypoint nodes for targeted NPC's grid"); + return; + } + + if (is_add) { + const uint32 grid_id = Strings::ToUnsignedInt(sep->arg[2]); + const uint8 wander_type = static_cast(Strings::ToUnsignedInt(sep->arg[3])); + const uint8 pause_type = static_cast(Strings::ToUnsignedInt(sep->arg[4])); + + if (!grid_id) { + c->Message(Chat::White, "You must specify a valid grid ID."); + return; + } + + if (!content_db.GridExistsInZone(zone->GetZoneID(), grid_id)) { + content_db.ModifyGrid(c, false, grid_id, wander_type, pause_type, zone->GetZoneID()); + c->Message( Chat::White, fmt::format( "Grid {} added to zone ID {} with wander type {} and pause type {}.", grid_id, - zone_id, + zone->GetZoneID(), wander_type, pause_type ).c_str() ); - } - else { + } else { c->Message( Chat::White, fmt::format( "Grid {} already exists in zone ID {}.", grid_id, - zone_id + zone->GetZoneID() ).c_str() ); - return; } - } - else if (strcasecmp("show", command_type) == 0) { - Mob *target = c->GetTarget(); - if (!target || !target->IsNPC()) { - c->Message(Chat::White, "You need to target an NPC!"); + } else if (is_delete) { + const uint32 grid_id = Strings::ToUnsignedInt(sep->arg[2]); + + content_db.ModifyGrid(c, true, grid_id, 0, 0, zone->GetZoneID()); + + c->Message( + Chat::White, + fmt::format( + "Grid {} deleted from zone ID {}.", + grid_id, + zone->GetZoneID() + ).c_str() + ); + } else if (is_hide) { + Mob* t = c->GetTarget(); + if (!t || !t->IsNPC()) { + c->Message(Chat::White, "You must target an NPC to use this command."); return; } - auto grid_id = target->CastToNPC()->GetGrid(); - std::string query = fmt::format( - "SELECT `x`, `y`, `z`, `heading`, `number` " - "FROM `grid_entries` " - "WHERE `zoneid` = {} AND `gridid` = {} " - "ORDER BY `number`", - zone_id, - grid_id + const uint32 grid_id = t->CastToNPC()->GetGrid(); + + entity_list.DespawnGridNodes(grid_id); + + c->Message( + Chat::White, + fmt::format( + "Depawning nodes for grid {}.", + grid_id + ).c_str() + ); + } else if (is_max) { + c->Message( + Chat::White, + fmt::format( + "Highest grid ID in this zone is {}.", + content_db.GetHighestGrid(zone->GetZoneID()) + ).c_str() + ); + } else if (is_show) { + Mob* t = c->GetTarget(); + if (!t || !t->IsNPC()) { + c->Message(Chat::White, "You must target an NPC to use this command."); + return; + } + + const uint32 grid_id = t->CastToNPC()->GetGrid(); + + const auto& l = GridEntriesRepository::GetWhere( + content_db, + fmt::format( + "`zoneid` = {} AND `gridid` = {} ORDER BY `number`", + zone->GetZoneID(), + grid_id + ) ); - auto results = content_db.QueryDatabase(query); - if (!results.Success()) { - c->Message(Chat::White, "Error querying database."); - c->Message(Chat::White, query.c_str()); - } - - if (results.RowCount() == 0) { + if (l.empty()) { c->Message(Chat::White, "No grid found."); return; } - // Depop any node npc's already spawned + // Depop any grid nodes already spawned entity_list.DespawnGridNodes(grid_id); // Spawn grid nodes std::map, int32> zoffset; - for (auto row : results) { - glm::vec4 node_position = glm::vec4(Strings::ToFloat(row[0]), Strings::ToFloat(row[1]), Strings::ToFloat(row[2]), Strings::ToFloat(row[3])); + + for (const auto& e : l) { + glm::vec4 node_position = glm::vec4(e.x, e.y, e.z, e.heading); + std::vector node_loc{ node_position.x, node_position.y, @@ -84,19 +140,20 @@ void command_grid(Client *c, const Seperator *sep) }; // If we already have a node at this location, set the z offset - // higher from the existing one so we can see it. Adjust so if + // higher from the existing one, so we can see it. Adjust so if // there is another at the same spot we adjust again. auto search = zoffset.find(node_loc); if (search != zoffset.end()) { - search->second = search->second + 3; - } - else { + search->second += 3; + } else { zoffset[node_loc] = 0.0; } node_position.z += zoffset[node_loc]; - NPC::SpawnGridNodeNPC(node_position, grid_id, Strings::ToInt(row[4]), zoffset[node_loc]); + + NPC::SpawnGridNodeNPC(node_position, grid_id, e.number, zoffset[node_loc]); } + c->Message( Chat::White, fmt::format( @@ -105,39 +162,4 @@ void command_grid(Client *c, const Seperator *sep) ).c_str() ); } - else if (strcasecmp("hide", command_type) == 0) { - Mob *target = c->GetTarget(); - if (!target || !target->IsNPC()) { - c->Message(Chat::White, "You need to target an NPC!"); - return; - } - - auto grid_id = target->CastToNPC()->GetGrid(); - entity_list.DespawnGridNodes(grid_id); - c->Message( - Chat::White, - fmt::format( - "Depawning nodes for grid {}.", - grid_id - ).c_str() - ); - } - else if (strcasecmp("delete", command_type) == 0) { - auto grid_id = Strings::ToInt(sep->arg[2]); - content_db.ModifyGrid(c, true, grid_id, 0, 0, zone_id); - c->Message( - Chat::White, - fmt::format( - "Grid {} deleted from zone ID {}.", - grid_id, - zone_id - ).c_str() - ); - } - else { - c->Message(Chat::White, "Usage: #grid [add|delete] [grid_id] [wander_type] [pause_type]"); - c->Message(Chat::White, "Usage: #grid [max] - displays the highest grid ID used in this zone (for add)"); - c->Message(Chat::White, "Usage: #grid [show] - displays wp nodes as boxes"); - } } - diff --git a/zone/gm_commands/wp.cpp b/zone/gm_commands/wp.cpp index 407a76d2e..8307ebaa7 100755 --- a/zone/gm_commands/wp.cpp +++ b/zone/gm_commands/wp.cpp @@ -14,12 +14,12 @@ void command_wp(Client *c, const Seperator *sep) } if (strcasecmp("-h", sep->arg[5]) == 0) { - content_db.AddWP(c, grid_id, waypoint, c->GetPosition(), pause, zone_id); + content_db.AddWaypoint(c, grid_id, waypoint, c->GetPosition(), pause, zone_id); } else { auto position = c->GetPosition(); position.w = -1; - content_db.AddWP(c, grid_id, waypoint, position, pause, zone_id); + content_db.AddWaypoint(c, grid_id, waypoint, position, pause, zone_id); } c->Message( Chat::White, diff --git a/zone/gm_commands/wpadd.cpp b/zone/gm_commands/wpadd.cpp index 2ce56faac..b8f114c7b 100755 --- a/zone/gm_commands/wpadd.cpp +++ b/zone/gm_commands/wpadd.cpp @@ -29,7 +29,7 @@ void command_wpadd(Client *c, const Seperator *sep) } auto zone_id = zone->GetZoneID(); - uint32 tmp_grid = content_db.AddWPForSpawn(c, s2info->GetID(), position, pause, type1, type2, zone_id); + uint32 tmp_grid = content_db.AddWaypointForSpawn(c, s2info->GetID(), position, pause, type1, type2, zone_id); if (tmp_grid) { target->CastToNPC()->SetGrid(tmp_grid); } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 6f2d3414c..ee3d9541b 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -41,6 +41,7 @@ #include "../common/repositories/tradeskill_recipe_repository.h" #include "../common/repositories/instance_list_repository.h" +#include "../common/repositories/grid_entries_repository.h" #include #include @@ -1988,38 +1989,48 @@ void QuestManager::setanim(int npc_type, int animnum) { } //displays an in game path based on a waypoint grid -void QuestManager::showgrid(int grid) { +void QuestManager::showgrid(int grid_id) +{ QuestManagerCurrentQuestVars(); - if(initiator == nullptr) + + if (!initiator) { return; + } - FindPerson_Point pt; - std::vector pts; + std::vector v; - pt.x = initiator->GetX(); - pt.y = initiator->GetY(); - pt.z = initiator->GetZ(); - pts.push_back(pt); + v.push_back( + FindPerson_Point{ + .y = initiator->GetY(), + .x = initiator->GetX(), + .z = initiator->GetZ() + } + ); - // Retrieve all waypoints for this grid - std::string query = StringFormat("SELECT `x`,`y`,`z` FROM grid_entries " - "WHERE `gridid` = %i AND `zoneid` = %i " - "ORDER BY `number`", grid, zone->GetZoneID()); - auto results = content_db.QueryDatabase(query); - if (!results.Success()) { - LogQuests("Error loading grid [{}] for showgrid(): [{}]", grid, results.ErrorMessage().c_str()); + const auto& l = GridEntriesRepository::GetWhere( + content_db, + fmt::format( + "`gridid` = {} AND `zoneid` = {} ORDER BY `number`", + grid_id, + zone->GetZoneID() + ) + ); + + if (l.empty()) { return; - } + } - for(auto row = results.begin(); row != results.end(); ++row) { - pt.x = Strings::ToFloat(row[0]); - pt.y = Strings::ToFloat(row[1]); - pt.z = Strings::ToFloat(row[2]); + for (const auto& e : l) { + v.push_back( + FindPerson_Point{ + .y = e.y, + .x = e.x, + .z = e.z + } + ); + } - pts.push_back(pt); - } - - initiator->SendPathPacket(pts); + initiator->SendPathPacket(v); } diff --git a/zone/questmgr.h b/zone/questmgr.h index d4f470682..11eec9d39 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -183,7 +183,7 @@ public: void enable_proximity_say(); void disable_proximity_say(); void setanim(int npc_type, int animnum); - void showgrid(int gridid); + void showgrid(int grid_id); void spawn_condition(const char *zone_short, uint32 instance_id, uint16 condition_id, short new_value); short get_spawn_condition(const char *zone_short, uint32 instance_id, uint16 condition_id); void toggle_spawn_event(int event_id, bool enable, bool strict, bool reset_base); diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index 67862185a..e4c7ef745 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -256,7 +256,7 @@ bool Spawn2::Process() { if (spawn_group->wp_spawns && grid_ > 0) { glm::vec4 wploc; - starting_wp = content_db.GetRandomWaypointLocFromGrid(wploc, zone->GetZoneID(), grid_); + starting_wp = content_db.GetRandomWaypointFromGrid(wploc, zone->GetZoneID(), grid_); if (wploc.x != 0.0f || wploc.y != 0.0f || wploc.z != 0.0f) { loc = wploc; diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 76cf961e8..457e76221 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -32,6 +32,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "fastmath.h" #include "mob_movement_manager.h" +#include "../common/repositories/grid_repository.h" +#include "../common/repositories/grid_entries_repository.h" +#include "../common/repositories/spawn2_repository.h" + #include extern FastMath g_Math; @@ -1052,233 +1056,198 @@ glm::vec4 Mob::TryMoveAlong(const glm::vec4 &start, float distance, float angle) return {new_pos.x, new_pos.y, new_pos.z, start.w}; } -int ZoneDatabase::GetHighestGrid(uint32 zoneid) { - - std::string query = StringFormat("SELECT COALESCE(MAX(id), 0) FROM grid WHERE zoneid = %i", zoneid); - auto results = QueryDatabase(query); - if (!results.Success()) { - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - return Strings::ToInt(row[0]); +int ZoneDatabase::GetHighestGrid(uint32 zone_id) +{ + return GridRepository::GetHighestGrid(*this, zone_id); } -/****************** -* ModifyGrid - Either adds an empty grid, or removes a grid and all its waypoints, for a particular zone. -* remove: TRUE if we are deleting the specified grid, FALSE if we are adding it -* id: The ID# of the grid to add or delete -* type,type2: The type and type2 values for the grid being created (ignored if grid is being deleted) -* zoneid: The ID number of the zone the grid is being created/deleted in -*/ -void ZoneDatabase::ModifyGrid(Client *client, bool remove, uint32 id, uint8 type, uint8 type2, uint16 zoneid) { +void ZoneDatabase::ModifyGrid( + Client* c, + bool remove, + uint32 grid_id, + uint8 type, + uint8 type2, + uint32 zone_id +) +{ + if (!remove) { + GridRepository::InsertOne( + *this, + GridRepository::Grid{ + .id = static_cast(grid_id), + .zoneid = static_cast(zone_id), + .type = type, + .type2 = type2 + } + ); - if (!remove) - { - std::string query = StringFormat("INSERT INTO grid(id, zoneid, type, type2) " - "VALUES (%i, %i, %i, %i)", id, zoneid, type, type2); - auto results = QueryDatabase(query); - if (!results.Success()) { - return; + return; + } + + GridRepository::DeleteWhere( + *this, + fmt::format( + "`id` = {} AND `zoneid` = {}", + grid_id, + zone_id + ) + ); + + GridEntriesRepository::DeleteWhere( + *this, + fmt::format( + "`gridid` = {} AND `zoneid` = {}", + grid_id, + zone_id + ) + ); +} + +bool ZoneDatabase::GridExistsInZone(uint32 zone_id, uint32 grid_id) +{ + const auto& l = GridRepository::GetWhere( + *this, + fmt::format( + "`id` = {} AND `zoneid` = {}", + grid_id, + zone_id + ) + ); + + if (l.empty()) { + return false; + } + + return true; +} + +void ZoneDatabase::AddWaypoint( + Client* c, + uint32 grid_id, + uint32 number, + const glm::vec4& position, + uint32 pause, + uint32 zone_id +) +{ + GridEntriesRepository::InsertOne( + *this, + GridEntriesRepository::GridEntries{ + .gridid = static_cast(grid_id), + .zoneid = static_cast(zone_id), + .number = static_cast(number), + .x = position.x, + .y = position.y, + .z = position.z, + .heading = position.w, + .pause = static_cast(pause) + } + ); +} + +void ZoneDatabase::DeleteWaypoint(Client* c, uint32 grid_id, uint32 number, uint32 zone_id) +{ + GridEntriesRepository::DeleteWhere( + *this, + fmt::format( + "`gridid` = {} AND `zoneid` = {} AND `number` = {}", + grid_id, + zone_id, + number + ) + ); +} + +uint32 ZoneDatabase::AddWaypointForSpawn( + Client* c, + uint32 spawn2_id, + const glm::vec4& position, + uint32 pause, + int type, + int type2, + uint32 zone_id +) +{ + uint32 grid_id = Spawn2Repository::GetPathGridBySpawn2ID(*this, spawn2_id); // The grid number the spawn is assigned to (if spawn has no grid, will be the grid number we end up creating) + bool created; // Did we create a new grid in this function? + + if (!grid_id) { // Our spawn doesn't have a grid assigned to it -- we need to create a new grid and assign it to the spawn + created = true; + grid_id = GetFreeGrid(zone_id); + + if (grid_id == 0) { // There are no grids for the current zone -- create Grid #1 + grid_id = 1; } - return; + GridRepository::InsertOne( + *this, + GridRepository::Grid{ + .id = static_cast(grid_id), + .zoneid = static_cast(zone_id), + .type = type, + .type2 = type2 + } + ); + + Spawn2Repository::SetPathGridBySpawn2ID(*this, spawn2_id, grid_id); + } else { // NPC had a grid assigned to it + created = false; } - std::string query = StringFormat("DELETE FROM grid where id=%i and zoneid=%i", id, zoneid); - auto results = QueryDatabase(query); + int next_waypoint = GridEntriesRepository::GetNextWaypoint(*this, zone_id, grid_id); // The waypoint number we should be assigning to the new waypoint - query = StringFormat("DELETE FROM grid_entries WHERE zoneid = %i AND gridid = %i", zoneid, id); - results = QueryDatabase(query); -} - -bool ZoneDatabase::GridExistsInZone(uint32 zone_id, uint32 grid_id) { - bool grid_exists = false; - std::string query = fmt::format( - "SELECT * FROM `grid` WHERE `id` = {} AND `zoneid` = {}", - grid_id, - zone_id + GridEntriesRepository::InsertOne( + *this, + GridEntriesRepository::GridEntries{ + .gridid = static_cast(grid_id), + .zoneid = static_cast(zone_id), + .number = next_waypoint, + .x = position.x, + .y = position.y, + .z = position.z, + .heading = position.w, + .pause = static_cast(pause) + } ); - auto results = QueryDatabase(query); - if (!results.Success()) { - return grid_exists; - } - if (results.RowCount() == 1) { - grid_exists = true; - } - return grid_exists; + return created ? grid_id : 0; } -/************************************** -* AddWP - Adds a new waypoint to a specific grid for a specific zone. -*/ -void ZoneDatabase::AddWP(Client *client, uint32 gridid, uint32 wpnum, const glm::vec4& position, uint32 pause, uint16 zoneid) +uint32 ZoneDatabase::GetFreeGrid(uint32 zone_id) { - std::string query = StringFormat("INSERT INTO grid_entries (gridid, zoneid, `number`, x, y, z, pause, heading) " - "VALUES (%i, %i, %i, %f, %f, %f, %i, %f)", - gridid, zoneid, wpnum, position.x, position.y, position.z, pause, position.w); - auto results = QueryDatabase(query); - if (!results.Success()) { - return; - } + return GridRepository::GetHighestGrid(*this, zone_id) + 1; } - -/********** -* ModifyWP() has been obsoleted. The #wp command either uses AddWP() or DeleteWaypoint() -***********/ - -/****************** -* DeleteWaypoint - Removes a specific waypoint from the grid -* grid_id: The ID number of the grid whose wp is being deleted -* wp_num: The number of the waypoint being deleted -* zoneid: The ID number of the zone that Contains the waypoint being deleted -*/ -void ZoneDatabase::DeleteWaypoint(Client *client, uint32 grid_num, uint32 wp_num, uint16 zoneid) +int ZoneDatabase::GetHighestWaypoint(uint32 zone_id, uint32 grid_id) { - std::string query = StringFormat("DELETE FROM grid_entries WHERE " - "gridid = %i AND zoneid = %i AND `number` = %i", - grid_num, zoneid, wp_num); - auto results = QueryDatabase(query); - if (!results.Success()) { - return; - } + return GridEntriesRepository::GetHighestWaypoint(*this, zone_id, grid_id); } - -/****************** -* AddWPForSpawn - Used by the #wpadd command - for a given spawn, this will add a new waypoint to whatever grid that spawn is assigned to. -* If there is currently no grid assigned to the spawn, a new grid will be created using the next available Grid ID number for the zone -* the spawn is in. -* Returns 0 if the function didn't have to create a new grid. If the function had to create a new grid for the spawn, then the ID of -* the created grid is returned. -*/ -uint32 ZoneDatabase::AddWPForSpawn(Client *client, uint32 spawn2id, const glm::vec4& position, uint32 pause, int type1, int type2, uint16 zoneid) { - - uint32 grid_num; // The grid number the spawn is assigned to (if spawn has no grid, will be the grid number we end up creating) - uint32 next_wp_num; // The waypoint number we should be assigning to the new waypoint - bool createdNewGrid; // Did we create a new grid in this function? - - // See what grid number our spawn is assigned - std::string query = StringFormat("SELECT pathgrid FROM spawn2 WHERE id = %i", spawn2id); - auto results = QueryDatabase(query); - if (!results.Success()) { - // Query error - return 0; - } - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - grid_num = Strings::ToInt(row[0]); - - if (grid_num == 0) - { // Our spawn doesn't have a grid assigned to it -- we need to create a new grid and assign it to the spawn - createdNewGrid = true; - grid_num = GetFreeGrid(zoneid); - if (grid_num == 0) // There are no grids for the current zone -- create Grid #1 - grid_num = 1; - - query = StringFormat("INSERT INTO grid SET id = '%i', zoneid = %i, type ='%i', type2 = '%i'", - grid_num, zoneid, type1, type2); - QueryDatabase(query); - - query = StringFormat("UPDATE spawn2 SET pathgrid = '%i' WHERE id = '%i'", grid_num, spawn2id); - QueryDatabase(query); - - } - else // NPC had a grid assigned to it - createdNewGrid = false; - - // Find out what the next waypoint is for this grid - query = StringFormat("SELECT max(`number`) FROM grid_entries WHERE zoneid = '%i' AND gridid = '%i'", zoneid, grid_num); - - results = QueryDatabase(query); - if (!results.Success()) { // Query error - return 0; - } - - row = results.begin(); - if (row[0] != 0) - next_wp_num = Strings::ToInt(row[0]) + 1; - else // No waypoints in this grid yet - next_wp_num = 1; - - query = StringFormat("INSERT INTO grid_entries(gridid, zoneid, `number`, x, y, z, pause, heading) " - "VALUES (%i, %i, %i, %f, %f, %f, %i, %f)", - grid_num, zoneid, next_wp_num, position.x, position.y, position.z, pause, position.w); - results = QueryDatabase(query); - - return createdNewGrid ? grid_num : 0; -} - -uint32 ZoneDatabase::GetFreeGrid(uint16 zoneid) { - - std::string query = StringFormat("SELECT max(id) FROM grid WHERE zoneid = %i", zoneid); - auto results = QueryDatabase(query); - if (!results.Success()) { - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - uint32 freeGridID = row[0] ? Strings::ToInt(row[0]) + 1 : 1; - - return freeGridID; -} - -int ZoneDatabase::GetHighestWaypoint(uint32 zoneid, uint32 gridid) { - - std::string query = StringFormat("SELECT COALESCE(MAX(number), 0) FROM grid_entries " - "WHERE zoneid = %i AND gridid = %i", zoneid, gridid); - auto results = QueryDatabase(query); - if (!results.Success()) { - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - return Strings::ToInt(row[0]); -} - -int ZoneDatabase::GetRandomWaypointLocFromGrid(glm::vec4 &loc, uint16 zoneid, int grid) +int ZoneDatabase::GetRandomWaypointFromGrid(glm::vec4 &loc, uint32 zone_id, uint32 grid_id) { loc.x = loc.y = loc.z = loc.w = 0.0f; - std::string query = StringFormat("SELECT `x`,`y`,`z`,`heading` " - "FROM grid_entries WHERE `gridid` = %i AND `zoneid` = %u ORDER BY `number`", grid, zone->GetZoneID()); - auto results = content_db.QueryDatabase(query); - if (!results.Success()) { - Log(Logs::General, Logs::Error, "MySQL Error while trying get random waypoint loc from grid %i in zoneid %u; %s", grid, zoneid, results.ErrorMessage().c_str()); + const auto& l = GridEntriesRepository::GetWhere( + *this, + fmt::format( + "`zoneid` = {} AND `gridid` = {} ORDER BY RAND() LIMIT 1", + zone_id, + grid_id + ) + ); + + if (l.empty()) { return 0; } - if (results.RowCount() > 0) - { - int roll = zone->random.Int(0, results.RowCount() - 1); - int i = 0; - auto row = results.begin(); - while (i < roll) - { - row++; - i++; - } - loc.x = Strings::ToFloat(row[0]); - loc.y = Strings::ToFloat(row[1]); - loc.z = Strings::ToFloat(row[2]); - loc.w = Strings::ToFloat(row[3]); - return i; - } - return 0; + auto e = l.front(); + + loc.x = e.x; + loc.y = e.y; + loc.z = e.z; + loc.w = e.heading; + + return e.number; } void NPC::SaveGuardSpotCharm() diff --git a/zone/zonedb.h b/zone/zonedb.h index 4eb2ca0f0..2d20cff00 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -534,17 +534,15 @@ public: void UpdateSpawn2Status(uint32 id, uint8 new_status, uint32 instance_id); /* Grids/Paths */ - uint32 GetFreeGrid(uint16 zoneid); - void DeleteGrid(Client *c, uint32 sg2, uint32 grid_num, bool grid_too, uint16 zoneid); - void DeleteWaypoint(Client *c, uint32 grid_num, uint32 wp_num, uint16 zoneid); - void AddWP(Client *c, uint32 gridid, uint32 wpnum, const glm::vec4& position, uint32 pause, uint16 zoneid); - uint32 AddWPForSpawn(Client *c, uint32 spawn2id, const glm::vec4& position, uint32 pause, int type1, int type2, uint16 zoneid); - void ModifyGrid(Client *c, bool remove, uint32 id, uint8 type = 0, uint8 type2 = 0, uint16 zoneid = 0); - bool GridExistsInZone(uint32 zone_id, uint32 grid_id); - void ModifyWP(Client *c, uint32 grid_id, uint32 wp_num, const glm::vec3& location, uint32 script = 0, uint16 zoneid = 0); - int GetHighestGrid(uint32 zoneid); - int GetHighestWaypoint(uint32 zoneid, uint32 gridid); - int GetRandomWaypointLocFromGrid(glm::vec4 &loc, uint16 zoneid, int grid); + uint32 GetFreeGrid(uint32 zone_id); + void DeleteWaypoint(Client* c, uint32 grid_id, uint32 number, uint32 zone_id); + void AddWaypoint(Client* c, uint32 grid_id, uint32 number, const glm::vec4 &position, uint32 pause, uint32 zone_id); + uint32 AddWaypointForSpawn(Client* c, uint32 spawn2_id, const glm::vec4 &position, uint32 pause, int type, int type2, uint32 zone_id); + void ModifyGrid(Client* c, bool remove, uint32 grid_id, uint8 type = 0, uint8 type2 = 0, uint32 zone_id = 0); + bool GridExistsInZone(uint32 zone_id, uint32 grid_id); + int GetHighestGrid(uint32 zone_id); + int GetHighestWaypoint(uint32 zone_id, uint32 grid_id); + int GetRandomWaypointFromGrid(glm::vec4 &loc, uint32 zone_id, uint32 grid_id); /* NPCs */