Skip to content

Commit

Permalink
[c12661] Improve Waypoint Management
Browse files Browse the repository at this point in the history
* 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

(based on commit [12469] - 382f837)
  • Loading branch information
Schmoozerd authored and Dramacydal committed Aug 19, 2013
1 parent 75ed656 commit 6392317
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 115 deletions.
3 changes: 2 additions & 1 deletion src/game/Level2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() : "<not found>"), wpGuid);
PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
Expand Down
120 changes: 36 additions & 84 deletions src/game/WaypointManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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)
Expand All @@ -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();
}

Expand All @@ -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)
Expand All @@ -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);
Expand All @@ -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 : "";
Expand All @@ -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<int32>& ids)
inline void CheckWPText(bool isTemplate, uint32 entryOrGuid, uint32 point, WaypointBehavior* be, std::set<int32>& ids)
{
int zeroCount = 0; // Counting leading zeros for futher textid shift
for (int j = 0; j < MAX_WAYPOINT_TEXT; ++j)
Expand All @@ -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;
Expand All @@ -594,15 +546,15 @@ void WaypointManager::CheckTextsExistance(std::set<int32>& 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);
}
}
6 changes: 2 additions & 4 deletions src/game/WaypointManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<WaypointNode> WaypointPath;
typedef std::map<uint32 /*pointId*/, WaypointNode> WaypointPath;

class WaypointManager
{
Expand All @@ -64,8 +64,6 @@ class WaypointManager
void Load();
void Unload();

void Cleanup();

WaypointPath* GetPath(uint32 id)
{
WaypointPathMap::iterator itr = m_pathMap.find(id);
Expand All @@ -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<uint32, WaypointPath> WaypointPathMap;
typedef UNORDERED_MAP<uint32 /*guidOrEntry*/, WaypointPath> WaypointPathMap;
WaypointPathMap m_pathMap;
WaypointPathMap m_pathTemplateMap;
};
Expand Down
54 changes: 29 additions & 25 deletions src/game/WaypointMovementGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <ctime>

#include "WaypointMovementGenerator.h"
Expand Down Expand Up @@ -76,6 +62,11 @@ void WaypointMovementGenerator<Creature>::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<Creature>::Initialize(Creature& creature)
Expand Down Expand Up @@ -119,14 +110,18 @@ void WaypointMovementGenerator<Creature>::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);
Expand Down Expand Up @@ -159,7 +154,7 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)

// Inform script
MovementInform(creature);
Stop(i_path->at(i_currentNode).delay);
Stop(node.delay);
}

void WaypointMovementGenerator<Creature>::StartMoveNow(Creature& creature)
Expand All @@ -177,26 +172,35 @@ void WaypointMovementGenerator<Creature>::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);
creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
}

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();
}
Expand Down
2 changes: 1 addition & 1 deletion src/shared/revision_nr.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "12660"
#define REVISION_NR "12661"
#endif // __REVISION_NR_H__

0 comments on commit 6392317

Please sign in to comment.