diff options
Diffstat (limited to 'src/game/WaypointManager.cpp')
-rw-r--r-- | src/game/WaypointManager.cpp | 494 |
1 files changed, 152 insertions, 342 deletions
diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp index 831f616060b..501a95f6442 100644 --- a/src/game/WaypointManager.cpp +++ b/src/game/WaypointManager.cpp @@ -1,342 +1,152 @@ -/* - * 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 - * 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" -#include "ObjectMgr.h" - -INSTANTIATE_SINGLETON_1(WaypointManager); - -bool WaypointBehavior::isEmpty() -{ - if (emote || spell || model1 || model2) - return false; - - for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i) - if(textid[i]) - return false; - - return true; -} - -WaypointBehavior::WaypointBehavior(const WaypointBehavior &b) -{ - emote = b.emote; - spell = b.spell; - 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(); - 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, textid1, textid2, textid3, textid4, textid5, 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(!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); - 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; - } -} - -void WaypointManager::CheckTextsExistance(std::set<int32>& ids) -{ - WaypointPathMap::iterator pmItr = m_pathMap.begin(); - for ( ; pmItr != m_pathMap.end(); ++pmItr) - { - for (int i = 0; i < pmItr->second.size(); ++i) - { - if (!pmItr->second[i].behavior) - continue; - - // Now we check text existence and put all zero texts ids to the end of array - - // Counting leading zeros for futher textid shift - int zeroCount = 0; - for (int j = 0; j < MAX_WAYPOINT_TEXT; ++j) - { - 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 - if (zeroCount) - { - // Correct textid but some zeros leading, so move it forward. - pmItr->second[i].behavior->textid[j-zeroCount] = pmItr->second[i].behavior->textid[j]; - pmItr->second[i].behavior->textid[j] = 0; - } - } - } - } - } -} +/*
+ * 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
+ * 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 "WaypointManager.h"
+#include "ProgressBar.h"
+#include "MapManager.h"
+
+UNORDERED_MAP<uint32, WaypointPath*> waypoint_map;
+WaypointStore WaypointMgr;
+
+void WaypointStore::Free()
+{
+ waypoint_map.clear();
+}
+
+void WaypointStore::Load()
+{
+ QueryResult *result = WorldDatabase.PQuery("SELECT MAX(`id`) FROM `waypoint_data");
+ if(!result)
+ {
+ sLog.outError(" an error occured while loading the table `waypoint_data` ( maybe it doesn't exist ?)\n");
+ exit(1); // Stop server at loading non exited table or not accessable table
+ }
+
+ records = (*result)[0].GetUInt32();
+ 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)
+ {
+ sLog.outErrorDb("The table `creature_addon` is empty or corrupted");
+ return;
+ }
+
+ WaypointPath* path_data;
+ uint32 total_records = result->GetRowCount();
+
+ barGoLink bar( total_records);
+ Field *fields;
+ uint32 last_id = 0;
+
+ do
+ {
+ fields = result->Fetch();
+ uint32 id = fields[0].GetUInt32();
+ 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 WaypointStore::UpdatePath(uint32 id)
+{
+
+ 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
+ {
+ fields = result->Fetch();
+ uint32 id = fields[0].GetUInt32();
+
+ WaypointData *wp = new WaypointData;
+
+ 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);
+
+ }while (result->NextRow());
+
+ waypoint_map[id] = path_data;
+
+ delete result;
+}
|