From e269f49f8e74933d501940b02c67774dc83a2981 Mon Sep 17 00:00:00 2001 From: Schmoozerd Date: Mon, 19 Aug 2013 16:27:01 +0300 Subject: [PATCH] [12672] Improve Waypoint Management * Allow waypoints that have point-ids not from 1 to n * Remove possibly bad sql-statements to "fix" the above property * Simplify code a little bit Remaining TODO: Bring commands up-to-date and also make things more simple instead of using the database to store visual waypoints --- src/game/Level2.cpp | 3 +- src/game/WaypointManager.cpp | 120 ++++++++----------------- src/game/WaypointManager.h | 6 +- src/game/WaypointMovementGenerator.cpp | 54 +++++------ src/shared/revision_nr.h | 2 +- 5 files changed, 70 insertions(+), 115 deletions(-) diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index c0af6cf51..b6b9ef46b 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -3635,7 +3635,8 @@ bool ChatHandler::HandleWpShowCommand(char* args) uint32 model2 = fields[11].GetUInt32(); // Get the creature for which we read the waypoint - Creature* wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HIGHGUID_UNIT, VISUAL_WAYPOINT, wpGuid)); + CreatureData const* data = sObjectMgr.GetCreatureData(wpGuid); + Creature* wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(data ? data->GetObjectGuid(wpGuid) : ObjectGuid(HIGHGUID_UNIT, VISUAL_WAYPOINT, wpGuid)); PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : ""), wpGuid); PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime); diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp index 59e40ed2e..ef68434f3 100644 --- a/src/game/WaypointManager.cpp +++ b/src/game/WaypointManager.cpp @@ -51,8 +51,6 @@ WaypointBehavior::WaypointBehavior(const WaypointBehavior& b) void WaypointManager::Load() { - Cleanup(); - uint32 total_paths = 0; uint32 total_nodes = 0; uint32 total_behaviors = 0; @@ -85,7 +83,6 @@ void WaypointManager::Load() uint32 id = fields[0].GetUInt32(); uint32 count = fields[1].GetUInt32(); - m_pathMap[id].resize(count); total_nodes += count; } while (result->NextRow()); @@ -124,11 +121,7 @@ void WaypointManager::Load() creatureNoMoveType.insert(id); WaypointPath& path = m_pathMap[id]; - - // the cleanup queries make sure the following is true - MANGOS_ASSERT(point >= 1 && point <= path.size()); - - WaypointNode& node = path[point - 1]; + WaypointNode& node = path[point]; node.x = fields[2].GetFloat(); node.y = fields[3].GetFloat(); @@ -263,7 +256,6 @@ void WaypointManager::Load() uint32 entry = fields[0].GetUInt32(); uint32 count = fields[1].GetUInt32(); - m_pathTemplateMap[entry].resize(count); total_nodes += count; } while (result->NextRow()); @@ -297,11 +289,7 @@ void WaypointManager::Load() } WaypointPath& path = m_pathTemplateMap[entry]; - - // the cleanup queries make sure the following is true - MANGOS_ASSERT(point >= 1 && point <= path.size()); - - WaypointNode& node = path[point - 1]; + WaypointNode& node = path[point]; node.x = fields[2].GetFloat(); node.y = fields[3].GetFloat(); @@ -394,40 +382,6 @@ void WaypointManager::Load() } } -void WaypointManager::Cleanup() -{ - // check if points need to be renumbered and do it - if (QueryResult* result = WorldDatabase.Query("SELECT 1 from creature_movement As T WHERE point <> (SELECT COUNT(*) FROM creature_movement WHERE id = T.id AND point <= T.point) LIMIT 1")) - { - delete result; - WorldDatabase.DirectExecute("CREATE TEMPORARY TABLE temp LIKE creature_movement"); - WorldDatabase.DirectExecute("INSERT INTO temp SELECT * FROM creature_movement"); - WorldDatabase.DirectExecute("ALTER TABLE creature_movement DROP PRIMARY KEY"); - WorldDatabase.DirectExecute("UPDATE creature_movement AS T SET point = (SELECT COUNT(*) FROM temp WHERE id = T.id AND point <= T.point)"); - WorldDatabase.DirectExecute("ALTER TABLE creature_movement ADD PRIMARY KEY (id, point)"); - WorldDatabase.DirectExecute("DROP TABLE temp"); - - sLog.outErrorDb("Table `creature_movement` was auto corrected for using points out of order (invalid or points missing)"); - - MANGOS_ASSERT(!(result = WorldDatabase.Query("SELECT 1 from creature_movement As T WHERE point <> (SELECT COUNT(*) FROM creature_movement WHERE id = T.id AND point <= T.point) LIMIT 1"))); - } - - if (QueryResult* result = WorldDatabase.Query("SELECT 1 from creature_movement_template As T WHERE point <> (SELECT COUNT(*) FROM creature_movement_template WHERE entry = T.entry AND point <= T.point) LIMIT 1")) - { - delete result; - WorldDatabase.DirectExecute("CREATE TEMPORARY TABLE temp LIKE creature_movement_template"); - WorldDatabase.DirectExecute("INSERT INTO temp SELECT * FROM creature_movement_template"); - WorldDatabase.DirectExecute("ALTER TABLE creature_movement_template DROP PRIMARY KEY"); - WorldDatabase.DirectExecute("UPDATE creature_movement_template AS T SET point = (SELECT COUNT(*) FROM temp WHERE entry = T.entry AND point <= T.point)"); - WorldDatabase.DirectExecute("ALTER TABLE creature_movement_template ADD PRIMARY KEY (entry, point)"); - WorldDatabase.DirectExecute("DROP TABLE temp"); - - sLog.outErrorDb("Table `creature_movement_template` was auto corrected for using points out of order (invalid or points missing)"); - - MANGOS_ASSERT(!(result = WorldDatabase.Query("SELECT 1 from creature_movement_template As T WHERE point <> (SELECT COUNT(*) FROM creature_movement_template WHERE entry = T.entry AND point <= T.point) LIMIT 1"))); - } -} - void WaypointManager::Unload() { for (WaypointPathMap::iterator itr = m_pathMap.begin(); itr != m_pathMap.end(); ++itr) @@ -442,7 +396,7 @@ void WaypointManager::Unload() void WaypointManager::_clearPath(WaypointPath& path) { for (WaypointPath::const_iterator itr = path.begin(); itr != path.end(); ++itr) - delete itr->behavior; + delete itr->second.behavior; path.clear(); } @@ -464,39 +418,31 @@ void WaypointManager::AddAfterNode(uint32 id, uint32 point, float x, float y, fl /// - Insert without checking for collision void WaypointManager::_addNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid) { - if (point == 0) return; // counted from 1 in the DB WorldDatabase.PExecuteLog("INSERT INTO creature_movement (id,point,position_x,position_y,position_z,orientation,wpguid,waittime) " "VALUES (%u,%u, %f,%f,%f,%f, %u,%u)", id, point, x, y, z, o, wpGuid, delay); - WaypointPathMap::iterator itr = m_pathMap.find(id); - if (itr == m_pathMap.end()) - itr = m_pathMap.insert(WaypointPathMap::value_type(id, WaypointPath())).first; - itr->second.insert(itr->second.begin() + (point - 1), WaypointNode(x, y, z, o, delay, 0, NULL)); + + m_pathMap[id][point] = WaypointNode(x, y, z, o, delay, 0, NULL); } uint32 WaypointManager::GetLastPoint(uint32 id, uint32 default_notfound) { - uint32 point = default_notfound; - /*QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'", id); - if( result ) - { - point = (*result)[0].GetUInt32()+1; - delete result; - }*/ WaypointPathMap::const_iterator itr = m_pathMap.find(id); - if (itr != m_pathMap.end() && itr->second.size() != 0) - point = itr->second.size(); - return point; + if (itr != m_pathMap.end() && itr->second.rbegin() != itr->second.rend()) + default_notfound = itr->second.rbegin()->first; + + return default_notfound; } void WaypointManager::DeleteNode(uint32 id, uint32 point) { - if (point == 0) return; // counted from 1 in the DB WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id=%u AND point=%u", id, point); WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point-1 WHERE id=%u AND point>%u", id, point); WaypointPathMap::iterator itr = m_pathMap.find(id); - if (itr != m_pathMap.end() && point <= itr->second.size()) - itr->second.erase(itr->second.begin() + (point - 1)); + if (itr == m_pathMap.end()) + return; + + itr->second.erase(point); } void WaypointManager::DeletePath(uint32 id) @@ -513,20 +459,22 @@ void WaypointManager::DeletePath(uint32 id) void WaypointManager::SetNodePosition(uint32 id, uint32 point, float x, float y, float z) { - if (point == 0) return; // counted from 1 in the DB WorldDatabase.PExecuteLog("UPDATE creature_movement SET position_x=%f, position_y=%f, position_z=%f WHERE id=%u AND point=%u", x, y, z, id, point); WaypointPathMap::iterator itr = m_pathMap.find(id); - if (itr != m_pathMap.end() && point <= itr->second.size()) + if (itr == m_pathMap.end()) + return; + + WaypointPath::iterator find = itr->second.find(point); + if (find != itr->second.end()) { - itr->second[point - 1].x = x; - itr->second[point - 1].y = y; - itr->second[point - 1].z = z; + find->second.x = x; + find->second.y = y; + find->second.z = z; } } void WaypointManager::SetNodeText(uint32 id, uint32 point, const char* text_field, const char* text) { - if (point == 0) return; // counted from 1 in the DB if (!text_field) return; std::string field = text_field; WorldDatabase.escape_string(field); @@ -543,9 +491,13 @@ void WaypointManager::SetNodeText(uint32 id, uint32 point, const char* text_fiel } WaypointPathMap::iterator itr = m_pathMap.find(id); - if (itr != m_pathMap.end() && point <= itr->second.size()) + if (itr == m_pathMap.end()) + return; + + WaypointPath::iterator find = itr->second.find(point); + if (find != itr->second.end()) { - WaypointNode& node = itr->second[point - 1]; + WaypointNode& node = find->second; if (!node.behavior) node.behavior = new WaypointBehavior(); // if(field == "text1") node.behavior->text[0] = text ? text : ""; @@ -560,7 +512,7 @@ void WaypointManager::SetNodeText(uint32 id, uint32 point, const char* text_fiel } } -inline void CheckWPText(bool isTemplate, uint32 entryOrGuid, size_t point, WaypointBehavior* be, std::set& ids) +inline void CheckWPText(bool isTemplate, uint32 entryOrGuid, uint32 point, WaypointBehavior* be, std::set& ids) { int zeroCount = 0; // Counting leading zeros for futher textid shift for (int j = 0; j < MAX_WAYPOINT_TEXT; ++j) @@ -573,7 +525,7 @@ inline void CheckWPText(bool isTemplate, uint32 entryOrGuid, size_t point, Waypo if (!sObjectMgr.GetMangosStringLocale(be->textid[j])) { sLog.outErrorDb("Table `creature_movement%s %u, PointId %u has textid%u with non existing textid %i.", - isTemplate ? "_template` Entry:" : "` Id:", entryOrGuid, point + 1, j, be->textid[j]); + isTemplate ? "_template` Entry:" : "` Id:", entryOrGuid, point, j, be->textid[j]); be->textid[j] = 0; ++zeroCount; continue; @@ -594,15 +546,15 @@ void WaypointManager::CheckTextsExistance(std::set& ids) { for (WaypointPathMap::const_iterator pmItr = m_pathMap.begin(); pmItr != m_pathMap.end(); ++pmItr) { - for (size_t i = 0; i < pmItr->second.size(); ++i) - if (pmItr->second[i].behavior) - CheckWPText(false, pmItr->first, i, pmItr->second[i].behavior, ids); + for (WaypointPath::const_iterator pItr = pmItr->second.begin(); pItr != pmItr->second.end(); ++pItr) + if (pItr->second.behavior) + CheckWPText(false, pmItr->first, pItr->first, pItr->second.behavior, ids); } - for (WaypointPathMap::const_iterator wptItr = m_pathTemplateMap.begin(); wptItr != m_pathTemplateMap.end(); ++wptItr) + for (WaypointPathMap::const_iterator pmItr = m_pathTemplateMap.begin(); pmItr != m_pathTemplateMap.end(); ++pmItr) { - for (size_t i = 0; i < wptItr->second.size(); ++i) - if (wptItr->second[i].behavior) - CheckWPText(true, wptItr->first, i, wptItr->second[i].behavior, ids); + for (WaypointPath::const_iterator pItr = pmItr->second.begin(); pItr != pmItr->second.end(); ++pItr) + if (pItr->second.behavior) + CheckWPText(false, pmItr->first, pItr->first, pItr->second.behavior, ids); } } diff --git a/src/game/WaypointManager.h b/src/game/WaypointManager.h index b4bcc9e58..c0aec684f 100644 --- a/src/game/WaypointManager.h +++ b/src/game/WaypointManager.h @@ -53,7 +53,7 @@ struct WaypointNode : x(_x), y(_y), z(_z), orientation(_o), delay(_delay), script_id(_script_id), behavior(_behavior) {} }; -typedef std::vector WaypointPath; +typedef std::map WaypointPath; class WaypointManager { @@ -64,8 +64,6 @@ class WaypointManager void Load(); void Unload(); - void Cleanup(); - WaypointPath* GetPath(uint32 id) { WaypointPathMap::iterator itr = m_pathMap.find(id); @@ -91,7 +89,7 @@ class WaypointManager void _addNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid); void _clearPath(WaypointPath& path); - typedef UNORDERED_MAP WaypointPathMap; + typedef UNORDERED_MAP WaypointPathMap; WaypointPathMap m_pathMap; WaypointPathMap m_pathTemplateMap; }; diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp index 5a898642b..7a03d7388 100644 --- a/src/game/WaypointMovementGenerator.cpp +++ b/src/game/WaypointMovementGenerator.cpp @@ -16,20 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* -creature_movement Table - -alter table creature_movement add `textid1` int(11) NOT NULL default '0'; -alter table creature_movement add `textid2` int(11) NOT NULL default '0'; -alter table creature_movement add `textid3` int(11) NOT NULL default '0'; -alter table creature_movement add `textid4` int(11) NOT NULL default '0'; -alter table creature_movement add `textid5` int(11) NOT NULL default '0'; -alter table creature_movement add `emote` int(10) unsigned default '0'; -alter table creature_movement add `spell` int(5) unsigned default '0'; -alter table creature_movement add `wpguid` int(11) default '0'; - -*/ - #include #include "WaypointMovementGenerator.h" @@ -76,6 +62,11 @@ void WaypointMovementGenerator::LoadPath(Creature& creature) return; } } + + // Initialize the i_currentNode to point to the first node + if (i_path->empty()) + return; + i_currentNode = i_path->begin()->first; } void WaypointMovementGenerator::Initialize(Creature& creature) @@ -119,14 +110,18 @@ void WaypointMovementGenerator::OnArrived(Creature& creature) creature.clearUnitState(UNIT_STAT_ROAMING_MOVE); m_isArrivalDone = true; - if (i_path->at(i_currentNode).script_id) + WaypointPath::const_iterator currPoint = i_path->find(i_currentNode); + MANGOS_ASSERT(currPoint != i_path->end()); + WaypointNode const& node = currPoint->second; + + if (node.script_id) { - DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for %s.", i_path->at(i_currentNode).script_id, i_currentNode, creature.GetGuidStr().c_str()); - creature.GetMap()->ScriptsStart(sCreatureMovementScripts, i_path->at(i_currentNode).script_id, &creature, &creature); + DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for %s.", node.script_id, i_currentNode, creature.GetGuidStr().c_str()); + creature.GetMap()->ScriptsStart(sCreatureMovementScripts, node.script_id, &creature, &creature); } // We have reached the destination and can process behavior - if (WaypointBehavior* behavior = i_path->at(i_currentNode).behavior) + if (WaypointBehavior* behavior = node.behavior) { if (behavior->emote != 0) creature.HandleEmote(behavior->emote); @@ -159,7 +154,7 @@ void WaypointMovementGenerator::OnArrived(Creature& creature) // Inform script MovementInform(creature); - Stop(i_path->at(i_currentNode).delay); + Stop(node.delay); } void WaypointMovementGenerator::StartMoveNow(Creature& creature) @@ -177,7 +172,10 @@ void WaypointMovementGenerator::StartMove(Creature& creature) if (Stopped(creature)) return; - if (WaypointBehavior* behavior = i_path->at(i_currentNode).behavior) + WaypointPath::const_iterator currPoint = i_path->find(i_currentNode); + MANGOS_ASSERT(currPoint != i_path->end()); + + if (WaypointBehavior* behavior = currPoint->second.behavior) { if (behavior->model2 != 0) creature.SetDisplayId(behavior->model2); @@ -185,18 +183,24 @@ void WaypointMovementGenerator::StartMove(Creature& creature) } if (m_isArrivalDone) - i_currentNode = (i_currentNode + 1) % i_path->size(); + { + ++currPoint; + if (currPoint == i_path->end()) + currPoint = i_path->begin(); + + i_currentNode = currPoint->first; + } m_isArrivalDone = false; creature.addUnitState(UNIT_STAT_ROAMING_MOVE); - const WaypointNode& node = i_path->at(i_currentNode); + WaypointNode const& nextNode = currPoint->second;; Movement::MoveSplineInit init(creature); - init.MoveTo(node.x, node.y, node.z, true); + init.MoveTo(nextNode.x, nextNode.y, nextNode.z, true); - if (node.orientation != 100 && node.delay != 0) - init.SetFacing(node.orientation); + if (nextNode.orientation != 100 && nextNode.delay != 0) + init.SetFacing(nextNode.orientation); creature.SetWalk(!creature.hasUnitState(UNIT_STAT_RUNNING_STATE) && !creature.IsLevitating(), false); init.Launch(); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index bc03c16e1..3725f7522 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "12671" + #define REVISION_NR "12672" #endif // __REVISION_NR_H__