EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Server Code Submissions (https://www.eqemulator.org/forums/forumdisplay.php?f=669)
-   -   COMMITTED: Grid Waypoints (https://www.eqemulator.org/forums/showthread.php?t=31420)

joligario 06-04-2010 09:12 AM

COMMITTED: Grid Waypoints
 
Changes which allow the mob AI to use headings from the grid entries table. Also changes to the #wp and #wpadd commands to save heading data when adding a new grid entry.

zone/command.cpp
Code:

Index: zone/command.cpp
===================================================================
--- zone/command.cpp        (revision 1520)
+++ zone/command.cpp        (working copy)
@@ -2433,7 +2433,7 @@
        if (strcasecmp("add",sep->arg[1]) == 0) {
                if (wp == 0) //AndMetal: default to highest if it's left blank, or we enter 0
                        wp = database.GetHighestWaypoint(zone->GetZoneID(), atoi(sep->arg[2])) + 1;
-                database.AddWP(c, atoi(sep->arg[2]),wp, c->GetX(), c->GetY(), c->GetZ(), atoi(sep->arg[3]),zone->GetZoneID());
+                database.AddWP(c, atoi(sep->arg[2]),wp, c->GetX(), c->GetY(), c->GetZ(), atoi(sep->arg[3]),zone->GetZoneID(), c->GetHeading());
        }
        else if (strcasecmp("delete",sep->arg[1]) == 0)
                database.DeleteWaypoint(c, atoi(sep->arg[2]),wp,zone->GetZoneID());
@@ -5955,7 +5955,7 @@
                                return;
                        }
                }
-                int32 tmp_grid = database.AddWPForSpawn(c, s2info->GetID(), c->GetX(),c->GetY(),c->GetZ(), pause, type1, type2, zone->GetZoneID());
+                int32 tmp_grid = database.AddWPForSpawn(c, s2info->GetID(), c->GetX(),c->GetY(),c->GetZ(), pause, type1, type2, zone->GetZoneID(),c->GetHeading());
                if (tmp_grid)
                        t->CastToNPC()->SetGrid(tmp_grid);

zone/mob.h
Code:

Index: zone/mob.h
===================================================================
--- zone/mob.h        (revision 1520)
+++ zone/mob.h        (working copy)
@@ -1199,6 +1200,7 @@
        float cur_wp_y;
        float cur_wp_z;
        int cur_wp_pause;
+        float cur_wp_heading;
 
        int patrol;
        float fear_walkto_x;

zone/MobAI.cpp
Code:

Index: zone/MobAI.cpp
===================================================================
--- zone/MobAI.cpp        (revision 1520)
+++ zone/MobAI.cpp        (working copy)
@@ -1594,6 +1594,7 @@
                                if (cur_wp_x == GetX() && cur_wp_y == GetY())
                                {        // are we there yet? then stop
                                        mlog(AI__WAYPOINTS, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid());
+                                        SetHeading(cur_wp_heading);
                                        SetWaypointPause();
                                        SetAppearance(eaStanding, false);
                                        SetMoving(false);

Index: zone/waypoints.cpp
Code:

Index: waypoints.cpp
===================================================================
--- waypoints.cpp        (revision 1520)
+++ waypoints.cpp        (working copy)
@@ -202,6 +202,7 @@
        cur_wp_y = mty;
        cur_wp_z = mtz;
        cur_wp_pause = 0;
+        cur_wp_heading = mth;
 }
 
 void NPC::UpdateWaypoint(int wp_index)
@@ -218,7 +219,8 @@
        cur_wp_y = cur->y;
        cur_wp_z = cur->z;
        cur_wp_pause = cur->pause;
-        mlog(AI__WAYPOINTS, "Next waypoint %d: (%.3f, %.3f, %.3f)", wp_index, cur_wp_x, cur_wp_y, cur_wp_z);
+        cur_wp_heading = cur->heading;
+        mlog(AI__WAYPOINTS, "Next waypoint %d: (%.3f, %.3f, %.3f, %.3f)", wp_index, cur_wp_x, cur_wp_y, cur_wp_z, cur_wp_heading);
               
        //fix up pathing Z
        if(zone->HasMap() && RuleB(Map, FixPathingZAtWaypoints))
