*Recommit four files because of eol issue.
--HG-- branch : trunk
This commit is contained in:
+108
-298
@@ -10,333 +10,143 @@
|
|||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Database/DatabaseEnv.h"
|
#include "Database/DatabaseEnv.h"
|
||||||
#include "GridDefines.h"
|
#include "GridDefines.h"
|
||||||
#include "Policies/SingletonImp.h"
|
|
||||||
#include "WaypointManager.h"
|
#include "WaypointManager.h"
|
||||||
#include "ProgressBar.h"
|
#include "ProgressBar.h"
|
||||||
#include "MapManager.h"
|
#include "MapManager.h"
|
||||||
#include "ObjectMgr.h"
|
|
||||||
|
|
||||||
INSTANTIATE_SINGLETON_1(WaypointManager);
|
UNORDERED_MAP<uint32, WaypointPath*> waypoint_map;
|
||||||
|
WaypointStore WaypointMgr;
|
||||||
|
|
||||||
bool WaypointBehavior::isEmpty()
|
void WaypointStore::Free()
|
||||||
{
|
{
|
||||||
if (emote || spell || model1 || model2)
|
waypoint_map.clear();
|
||||||
return false;
|
|
||||||
|
|
||||||
for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
|
|
||||||
if(textid[i])
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WaypointBehavior::WaypointBehavior(const WaypointBehavior &b)
|
void WaypointStore::Load()
|
||||||
{
|
{
|
||||||
emote = b.emote;
|
QueryResult *result = WorldDatabase.PQuery("SELECT MAX(`id`) FROM `waypoint_data");
|
||||||
spell = b.spell;
|
if(!result)
|
||||||
model1 = b.model1;
|
|
||||||
model2 = b.model2;
|
|
||||||
for(int i=0; i < MAX_WAYPOINT_TEXT; ++i)
|
|
||||||
textid[i] = b.textid[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
sLog.outError(" an error occured while loading the table `waypoint_data` ( maybe it doesn't exist ?)\n");
|
||||||
barGoLink bar( total_paths );
|
exit(1); // Stop server at loading non exited table or not accessable table
|
||||||
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, textid1, textid2, textid3, textid4, textid5, id, point FROM creature_movement");
|
records = (*result)[0].GetUInt32();
|
||||||
if(result)
|
delete result;
|
||||||
|
|
||||||
|
|
||||||
|
result = WorldDatabase.PQuery("SELECT `id`,`point`,`position_x`,`position_y`,`position_z`,`move_flag`,`delay`,`action`,`action_chance` FROM `waypoint_data` ORDER BY `id`, `point`");
|
||||||
|
if(!result)
|
||||||
{
|
{
|
||||||
barGoLink bar( result->GetRowCount() );
|
sLog.outErrorDb("The table `creature_addon` is empty or corrupted");
|
||||||
do
|
return;
|
||||||
{
|
|
||||||
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(!Trinity::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: %f, Y: %f).",
|
|
||||||
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: %f, Y: %f).",
|
|
||||||
id, point, node.x, node.y);
|
|
||||||
|
|
||||||
Trinity::NormalizeMapCoord(node.x);
|
|
||||||
Trinity::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();
|
|
||||||
|
|
||||||
for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
|
|
||||||
{
|
|
||||||
be.textid[i] = fields[9+i].GetUInt32();
|
|
||||||
if(be.textid[i])
|
|
||||||
{
|
|
||||||
if (be.textid[i] < MIN_DB_SCRIPT_STRING_ID || be.textid[i] >= MAX_DB_SCRIPT_STRING_ID)
|
|
||||||
{
|
|
||||||
sLog.outErrorDb( "Table `db_script_string` not have string id %u", be.textid[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
WaypointPath* path_data;
|
||||||
if(itr != m_pathMap.end() && point <= itr->second.size())
|
uint32 total_records = result->GetRowCount();
|
||||||
{
|
|
||||||
WaypointNode &node = itr->second[point-1];
|
|
||||||
if(!node.behavior) node.behavior = new WaypointBehavior();
|
|
||||||
|
|
||||||
// if(field == "text1") node.behavior->text[0] = text ? text : "";
|
barGoLink bar( total_records);
|
||||||
// if(field == "text2") node.behavior->text[1] = text ? text : "";
|
Field *fields;
|
||||||
// if(field == "text3") node.behavior->text[2] = text ? text : "";
|
uint32 last_id = 0;
|
||||||
// if(field == "text4") node.behavior->text[3] = text ? text : "";
|
|
||||||
// if(field == "text5") node.behavior->text[4] = text ? text : "";
|
do
|
||||||
if(field == "emote") node.behavior->emote = text ? atoi(text) : 0;
|
{
|
||||||
if(field == "spell") node.behavior->spell = text ? atoi(text) : 0;
|
fields = result->Fetch();
|
||||||
if(field == "model1") node.behavior->model1 = text ? atoi(text) : 0;
|
uint32 id = fields[0].GetUInt32();
|
||||||
if(field == "model2") node.behavior->model2 = text ? atoi(text) : 0;
|
bar.step();
|
||||||
}
|
WaypointData *wp = new WaypointData;
|
||||||
|
|
||||||
|
if(last_id != id)
|
||||||
|
path_data = new WaypointPath;
|
||||||
|
|
||||||
|
float x,y,z;
|
||||||
|
x = fields[2].GetFloat();
|
||||||
|
y = fields[3].GetFloat();
|
||||||
|
z = fields[4].GetFloat();
|
||||||
|
|
||||||
|
Trinity::NormalizeMapCoord(x);
|
||||||
|
Trinity::NormalizeMapCoord(y);
|
||||||
|
|
||||||
|
wp->id = fields[1].GetUInt32();
|
||||||
|
wp->x = x;
|
||||||
|
wp->y = y;
|
||||||
|
wp->z = z;
|
||||||
|
wp->run = fields[5].GetBool();
|
||||||
|
wp->delay = fields[6].GetUInt32();
|
||||||
|
wp->event_id = fields[7].GetUInt32();
|
||||||
|
wp->event_chance = fields[8].GetUInt8();
|
||||||
|
|
||||||
|
path_data->push_back(wp);
|
||||||
|
|
||||||
|
if(id != last_id)
|
||||||
|
waypoint_map[id] = path_data;
|
||||||
|
|
||||||
|
last_id = id;
|
||||||
|
|
||||||
|
} while(result->NextRow()) ;
|
||||||
|
|
||||||
|
|
||||||
|
delete result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaypointManager::CheckTextsExistance(std::set<int32>& ids)
|
void WaypointStore::UpdatePath(uint32 id)
|
||||||
{
|
{
|
||||||
WaypointPathMap::iterator pmItr = m_pathMap.begin();
|
|
||||||
for ( ; pmItr != m_pathMap.end(); ++pmItr)
|
if(waypoint_map.find(id)!= waypoint_map.end())
|
||||||
|
waypoint_map[id]->clear();
|
||||||
|
|
||||||
|
QueryResult *result;
|
||||||
|
|
||||||
|
result = WorldDatabase.PQuery("SELECT `id`,`point`,`position_x`,`position_y`,`position_z`,`move_flag`,`delay`,`action`,`action_chance` FROM `waypoint_data` WHERE id = %u ORDER BY `point`", id);
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
return;
|
||||||
|
|
||||||
|
WaypointPath* path_data;
|
||||||
|
|
||||||
|
path_data = new WaypointPath;
|
||||||
|
|
||||||
|
Field *fields;
|
||||||
|
|
||||||
|
do
|
||||||
{
|
{
|
||||||
for (int i = 0; i < pmItr->second.size(); ++i)
|
fields = result->Fetch();
|
||||||
{
|
uint32 id = fields[0].GetUInt32();
|
||||||
if (!pmItr->second[i].behavior)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Now we check text existence and put all zero texts ids to the end of array
|
WaypointData *wp = new WaypointData;
|
||||||
|
|
||||||
// Counting leading zeros for futher textid shift
|
float x,y,z;
|
||||||
int zeroCount = 0;
|
x = fields[2].GetFloat();
|
||||||
for (int j = 0; j < MAX_WAYPOINT_TEXT; ++j)
|
y = fields[3].GetFloat();
|
||||||
{
|
z = fields[4].GetFloat();
|
||||||
if (!pmItr->second[i].behavior->textid[j])
|
|
||||||
{
|
|
||||||
++zeroCount;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!objmgr.GetTrinityStringLocale(pmItr->second[i].behavior->textid[j]))
|
|
||||||
{
|
|
||||||
sLog.outErrorDb("ERROR: Some waypoint has textid%u with not existing %u text.", j, pmItr->second[i].behavior->textid[j]);
|
|
||||||
pmItr->second[i].behavior->textid[j] = 0;
|
|
||||||
++zeroCount;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ids.erase(pmItr->second[i].behavior->textid[j]);
|
|
||||||
|
|
||||||
// Shifting check
|
Trinity::NormalizeMapCoord(x);
|
||||||
if (zeroCount)
|
Trinity::NormalizeMapCoord(y);
|
||||||
{
|
|
||||||
// Correct textid but some zeros leading, so move it forward.
|
wp->id = fields[1].GetUInt32();
|
||||||
pmItr->second[i].behavior->textid[j-zeroCount] = pmItr->second[i].behavior->textid[j];
|
wp->x = x;
|
||||||
pmItr->second[i].behavior->textid[j] = 0;
|
wp->y = y;
|
||||||
}
|
wp->z = z;
|
||||||
}
|
wp->run = fields[5].GetBool();
|
||||||
}
|
wp->delay = fields[6].GetUInt32();
|
||||||
}
|
wp->event_id = fields[7].GetUInt32();
|
||||||
}
|
wp->event_chance = fields[8].GetUInt8();
|
||||||
|
|
||||||
|
path_data->push_back(wp);
|
||||||
|
|
||||||
|
}while (result->NextRow());
|
||||||
|
|
||||||
|
waypoint_map[id] = path_data;
|
||||||
|
|
||||||
|
delete result;
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-54
@@ -22,72 +22,40 @@
|
|||||||
#define TRINITY_WAYPOINTMANAGER_H
|
#define TRINITY_WAYPOINTMANAGER_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
|
||||||
#include "Utilities/UnorderedMap.h"
|
|
||||||
|
|
||||||
#define MAX_WAYPOINT_TEXT 5
|
struct WaypointData
|
||||||
struct WaypointBehavior
|
|
||||||
{
|
{
|
||||||
uint32 emote;
|
uint32 id;
|
||||||
uint32 spell;
|
float x,y,z;
|
||||||
int32 textid[MAX_WAYPOINT_TEXT];
|
bool run;
|
||||||
uint32 model1;
|
|
||||||
uint32 model2;
|
|
||||||
|
|
||||||
bool isEmpty();
|
|
||||||
WaypointBehavior() {}
|
|
||||||
WaypointBehavior(const WaypointBehavior &b);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WaypointNode
|
|
||||||
{
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
float z;
|
|
||||||
float orientation;
|
|
||||||
uint32 delay;
|
uint32 delay;
|
||||||
WaypointBehavior * behavior;
|
uint32 event_id;
|
||||||
WaypointNode() {}
|
uint8 event_chance;
|
||||||
WaypointNode(float _x, float _y, float _z, float _o, uint32 _delay, WaypointBehavior * _behavior)
|
|
||||||
: x(_x), y(_y), z(_z), orientation(_o), delay(_delay), behavior(_behavior) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<WaypointNode> WaypointPath;
|
typedef std::vector<WaypointData*> WaypointPath;
|
||||||
|
extern UNORDERED_MAP<uint32, WaypointPath*> waypoint_map;
|
||||||
|
|
||||||
class WaypointManager
|
class WaypointStore
|
||||||
{
|
{
|
||||||
public:
|
private :
|
||||||
WaypointManager() {}
|
uint32 records;
|
||||||
~WaypointManager() { Unload(); }
|
|
||||||
|
|
||||||
void Load();
|
public:
|
||||||
void Unload();
|
void UpdatePath(uint32 id);
|
||||||
|
void Load();
|
||||||
|
void Free();
|
||||||
|
|
||||||
void Cleanup();
|
WaypointPath* GetPath(uint32 id)
|
||||||
|
|
||||||
WaypointPath *GetPath(uint32 id)
|
|
||||||
{
|
{
|
||||||
WaypointPathMap::iterator itr = m_pathMap.find(id);
|
if(waypoint_map.find(id) != waypoint_map.end())
|
||||||
return itr != m_pathMap.end() ? &itr->second : NULL;
|
return waypoint_map[id];
|
||||||
}
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void AddLastNode(uint32 id, float x, float y, float z, float o, uint32 delay, uint32 wpGuid);
|
inline uint32 GetRecordsCount() { return records; }
|
||||||
void AddAfterNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid);
|
|
||||||
uint32 GetLastPoint(uint32 id, uint32 default_notfound);
|
|
||||||
void DeleteNode(uint32 id, uint32 point);
|
|
||||||
void DeletePath(uint32 id);
|
|
||||||
void SetNodePosition(uint32 id, uint32 point, float x, float y, float z);
|
|
||||||
void SetNodeText(uint32 id, uint32 point, const char *text_field, const char *text);
|
|
||||||
void CheckTextsExistance(std::set<int32>& ids);
|
|
||||||
|
|
||||||
private:
|
|
||||||
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;
|
|
||||||
WaypointPathMap m_pathMap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WaypointMgr Trinity::Singleton<WaypointManager>::Instance()
|
extern WaypointStore WaypointMgr;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
@@ -10,210 +8,188 @@
|
|||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
//Basic header
|
||||||
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 <ctime>
|
||||||
|
|
||||||
#include "WaypointMovementGenerator.h"
|
#include "WaypointMovementGenerator.h"
|
||||||
|
//Accessors
|
||||||
|
#include "Database/DatabaseEnv.h"
|
||||||
#include "ObjectMgr.h"
|
#include "ObjectMgr.h"
|
||||||
|
#include "World.h"
|
||||||
|
//Creature-specific headers
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "DestinationHolderImp.h"
|
|
||||||
#include "CreatureAI.h"
|
#include "CreatureAI.h"
|
||||||
#include "WaypointManager.h"
|
//Player-Specific
|
||||||
|
#include "Player.h"
|
||||||
|
//Visual
|
||||||
|
#include "ProgressBar.h"
|
||||||
|
#include "MapManager.h"
|
||||||
|
|
||||||
#include <cassert>
|
template<class T>
|
||||||
|
|
||||||
//-----------------------------------------------//
|
|
||||||
void
|
void
|
||||||
WaypointMovementGenerator<Creature>::LoadPath(Creature &c)
|
WaypointMovementGenerator<T>::Initialize(T &u){}
|
||||||
{
|
|
||||||
sLog.outDetail("LoadPath: loading waypoint path for creature %d,%d", c.GetGUIDLow(), c.GetDBTableGUIDLow());
|
|
||||||
|
|
||||||
i_path = WaypointMgr.GetPath(c.GetDBTableGUIDLow());
|
|
||||||
if(!i_path)
|
|
||||||
{
|
|
||||||
sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %d) doesn't have waypoint path",
|
|
||||||
c.GetName(), c.GetEntry(), c.GetDBTableGUIDLow());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 node_count = i_path->size();
|
|
||||||
i_hasDone.resize(node_count);
|
|
||||||
for(uint32 i = 0; i < node_count-1; i++)
|
|
||||||
i_hasDone[i] = false;
|
|
||||||
|
|
||||||
// to prevent a misbehaviour inside "update"
|
|
||||||
// update is always called with the next wp - but the wpSys needs the current
|
|
||||||
// so when the routine is called the first time, wpSys gets the last waypoint
|
|
||||||
// and this prevents the system from performing text/emote, etc
|
|
||||||
i_hasDone[node_count - 1] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template<>
|
||||||
void
|
void
|
||||||
WaypointMovementGenerator<Creature>::ClearWaypoints()
|
WaypointMovementGenerator<Creature>::Initialize(Creature &u)
|
||||||
{
|
{
|
||||||
i_path = NULL;
|
i_currentNode = -1;
|
||||||
|
u.StopMoving();
|
||||||
|
if(!path_id)
|
||||||
|
path_id = u.GetWaypointPath();
|
||||||
|
waypoints = WaypointMgr.GetPath(path_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
void
|
void
|
||||||
WaypointMovementGenerator<Creature>::Initialize()
|
WaypointMovementGenerator<Creature>::Finalize(Creature &u){}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
template<>
|
||||||
WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
|
void
|
||||||
{
|
WaypointMovementGenerator<Player>::Finalize(Player &u){}
|
||||||
if(!&creature)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Waypoint movement can be switched on/off
|
template<class T>
|
||||||
// This is quite handy for escort quests and other stuff
|
void
|
||||||
if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
|
WaypointMovementGenerator<T>::MovementInform(T &unit){}
|
||||||
return true;
|
|
||||||
|
|
||||||
// prevent a crash at empty waypoint path.
|
|
||||||
if(!i_path || i_path->empty())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// i_path was modified by chat commands for example
|
|
||||||
if(i_path->size() != i_hasDone.size())
|
|
||||||
i_hasDone.resize(i_path->size());
|
|
||||||
if(i_currentNode >= i_path->size())
|
|
||||||
i_currentNode = 0;
|
|
||||||
|
|
||||||
CreatureTraveller traveller(creature);
|
|
||||||
|
|
||||||
i_nextMoveTime.Update(diff);
|
|
||||||
i_destinationHolder.UpdateTraveller(traveller, diff, false, true);
|
|
||||||
|
|
||||||
// creature has been stoped in middle of the waypoint segment
|
|
||||||
if (!i_destinationHolder.HasArrived() && creature.IsStopped())
|
|
||||||
{
|
|
||||||
if( i_nextMoveTime.Passed()) // Timer has elapsed, meaning this part controlled it
|
|
||||||
{
|
|
||||||
SetStopedByPlayer(false);
|
|
||||||
// Now we re-set destination to same node and start travel
|
|
||||||
creature.addUnitState(UNIT_STAT_ROAMING);
|
|
||||||
if (creature.canFly())
|
|
||||||
creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
|
|
||||||
const WaypointNode &node = i_path->at(i_currentNode);
|
|
||||||
i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
|
|
||||||
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
|
|
||||||
}
|
|
||||||
else // if( !i_nextMoveTime.Passed())
|
|
||||||
{ // unexpected end of timer && creature stopped && not at end of segment
|
|
||||||
if (!IsStopedByPlayer())
|
|
||||||
{ // Put 30 seconds delay
|
|
||||||
i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
|
|
||||||
i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
|
|
||||||
SetStopedByPlayer(true); // Mark we did it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true; // Abort here this update
|
|
||||||
}
|
|
||||||
|
|
||||||
if( creature.IsStopped())
|
|
||||||
{
|
|
||||||
uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1;
|
|
||||||
|
|
||||||
if (!i_hasDone[idx])
|
|
||||||
{
|
|
||||||
if (i_path->at(idx).orientation !=100)
|
|
||||||
creature.SetOrientation(i_path->at(idx).orientation);
|
|
||||||
|
|
||||||
if(WaypointBehavior *behavior = i_path->at(idx).behavior)
|
|
||||||
{
|
|
||||||
if(behavior->emote != 0)
|
|
||||||
creature.SetUInt32Value(UNIT_NPC_EMOTESTATE,behavior->emote);
|
|
||||||
if(behavior->spell != 0)
|
|
||||||
creature.CastSpell(&creature,behavior->spell, false);
|
|
||||||
if(behavior->model1 != 0)
|
|
||||||
creature.SetDisplayId(behavior->model1);
|
|
||||||
if(behavior->textid[0])
|
|
||||||
{
|
|
||||||
// Not only one text is set
|
|
||||||
if( behavior->textid[1] )
|
|
||||||
{
|
|
||||||
// Select one from max 5 texts (0 and 1 already checked)
|
|
||||||
int i = 2;
|
|
||||||
for( ; i < MAX_WAYPOINT_TEXT; ++i )
|
|
||||||
if( !behavior->textid[i] )
|
|
||||||
break;
|
|
||||||
|
|
||||||
creature.Say(behavior->textid[rand() % i], 0, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
creature.Say(behavior->textid[0], 0, 0);
|
|
||||||
}
|
|
||||||
} // wpBehaviour found
|
|
||||||
i_hasDone[idx] = true;
|
|
||||||
MovementInform(creature);
|
|
||||||
} // HasDone == false
|
|
||||||
} // i_creature.IsStopped()
|
|
||||||
|
|
||||||
if( i_nextMoveTime.Passed() ) // This is at the end of waypoint segment or has been stopped by player
|
|
||||||
{
|
|
||||||
if( creature.IsStopped() ) // If stopped then begin a new move segment
|
|
||||||
{
|
|
||||||
creature.addUnitState(UNIT_STAT_ROAMING);
|
|
||||||
if (creature.canFly())
|
|
||||||
creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
|
|
||||||
const WaypointNode &node = i_path->at(i_currentNode);
|
|
||||||
i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
|
|
||||||
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
|
|
||||||
uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1;
|
|
||||||
|
|
||||||
if (i_path->at(idx).orientation !=100)
|
|
||||||
creature.SetOrientation(i_path->at(idx).orientation);
|
|
||||||
|
|
||||||
if(WaypointBehavior *behavior = i_path->at(idx).behavior )
|
|
||||||
{
|
|
||||||
i_hasDone[idx] = false;
|
|
||||||
if(behavior->model2 != 0)
|
|
||||||
creature.SetDisplayId(behavior->model2);
|
|
||||||
|
|
||||||
creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // If not stopped then stop it and set the reset of TimeTracker to waittime
|
|
||||||
{
|
|
||||||
creature.StopMoving();
|
|
||||||
SetStopedByPlayer(false);
|
|
||||||
i_nextMoveTime.Reset(i_path->at(i_currentNode).delay);
|
|
||||||
++i_currentNode;
|
|
||||||
if( i_currentNode >= i_path->size() )
|
|
||||||
i_currentNode = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template<>
|
||||||
void WaypointMovementGenerator<Creature>::MovementInform(Creature &unit)
|
void WaypointMovementGenerator<Creature>::MovementInform(Creature &unit)
|
||||||
{
|
{
|
||||||
if(unit.AI())
|
unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
|
||||||
unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void WaypointMovementGenerator<Creature>::Reset(Creature &unit){}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void WaypointMovementGenerator<Player>::Reset(Player &unit){}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void WaypointMovementGenerator<Creature>::InitTraveller(Creature &unit, const WaypointData &node)
|
||||||
|
{
|
||||||
|
node.run ? unit.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE): unit.AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||||
|
|
||||||
|
unit.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||||
|
unit.SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
|
||||||
|
|
||||||
|
if(unit.canFly())
|
||||||
|
unit.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
|
||||||
|
|
||||||
|
unit.addUnitState(UNIT_STAT_ROAMING);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void WaypointMovementGenerator<Player>::InitTraveller(Player &unit, const WaypointData &node){}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool
|
||||||
|
WaypointMovementGenerator<T>::Update(T &unit, const uint32 &diff)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
bool
|
||||||
|
WaypointMovementGenerator<Creature>::Update(Creature &unit, const uint32 &diff)
|
||||||
|
{
|
||||||
|
if(!&unit)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(!path_id)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Waypoint movement can be switched on/off
|
||||||
|
// This is quite handy for escort quests and other stuff
|
||||||
|
if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Clear the generator if the path doesn't exist
|
||||||
|
if(!waypoints || !waypoints->size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Traveller<Creature> traveller(unit);
|
||||||
|
|
||||||
|
i_nextMoveTime.Update(diff);
|
||||||
|
i_destinationHolder.UpdateTraveller(traveller, diff, false, true);
|
||||||
|
|
||||||
|
if(i_nextMoveTime.Passed())
|
||||||
|
{
|
||||||
|
if(unit.IsStopped())
|
||||||
|
{
|
||||||
|
if(StopedByPlayer)
|
||||||
|
{
|
||||||
|
InitTraveller(unit,node);
|
||||||
|
i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
|
||||||
|
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
|
||||||
|
StopedByPlayer = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i_currentNode == waypoints->size() - 1) //If that's our last waypoint
|
||||||
|
{
|
||||||
|
if(repeating) //If the movement is repeating
|
||||||
|
i_currentNode = 0; //Start moving all over again
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unit.GetMotionMaster()->Initialize();
|
||||||
|
return false; //Clear the waypoint movement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i_currentNode++;
|
||||||
|
|
||||||
|
node = *(waypoints->at(i_currentNode));
|
||||||
|
InitTraveller(unit,node);
|
||||||
|
i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
|
||||||
|
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Determine waittime
|
||||||
|
if(node.delay)
|
||||||
|
i_nextMoveTime.Reset(node.delay);
|
||||||
|
else
|
||||||
|
i_nextMoveTime.Reset(100); //Prevents some lag
|
||||||
|
|
||||||
|
if(node.event_id && rand()%100 < node.event_chance && !ExecuteScript)
|
||||||
|
{
|
||||||
|
sWorld.ScriptsStart(sWaypointScripts, node.event_id, &unit, NULL);
|
||||||
|
ExecuteScript = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MovementInform(unit);
|
||||||
|
unit.UpdateWaypointID(i_currentNode);
|
||||||
|
traveller.Relocation(node.x, node.y, node.z);
|
||||||
|
unit.clearUnitState(UNIT_STAT_MOVING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(unit.IsStopped() && !i_destinationHolder.HasArrived())
|
||||||
|
{
|
||||||
|
if(!StopedByPlayer)
|
||||||
|
{
|
||||||
|
i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
|
||||||
|
i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
|
||||||
|
StopedByPlayer = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template void WaypointMovementGenerator<Player>::Initialize(Player &);
|
||||||
|
template bool WaypointMovementGenerator<Player>::Update(Player &, const uint32 &);
|
||||||
|
template void WaypointMovementGenerator<Player>::MovementInform(Player &);
|
||||||
|
|
||||||
//----------------------------------------------------//
|
//----------------------------------------------------//
|
||||||
void
|
void
|
||||||
FlightPathMovementGenerator::LoadPath(Player &)
|
FlightPathMovementGenerator::LoadPath(Player &)
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ class TRINITY_DLL_SPEC PathMovementBase
|
|||||||
|
|
||||||
inline bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); }
|
inline bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); }
|
||||||
|
|
||||||
// template pattern, not defined .. override required
|
|
||||||
void LoadPath(T &);
|
void LoadPath(T &);
|
||||||
void ReloadPath(T &);
|
void ReloadPath(T &);
|
||||||
uint32 GetCurrentNode() const { return i_currentNode; }
|
uint32 GetCurrentNode() const { return i_currentNode; }
|
||||||
@@ -61,53 +60,31 @@ class TRINITY_DLL_SPEC PathMovementBase
|
|||||||
P i_path;
|
P i_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** WaypointMovementGenerator loads a series of way points
|
|
||||||
* from the DB and apply it to the creature's movement generator.
|
|
||||||
* Hence, the creature will move according to its predefined way points.
|
|
||||||
*/
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class TRINITY_DLL_SPEC WaypointMovementGenerator;
|
|
||||||
|
|
||||||
template<>
|
class TRINITY_DLL_SPEC WaypointMovementGenerator
|
||||||
class TRINITY_DLL_SPEC WaypointMovementGenerator<Creature>
|
: public MovementGeneratorMedium< T, WaypointMovementGenerator<T> >, public PathMovementBase<T>
|
||||||
: public MovementGeneratorMedium< Creature, WaypointMovementGenerator<Creature> >,
|
|
||||||
public PathMovementBase<Creature, WaypointPath*>
|
|
||||||
{
|
{
|
||||||
TimeTrackerSmall i_nextMoveTime;
|
public:
|
||||||
std::vector<bool> i_hasDone;
|
WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true) :
|
||||||
public:
|
i_nextMoveTime(0), path_id(_path_id), repeating(_repeating), StopedByPlayer(false){}
|
||||||
WaypointMovementGenerator(Creature &) : i_nextMoveTime(0) {}
|
|
||||||
~WaypointMovementGenerator() { ClearWaypoints(); }
|
|
||||||
void Initialize(Creature &u)
|
|
||||||
{
|
|
||||||
i_nextMoveTime.Reset(0); // TODO: check the lower bound (0 is probably too small)
|
|
||||||
u.StopMoving();
|
|
||||||
LoadPath(u);
|
|
||||||
}
|
|
||||||
void Finalize(Creature &) {}
|
|
||||||
void Reset(Creature &u) { ReloadPath(u); }
|
|
||||||
bool Update(Creature &u, const uint32 &diff);
|
|
||||||
|
|
||||||
void MovementInform(Creature &);
|
void Initialize(T &);
|
||||||
|
void Finalize(T &);
|
||||||
|
void MovementInform(T &);
|
||||||
|
void InitTraveller(T &, const WaypointData &);
|
||||||
|
void GeneratePathId(T &);
|
||||||
|
void Reset(T &unit);
|
||||||
|
bool Update(T &, const uint32 &);
|
||||||
|
bool GetDestination(float &x, float &y, float &z) const{if(i_destinationHolder.HasArrived())return false; i_destinationHolder.GetDestination(x, y, z); return true;}
|
||||||
|
MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; }
|
||||||
|
|
||||||
MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; }
|
private:
|
||||||
|
WaypointData node;
|
||||||
// now path movement implmementation
|
uint32 i_currentNode, path_id;
|
||||||
void LoadPath(Creature &c);
|
TimeTrackerSmall i_nextMoveTime;
|
||||||
void ReloadPath(Creature &c) { ClearWaypoints(); LoadPath(c); }
|
WaypointPath *waypoints;
|
||||||
|
bool repeating, custom_path, ExecuteScript, StopedByPlayer;
|
||||||
// Player stoping creature
|
|
||||||
bool IsStopedByPlayer() { return b_StopedByPlayer; }
|
|
||||||
void SetStopedByPlayer(bool val) { b_StopedByPlayer = val; }
|
|
||||||
|
|
||||||
// statics
|
|
||||||
static void Initialize(void);
|
|
||||||
|
|
||||||
bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; }
|
|
||||||
private:
|
|
||||||
void ClearWaypoints();
|
|
||||||
bool b_StopedByPlayer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** FlightPathMovementGenerator generates movement of the player for the paths
|
/** FlightPathMovementGenerator generates movement of the player for the paths
|
||||||
@@ -135,6 +112,7 @@ public PathMovementBase<Player>
|
|||||||
inline bool HasArrived() const { return (i_currentNode >= i_path.Size()); }
|
inline bool HasArrived() const { return (i_currentNode >= i_path.Size()); }
|
||||||
void SetCurrentNodeAfterTeleport();
|
void SetCurrentNodeAfterTeleport();
|
||||||
void SkipCurrentNode() { ++i_currentNode; }
|
void SkipCurrentNode() { ++i_currentNode; }
|
||||||
bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; }
|
bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; }
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user