root/trunk/src/game/WaypointManager.cpp @ 94

Revision 44, 11.7 kB (checked in by yumileroy, 17 years ago)

[svn] * Merge Temp dev SVN with Assembla.
* Changes include:

  • Implementation of w12x's Outdoor PvP and Game Event Systems.
  • Temporary removal of IRC Chat Bot (until infinite loop when disabled is fixed).
  • All mangos -> trinity (to convert your mangos_string table, please run mangos_string_to_trinity_string.sql).
  • Improved Config cleanup.
  • And many more changes.

Original author: Seline
Date: 2008-10-14 11:57:03-05:00

Line 
1/*
2 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
3 *
4 * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "Database/DatabaseEnv.h"
22#include "GridDefines.h"
23#include "Policies/SingletonImp.h"
24#include "WaypointManager.h"
25#include "ProgressBar.h"
26#include "MapManager.h"
27
28INSTANTIATE_SINGLETON_1(WaypointManager);
29
30bool WaypointBehavior::isEmpty()
31{
32    return emote == 0 && spell == 0 && model1 == 0 && model2 == 0 && text[0].empty() &&
33        text[1].empty() && text[2].empty() && text[3].empty() && text[4].empty();
34}
35
36WaypointBehavior::WaypointBehavior(const WaypointBehavior &b)
37{
38    emote = b.emote; spell = b.spell; model1 = b.model1; model2 = b.model2;
39    text[0] = b.text[0]; text[1] = b.text[1]; text[2] = b.text[2];
40    text[3] = b.text[3]; text[4] = b.text[4];
41}
42
43void WaypointManager::Load()
44{
45    Cleanup();
46
47    uint32 total_paths = 0;
48    uint32 total_nodes = 0;
49    uint32 total_behaviors = 0;
50
51    QueryResult *result = WorldDatabase.Query("SELECT id, COUNT(point) FROM creature_movement GROUP BY id");
52    if(result)
53    {
54        total_paths = result->GetRowCount();
55        barGoLink bar( total_paths );
56        do
57        {
58            Field *fields = result->Fetch();
59            uint32 id    = fields[0].GetUInt32();
60            uint32 count = fields[1].GetUInt32();
61            m_pathMap[id].resize(count);
62
63            total_nodes += count;
64            bar.step();
65        } while( result->NextRow() );
66        delete result;
67    }
68
69    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");
70    if(result)
71    {
72        barGoLink bar( result->GetRowCount() );
73        do
74        {
75            Field *fields = result->Fetch();
76            uint32 point        = fields[15].GetUInt32();
77            uint32 id           = fields[14].GetUInt32();
78
79            WaypointPath &path  = m_pathMap[id];
80            // the cleanup queries make sure the following is true
81            assert(point >= 1 && point <= path.size());
82            WaypointNode &node  = path[point-1];
83
84            node.x              = fields[0].GetFloat();
85            node.y              = fields[1].GetFloat();
86            node.z              = fields[2].GetFloat();
87            node.orientation    = fields[3].GetFloat();
88            node.delay          = fields[6].GetUInt16();
89
90            // prevent using invalid coordinates
91            if(!Trinity::IsValidMapCoord(node.x, node.y, node.z, node.orientation))
92            {
93                QueryResult *result1 = WorldDatabase.PQuery("SELECT id, map FROM creature WHERE guid = '%u'", id);
94                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);
95                else sLog.outErrorDb("ERROR: Waypoint path %d, have invalid coordinates in his waypoint %d (X: %d, Y: %d).", id, point, node.x, node.y);
96
97                Trinity::NormalizeMapCoord(node.x);
98                Trinity::NormalizeMapCoord(node.y);
99                if(result1)
100                {
101                    node.z = MapManager::Instance ().GetBaseMap(result1->Fetch()[1].GetUInt32())->GetHeight(node.x, node.y, node.z);
102                    delete result1;
103                }
104                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);
105            }
106
107            WaypointBehavior be;
108            be.model1           = fields[4].GetUInt32();
109            be.model2           = fields[5].GetUInt32();
110            be.emote            = fields[7].GetUInt32();
111            be.spell            = fields[8].GetUInt32();
112            be.text[0]          = fields[9].GetCppString();
113            be.text[1]          = fields[10].GetCppString();
114            be.text[2]          = fields[11].GetCppString();
115            be.text[3]          = fields[12].GetCppString();
116            be.text[4]          = fields[13].GetCppString();
117
118            // save memory by not storing empty behaviors
119            if(!be.isEmpty())
120            {
121                node.behavior   = new WaypointBehavior(be);
122                ++total_behaviors;
123            }
124            else
125                node.behavior   = NULL;
126            bar.step();
127        } while( result->NextRow() );
128        delete result;
129    }
130    sLog.outString( ">> Loaded %u paths, %u nodes and %u behaviors", total_paths, total_nodes, total_behaviors);
131}
132
133void WaypointManager::Cleanup()
134{
135    // check if points need to be renumbered and do it
136    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"))
137    {
138        delete result;
139        WorldDatabase.DirectExecute("CREATE TEMPORARY TABLE temp LIKE creature_movement");
140        WorldDatabase.DirectExecute("INSERT INTO temp SELECT * FROM creature_movement");
141        WorldDatabase.DirectExecute("ALTER TABLE creature_movement DROP PRIMARY KEY");
142        WorldDatabase.DirectExecute("UPDATE creature_movement AS T SET point = (SELECT COUNT(*) FROM temp WHERE id = T.id AND point <= T.point)");
143        WorldDatabase.DirectExecute("ALTER TABLE creature_movement ADD PRIMARY KEY (id, point)");
144        WorldDatabase.DirectExecute("DROP TABLE temp");
145        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")));
146    }
147}
148
149void WaypointManager::Unload()
150{
151    for(WaypointPathMap::iterator itr = m_pathMap.begin(); itr != m_pathMap.end(); ++itr)
152        _clearPath(itr->second);
153    m_pathMap.clear();
154}
155
156void WaypointManager::_clearPath(WaypointPath &path)
157{
158    for(WaypointPath::iterator itr = path.begin(); itr != path.end(); ++itr)
159        if(itr->behavior)
160            delete itr->behavior;
161    path.clear();
162}
163
164/// - Insert after the last point
165void WaypointManager::AddLastNode(uint32 id, float x, float y, float z, float o, uint32 delay, uint32 wpGuid)
166{
167    _addNode(id, GetLastPoint(id, 0) + 1, x, y, z, o, delay, wpGuid);
168}
169
170/// - Insert after a certain point
171void WaypointManager::AddAfterNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid)
172{
173    for(uint32 i = GetLastPoint(id, 0); i > point; i--)
174        WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point+1 WHERE id='%u' AND point='%u'", id, i);
175
176    _addNode(id, point + 1, x, y, z, o, delay, wpGuid);
177}
178
179/// - Insert without checking for collision
180void WaypointManager::_addNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid)
181{
182    if(point == 0) return;                                  // counted from 1 in the DB
183    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);
184    WaypointPathMap::iterator itr = m_pathMap.find(id);
185    if(itr == m_pathMap.end())
186        itr = m_pathMap.insert(WaypointPathMap::value_type(id, WaypointPath())).first;
187    itr->second.insert(itr->second.begin() + (point - 1), WaypointNode(x, y, z, o, delay, NULL));
188}
189
190uint32 WaypointManager::GetLastPoint(uint32 id, uint32 default_notfound)
191{
192    uint32 point = default_notfound;
193    /*QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'", id);
194    if( result )
195    {
196        point = (*result)[0].GetUInt32()+1;
197        delete result;
198    }*/
199    WaypointPathMap::iterator itr = m_pathMap.find(id);
200    if(itr != m_pathMap.end() && itr->second.size() != 0)
201        point = itr->second.size();
202    return point;
203}
204
205void WaypointManager::DeleteNode(uint32 id, uint32 point)
206{
207    if(point == 0) return;                                  // counted from 1 in the DB
208    WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id='%u' AND point='%u'", id, point);
209    WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point-1 WHERE id='%u' AND point>'%u'", id, point);
210    WaypointPathMap::iterator itr = m_pathMap.find(id);
211    if(itr != m_pathMap.end() && point <= itr->second.size())
212        itr->second.erase(itr->second.begin() + (point-1));
213}
214
215void WaypointManager::DeletePath(uint32 id)
216{
217    WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id='%u'", id);
218    WaypointPathMap::iterator itr = m_pathMap.find(id);
219    if(itr != m_pathMap.end())
220        _clearPath(itr->second);
221    // the path is not removed from the map, just cleared
222    // WMGs have pointers to the path, so deleting them would crash
223    // this wastes some memory, but these functions are
224    // only meant to be called by GM commands
225}
226
227void WaypointManager::SetNodePosition(uint32 id, uint32 point, float x, float y, float z)
228{
229    if(point == 0) return;                                  // counted from 1 in the DB
230    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);
231    WaypointPathMap::iterator itr = m_pathMap.find(id);
232    if(itr != m_pathMap.end() && point <= itr->second.size())
233    {
234        itr->second[point-1].x = x;
235        itr->second[point-1].y = y;
236        itr->second[point-1].z = z;
237    }
238}
239
240void WaypointManager::SetNodeText(uint32 id, uint32 point, const char *text_field, const char *text)
241{
242    if(point == 0) return;                                  // counted from 1 in the DB
243    if(!text_field) return;
244    std::string field = text_field;
245    WorldDatabase.escape_string(field);
246
247    if(!text)
248    {
249        WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s=NULL WHERE id='%u' AND point='%u'", field.c_str(), id, point);
250    }
251    else
252    {
253        std::string text2 = text;
254        WorldDatabase.escape_string(text2);
255        WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s='%s' WHERE id='%u' AND point='%u'", field.c_str(), text2.c_str(), id, point);
256    }
257
258    WaypointPathMap::iterator itr = m_pathMap.find(id);
259    if(itr != m_pathMap.end() && point <= itr->second.size())
260    {
261        WaypointNode &node = itr->second[point-1];
262        if(!node.behavior) node.behavior = new WaypointBehavior();
263
264        if(field == "text1") node.behavior->text[0] = text ? text : "";
265        if(field == "text2") node.behavior->text[1] = text ? text : "";
266        if(field == "text3") node.behavior->text[2] = text ? text : "";
267        if(field == "text4") node.behavior->text[3] = text ? text : "";
268        if(field == "text5") node.behavior->text[4] = text ? text : "";
269        if(field == "emote") node.behavior->emote   = text ? atoi(text) : 0;
270        if(field == "spell") node.behavior->spell   = text ? atoi(text) : 0;
271        if(field == "model1") node.behavior->model1 = text ? atoi(text) : 0;
272        if(field == "model2") node.behavior->model2 = text ? atoi(text) : 0;
273    }
274}
Note: See TracBrowser for help on using the browser.