Index: src/game/Creature.cpp =================================================================== --- src/game/Creature.cpp (revision 5406) +++ src/game/Creature.cpp (working copy) @@ -63,6 +63,8 @@ m_GlobalCooldown = 0; m_AlreadyCallAssistence = false; + + m_escort = false; } Creature::~Creature() @@ -205,7 +207,15 @@ i_motionMaster.Clear(); LoadCreaturesAddon(true); - //Call AI respawn virtual function + if(m_waypointID) //NULL the current ID of waypoint and reset the waypoint path if creature die on his waypoint way + { + m_waypointID = 0; + i_motionMaster.Initialize(); + } + + m_escort = cinfo->escort; + + //Call AI respawn virtual function i_AI->JustRespawned(); MapManager::Instance().GetMap(GetMapId(), this)->Add(this); @@ -1196,7 +1206,11 @@ SetSpeed(MOVE_SWIM, cinfo->speed ); SetSpeed(MOVE_SWIMBACK, cinfo->speed ); - // checked at loading + // check for escort option at loading + m_escort = cinfo->escort; + m_waypointID = 0; + + // checked at loading m_defaultMovementType = MovementGeneratorType(cinfo->MovementType); //Notify the map's instance data. Index: src/game/Creature.h =================================================================== --- src/game/Creature.h (revision 5406) +++ src/game/Creature.h (working copy) @@ -161,7 +161,9 @@ uint32 faction_H; uint32 npcflag; float speed; - float scale; + bool escort; //it can be taked from here cause the escort target is unique and not need GUIDLow pointer + uint32 wpID; //this is very handy for standart generis_escort script (make db definition of escort ending) but can be ignored + float scale; uint32 rank; float mindmg; float maxdmg; @@ -321,7 +323,12 @@ void GetRespawnDist(float &d) const { d = m_respawnradius; } uint32 GetEquipmentId() const { return m_equipmentId; } - bool isPet() const { return m_isPet; } + bool getEsc() {return m_escort;} + void setEsc(bool flag) {m_escort = flag;} + uint32 GetWaypointID(){return m_waypointID;} //waypoint ID allows you to control the npc at every reached waypoint with scriptdev2 + void SetWaypointID(uint32 wpID) {m_waypointID = wpID;} + + bool isPet() const { return m_isPet; } void SetRespawnCoord(float x, float y, float z) { respawn_cord[0] = x; respawn_cord[1] = y; respawn_cord[2] = z; } bool isTotem() const { return m_isTotem; } bool isRacialLeader() const { return GetCreatureInfo()->RacialLeader; } @@ -559,7 +566,11 @@ bool m_regenHealth; bool m_AI_locked; uint32 m_equipmentId; - private: + + bool m_escort; // escort state info + uint32 m_waypointID; // quite handy for waypoint scripting + + private: GridReference m_gridRef; }; #endif Index: src/game/Language.h =================================================================== --- src/game/Language.h (revision 5406) +++ src/game/Language.h (working copy) @@ -215,6 +215,10 @@ LANG_WAYPOINT_INFO_SPELL = 250, LANG_WAYPOINT_INFO_TEXT = 251, LANG_WAYPOINT_INFO_AISCRIPT = 252, + LANG_WAYPOINT_INFO_FLAG = 800, + LANG_WAYPOINT_INFO_STANDSTATE = 801, + LANG_WAYPOINT_INFO_YELL = 802, + LANG_WAYPOINT_INFO_TEXTEMOTE = 803, LANG_RENAME_PLAYER = 253, LANG_RENAME_PLAYER_GUID = 254, Index: src/game/Level2.cpp =================================================================== --- src/game/Level2.cpp (revision 5406) +++ src/game/Level2.cpp (working copy) @@ -1985,8 +1985,10 @@ && (show != "text1") && (show != "text2") && (show != "text3") && (show != "text4") && (show != "text5") && (show != "waittime") && (show != "del") && (show != "move") && (show != "add") && (show != "model1") && (show != "model2") && (show != "orientation") - && (show != "import") && (show != "export") ) - { + && (show != "import") && (show != "export") && (show != "flag") && (show != "standstate") && (show != "texemote") + && (show != "yell1")&& (show != "yell2")&& (show != "yell3")&& (show != "yell4")) + + { return false; } @@ -2080,11 +2082,18 @@ { arg_str = strtok((char*)NULL, "<>"); } - else + else if( show.find("yell") != std::string::npos ) { + arg_str = strtok((char*)NULL, "<>"); + } + else + { arg_str = strtok((char*)NULL, " "); } - } + + + + } } else { @@ -2097,12 +2106,18 @@ { arg_str = strtok((char*)NULL, "<>"); } - else - { + else if( show.find("yell") != std::string::npos ) + { + arg_str = strtok((char*)NULL, "<>"); + } + else + { arg_str = strtok((char*)NULL, " "); - } + } - if( !guid_str ) + + + if( !guid_str ) { SendSysMessage(LANG_WAYPOINT_NOGUID); return false; @@ -2187,7 +2202,7 @@ sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command"); // Check for argument - if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add") && (show != "aiscript")) + if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add") && (show != "aiscript") && (show != "textemote") && (show.find("yell") == std::string::npos ) && (show != "flag") && (show != "standstate")) { if( arg_str == NULL ) { @@ -2720,7 +2735,9 @@ //pCreature->GetPositionX(); QueryResult *result = + WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2, aiscript FROM creature_movement WHERE wpguid = %u", + pCreature->GetGUID() ); if(!result) { @@ -2732,7 +2749,8 @@ const char* maxDIFF = "0.01"; PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, pCreature->GetGUID()); - result = WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2, aiscript FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )", + result = WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2, aiscript, yell1, yell2, yell3, yell4, textemote, standstate, flag FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )", + pCreature->GetPositionX(), maxDIFF, pCreature->GetPositionY(), maxDIFF, pCreature->GetPositionZ(), maxDIFF); if(!result) { @@ -2756,7 +2774,17 @@ uint32 model1 = fields[10].GetUInt32(); uint32 model2 = fields[11].GetUInt32(); const char * aiscript = fields[12].GetString(); - // Get the creature for which we read the waypoint + const char * yell1 = fields[13].GetString(); + const char * yell2 = fields[14].GetString(); + const char * yell3 = fields[15].GetString(); + const char * yell4 = fields[16].GetString(); + const char * textemote = fields[17].GetString(); + uint32 standstate = fields[18].GetUInt32(); + uint32 flag = fields[19].GetUInt32(); + + + + // Get the creature for which we read the waypoint Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(creGUID,HIGHGUID_UNIT)); PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : ""), creGUID); @@ -2771,8 +2799,15 @@ PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 4, text4); PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 5, text5); PSendSysMessage(LANG_WAYPOINT_INFO_AISCRIPT, aiscript); - - }while( result->NextRow() ); + PSendSysMessage(LANG_WAYPOINT_INFO_FLAG, flag); + PSendSysMessage(LANG_WAYPOINT_INFO_STANDSTATE, standstate); + PSendSysMessage(LANG_WAYPOINT_INFO_YELL, 1, yell1); + PSendSysMessage(LANG_WAYPOINT_INFO_YELL, 2, yell2); + PSendSysMessage(LANG_WAYPOINT_INFO_YELL, 3, yell3); + PSendSysMessage(LANG_WAYPOINT_INFO_YELL, 4, yell4); + PSendSysMessage(LANG_WAYPOINT_INFO_TEXTEMOTE, textemote); + + }while( result->NextRow() ); // Cleanup memory delete result; return true; @@ -2843,7 +2878,7 @@ delete result; return false; } - wpCreature->SetVisibility(VISIBILITY_OFF); + sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u"); // set "wpguid" column to the visual waypoint WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point); Index: src/game/WaypointMovementGenerator.cpp =================================================================== --- src/game/WaypointMovementGenerator.cpp (revision 5406) +++ src/game/WaypointMovementGenerator.cpp (working copy) @@ -44,11 +44,16 @@ void WaypointMovementGenerator::LoadPath(Creature &c) { - QueryResult *result = NULL; + if(c.getEsc() == true) + return; + + QueryResult *result = NULL; sLog.outDebug("DEBUG: WaypointMovementGenerator::_load: GUID - %d", c.GetGUIDLow()); // Identify by GUID - result = WorldDatabase.PQuery("SELECT position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5, aiscript FROM creature_movement WHERE id = '%u' ORDER BY point", c.GetDBTableGUIDLow()); - /* + + result = WorldDatabase.PQuery("SELECT position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5, aiscript, textemote, yell1, yell2, yell3, yell4, standstate, flag FROM creature_movement WHERE id = '%u' ORDER BY point", c.GetDBTableGUIDLow()); + + /* if( result ) { sLog.outDebug("DEBUG: Number of hits: %d", result->GetRowCount()); } else { @@ -56,7 +61,7 @@ } */ - if( result ) + if( result ) { unsigned int count = 0; const unsigned int sz = result->GetRowCount(); @@ -83,13 +88,22 @@ std::string text4 = fields[12].GetCppString(); std::string text5 = fields[13].GetCppString(); std::string aiscript = fields[14].GetCppString(); - - if( (emote != 0) || (spell != 0) - || !text1.empty() || !text2.empty() || !text3.empty() || !text4.empty() || !text5.empty() - || !aiscript.empty() - || (model1 != 0) || (model2 != 0) || (orientation != 100)) + std::string textemote = fields[15].GetCppString(); + std::string yell1 = fields[16].GetCppString(); + std::string yell2 = fields[17].GetCppString(); + std::string yell3 = fields[18].GetCppString(); + std::string yell4 = fields[19].GetCppString(); + uint32 standstate = fields[20].GetUInt32(); + bool flag = fields[21].GetUInt32(); + + + + if( (emote != 0) || (spell != 0) + || (text1 != "") || (text2 != "") || (text3 != "") || (text4 != "") || (text5 != "") + || (aiscript != "") + || (model1 != 0) || (model2 != 0) || (orientation != 100) || (textemote != "") || (yell1 != "") || (yell2 != "") || (yell3 != "") || (yell4 != "") || (standstate != 0) || (flag != 0) ) { - WaypointBehavior *tmpWPB = new WaypointBehavior; + WayPoint *tmpWPB = new WayPoint; // sLog.outDebug("DEBUG: _load --- Adding WaypointBehavior"); @@ -104,7 +118,14 @@ tmpWPB->spell = spell; tmpWPB->model1 = model1; tmpWPB->model2 = model2; - tmpWPB->HasDone = false; + tmpWPB->textemote = textemote; + tmpWPB->yell[0] = yell1; + tmpWPB->yell[1] = yell2; + tmpWPB->yell[2] = yell3; + tmpWPB->yell[3] = yell4; + tmpWPB->standstate = standstate; + tmpWPB->flag = flag; + tmpWPB->HasDone = false; i_wpBehaviour[count] = tmpWPB; } else @@ -134,8 +155,8 @@ i_wpBehaviour[count]->HasDone = true; } } - //if( i_delays[count] < 30 /* millisecond */ ) - // i_delays[count] = (rand() % 5000); + if( i_delays[count] < 100 /* millisecond */ ) + i_delays[count] = 100; //good to be not null to prevent some lag ++count; } while( result->NextRow() ); @@ -149,7 +170,7 @@ void WaypointMovementGenerator::ClearWaypoints() { - for (std::vector::iterator itr = i_wpBehaviour.begin(); itr != i_wpBehaviour.end(); ++itr) + for (std::vector::iterator itr = i_wpBehaviour.begin(); itr != i_wpBehaviour.end(); ++itr) delete (*itr); i_wpBehaviour.clear(); } @@ -175,8 +196,12 @@ bool WaypointMovementGenerator::Update(Creature &creature, const uint32 &diff) { - if(!&creature) - return true; + + if(creature.getEsc() == true) + return true; + + if(!&creature) + return true; // Waypoint movement can be switched on/off // This is quite handy for escort quests and other stuff @@ -186,21 +211,10 @@ // prevent crash at empty waypoint path. if(i_path.Empty()) - { - return true; - } + return true; + + CreatureTraveller traveller(creature); - CreatureTraveller traveller(creature); - - /* - if( npcIsStopped[creature.GetGUID()] ) - { - i_nextMoveTime.Update(40000); - i_destinationHolder.UpdateTraveller(traveller, ((diff)-40000), false); - npcIsStopped[creature.GetGUID()] = false; - return true; - } - */ i_nextMoveTime.Update(diff); i_destinationHolder.UpdateTraveller(traveller, diff, false); @@ -210,7 +224,7 @@ if( i_wpBehaviour[wpB] != NULL ) { - struct WaypointBehavior *tmpBehavior = i_wpBehaviour[wpB]; + struct WayPoint *tmpBehavior = i_wpBehaviour[wpB]; if (!tmpBehavior->HasDone) { @@ -218,7 +232,7 @@ { creature.SetUInt32Value(UNIT_NPC_EMOTESTATE,tmpBehavior->emote); } - if(!tmpBehavior->aiscript.empty()) + if(!tmpBehavior->aiscript.empty()) { WPAIScript(creature, tmpBehavior->aiscript); } @@ -234,18 +248,18 @@ } else { - // Select one from max 5 texts (0 and 1 laready checked) + // Select one from max 5 texts int i = 2; - for( ; i < 5; ++i ) - if( tmpBehavior->text[i].empty() ) - break; + for(;i < 5; ++i) + if( tmpBehavior->text[i].empty() ) + break; - //sLog.outDebug("DEBUG: tmpBehavior->text[i] == \"\": %d", i); - //sLog.outDebug("DEBUG: rand() % (i): %d", rand() % (i)); + //sLog.outDebug("DEBUG: tmpBehavior->text[i] == \"\": %d", i); + //sLog.outDebug("DEBUG: rand() % (i): %d", rand() % (i)); - creature.Say(tmpBehavior->text[rand() % i].c_str(), 0, 0); + creature.Say(tmpBehavior->text[rand() % i].c_str(), 0, 0); } - } + } if(tmpBehavior->spell != 0) { //sLog.outDebug("DEBUG: wpSys - spell"); @@ -261,25 +275,67 @@ //sLog.outDebug("DEBUG: wpSys - model1"); creature.SetUInt32Value(UNIT_FIELD_DISPLAYID, tmpBehavior->model1); } - tmpBehavior->HasDone = true; + if(tmpBehavior->standstate != 0) + { + //sLog.outDebug("DEBUG: wpSys - standstate"); + creature.SetUInt32Value(UNIT_FIELD_BYTES_1, tmpBehavior->standstate); + }else if(!tmpBehavior->standstate) + creature.SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + + if(!tmpBehavior->yell[0].empty()) + { + //sLog.outDebug("DEBUG: tmpBehavior->yell[0] != \"\""); + // Only one text is set + if( tmpBehavior->yell[1].empty() ) + { + //sLog.outDebug("DEBUG: tmpBehavior->yell[1] == NULL"); + creature.Yell(tmpBehavior->yell[0].c_str(), 0, 0); + } + else + { + // Select one from max 5 texts + int i = 2; + for(;i < 5; ++i) + if( tmpBehavior->yell[i].empty() ) + break; + + creature.Yell(tmpBehavior->yell[rand() % i].c_str(), 0, 0); + + } + } + if(!tmpBehavior->textemote.empty()) + { + //sLog.outDebug("DEBUG: tmpBehavior->textemote != \"\""); + creature.TextEmote(tmpBehavior->textemote.c_str(), 0); + } + + creature.setMoveRunFlag(tmpBehavior->flag); + + tmpBehavior->HasDone = true; } // HasDone == false } // wpBehaviour found } // i_creature.IsStopped() - if( i_nextMoveTime.Passed() ) +if( i_nextMoveTime.Passed() ) { - if( creature.IsStopped() ) + + if( creature.IsStopped() ) { - assert( i_currentNode < i_path.Size() ); + assert( i_currentNode < i_path.Size() ); creature.addUnitState(UNIT_STAT_ROAMING); - const Path::PathNode &node(i_path(i_currentNode)); + creature.SetWaypointID(-1); + uint32 mapid = creature.GetMapId(); + + const Path::PathNode &node(i_path(i_currentNode)); i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z); - i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); + //MapManager::Instance().LoadGrid(mapid,node.x,node.y,&creature,true); + + i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime()); uint32 wpB = i_currentNode > 0 ? i_currentNode-1 : i_wpBehaviour.size()-1; if( i_wpBehaviour[wpB] != NULL ) { - struct WaypointBehavior *tmpBehavior = i_wpBehaviour[wpB]; + struct WayPoint *tmpBehavior = i_wpBehaviour[wpB]; tmpBehavior->HasDone = false; if(tmpBehavior->model2 != 0) { @@ -291,15 +347,22 @@ } creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); } - } + } else { - creature.StopMoving(); - i_nextMoveTime.Reset(i_delays[i_currentNode]); + //creature.StopMoving(); + creature.clearUnitState(UNIT_STAT_ROAMING); + creature.SendMonsterMove(i_path[i_currentNode].x,i_path[i_currentNode].y,i_path[i_currentNode].z,0,true,0); + creature.SetWaypointID(i_currentNode-1); + + i_nextMoveTime.Reset(i_delays[i_currentNode]); ++i_currentNode; if( i_currentNode >= i_path.Size() ) - i_currentNode = 0; - } + { + i_currentNode = 0; + creature.SetWaypointID(-1); + } + } } return true; } @@ -345,6 +408,25 @@ } sLog.outDebug("guard-sw"); } // guard-sw + +if( pAiscript == "escort-start") //demo script for WP-AI System +{ + if(pCreature.getEsc() != 1) + pCreature.setEsc(1); + + pCreature.SetUInt32Value(UNIT_NPC_FLAGS, 2); + sLog.outDebug("restart escort questgiver..."); +} + //script for NPC starting & finishing escort quest (must be at last waypoint & set escort true from the database) + + +if( pAiscript == "respawn") //demo script for WP-AI System +{ + pCreature.setDeathState(JUST_DIED); + pCreature.Respawn(); + sLog.outDebug("respawn at current waypoint"); +} + } // WPAIScript std::set WaypointMovementGenerator::si_waypointHolders; @@ -506,7 +588,7 @@ for (temp = 0; temp < count; temp++) { pathlist[temp] = temppathlist[upto]; - --upto; + ++upto; } G_Printf("ShortenASTARRoute: Path size reduced from %i to %i nodes...n", number, count); Index: src/game/WaypointMovementGenerator.h =================================================================== --- src/game/WaypointMovementGenerator.h (revision 5406) +++ src/game/WaypointMovementGenerator.h (working copy) @@ -39,9 +39,13 @@ #define VISUAL_WAYPOINT 1 -struct WaypointBehavior +struct WayPoint { - uint32 emote; + bool flag; + std::string textemote; + std::string yell[4]; + uint32 standstate; + uint32 emote; uint32 spell; std::string text[5]; float orientation; @@ -86,7 +90,7 @@ { TimeTracker i_nextMoveTime; std::vector i_delays; - std::vector i_wpBehaviour; + std::vector i_wpBehaviour; public: WaypointMovementGenerator(Creature &) : i_nextMoveTime(0) {} ~WaypointMovementGenerator() { ClearWaypoints(); } Index: src/shared/Database/SQLStorage.cpp =================================================================== --- src/shared/Database/SQLStorage.cpp (revision 5406) +++ src/shared/Database/SQLStorage.cpp (working copy) @@ -27,7 +27,7 @@ extern DatabaseMysql WorldDatabase; #endif -const char CreatureInfofmt[]="iiiiissiiiiiiiiiiffiffiiiiiiiiiiiffiiliiiiiiiiiiiiiiiisiilliis"; +const char CreatureInfofmt[]="iiiiissiiiiiiiiiifiififfiiiiiiiiiiiffiiliiiiiiiiiiiiiiiisiilliis"; const char CreatureDataAddonInfofmt[]="iiiiiis"; const char CreatureModelfmt[]="iffii"; const char CreatureInfoAddonInfofmt[]="iiiiiis";