@@ -847,7 +849,7 @@
            adverrorinfo = 7561;
 
            // Retrieve all waypoints for this grid
-            if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `x`,`y`,`z`,`pause` FROM grid_entries WHERE `gridid`=%i AND `zoneid`=%i ORDER BY `number`",grid,zone->GetZoneID()),errbuf,&result))
+            if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `x`,`y`,`z`,`pause`,`heading` FROM grid_entries WHERE `gridid`=%i AND `zoneid`=%i ORDER BY `number`",grid,zone->GetZoneID()),errbuf,&result))
            {
                    roamer = true;
                        max_wp = -1;        // Initialize it; will increment it for each waypoint successfully added to the list
@@ -878,6 +880,7 @@
                                }
 
                                newwp.pause = atoi(row[3]);
+                                newwp.heading = atof(row[4]);
                                Waypoints.push_back(newwp);
                            }
                        }
@@ -1033,7 +1036,7 @@
        char errbuff[MYSQL_ERRMSG_SIZE];
        MYSQL_RES *result;
        MYSQL_ROW row;
-        if (RunQuery(query, MakeAnyLenString(&query,"SELECT x, y, z, pause from grid_entries where gridid = %i and number = %i and zoneid = %i",grid,num,zoneid),errbuff,&result)) {
+        if (RunQuery(query, MakeAnyLenString(&query,"SELECT x, y, z, pause, heading from grid_entries where gridid = %i and number = %i and zoneid = %i",grid,num,zoneid),errbuff,&result)) {
                safe_delete_array(query);
                if (mysql_num_rows(result) == 1) {
                        row = mysql_fetch_row(result);
@@ -1042,6 +1045,7 @@
                                wp->y = atof( row[1] );
                                wp->z = atof( row[2] );
                                wp->pause = atoi( row[3] );
+                                wp->heading = atof( row[4] );
                        }
                        mysql_free_result(result);
                        return true;
@@ -1204,12 +1208,12 @@
 * AddWP - Adds a new waypoint to a specific grid for a specific zone.
 */
 
-void ZoneDatabase::AddWP(Client *c, int32 gridid, int32 wpnum, float xpos, float ypos, float zpos, int32 pause, int16 zoneid)
+void ZoneDatabase::AddWP(Client *c, int32 gridid, int32 wpnum, float xpos, float ypos, float zpos, int32 pause, int16 zoneid, float heading)
 { 
        char *query = 0;
        char errbuf[MYSQL_ERRMSG_SIZE];
 
-        if(!RunQuery(query,MakeAnyLenString(&query,"INSERT INTO grid_entries (gridid,zoneid,`number`,x,y,z,pause) values (%i,%i,%i,%f,%f,%f,%i)",gridid,zoneid,wpnum,xpos,ypos,zpos,pause), errbuf)) {
+        if(!RunQuery(query,MakeAnyLenString(&query,"INSERT INTO grid_entries (gridid,zoneid,`number`,x,y,z,pause,heading) values (%i,%i,%i,%f,%f,%f,%i,%f)",gridid,zoneid,wpnum,xpos,ypos,zpos,pause,heading), errbuf)) {
                LogFile->write(EQEMuLog::Error, "Error adding waypoint '%s': '%s'", query, errbuf);
        } else {
                if(c) c->LogSQL(query);
@@ -1251,7 +1255,7 @@
 * the created grid is returned.
 */
 
-int32 ZoneDatabase::AddWPForSpawn(Client *c, int32 spawn2id, float xpos, float ypos, float zpos, int32 pause, int type1, int type2, int16 zoneid) {
+int32 ZoneDatabase::AddWPForSpawn(Client *c, int32 spawn2id, float xpos, float ypos, float zpos, int32 pause, int type1, int type2, int16 zoneid, float heading) {
        char        *query = 0;
    int32        grid_num,        // The grid number the spawn is assigned to (if spawn has no grid, will be the grid number we end up creating)
                next_wp_num;        // The waypoint number we should be assigning to the new waypoint
@@ -1323,7 +1327,7 @@
        }
 
        query = 0;
-        if(!RunQuery(query, MakeAnyLenString(&query,"INSERT INTO grid_entries(gridid,zoneid,`number`,x,y,z,pause) VALUES (%i,%i,%i,%f,%f,%f,%i)",grid_num,zoneid,next_wp_num,xpos,ypos,zpos,pause), errbuf)) {
+        if(!RunQuery(query, MakeAnyLenString(&query,"INSERT INTO grid_entries(gridid,zoneid,`number`,x,y,z,pause,heading) VALUES (%i,%i,%i,%f,%f,%f,%i,%f)",grid_num,zoneid,next_wp_num,xpos,ypos,zpos,pause,heading), errbuf)) {
                LogFile->write(EQEMuLog::Error, "Error adding grid entry '%s': '%s'", query, errbuf);
        } else {
                if(c) c->LogSQL(query);

zone/zonedb.h
Code:

===================================================================
--- zone/zonedb.h        (revision 1520)
+++ zone/zonedb.h        (working copy)
@@ -12,6 +12,7 @@
        float y;
        float z;
        int          pause;
+        float heading;
 };
 
 #pragma pack(1)
@@ -226,8 +227,8 @@
        void        DeleteGrid(Client *c, int32 sg2, int32 grid_num, bool grid_too,int16 zoneid);
        void        DeleteWaypoint(Client *c, int32 grid_num, int32 wp_num,int16 zoneid);
 //        int32        AddWP(Client *c, int32 sg2, int16 grid_num, int8 wp_num, float xpos, float ypos, float zpos, int32 pause, float xpos1, float ypos1, float zpos1, int type1, int type2,int16 zoneid);
-        void        AddWP(Client *c, int32 gridid, int32 wpnum, float xpos, float ypos, float zpos, int32 pause, int16 zoneid);
-        int32        AddWPForSpawn(Client *c, int32 spawn2id, float xpos, float ypos, float zpos, int32 pause, int type1, int type2, int16 zoneid);
+        void        AddWP(Client *c, int32 gridid, int32 wpnum, float xpos, float ypos, float zpos, int32 pause, int16 zoneid, float heading);
+        int32        AddWPForSpawn(Client *c, int32 spawn2id, float xpos, float ypos, float zpos, int32 pause, int type1, int type2, int16 zoneid, float heading);
        void        ModifyGrid(Client *c, bool remove, int32 id, int8 type = 0, int8 type2 = 0,int16 zoneid = 0);
        void    ModifyWP(Client *c, int32 grid_id, int32 wp_num, float xpos, float ypos, float zpos, int32 script=0,int16 zoneid =0);
        int8    GetGridType(int32 grid,int32 zoneid);


KLS 06-04-2010 12:06 PM

Hm I'm not sure I'm going to add this as is. In some cases it's nice to not use the heading(for example random wander grids) and it'd be nice to preserve the old behavior too. I'll think of a way they both work and get it in though.

joligario 06-04-2010 02:47 PM

Hmm.. maybe an option is if we only do the SetHeading() if the heading is > 0

KLS 06-07-2010 03:22 AM

That's what I was thinking, plus an extra option in wp add to set heading or not.

joligario 06-11-2010 08:48 AM

Maybe this is a bit better. Overall changes:

1. Adds ability for MobAI to use heading from grid in database.
2. MobAI will continue to use default directional heading (in stride heading) if no heading set in database grid (-1 is default, 0+ will use heading).
3. New -h switch for #wp and #wpadd commands which uses your heading when adding new waypoint to grid. If ommitted, the default -1 will be entered into the grid.

Code:

Index: zone/command.cpp
===================================================================
--- zone/command.cpp        (revision 1535)
+++ zone/command.cpp        (working copy)
@@ -236,8 +236,8 @@
                command_add("setpass","[accountname] [password] - Set local password for accountname",150,command_setpass) ||
                command_add("setlsinfo","[email] [password] - Set login server email address and password (if supported by login server)",10,command_setlsinfo) ||
                command_add("grid","[add/delete] [grid_num] [wandertype] [pausetype] - Create/delete a wandering grid",170,command_grid) ||
-                command_add("wp","[add/delete] [grid_num] [pause] [wp_num] - Add/delete a waypoint to/from a wandering grid",170,command_wp) ||
-                command_add("wpadd","[pause] - Add your current location as a waypoint to your NPC target's AI path",170,command_wpadd) ||
+                command_add("wp","[add/delete] [grid_num] [pause] [wp_num] [-h] - Add/delete a waypoint to/from a wandering grid",170,command_wp) ||
+                command_add("wpadd","[pause] [-h] - Add your current location as a waypoint to your NPC target's AI path",170,command_wpadd) ||
                command_add("wpinfo","- Show waypoint info about your NPC target",170,command_wpinfo) ||
                command_add("iplookup","[charname] - Look up IP address of charname",200,command_iplookup) ||
                command_add("size","[size] - Change size of you or your target",50,command_size) ||
@@ -2434,12 +2434,17 @@
        if (strcasecmp("add",sep->arg[1]) == 0) {
                if (wp == 0) //AndMetal: default to highest if it's left blank, or we enter 0
                        wp = database.GetHighestWaypoint(zone->GetZoneID(), atoi(sep->arg[2])) + 1;
-                database.AddWP(c, atoi(sep->arg[2]),wp, c->GetX(), c->GetY(), c->GetZ(), atoi(sep->arg[3]),zone->GetZoneID());
+                if (strcasecmp("-h",sep->arg[5]) == 0) {
+                        database.AddWP(c, atoi(sep->arg[2]),wp, c->GetX(), c->GetY(), c->GetZ(), atoi(sep->arg[3]),zone->GetZoneID(), c->GetHeading());
+                }
+                else {
+                        database.AddWP(c, atoi(sep->arg[2]),wp, c->GetX(), c->GetY(), c->GetZ(), atoi(sep->arg[3]),zone->GetZoneID(), -1);
+                }
        }
        else if (strcasecmp("delete",sep->arg[1]) == 0)
                database.DeleteWaypoint(c, atoi(sep->arg[2]),wp,zone->GetZoneID());
        else
-                c->Message(0,"Usage: #wp add/delete grid_num pause wp_num");
+                c->Message(0,"Usage: #wp add/delete grid_num pause wp_num [-h]");
 }
 
 void command_iplookup(Client *c, const Seperator *sep)
@@ -5933,7 +5938,8 @@
 {
        int        type1=0,
                type2=0,
-                pause=0;        // Defaults for a new grid
+                pause=0,
+                heading=-1;        // Defaults for a new grid
 
        Mob *t=c->GetTarget();
        if (t && t->IsNPC())
@@ -5952,11 +5958,13 @@
                                pause=atoi(sep->arg[1]);
                        else
                        {
-                                c->Message(0,"Usage: #wpadd [pause]");
+                                c->Message(0,"Usage: #wpadd [pause] [-h]");
                                return;
                        }
                }
-                int32 tmp_grid = database.AddWPForSpawn(c, s2info->GetID(), c->GetX(),c->GetY(),c->GetZ(), pause, type1, type2, zone->GetZoneID());
+                if (strcmp("-h",sep->arg[2]) == 0)
+                        heading = c->GetHeading();
+                int32 tmp_grid = database.AddWPForSpawn(c, s2info->GetID(), c->GetX(),c->GetY(),c->GetZ(), pause, type1, type2, zone->GetZoneID(), heading);
                if (tmp_grid)
                        t->CastToNPC()->SetGrid(tmp_grid);

Code:

Index: zone/mob.h
===================================================================
--- zone/mob.h        (revision 1535)
+++ zone/mob.h        (working copy)
@@ -1200,6 +1200,7 @@
        float cur_wp_y;
        float cur_wp_z;
        int cur_wp_pause;
+        float cur_wp_heading;
 
        int patrol;
        float fear_walkto_x;

Code:

Index: zone/MobAI.cpp
===================================================================
--- zone/MobAI.cpp        (revision 1535)
+++ zone/MobAI.cpp        (working copy)
@@ -1597,6 +1597,9 @@
                                        SetWaypointPause();
                                        SetAppearance(eaStanding, false);
                                        SetMoving(false);
+                                        if (cur_wp_heading >= 0.0) {
+                                                SetHeading(cur_wp_heading);
+                                        }
                                        SendPosition();
                                       
                                        //kick off event_waypoint arrive

Code:

Index: zone/waypoints.cpp
===================================================================
--- zone/waypoints.cpp        (revision 1535)
+++ zone/waypoints.cpp        (working copy)
@@ -74,11 +74,12 @@
        cur = Waypoints.begin();
        end = Waypoints.end();
        for(; cur != end; cur++) {
-                c->Message(0,"Waypoint %d: (%.2f,%.2f,%.2f) pause %d",
+                c->Message(0,"Waypoint %d: (%.2f,%.2f,%.2f,%.2f) pause %d",
                                cur->index,
                                cur->x,
                                cur->y,
                                cur->z,
+                                cur->heading,
                                cur->pause );
        }
 }
@@ -202,6 +203,7 @@
        cur_wp_y = mty;
        cur_wp_z = mtz;
        cur_wp_pause = 0;
+        cur_wp_heading = mth;
 }
 
 void NPC::UpdateWaypoint(int wp_index)
@@ -218,7 +220,8 @@
        cur_wp_y = cur->y;
        cur_wp_z = cur->z;
        cur_wp_pause = cur->pause;
-        mlog(AI__WAYPOINTS, "Next waypoint %d: (%.3f, %.3f, %.3f)", wp_index, cur_wp_x, cur_wp_y, cur_wp_z);
+        cur_wp_heading = cur->heading;
+        mlog(AI__WAYPOINTS, "Next waypoint %d: (%.3f, %.3f, %.3f, %.3f)", wp_index, cur_wp_x, cur_wp_y, cur_wp_z, cur_wp_heading);
               
        //fix up pathing Z
        if(zone->HasMap() && RuleB(Map, FixPathingZAtWaypoints))
@@ -853,7 +856,7 @@
            adverrorinfo = 7561;
 
            // Retrieve all waypoints for this grid
-            if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `x`,`y`,`z`,`pause` FROM grid_entries WHERE `gridid`=%i AND `zoneid`=%i ORDER BY `number`",grid,zone->GetZoneID()),errbuf,&result))
+            if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `x`,`y`,`z`,`pause`,`heading` FROM grid_entries WHERE `gridid`=%i AND `zoneid`=%i ORDER BY `number`",grid,zone->GetZoneID()),errbuf,&result))
            {
                    roamer = true;
                        max_wp = -1;        // Initialize it; will increment it for each waypoint successfully added to the list
@@ -884,6 +887,7 @@
                                }
 
                                newwp.pause = atoi(row[3]);
+                                newwp.heading = atof(row[4]);
                                Waypoints.push_back(newwp);
                            }
                        }
@@ -1039,7 +1043,7 @@
        char errbuff[MYSQL_ERRMSG_SIZE];
        MYSQL_RES *result;
        MYSQL_ROW row;
-        if (RunQuery(query, MakeAnyLenString(&query,"SELECT x, y, z, pause from grid_entries where gridid = %i and number = %i and zoneid = %i",grid,num,zoneid),errbuff,&result)) {
+        if (RunQuery(query, MakeAnyLenString(&query,"SELECT x, y, z, pause, heading from grid_entries where gridid = %i and number = %i and zoneid = %i",grid,num,zoneid),errbuff,&result)) {
                safe_delete_array(query);
                if (mysql_num_rows(result) == 1) {
                        row = mysql_fetch_row(result);
@@ -1048,6 +1052,7 @@
                                wp->y = atof( row[1] );
                                wp->z = atof( row[2] );
                                wp->pause = atoi( row[3] );
+                                wp->heading = atof( row[4] );
                        }
                        mysql_free_result(result);
                        return true;
@@ -1210,12 +1215,12 @@
 * AddWP - Adds a new waypoint to a specific grid for a specific zone.
 */
 
-void ZoneDatabase::AddWP(Client *c, int32 gridid, int32 wpnum, float xpos, float ypos, float zpos, int32 pause, int16 zoneid)
+void ZoneDatabase::AddWP(Client *c, int32 gridid, int32 wpnum, float xpos, float ypos, float zpos, int32 pause, int16 zoneid, float heading)
 { 
        char *query = 0;
        char errbuf[MYSQL_ERRMSG_SIZE];
 
-        if(!RunQuery(query,MakeAnyLenString(&query,"INSERT INTO grid_entries (gridid,zoneid,`number`,x,y,z,pause) values (%i,%i,%i,%f,%f,%f,%i)",gridid,zoneid,wpnum,xpos,ypos,zpos,pause), errbuf)) {
+        if(!RunQuery(query,MakeAnyLenString(&query,"INSERT INTO grid_entries (gridid,zoneid,`number`,x,y,z,pause,heading) values (%i,%i,%i,%f,%f,%f,%i,%f)",gridid,zoneid,wpnum,xpos,ypos,zpos,pause,heading), errbuf)) {
                LogFile->write(EQEMuLog::Error, "Error adding waypoint '%s': '%s'", query, errbuf);
        } else {
                if(c) c->LogSQL(query);
@@ -1257,7 +1262,7 @@
 * the created grid is returned.
 */
 
-int32 ZoneDatabase::AddWPForSpawn(Client *c, int32 spawn2id, float xpos, float ypos, float zpos, int32 pause, int type1, int type2, int16 zoneid) {
+int32 ZoneDatabase::AddWPForSpawn(Client *c, int32 spawn2id, float xpos, float ypos, float zpos, int32 pause, int type1, int type2, int16 zoneid, float heading) {
        char        *query = 0;
    int32        grid_num,        // The grid number the spawn is assigned to (if spawn has no grid, will be the grid number we end up creating)
                next_wp_num;        // The waypoint number we should be assigning to the new waypoint
@@ -1329,7 +1334,7 @@
        }
 
        query = 0;
-        if(!RunQuery(query, MakeAnyLenString(&query,"INSERT INTO grid_entries(gridid,zoneid,`number`,x,y,z,pause) VALUES (%i,%i,%i,%f,%f,%f,%i)",grid_num,zoneid,next_wp_num,xpos,ypos,zpos,pause), errbuf)) {
+        if(!RunQuery(query, MakeAnyLenString(&query,"INSERT INTO grid_entries(gridid,zoneid,`number`,x,y,z,pause,heading) VALUES (%i,%i,%i,%f,%f,%f,%i,%f)",grid_num,zoneid,next_wp_num,xpos,ypos,zpos,pause,heading), errbuf)) {
                LogFile->write(EQEMuLog::Error, "Error adding grid entry '%s': '%s'", query, errbuf);
        } else {
                if(c) c->LogSQL(query);

Code:

Index: zone/zonedb.h
===================================================================
--- zone/zonedb.h        (revision 1535)
+++ zone/zonedb.h        (working copy)
@@ -12,6 +12,7 @@
        float y;
        float z;
        int          pause;
+        float heading;
 };
 
 #pragma pack(1)
@@ -226,8 +227,8 @@
        void        DeleteGrid(Client *c, int32 sg2, int32 grid_num, bool grid_too,int16 zoneid);
        void        DeleteWaypoint(Client *c, int32 grid_num, int32 wp_num,int16 zoneid);
 //        int32        AddWP(Client *c, int32 sg2, int16 grid_num, int8 wp_num, float xpos, float ypos, float zpos, int32 pause, float xpos1, float ypos1, float zpos1, int type1, int type2,int16 zoneid);
-        void        AddWP(Client *c, int32 gridid, int32 wpnum, float xpos, float ypos, float zpos, int32 pause, int16 zoneid);
-        int32        AddWPForSpawn(Client *c, int32 spawn2id, float xpos, float ypos, float zpos, int32 pause, int type1, int type2, int16 zoneid);
+        void        AddWP(Client *c, int32 gridid, int32 wpnum, float xpos, float ypos, float zpos, int32 pause, int16 zoneid, float heading);
+        int32        AddWPForSpawn(Client *c, int32 spawn2id, float xpos, float ypos, float zpos, int32 pause, int type1, int type2, int16 zoneid, float heading);
        void        ModifyGrid(Client *c, bool remove, int32 id, int8 type = 0, int8 type2 = 0,int16 zoneid = 0);
        void    ModifyWP(Client *c, int32 grid_id, int32 wp_num, float xpos, float ypos, float zpos, int32 script=0,int16 zoneid =0);
        int8    GetGridType(int32 grid,int32 zoneid);

Recommended SQL:
Code:

UPDATE grid_entries SET heading = -1;

joligario 07-06-2010 09:42 AM

Committed in r1586


All times are GMT -4. The time now is 09:57 PM.

Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.