mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 04:37:00 +00:00
Imported MaNGOS revision 6767 from http://mangos.svn.sourceforge.net/svnroot/mangos/trunk/
This commit is contained in:
parent
d767495d5b
commit
800ee76535
3322 changed files with 903437 additions and 0 deletions
272
src/game/WaypointManager.cpp
Normal file
272
src/game/WaypointManager.cpp
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "GridDefines.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "WaypointManager.h"
|
||||
#include "ProgressBar.h"
|
||||
#include "MapManager.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1(WaypointManager);
|
||||
|
||||
bool WaypointBehavior::isEmpty()
|
||||
{
|
||||
return emote == 0 && spell == 0 && model1 == 0 && model2 == 0 && text[0].empty() &&
|
||||
text[1].empty() && text[2].empty() && text[3].empty() && text[4].empty();
|
||||
}
|
||||
|
||||
WaypointBehavior::WaypointBehavior(const WaypointBehavior &b)
|
||||
{
|
||||
emote = b.emote; spell = b.spell; model1 = b.model1; model2 = b.model2;
|
||||
text[0] = b.text[0]; text[1] = b.text[1]; text[2] = b.text[2];
|
||||
text[3] = b.text[3]; text[4] = b.text[4];
|
||||
}
|
||||
|
||||
void WaypointManager::Load()
|
||||
{
|
||||
Cleanup();
|
||||
|
||||
uint32 total_paths = 0;
|
||||
uint32 total_nodes = 0;
|
||||
uint32 total_behaviors = 0;
|
||||
|
||||
QueryResult *result = WorldDatabase.Query("SELECT id, COUNT(point) FROM creature_movement GROUP BY id");
|
||||
if(result)
|
||||
{
|
||||
total_paths = result->GetRowCount();
|
||||
barGoLink bar( total_paths );
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
uint32 id = fields[0].GetUInt32();
|
||||
uint32 count = fields[1].GetUInt32();
|
||||
m_pathMap[id].resize(count);
|
||||
|
||||
total_nodes += count;
|
||||
bar.step();
|
||||
} while( result->NextRow() );
|
||||
delete result;
|
||||
}
|
||||
|
||||
result = WorldDatabase.Query("SELECT position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5, id, point FROM creature_movement");
|
||||
if(result)
|
||||
{
|
||||
barGoLink bar( result->GetRowCount() );
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
uint32 point = fields[15].GetUInt32();
|
||||
uint32 id = fields[14].GetUInt32();
|
||||
|
||||
WaypointPath &path = m_pathMap[id];
|
||||
// the cleanup queries make sure the following is true
|
||||
assert(point >= 1 && point <= path.size());
|
||||
WaypointNode &node = path[point-1];
|
||||
|
||||
node.x = fields[0].GetFloat();
|
||||
node.y = fields[1].GetFloat();
|
||||
node.z = fields[2].GetFloat();
|
||||
node.orientation = fields[3].GetFloat();
|
||||
node.delay = fields[6].GetUInt16();
|
||||
|
||||
// prevent using invalid coordinates
|
||||
if(!MaNGOS::IsValidMapCoord(node.x, node.y, node.z, node.orientation))
|
||||
{
|
||||
QueryResult *result1 = WorldDatabase.PQuery("SELECT id, map FROM creature WHERE guid = '%u'", id);
|
||||
if(result1) sLog.outErrorDb("ERROR: Creature (guidlow %d, entry %d) have invalid coordinates in his waypoint %d (X: %d, Y: %d).", id, result1->Fetch()[0].GetUInt32(), point, node.x, node.y);
|
||||
else sLog.outErrorDb("ERROR: Waypoint path %d, have invalid coordinates in his waypoint %d (X: %d, Y: %d).", id, point, node.x, node.y);
|
||||
|
||||
MaNGOS::NormalizeMapCoord(node.x);
|
||||
MaNGOS::NormalizeMapCoord(node.y);
|
||||
if(result1)
|
||||
{
|
||||
node.z = MapManager::Instance ().GetBaseMap(result1->Fetch()[1].GetUInt32())->GetHeight(node.x, node.y, node.z);
|
||||
delete result1;
|
||||
}
|
||||
WorldDatabase.PExecute("UPDATE creature_movement SET position_x = '%f', position_y = '%f', position_z = '%f' WHERE id = '%u' AND point = '%u'", node.x, node.y, node.z, id, point);
|
||||
}
|
||||
|
||||
WaypointBehavior be;
|
||||
be.model1 = fields[4].GetUInt32();
|
||||
be.model2 = fields[5].GetUInt32();
|
||||
be.emote = fields[7].GetUInt32();
|
||||
be.spell = fields[8].GetUInt32();
|
||||
be.text[0] = fields[9].GetCppString();
|
||||
be.text[1] = fields[10].GetCppString();
|
||||
be.text[2] = fields[11].GetCppString();
|
||||
be.text[3] = fields[12].GetCppString();
|
||||
be.text[4] = fields[13].GetCppString();
|
||||
|
||||
// save memory by not storing empty behaviors
|
||||
if(!be.isEmpty())
|
||||
{
|
||||
node.behavior = new WaypointBehavior(be);
|
||||
++total_behaviors;
|
||||
}
|
||||
else
|
||||
node.behavior = NULL;
|
||||
bar.step();
|
||||
} while( result->NextRow() );
|
||||
delete result;
|
||||
}
|
||||
sLog.outString( ">> Loaded %u paths, %u nodes and %u behaviors", total_paths, total_nodes, total_behaviors);
|
||||
}
|
||||
|
||||
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");
|
||||
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")));
|
||||
}
|
||||
}
|
||||
|
||||
void WaypointManager::Unload()
|
||||
{
|
||||
for(WaypointPathMap::iterator itr = m_pathMap.begin(); itr != m_pathMap.end(); ++itr)
|
||||
_clearPath(itr->second);
|
||||
m_pathMap.clear();
|
||||
}
|
||||
|
||||
void WaypointManager::_clearPath(WaypointPath &path)
|
||||
{
|
||||
for(WaypointPath::iterator itr = path.begin(); itr != path.end(); ++itr)
|
||||
if(itr->behavior)
|
||||
delete itr->behavior;
|
||||
path.clear();
|
||||
}
|
||||
|
||||
/// - Insert after the last point
|
||||
void WaypointManager::AddLastNode(uint32 id, float x, float y, float z, float o, uint32 delay, uint32 wpGuid)
|
||||
{
|
||||
_addNode(id, GetLastPoint(id, 0) + 1, x, y, z, o, delay, wpGuid);
|
||||
}
|
||||
|
||||
/// - Insert after a certain point
|
||||
void WaypointManager::AddAfterNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid)
|
||||
{
|
||||
for(uint32 i = GetLastPoint(id, 0); i > point; i--)
|
||||
WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point+1 WHERE id='%u' AND point='%u'", id, i);
|
||||
|
||||
_addNode(id, point + 1, x, y, z, o, delay, wpGuid);
|
||||
}
|
||||
|
||||
/// - 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', '%d', '%d')", 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, 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::iterator itr = m_pathMap.find(id);
|
||||
if(itr != m_pathMap.end() && itr->second.size() != 0)
|
||||
point = itr->second.size();
|
||||
return point;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void WaypointManager::DeletePath(uint32 id)
|
||||
{
|
||||
WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id='%u'", id);
|
||||
WaypointPathMap::iterator itr = m_pathMap.find(id);
|
||||
if(itr != m_pathMap.end())
|
||||
_clearPath(itr->second);
|
||||
// the path is not removed from the map, just cleared
|
||||
// WMGs have pointers to the path, so deleting them would crash
|
||||
// this wastes some memory, but these functions are
|
||||
// only meant to be called by GM commands
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
itr->second[point-1].x = x;
|
||||
itr->second[point-1].y = y;
|
||||
itr->second[point-1].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);
|
||||
|
||||
if(!text)
|
||||
{
|
||||
WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s=NULL WHERE id='%u' AND point='%u'", field.c_str(), id, point);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string text2 = text;
|
||||
WorldDatabase.escape_string(text2);
|
||||
WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s='%s' WHERE id='%u' AND point='%u'", field.c_str(), text2.c_str(), id, point);
|
||||
}
|
||||
|
||||
WaypointPathMap::iterator itr = m_pathMap.find(id);
|
||||
if(itr != m_pathMap.end() && point <= itr->second.size())
|
||||
{
|
||||
WaypointNode &node = itr->second[point-1];
|
||||
if(!node.behavior) node.behavior = new WaypointBehavior();
|
||||
|
||||
if(field == "text1") node.behavior->text[0] = text ? text : "";
|
||||
if(field == "text2") node.behavior->text[1] = text ? text : "";
|
||||
if(field == "text3") node.behavior->text[2] = text ? text : "";
|
||||
if(field == "text4") node.behavior->text[3] = text ? text : "";
|
||||
if(field == "text5") node.behavior->text[4] = text ? text : "";
|
||||
if(field == "emote") node.behavior->emote = text ? atoi(text) : 0;
|
||||
if(field == "spell") node.behavior->spell = text ? atoi(text) : 0;
|
||||
if(field == "model1") node.behavior->model1 = text ? atoi(text) : 0;
|
||||
if(field == "model2") node.behavior->model2 = text ? atoi(text) : 0;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue