rendered paste bodyIndex: src/game/AggressorAI.cpp
===================================================================
--- src/game/AggressorAI.cpp (revision 5687)
+++ src/game/AggressorAI.cpp (working copy)
@@ -111,7 +111,6 @@
i_creature.DeleteThreatList();
i_victimGuid = 0;
i_creature.CombatStop();
-
}
void
Index: src/game/Chat.cpp
===================================================================
--- src/game/Chat.cpp (revision 5687)
+++ src/game/Chat.cpp (working copy)
@@ -116,9 +116,13 @@
static ChatCommand wpCommandTable[] =
{
{ "show", SEC_GAMEMASTER, &ChatHandler::HandleWpShowCommand, "", NULL },
- { "add", SEC_GAMEMASTER, &ChatHandler::HandleWpAddCommand, "", NULL },
- { "modify", SEC_GAMEMASTER, &ChatHandler::HandleWpModifyCommand, "", NULL },
- { NULL, 0, NULL, "", NULL }
+ { "addwp", SEC_GAMEMASTER, &ChatHandler::HandleWpAddCommand, "", NULL },
+ { "load", SEC_GAMEMASTER, &ChatHandler::HandleWpLoadPathCommand, "", NULL },
+ { "modify", SEC_GAMEMASTER, &ChatHandler::HandleWpModifyCommand, "", NULL },
+ { "event", SEC_GAMEMASTER, &ChatHandler::HandleWpEventCommand, "", NULL },
+ { "unload", SEC_GAMEMASTER, &ChatHandler::HandleWpUnLoadPathCommand, "", NULL },
+
+ { NULL, 0, NULL, "", NULL }
};
static ChatCommand debugCommandTable[] =
@@ -162,6 +166,7 @@
{ "all_scripts", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAllScriptsCommand, "", NULL },
{ "all_spell", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAllSpellCommand, "", NULL },
+ { "waypoint_scripts", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAreaTriggerTavernCommand, "", NULL },
{ "areatrigger_tavern", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAreaTriggerTavernCommand, "", NULL },
{ "areatrigger_teleport", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAreaTriggerTeleportCommand, "", NULL },
{ "areatrigger_involvedrelation",SEC_ADMINISTRATOR, &ChatHandler::HandleReloadQuestAreaTriggersCommand, "", NULL },
@@ -234,7 +239,16 @@
{ NULL, 0, NULL, "", NULL }
};
- static ChatCommand resetCommandTable[] =
+ static ChatCommand formationCommandTable[] =
+ {
+ { "setleader", SEC_MODERATOR, &ChatHandler::HandleCreateFormationCommand, "", NULL },
+ { "dismiss", SEC_MODERATOR, &ChatHandler::HandleDismissFormationCommand, "", NULL },
+ { "followangle", SEC_MODERATOR, &ChatHandler::HandleAngleFormationCommand, "", NULL },
+ { "followdist", SEC_MODERATOR, &ChatHandler::HandleDistFormationCommand, "", NULL },
+ { NULL, 0, NULL, "", NULL }
+ };
+
+ static ChatCommand resetCommandTable[] =
{
{ "honor", SEC_ADMINISTRATOR, &ChatHandler::HandleResetHonorCommand, "", NULL },
{ "level", SEC_ADMINISTRATOR, &ChatHandler::HandleResetLevelCommand, "", NULL },
@@ -366,8 +380,9 @@
{ "password", SEC_PLAYER, &ChatHandler::HandlePasswordCommand, "", NULL },
{ "lockaccount", SEC_PLAYER, &ChatHandler::HandleLockAccountCommand, "", NULL },
{ "respawn", SEC_ADMINISTRATOR, &ChatHandler::HandleRespawnCommand, "", NULL },
- { "wp", SEC_GAMEMASTER, NULL, "", wpCommandTable },
- { "flymode", SEC_ADMINISTRATOR, &ChatHandler::HandleFlyModeCommand, "", NULL },
+ { "path", SEC_GAMEMASTER, NULL, "", wpCommandTable },
+ { "formation", SEC_ADMINISTRATOR, NULL, "", formationCommandTable },
+ { "flymode", SEC_ADMINISTRATOR, &ChatHandler::HandleFlyModeCommand, "", NULL },
{ "sendmail", SEC_MODERATOR, &ChatHandler::HandleSendMailCommand, "", NULL },
{ "rename", SEC_GAMEMASTER, &ChatHandler::HandleRenameCommand, "", NULL },
{ "nametele", SEC_MODERATOR, &ChatHandler::HandleNameTeleCommand, "", NULL },
@@ -383,8 +398,14 @@
{ "cast", SEC_ADMINISTRATOR, &ChatHandler::HandleCastCommand, "", NULL },
{ "castback", SEC_ADMINISTRATOR, &ChatHandler::HandleCastBackCommand, "", NULL },
{ "casttarget", SEC_ADMINISTRATOR, &ChatHandler::HandleCastTargetCommand, "", NULL },
+
+ { "loadpath", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadAllPaths, "", NULL },
+
{ "cometome", SEC_ADMINISTRATOR, &ChatHandler::HandleComeToMeCommand, "", NULL },
+
+
+
//! Development Commands
{ "setvalue", SEC_ADMINISTRATOR, &ChatHandler::HandleSetValue, "", NULL },
{ "getvalue", SEC_ADMINISTRATOR, &ChatHandler::HandleGetValue, "", NULL },
Index: src/game/Chat.h
===================================================================
--- src/game/Chat.h (revision 5687)
+++ src/game/Chat.h (working copy)
@@ -145,7 +145,8 @@
bool HandleReloadAllScriptsCommand(const char* args);
bool HandleReloadAllSpellCommand(const char* args);
- bool HandleReloadAreaTriggerTavernCommand(const char* args);
+ bool HandleReloadWaypointScriptsCommand(const char* arg);
+ bool HandleReloadAreaTriggerTavernCommand(const char* args);
bool HandleReloadAreaTriggerTeleportCommand(const char* args);
bool HandleReloadEventScriptsCommand(const char* args);
bool HandleReloadCommandCommand(const char* args);
@@ -179,10 +180,13 @@
bool HandleReloadSpellScriptTargetCommand(const char* args);
bool HandleReloadSpellScriptsCommand(const char* args);
bool HandleReloadSpellTeleportCommand(const char* args);
+ bool HandleReloadAllPaths(const char* args);
+
+ bool HandleAddHonorCommand(const char* args);
+
bool HandleReloadSpellThreatsCommand(const char* args);
- bool HandleAddHonorCommand(const char* args);
- bool HandleHonorAddKillCommand(const char* args);
+ bool HandleHonorAddKillCommand(const char* args);
bool HandleHonorFlushKillsCommand(const char* args);
bool HandleUpdateHonorFieldsCommand(const char* args);
@@ -316,8 +320,15 @@
bool HandleLockAccountCommand(const char* args);
bool HandleRespawnCommand(const char* args);
bool HandleWpAddCommand(const char* args);
- bool HandleWpModifyCommand(const char* args);
- bool HandleWpShowCommand(const char* args);
+ bool HandleWpLoadPathCommand(const char* args);
+ bool HandleWpUnLoadPathCommand(const char* args);
+ bool HandleWpModifyCommand(const char* args);
+ bool HandleWpEventCommand(const char* args);
+ bool HandleCreateFormationCommand(const char* args);
+ bool ChatHandler::HandleDismissFormationCommand(const char* args);
+ bool ChatHandler::HandleDistFormationCommand(const char* args);
+ bool ChatHandler::HandleAngleFormationCommand(const char* args);
+ bool HandleWpShowCommand(const char* args);
bool HandleFlyModeCommand(const char* args);
bool HandleSendOpcodeCommand(const char* args);
bool HandleSellErrorCommand(const char* args);
Index: src/game/Creature.cpp
===================================================================
--- src/game/Creature.cpp (revision 5687)
+++ src/game/Creature.cpp (working copy)
@@ -61,6 +61,7 @@
m_CreatureSpellCooldowns.clear();
m_CreatureCategoryCooldowns.clear();
m_GlobalCooldown = 0;
+ m_waypointID = 0;
}
Creature::~Creature()
@@ -150,9 +151,13 @@
loot.clear();
m_respawnTime = time(NULL) + m_respawnDelay;
- float x,y,z;
- GetRespawnCoord(x, y, z);
- MapManager::Instance().GetMap(GetMapId(), this)->CreatureRelocation(this,x,y,z,GetOrientation());
+
+ if(!this->GetCurrentWaypointID())
+ {
+ float x,y,z;
+ GetRespawnCoord(x, y, z);
+ MapManager::Instance().GetMap(GetMapId(), this)->CreatureRelocation(this,x,y,z,GetOrientation());
+ }
}
void Creature::Update(uint32 diff)
@@ -201,12 +206,21 @@
clearUnitState(UNIT_STAT_ALL_STATE);
i_motionMaster.Clear();
LoadCreaturesAddon(true);
-
+
//Call AI respawn virtual function
i_AI->JustRespawned();
MapManager::Instance().GetMap(GetMapId(), this)->Add(this);
- }
+
+ if(IsFollower())
+ {
+ uint32 guid = this->GetCreatureFormation()->leader;
+ uint32 entry = objmgr.GetCreatureData(guid)->id;
+ Creature* Leader = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(guid, entry, HIGHGUID_UNIT), (Creature*)NULL);
+ if(Leader)
+ Leader->SetLinkedtoFormation(false);
+ }
+ }
break;
}
case CORPSE:
@@ -1116,8 +1130,9 @@
return false;
}
- Object::_Create(guidlow, Entry, HIGHGUID_UNIT);
+ Object::_Create(guidlow, Entry, HIGHGUID_UNIT);
+
m_DBTableGuid = guidlow;
SetUInt32Value(OBJECT_FIELD_ENTRY, Entry);
@@ -1249,7 +1264,8 @@
m_DBTableGuid = stored_guid;
LoadCreaturesAddon();
- if(GetCreatureInfo()->rank > 0)
+ LoadCreatureFormation();
+ if(GetCreatureInfo()->rank > 0)
this->m_corpseDelay *= 3; //if creature is elite, then remove corpse later
m_respawnradius = data->spawndist;
@@ -1283,8 +1299,8 @@
// checked at creature_template loading
m_defaultMovementType = MovementGeneratorType(data->movementType);
-
- AIM_Initialize();
+
+ AIM_Initialize();
return true;
}
@@ -1713,7 +1729,10 @@
if (cainfo->emote != 0)
SetUInt32Value(UNIT_NPC_EMOTESTATE, cainfo->emote);
- if(cainfo->auras)
+ if (cainfo->path_id != 0)
+ m_path_id = cainfo->path_id;
+
+ if(cainfo->auras)
{
for (CreatureDataAddonAura const* cAura = cainfo->auras; cAura->spell_id; ++cAura)
{
@@ -1806,3 +1825,20 @@
break;
return i < CREATURE_MAX_SPELLS; //broke before end of iteration of known spells
}
+
+
+CreatureFormation const* Creature::GetCreatureFormation() const
+{
+ CreatureFormation const* form = ObjectMgr::GetFormation(m_DBTableGuid);
+ return form;
+}
+
+//Load Formations
+bool Creature::LoadCreatureFormation()
+{
+CreatureFormation const *info = GetCreatureFormation();
+if(!info)
+ return false;
+ m_formation = true;
+ return m_formation;
+}
\ No newline at end of file
Index: src/game/Creature.h
===================================================================
--- src/game/Creature.h (revision 5687)
+++ src/game/Creature.h (working copy)
@@ -257,7 +257,8 @@
struct CreatureDataAddon
{
uint32 guidOrEntry;
- uint32 mount;
+ uint32 path_id;
+ uint32 mount;
uint32 bytes0;
uint32 bytes1;
uint32 bytes2;
@@ -281,6 +282,14 @@
INHAVIT_ANYWHERE = INHAVIT_GROUND | INHAVIT_WATER
};
+struct CreatureFormation
+{
+uint32 follower;
+uint32 leader;
+float offset_angle;
+float offset_dist;
+};
+
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
#if defined( __GNUC__ )
#pragma pack()
@@ -303,7 +312,12 @@
public:
- explicit Creature( WorldObject *instantiator );
+ bool IsFollower(){return m_formation;}
+ bool LoadCreatureFormation();
+
+ CreatureFormation const* GetCreatureFormation() const;
+
+ explicit Creature( WorldObject *instantiator );
virtual ~Creature();
void AddToWorld();
@@ -320,7 +334,11 @@
void Update( uint32 time ); // overwrited Unit::Update
void GetRespawnCoord(float &x, float &y, float &z) const { x = respawn_cord[0]; y = respawn_cord[1]; z = respawn_cord[2]; }
- void GetRespawnDist(float &d) const { d = m_respawnradius; }
+
+ void SetCoordsBeforeBattle(float x, float y, float z) { last_cord[0] = x; last_cord[1] = y; last_cord[2] = z; }
+ void GetCoordsBeforeBattle(float &x, float &y, float &z) const { x = last_cord[0]; y = last_cord[1]; z = last_cord[2]; }
+
+ void GetRespawnDist(float &d) const { d = m_respawnradius; }
uint32 GetEquipmentId() const { return m_equipmentId; }
bool isPet() const { return m_isPet; }
@@ -375,9 +393,11 @@
bool HasSpellCooldown(uint32 spell_id) const;
bool HasCategoryCooldown(uint32 spell_id) const;
- bool HasSpell(uint32 spellID) const;
-
- bool UpdateStats(Stats stat);
+ bool HasSpell(uint32 spellID) const;
+ uint32 GetCurrentWaypointID(){return m_waypointID;}
+ void UpdateWaypointID(uint32 wpID){m_waypointID = wpID;}
+
+ bool UpdateStats(Stats stat);
bool UpdateAllStats();
void UpdateResistances(uint32 school);
void UpdateArmor();
@@ -520,8 +540,17 @@
else
return m_charmInfo->GetCharmSpell(pos)->spellId;
}
-
- protected:
+
+ bool isLinkedtoFormation(){return m_link;}
+ void SetLinkedtoFormation(bool link) {m_link = link;}
+
+ uint32 Creature::GetWaypointPath(){return m_path_id;}
+ void LoadPath(uint32 pathid) { m_path_id = pathid; }
+
+ bool IsStoppedByEvent(){return m_wpevent;}
+ void SetStoppedByEvent(bool wpevent) {m_wpevent = wpevent;}
+
+ protected:
// vendor items
typedef std::vector<CreatureItem> CreatureItems;
CreatureItems m_vendor_items;
@@ -552,8 +581,9 @@
uint32 m_NPCTextId; // cached value
float respawn_cord[3];
-
- uint8 m_emoteState;
+ float last_cord[3];
+
+ uint8 m_emoteState;
bool m_isPet; // set only in Pet::Pet
bool m_isTotem; // set only in Totem::Totem
void RegenerateMana();
@@ -568,7 +598,12 @@
bool m_regenHealth;
bool m_AI_locked;
bool m_isDeadByDefault;
- private:
+ uint32 m_waypointID;
+ bool m_formation;
+ bool m_link;
+ bool m_wpevent;
+ uint32 m_path_id;
+ private:
GridReference<Creature> m_gridRef;
};
#endif
Index: src/game/CreatureAI.h
===================================================================
--- src/game/CreatureAI.h (revision 5687)
+++ src/game/CreatureAI.h (working copy)
@@ -79,11 +79,15 @@
// Called when the creature is attacked
virtual void AttackedBy(Unit * /*attacker*/) {}
- // Called when creature is spawned or respawned (for reseting variables)
+ // Called when creature reach any waypoint
+ virtual void MovementInform(uint32) {}
+
+ // Called when creature is spawned or respawned (for reseting variables)
virtual void JustRespawned() {}
+
+ // Called at waypoint reached or point movement finished
+ virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {}
- // Called at waypoint reached or point movement finished
- virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {}
};
struct SelectableAI : public FactoryHolder<CreatureAI>, public Permissible<Creature>
Index: src/game/GameEvent.cpp
===================================================================
--- src/game/GameEvent.cpp (revision 5687)
+++ src/game/GameEvent.cpp (working copy)
@@ -146,7 +146,7 @@
if(max_event_id + event_id >= mGameEventCreatureGuids.size())
{
- sLog.outErrorDb("`game_event_creature` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
+ sLog.outErrorDb("`creature_game_event` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
continue;
}
@@ -160,7 +160,52 @@
delete result;
}
- mGameEventGameobjectGuids.resize((max_event_id * 2) + 1);
+ ///////////////////////////////wp event
+ mWpEvent.resize((max_event_id * 2) + 1);
+ // 1 2
+ result = WorldDatabase.Query("SELECT creature.guid, waypoint_event.event "
+ "FROM creature JOIN waypoint_event ON creature.guid = waypoint_event.guid");
+
+ count = 0;
+ if( !result )
+ {
+ barGoLink bar2(1);
+ bar2.step();
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u creatures in waypoint events", count );
+ }
+ else
+ {
+
+ barGoLink bar2( result->GetRowCount() );
+ do
+ {
+ Field *fields = result->Fetch();
+
+ bar2.step();
+
+ uint32 guid = fields[0].GetUInt32();
+ int16 event_id = fields[1].GetInt16();
+
+ if(max_event_id + event_id >= mWpEvent.size())
+ {
+ sLog.outErrorDb("`waypoint_event` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
+ continue;
+ }
+
+ ++count;
+ GuidList& crelist = mWpEvent[max_event_id + event_id];
+ crelist.push_back(guid);
+
+ } while( result->NextRow() );
+ sLog.outString();
+ sLog.outString( ">> Loaded %u creatures in waypoint events", count );
+ delete result;
+ }
+////////////////////////////
+
+ mGameEventGameobjectGuids.resize((max_event_id * 2) + 1);
// 1 2
result = WorldDatabase.Query("SELECT gameobject.guid, game_event_gameobject.event "
"FROM gameobject JOIN game_event_gameobject ON gameobject.guid=game_event_gameobject.guid");
@@ -361,6 +406,9 @@
ChangeEquipOrModel(event_id, false);
// Remove quests that are events only to non event npc
UpdateEventQuests(event_id, false);
+ //Make creatures stop moving
+ WaypointEvent(event_id, false);
+
}
void GameEvent::ApplyNewEvent(uint16 event_id)
@@ -386,6 +434,8 @@
ChangeEquipOrModel(event_id, true);
// Add quests that are events only to non event npc
UpdateEventQuests(event_id, true);
+ //Make creatures move
+ WaypointEvent(event_id, true);
}
void GameEvent::GameEventSpawn(int16 event_id)
@@ -605,6 +655,43 @@
}
}
+void GameEvent::WaypointEvent(uint16 event_id, bool Activate)
+{
+
+ for (GuidList::iterator itr = mWpEvent[max_event_id + event_id].begin();itr != mWpEvent[max_event_id + event_id].end();++itr)
+
+ {
+
+ CreatureData const* data = objmgr.GetCreatureData(*itr);
+ if(!data)
+ continue;
+
+ Creature* pCreature;
+ pCreature = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(*itr, data->id, HIGHGUID_UNIT), (Creature*)NULL);
+ if (pCreature)
+ {
+ if (Activate)
+ {
+ WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE, pCreature->GetGUIDLow());
+
+ pCreature->SetStoppedByEvent(false);
+ pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
+ pCreature->GetMotionMaster()->Initialize();
+ pCreature->Say("Event Started",0,0);
+ }
+ else
+ {
+ WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", IDLE_MOTION_TYPE, pCreature->GetGUIDLow());
+
+ pCreature->SetStoppedByEvent(true);
+ pCreature->SetDefaultMovementType(IDLE_MOTION_TYPE);
+ pCreature->GetMotionMaster()->Initialize();
+ pCreature->Say("Event Stopped",0,0);
+ }
+ }
+ }
+}
+
GameEvent::GameEvent()
{
isSystemInit = false;
Index: src/game/GameEvent.h
===================================================================
--- src/game/GameEvent.h (revision 5687)
+++ src/game/GameEvent.h (working copy)
@@ -64,7 +64,8 @@
void ChangeEquipOrModel(int16 event_id, bool activate);
void UpdateEventQuests(uint16 event_id, bool Activate);
uint32 NextCheck(uint16 entry);
- protected:
+ void WaypointEvent(uint16 event_id, bool Activate);
+ protected:
typedef std::vector<GameEventData> GameEventDataMap;
typedef std::list<uint32> GuidList;
typedef std::vector<GuidList> GameEventGuidMap;
@@ -79,7 +80,8 @@
GameEventGuidMap mGameEventCreatureGuids;
GameEventGuidMap mGameEventGameobjectGuids;
GameEventDataMap mGameEvent;
- ActiveEvents m_ActiveEvents;
+ GameEventGuidMap mWpEvent;
+ ActiveEvents m_ActiveEvents;
bool isSystemInit;
uint16 max_event_id;
};
Index: src/game/HomeMovementGenerator.cpp
===================================================================
--- src/game/HomeMovementGenerator.cpp (revision 5687)
+++ src/game/HomeMovementGenerator.cpp (working copy)
@@ -47,10 +47,14 @@
return;
float x, y, z;
- owner.GetRespawnCoord(x, y, z);
+
+ if(!owner.GetCurrentWaypointID())
+ owner.GetRespawnCoord(x, y, z);
+ else
+ owner.GetCoordsBeforeBattle(x, y, z);
+
+ CreatureTraveller traveller(owner);
- CreatureTraveller traveller(owner);
-
uint32 travel_time = i_destinationHolder.SetDestination(traveller, x, y, z);
modifyTravelTime(travel_time);
owner.clearUnitState(UNIT_STAT_ALL_STATE);
Index: src/game/Level2.cpp
===================================================================
--- src/game/Level2.cpp (revision 5687)
+++ src/game/Level2.cpp (working copy)
@@ -1049,7 +1049,7 @@
uint32 point;
- QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
+ QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM waypoint_data WHERE id = '%u'",lowguid);
if( result )
{
point = (*result)[0].GetUInt32()+1;
@@ -1061,7 +1061,7 @@
Player* player = m_session->GetPlayer();
- WorldDatabase.PExecuteLog("INSERT INTO creature_movement (id,point,position_x,position_y,position_z,waittime) VALUES ('%u','%u','%f', '%f', '%f','%u')",
+ WorldDatabase.PExecuteLog("INSERT INTO waypoint_data(id,point,position_x,position_y,position_z,delay) VALUES ('%u','%u','%f', '%f', '%f','%u')",
lowguid, point, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), wait);
// update movement type
@@ -1203,7 +1203,7 @@
if( doNotDelete == false )
{
//sLog.outError("DEBUG: doNotDelete == false");
- WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id = '%u'",lowguid);
+ WorldDatabase.PExecuteLog("DELETE FROM waypoint_data WHERE id = '%u'",lowguid);
}
WorldDatabase.CommitTransaction();
if(pCreature)
@@ -1828,185 +1828,606 @@
return true;
}
-/**
- * Add a waypoint to a creature.
- *
- * The user can either select an npc or provide its GUID.
- *
- * The user can even select a visual waypoint - then the new waypoint
- * is placed *after* the selected one - this makes insertion of new
- * waypoints possible.
- *
- * eg:
- * .wp add 12345
- * -> adds a waypoint to the npc with the GUID 12345
- *
- * .wp add
- * -> adds a waypoint to the currently selected creature
- *
- *
- * @param args if the user did not provide a GUID, it is NULL
- *
- * @return true - command did succeed, false - something went wrong
- */
+/////WAYPOINT COMMANDS
+
bool ChatHandler::HandleWpAddCommand(const char* args)
{
sLog.outDebug("DEBUG: HandleWpAddCommand");
// optional
- char* guid_str = NULL;
+ char* path_number = NULL;
+ uint32 pathid = 0;
+
+ if(*args)
+ path_number = strtok((char*)args, " ");
+
+ uint32 point = 0;
+ Creature* target = getSelectedCreature();
+
+ if (!path_number)
+ {
+ if(target)
+ pathid = target->GetWaypointPath();
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(id) FROM waypoint_data");
+ uint32 maxpathid = result->Fetch()->GetInt32();
+ pathid = maxpathid+1;
+ sLog.outDebug("DEBUG: HandleWpAddCommand - New path started.");
+ SendSysMessage("New path started.");
+
+ }
+ }
+ else
+ pathid = atoi(path_number);
+
+ // path_id -> ID of the Path
+ // point -> number of the waypoint (if not 0)
+
+ if(!pathid)
+ {
+ sLog.outDebug("DEBUG: HandleWpAddCommand - Current creature haven't loaded path.");
+ SendSysMessage("Current creature haven't loaded path.");
+ return true;
+ }
+
+ sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
- if(*args)
+ QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM waypoint_data WHERE id = '%u'",pathid);
+ if( result )
{
- guid_str = strtok((char*)args, " ");
+ point = (*result)[0].GetUInt32()+1;
+ delete result;
}
+ else
+ point = 1;
- uint32 lowguid = 0;
- uint32 point = 0;
- Unit* target = getSelectedCreature();
- // Did player provide a GUID?
- if (!guid_str)
- {
- sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided");
+ Player* player = m_session->GetPlayer();
- // No GUID provided
- // -> Player must have selected a creature
+ WorldDatabase.PExecuteLog("INSERT INTO waypoint_data (id,point,position_x,position_y,position_z) VALUES ('%u','%u','%f', '%f', '%f')",
+ pathid, point, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
- if(!target)
+ Creature* wpCreature = new Creature(player);
+ if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), player->GetMapId(),
+ player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), VISUAL_WAYPOINT,0))
{
- SendSysMessage(LANG_SELECT_CREATURE);
- return true;
+ PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
+ delete wpCreature;
+ return false;
}
- if (target->GetEntry() == VISUAL_WAYPOINT )
- {
- sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
+ WorldDatabase.PExecute("UPDATE waypoint_data SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), pathid, point);
- QueryResult *result =
- WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
- target->GetGUIDLow() );
- if(!result)
- {
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
- // User selected a visual spawnpoint -> get the NPC
- // Select NPC GUID
- // Since we compare float values, we have to deal with
- // some difficulties.
- // Here we search for all waypoints that only differ in one from 1 thousand
- // (0.001) - There is no other way to compare C++ floats with mySQL floats
- // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
- const char* maxDIFF = "0.01";
- result = WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )",
- target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
- if(!result)
- {
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
- return true;
- }
- }
- do
- {
- Field *fields = result->Fetch();
- lowguid = fields[0].GetUInt32();
- point = fields[1].GetUInt32();
- }while( result->NextRow() );
- delete result;
- }
- else
- {
- lowguid = target->GetGUIDLow();
- }
+ wpCreature->SaveToDB();
+ // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
+ wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), player->GetInstanceId());
+ MapManager::Instance().GetMap(wpCreature->GetMapId(), wpCreature)->Add(wpCreature);
+
+ if(target)
+ {
+ if(pathid = target->GetWaypointPath())
+ {
+ wpCreature->SetDisplayId(target->GetDisplayId());
+ wpCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5);
+ }
+ }
+
+ PSendSysMessage("PathID: %u: Waypoint %u created. ",pathid, point);
- }
- else
- {
- sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided");
+ return true;
+} // HandleWpAddCommand
- // GUID provided
- // Warn if player also selected a creature
- // -> Creature selection is ignored <-
- if(target)
- {
- SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
- }
- lowguid = atoi((char*)guid_str);
- }
- // lowguid -> GUID of the NPC
- // point -> number of the waypoint (if not 0)
- sLog.outDebug("DEBUG: HandleWpAddCommand - danach");
+bool ChatHandler::HandleWpLoadPathCommand(const char *args)
+{
- Creature* pCreature = NULL;
+ if(!*args)
+ return false;
+
+ // optional
+ char* path_number = NULL;
- /* impossible without entry
- if(lowguid)
- pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
- */
+ if(*args)
+ {
+ path_number = strtok((char*)args, " ");
+ }
- // attempt check creature existence by DB data
- if(!pCreature)
- {
- CreatureData const* data = objmgr.GetCreatureData(lowguid);
- if(!data)
+uint32 pathid = 0;
+ uint32 guidlow = 0;
+ Creature* target = getSelectedCreature();
+
+ // Did player provide a path_id?
+ if (!path_number)
+ sLog.outDebug("DEBUG: HandleWpLoadPathCommand - No path number provided");
+
+ if(!target)
+ {
+ SendSysMessage(LANG_SELECT_CREATURE);
+ return true;
+ }
+ if(target->GetEntry() == 1)
{
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
+ SendSysMessage("You want to load path to a waypoint? Aren't you?");
return true;
}
- }
+
+
+ pathid = atoi(path_number);
+ if(!pathid)
+ {
+ SendSysMessage("No vallid path number provided.");
+ return true;
+ }
+
+ guidlow = target->GetGUIDLow();
+
+ QueryResult *result = WorldDatabase.PQuery( "SELECT guid FROM creature_addon WHERE guid = '%u'",guidlow);
+
+ if( result )
+ {
+ WorldDatabase.PExecute("UPDATE creature_addon SET path_id = '%u' WHERE guid = '%u'", pathid, guidlow);
+ delete result;
+ }
+ else
+ WorldDatabase.PExecute("INSERT INTO creature_addon(guid,path_id) VALUES ('%u','%u')", guidlow, pathid);
+
+ WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE, guidlow);
+
+ target->LoadPath(pathid);
+
+ target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
+
+ target->GetMotionMaster()->Initialize();
+
+ target->Say("Path loaded.",0,0);
+
+ return true;
+}
- sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
+bool ChatHandler::HandleReloadAllPaths(const char* args)
+{
+if(!*args)
+ return false;
- QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
- if( result )
+uint32 id = atoi(args);
+
+if(!id)
+ return false;
+
+PSendSysMessage("Loading Path: %u", id);
+ sWaypointStore.UpdatePath(id);
+ return true;
+}
+
+bool ChatHandler::HandleWpUnLoadPathCommand(const char *args)
+{
+uint32 guidlow = 0;
+Creature* target = getSelectedCreature();
+
+if(!target)
+{
+ SendSysMessage("You must select target.");
+ return true;
+}
+
+if(target->GetCreatureAddon())
+{
+ if(target->GetCreatureAddon()->path_id != 0)
+ {
+ WorldDatabase.PExecute("DELETE FROM creature_addon WHERE guid = %u", target->GetGUIDLow());
+ target->UpdateWaypointID(0);
+ WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", IDLE_MOTION_TYPE, guidlow);
+ target->LoadPath(0);
+ target->SetDefaultMovementType(IDLE_MOTION_TYPE);
+ target->GetMotionMaster()->TargetedHome();
+ target->Say("Path unloaded.",0,0);
+ return true;
+ }
+ SendSysMessage("Target have no loaded path.");
+ return true;
+}
+SendSysMessage("Target have no loaded path.");
+return true;
+}
+
+bool ChatHandler::HandleWpEventCommand(const char* args)
+{
+if(!*args)
+ return false;
+
+ char* show_str = strtok((char*)args, " ");
+
+ std::string show = show_str;
+
+ // Check
+ if( (show != "add") && (show != "mod") && (show != "del") && (show != "listid")) return false;
+
+
+ if(show == "add")
+ {
+ uint32 id = 0;
+ char* arg_id = strtok(NULL, " ");
+
+ if(arg_id)
+ uint32 id = atoi(arg_id);
+
+ if(id)
+ {
+ QueryResult *result = WorldDatabase.PQuery( "SELECT `id` FROM waypoint_scripts WHERE guid = %u", id);
+
+ if( !result )
+ {
+ WorldDatabase.PExecute("INSERT INTO waypoint_scripts(guid)VALUES(%u)", id);
+ PSendSysMessage("Wp Event: New waypoint event added: %u", id);
+ }
+ else
+ {
+ PSendSysMessage("Wp Event: You have choosed an existing waypoint script guid: %u", id);
+ delete result;
+ }
+ }
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(guid) FROM waypoint_scripts");
+ id = result->Fetch()->GetUInt32();
+ WorldDatabase.PExecute("INSERT INTO waypoint_scripts(guid)VALUES(%u)", id+1);
+ PSendSysMessage("Wp Event: New waypoint event added: %u", id+1);
+ }
+
+ return true;
+ }
+
+
+ if(show == "listid")
+ {
+ uint32 id;
+ char* arg_id = strtok(NULL, " ");
+
+ if(!arg_id)
+ {
+ SendSysMessage("Wp Event: You must provide waypoint script id.");
+ return true;
+ }
+
+ id = atoi(arg_id);
+
+ uint32 a2, a3, a4, a5, a6;
+ float a8, a9, a10, a11;
+ char const* a7;
+
+ QueryResult *result = WorldDatabase.PQuery( "SELECT `guid`, `delay`, `command`, `datalong`, `datalong2`, `datatext`, `x`, `y`, `z`, `o` FROM waypoint_scripts WHERE id = %u", id);
+
+ if( !result )
+ {
+ PSendSysMessage("Wp Event: No waypoint scripts found on id: %u", id);
+ return true;
+ }
+
+ Field *fields;
+
+ do
+ {
+ fields = result->Fetch();
+ a2 = fields[0].GetUInt32();
+ a3 = fields[1].GetUInt32();
+ a4 = fields[2].GetUInt32();
+ a5 = fields[3].GetUInt32();
+ a6 = fields[4].GetUInt32();
+ a7 = fields[5].GetString();
+ a8 = fields[6].GetFloat();
+ a9 = fields[7].GetFloat();
+ a10 = fields[8].GetFloat();
+ a11 = fields[9].GetFloat();
+
+ PSendSysMessage("id: %u, guid: %u, delay: %u, command: %u, datalong: %u, datalong2: %u, datatext: %s, posx: %f, posy: %f, posz: %f, orientation: %f", id, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+ }while(result->NextRow());
+
+ delete result;
+ }
+
+ if(show == "del")
+ {
+
+ char* arg_id = strtok(NULL, " ");
+ uint32 id = atoi(arg_id);
+
+ QueryResult *result = WorldDatabase.PQuery( "SELECT `guid` FROM waypoint_scripts WHERE guid = %u", id);
+
+ if( result )
{
- point = (*result)[0].GetUInt32()+1;
- delete result;
- }
+ WorldDatabase.PExecuteLog("DELETE FROM waypoint_scripts WHERE guid = %u", id);
+ PSendSysMessage("Wp Event: Waypoint script removed: %u", id);
+ delete result;
+ }
else
- point = 1;
+ PSendSysMessage("Wp Event: ERROR: you have selected a non existing script: %u", id);
+
+ return true;
+ }
+
+
+ if(show == "mod")
+ {
+ char* arg_1 = strtok(NULL," ");
+
+ if(!arg_1)
+ {
+ SendSysMessage("ERROR: Waypoint script guid not present.");
+ return true;
+ }
+
+ uint32 id = atoi(arg_1);
- Player* player = m_session->GetPlayer();
+ if(!id)
+ {
+ SendSysMessage("ERROR: No vallid waypoint script id not present.");
+ return true;
+ }
- WorldDatabase.PExecuteLog("INSERT INTO creature_movement (id,point,position_x,position_y,position_z,orientation) VALUES ('%u','%u','%f', '%f', '%f', '%f')",
- lowguid, point, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation());
+ char* arg_2 = strtok(NULL," ");
+
+ if(!arg_2)
+ { SendSysMessage("ERROR: No argument present.");
+ return true;}
+
+
+ std::string arg_string = arg_2;
+
+
+if( (arg_string != "setid") && (arg_string != "delay") && (arg_string != "command")
+&& (arg_string != "datalong") && (arg_string != "datalong2") && (arg_string != "datatext") && (arg_string != "posx")
+&& (arg_string != "posy") && (arg_string != "posz") && (arg_string != "orientation")
+) { SendSysMessage("ERROR: No valid argument present.");
+ return true;}
- // update movement type
- WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
- if(pCreature)
+char* arg_3;
+std::string arg_str_2 = arg_2;
+
+if(arg_str_2 != "datatext")
+ arg_3 = strtok(NULL," ");
+ else arg_3 = strtok(NULL,"<>");
+
+if(!arg_3)
+{SendSysMessage("ERROR: No additional argument present.");
+ return true;}
+
+float coord;
+
+ if(arg_str_2 == "setid")
+ {
+ uint32 newid = atoi(arg_3);
+ PSendSysMessage("Wp Event: Wypoint scipt guid: %u id changed: %u", newid, id);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET id='%u' WHERE guid='%u'",
+ newid, id); return true;
+ }
+ else
+ {
+
+ QueryResult *result = WorldDatabase.PQuery("SELECT id FROM waypoint_scripts WHERE guid='%u'",id);
+
+ if(!result)
+ {
+ SendSysMessage("ERROR: You have selected an non existing waypoint script guid.");
+ return true;
+ }
+
+ delete result;
+
+if(arg_str_2 == "posx")
+{
+ coord = atof(arg_3);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET x='%f' WHERE guid='%u'",
+ coord, id);
+ PSendSysMessage("Waypoint script: %u position_x updated.", id);
+ return true;
+}else if(arg_str_2 == "posy")
+{
+ coord = atof(arg_3);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET y='%f' WHERE guid='%u'",
+ coord, id);
+ PSendSysMessage("Waypoint script: %u position_y updated.", id);
+ return true;
+} else if(arg_str_2 == "posz")
+{
+ coord = atof(arg_3);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET z='%f' WHERE guid='%u'",
+ coord, id);
+ PSendSysMessage("Waypoint script: %u position_z updated.", id);
+ return true;
+} else if(arg_str_2 == "orientation")
+{
+ coord = atof(arg_3);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET o='%f' WHERE guid='%u'",
+ coord, id);
+ PSendSysMessage("Waypoint script: %u orientation updated.", id);
+ return true;
+} else if(arg_str_2 == "datatext")
+{
+ std::string arg_str_3 = arg_3;
+
+ if(arg_str_3 == "NULL")
+ {
+ WorldDatabase.PExecute("UPDATE waypoint_scripts SET %s= NULL WHERE guid='%u'", arg_2, id);
+ PSendSysMessage("Waypoint script: %u datatext updated.", id);
+ return true;
+ }
+ WorldDatabase.escape_string(arg_str_3);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%s' WHERE guid='%u'",
+ arg_2, arg_str_3.c_str(), id);
+ PSendSysMessage("Waypoint script: %u datatext updated.", id);
+ return true;
+}else
+{
+ std::string arg_str_3 = arg_3;
+ WorldDatabase.escape_string(arg_str_3);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%s' WHERE guid='%u'",
+ arg_2, arg_str_3.c_str(), id);
+}
+}
+ PSendSysMessage("Waypoint script: %u: %s updated.", id,arg_2);
+}
+return true;
+}
+
+bool ChatHandler::HandleDistFormationCommand(const char* args)
+{
+if(!*args)
+ {
+ SendSysMessage("No formation dist provided.");
+ return true;
+ }
+uint32 dist = atoi(args);
+Creature *target = getSelectedCreature();
+
+if(!dist)
+ {
+ SendSysMessage("No valid formation dist provided.");
+ return true;
+ }
+
+QueryResult *result = WorldDatabase.PQuery("SELECT follower FROM creature_formations WHERE follower='%u'", target->GetGUIDLow());
+
+if(!result)
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT leader FROM creature_formations WHERE leader='%u'", target->GetGUIDLow());
+
+ if(!result)
+ SendSysMessage("Current creature is not in formation.");
+ else
+ {
+ WorldDatabase.PExecute("UPDATE creature_formations SET dist='%u' WHERE leader='%u'",dist,target->GetGUIDLow());
+ delete result;
+ }
+ }
+ else
+ {
+ WorldDatabase.PExecute("UPDATE creature_formations SET dist='%u' WHERE follower='%u'", dist,target->GetGUIDLow());
+ delete result;
+ }
+SendSysMessage("Creature formation dist updated.");
+
+
+return true;
+}
+
+bool ChatHandler::HandleAngleFormationCommand(const char* args)
+{
+if(!*args)
+ {
+ SendSysMessage("No formation angle provided.");
+ return true;
+ }
+uint32 angle = atof(args);
+Creature *target = getSelectedCreature();
+
+if(!angle)
+ {
+ SendSysMessage("No valid formation angle provided.");
+ return true;
+ }
+
+QueryResult *result = WorldDatabase.PQuery("SELECT follower FROM creature_formations WHERE follower='%u'", target->GetGUIDLow());
+
+if(!result)
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT leader FROM creature_formations WHERE leader='%u'", target->GetGUIDLow());
+
+ if(!result)
+ SendSysMessage("Current creature is not in formation.");
+ else
+ {
+ WorldDatabase.PExecute("UPDATE creature_formations SET angle='%u' WHERE leader='%u'", angle,target->GetGUIDLow());
+ delete result;
+ }
+ }
+ else
+ {
+ WorldDatabase.PExecute("UPDATE creature_formations SET angle='%u' WHERE follower='%u'", angle,target->GetGUIDLow());
+ delete result;
+ }
+SendSysMessage("Creature formation angle updated.");
+return true;
+}
+
+bool ChatHandler::HandleCreateFormationCommand(const char* args)
+{
+if(!*args)
+ {
+ SendSysMessage("No leader GUID provided.");
+ return true;
+ }
+
+uint32 LeaderGuid = atoi(args);
+Creature *target = getSelectedCreature();
+
+if (!LeaderGuid)
{
- pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
- pCreature->GetMotionMaster()->Initialize();
- if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
- {
- pCreature->setDeathState(JUST_DIED);
- pCreature->RemoveCorpse();
- pCreature->Respawn();
- }
+ SendSysMessage("No vallid leader GUID provided.");
+ return true;
+ }
+
+if(!target)
+ {
+ SendSysMessage("No follower selected.");
+ return true;
}
- PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
+QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE guid='%u'", LeaderGuid);
- return true;
-} // HandleWpAddCommand
+ if(!result)
+ {
+ SendSysMessage("ERROR: You have selected GUID of non existing creature.");
+ return true;
+ }
+ else delete result;
-/**
- * .wp modify emote | spell | text | del | move | add
- *
- * add -> add a WP after the selected visual waypoint
- * User must select a visual waypoint and then issue ".wp modify add"
- *
- * emote <emoteID>
- * User has selected a visual waypoint before.
- * <emoteID> is added to this waypoint. Everytime the
- * NPC comes to this waypoint, the emote is called.
- *
- * emote <GUID> <WPNUM> <emoteID>
- * User has not selected visual waypoint before.
- * For the waypoint <WPNUM> for the NPC with <GUID>
- * an emote <emoteID> is added.
- * Everytime the NPC comes to this waypoint, the emote is called.
- *
- *
- * info <GUID> <WPNUM> -> User did not select a visual waypoint and
- */
+QueryResult *result1 = WorldDatabase.PQuery("SELECT follower FROM creature_formations WHERE follower='%u'", LeaderGuid);
+
+if(!result1)
+ {
+ WorldDatabase.PExecute("INSERT INTO creature_formations(leader,follower) VALUES('%u','%u')", LeaderGuid,target->GetGUIDLow());
+ }
+ else
+ {
+ delete result1;
+ WorldDatabase.PExecute("UPDATE creature_formations SET leader='%u' WHERE follower='%u'", LeaderGuid,target->GetGUIDLow());
+ }
+SendSysMessage("Formation created successfuly.");
+return true;
+}
+
+bool ChatHandler::HandleDismissFormationCommand(const char* args)
+{
+
+Creature *target = getSelectedCreature();
+
+if(!target)
+ {
+ SendSysMessage("No creature selected.");
+ return true;
+ }
+
+QueryResult *result = WorldDatabase.PQuery("SELECT follower FROM creature_formations WHERE follower='%u'", target->GetGUIDLow());
+
+if(!result)
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT leader FROM creature_formations WHERE leader='%u'", target->GetGUIDLow());
+
+ if(!result)
+ SendSysMessage("Current creature is not in formation.");
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery("DELETE * FROM creature_formations WHERE leader='%u'", target->GetGUIDLow());
+ delete result;
+ }
+ }
+ else
+ {
+ WorldDatabase.PExecute("DELETE FROM creature_formations WHERE follower='%u'", target->GetGUIDLow());
+ delete result;
+ }
+SendSysMessage("Formation dismissed successfuly.");
+return true;
+}
+
bool ChatHandler::HandleWpModifyCommand(const char* args)
{
sLog.outDebug("DEBUG: HandleWpModifyCommand");
@@ -2024,11 +2445,9 @@
std::string show = show_str;
// Check
// Remember: "show" must also be the name of a column!
- if( (show != "emote") && (show != "spell") && (show != "aiscript")
- && (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") )
+ if( (show != "delay") && (show != "event_id") && (show != "event_chance")
+ && (show != "flag") && (show != "del") && (show != "move") && (show != "wpadd")
+ )
{
return false;
}
@@ -2039,10 +2458,10 @@
// Did user provide a GUID
// or did the user select a creature?
// -> variable lowguid is filled with the GUID of the NPC
- uint32 lowguid = 0;
+ uint32 pathid = 0;
uint32 point = 0;
uint32 wpGuid = 0;
- Unit* target = getSelectedCreature();
+ Creature* target = getSelectedCreature();
if(target)
{
@@ -2051,39 +2470,30 @@
// The visual waypoint
Creature* wpCreature = NULL;
- wpGuid = target->GetGUIDLow();
+ wpGuid = target->GetGUIDLow();
// Did the user select a visual spawnpoint?
if(wpGuid)
- wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
- // attempt check creature existence by DB data
+ wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
+
+ // attempt check creature existence by DB data
if(!wpCreature)
{
- CreatureData const* data = objmgr.GetCreatureData(wpGuid);
- if(!data)
- {
+ QueryResult *result = WorldDatabase.PQuery( "SELECT guid FROM creature_addon WHERE path_id = '%u'",wpGuid);
+ if(!result)
+ {
PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, wpGuid);
return true;
}
}
- // User did select a visual waypoint?
- // Check the creature
- if (wpCreature->GetEntry() != VISUAL_WAYPOINT )
- {
- if( (show != "export") && (show != "import") )
- {
- PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
- return true;
- }
- lowguid = wpGuid;
- arg_str = strtok((char*)NULL, " ");
- }
- else
- {
+ // User did select a visual waypoint?
+ // Check the creature
+ if (wpCreature->GetEntry() == VISUAL_WAYPOINT )
+ {
QueryResult *result =
- WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
- target->GetGUIDLow() );
+ WorldDatabase.PQuery( "SELECT id, point FROM waypoint_data WHERE wpguid = %u",
+ wpGuid);
if(!result)
{
sLog.outDebug("DEBUG: HandleWpModifyCommand - No waypoint found - used 'wpguid'");
@@ -2096,7 +2506,7 @@
// (0.001) - There is no other way to compare C++ floats with mySQL floats
// See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
const char* maxDIFF = "0.01";
- result = WorldDatabase.PQuery( "SELECT id, point 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 FROM waypoint_data WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )",
wpCreature->GetPositionX(), maxDIFF, wpCreature->GetPositionY(), maxDIFF, wpCreature->GetPositionZ(), maxDIFF);
if(!result)
{
@@ -2109,8 +2519,8 @@
do
{
Field *fields = result->Fetch();
- lowguid = fields[0].GetUInt32();
- point = fields[1].GetUInt32();
+ pathid = fields[0].GetUInt32();
+ point = fields[1].GetUInt32();
}while( result->NextRow() );
// Cleanup memory
@@ -2118,14 +2528,9 @@
delete result;
// We have the waypoint number and the GUID of the "master npc"
// Text is enclosed in "<>", all other arguments not
- if( show.find("text") != std::string::npos )
- {
- arg_str = strtok((char*)NULL, "<>");
- }
- else
- {
- arg_str = strtok((char*)NULL, " ");
- }
+
+ arg_str = strtok((char*)NULL, " ");
+
}
}
else
@@ -2134,18 +2539,10 @@
char* guid_str = strtok((char*)NULL, " ");
char* point_str = strtok((char*)NULL, " ");
- // Text is enclosed in "<>", all other arguments not
- if( show.find("text") != std::string::npos )
+ arg_str = strtok((char*)NULL, " ");
+
+ if( !guid_str )
{
- arg_str = strtok((char*)NULL, "<>");
- }
- else
- {
- arg_str = strtok((char*)NULL, " ");
- }
-
- if( !guid_str )
- {
SendSysMessage(LANG_WAYPOINT_NOGUID);
return false;
}
@@ -2154,7 +2551,7 @@
SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
return false;
}
- if( (show != "del") && (show != "move") && (show != "add") )
+ if( (show != "del") && (show != "move") )
{
if( !arg_str )
{
@@ -2162,15 +2559,15 @@
return false;
}
}
- lowguid = atoi((char*)guid_str);
- PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
+ pathid = atoi((char*)guid_str);
+ PSendSysMessage("DEBUG: GUID provided: %d", pathid);
point = atoi((char*)point_str);
PSendSysMessage("DEBUG: wpNumber provided: %d", point);
// Now we need the GUID of the visual waypoint
// -> "del", "move", "add" command
- QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u'", lowguid, point);
+ QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM waypoint_data WHERE id = '%u' AND point = '%u'", pathid, point);
if(result)
{
do
@@ -2184,12 +2581,12 @@
}
else
{
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
+ PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, pathid, point);
// Select waypoint number from database
- QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='%d' AND id = '%u'", point, lowguid);
+ QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM waypoint_data WHERE point='%d' AND id = '%u'", point, pathid);
if(!result)
{
- PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
+ PSendSysMessage(LANG_WAYPOINT_NOTFOUND, pathid);
return true;
}
@@ -2229,7 +2626,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 != "del") && (show != "move"))
{
if( arg_str == NULL )
{
@@ -2237,97 +2634,12 @@
return false;
}
}
- // wpGuid -> GUID of the waypoint creature
- // lowguid -> GUID of the NPC
- // point -> waypoint number
-
- // Special functions:
- // add - move - del -> no args commands
- // Add a waypoint after the selected visual
- if(show == "add" && target)
- {
- PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
-
- // Get the creature for which we read the waypoint
- /* impossible without entry
- Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_GUID(lowguid, HIGHGUID_UNIT));
- */
- Creature* npcCreature = (Creature*)target;
-
- if( !npcCreature )
- {
- PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
- return true;
- }
- else
- {
- // obtain real GUID for DB operations
- lowguid = npcCreature->GetDBTableGUIDLow();
- }
- sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature");
-
- // What to do:
- // Add the visual spawnpoint (DB only)
- // Adjust the waypoints
- // Respawn the owner of the waypoints
- sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- SELECT MAX(`point`)");
- QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
- uint32 maxPoint = 0;
- if( result )
- {
- maxPoint = (*result)[0].GetUInt32();
- delete result;
- }
- for( uint32 i=maxPoint; i>point; i-- )
- {
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point+1 WHERE id='%u' AND point='%u'", lowguid, i);
- }
-
- Player* chr = m_session->GetPlayer();
- WorldDatabase.PExecuteLog("INSERT INTO creature_movement (id,point,position_x,position_y,position_z) VALUES ('%u','%u','%f', '%f', '%f')",
- lowguid, point+1, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
-
- if(npcCreature)
- {
- npcCreature->GetMotionMaster()->Initialize();
- if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
- {
- npcCreature->setDeathState(JUST_DIED);
- npcCreature->RemoveCorpse();
- npcCreature->Respawn();
- }
- }
-
- Creature* wpCreature = new Creature(chr);
- if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), chr->GetMapId(),
- chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation(), VISUAL_WAYPOINT,0))
- {
- PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
- delete wpCreature;
- return false;
- }
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point+1);
-
- wpCreature->SaveToDB();
- // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
- wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), chr->GetInstanceId());
- MapManager::Instance().GetMap(wpCreature->GetMapId(), wpCreature)->Add(wpCreature);
-
- PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
- return true;
- } // add
-
+
if(show == "del" && target)
{
- PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
+ PSendSysMessage("DEBUG: wp modify del, PathID: %u", pathid);
- // Get the creature for which we read the waypoint
- /* impossible without entry
- Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid, HIGHGUID_UNIT));
- */
- Creature* npcCreature = (Creature*)target;
-
- // wpCreature
+ // wpCreature
Creature* wpCreature = NULL;
if( wpGuid != 0 )
{
@@ -2337,55 +2649,22 @@
ObjectAccessor::Instance().AddObjectToRemoveList(wpCreature);
}
- // What to do:
- // Remove the visual spawnpoint
- // Adjust the waypoints
- // Respawn the owner of the waypoints
+ WorldDatabase.PExecuteLog("DELETE FROM waypoint_data WHERE id='%u' AND point='%u'",
+ pathid, point);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET point=point-1 WHERE id='%u' AND point>'%u'",
+ pathid, point);
- WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id='%u' AND point='%u'",
- lowguid, point);
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point-1 WHERE id='%u' AND point>'%u'",
- lowguid, point);
-
- if(npcCreature)
- {
- // Any waypoints left?
- QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
- if(!result2)
- {
- npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
- }
- else
- {
- npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
- delete result2;
- }
- npcCreature->GetMotionMaster()->Initialize();
- if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
- {
- npcCreature->setDeathState(JUST_DIED);
- npcCreature->RemoveCorpse();
- npcCreature->Respawn();
- }
- }
-
PSendSysMessage(LANG_WAYPOINT_REMOVED);
return true;
} // del
if(show == "move" && target)
{
- PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
+ PSendSysMessage("DEBUG: wp move, PathID: %u", pathid);
Player *chr = m_session->GetPlayer();
{
- // Get the creature for which we read the waypoint
- /* impossible without entry
- Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
- */
- Creature* npcCreature = (Creature*)target;
-
- // wpCreature
+ // wpCreature
Creature* wpCreature = NULL;
// What to do:
// Move the visual spawnpoint
@@ -2406,263 +2685,42 @@
return false;
}
wpCreature2->SaveToDB();
- // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
- wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), chr->GetInstanceId());
- MapManager::Instance().GetMap(npcCreature->GetMapId(), npcCreature)->Add(wpCreature2);
- //MapManager::Instance().GetMap(npcCreature->GetMapId())->Add(wpCreature2);
+ wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), chr->GetInstanceId());
+ MapManager::Instance().GetMap(chr->GetMapId(), chr)->Add(wpCreature2);
+
}
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET position_x = '%f',position_y = '%f',position_z = '%f' where id = '%u' AND point='%u'",
- chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), lowguid, point );
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET position_x = '%f',position_y = '%f',position_z = '%f' where id = '%u' AND point='%u'",
+ chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), pathid, point );
- if(npcCreature)
- {
- npcCreature->GetMotionMaster()->Initialize();
- if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
- {
- npcCreature->setDeathState(JUST_DIED);
- npcCreature->RemoveCorpse();
- npcCreature->Respawn();
- }
- }
PSendSysMessage(LANG_WAYPOINT_CHANGED);
}
return true;
} // move
- if(show == "export")
- {
- PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
-
- std::ofstream outfile;
- outfile.open (arg_str);
-
- QueryResult *result = WorldDatabase.PQuery(
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- "SELECT point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5, id FROM creature_movement WHERE id = '%u' ORDER BY point", lowguid );
-
- if( result )
- {
- do
- {
- Field *fields = result->Fetch();
-
- outfile << "insert into creature_movement ";
- outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5 ) values ";
-
- //sLog.outDebug("( ");
- outfile << "( ";
- //sLog.outDebug("id");
- outfile << fields[16].GetUInt32(); // id
- outfile << ", ";
- //sLog.outDebug("point");
- outfile << fields[0].GetUInt32(); // point
- outfile << ", ";
- //sLog.outDebug("position_x");
- outfile << fields[1].GetFloat(); // position_x
- outfile << ", ";
- //sLog.outDebug("position_y");
- outfile << fields[2].GetFloat(); // position_y
- outfile << ", ";
- //sLog.outDebug("position_z");
- outfile << fields[3].GetUInt32(); // position_z
- outfile << ", ";
- //sLog.outDebug("orientation");
- outfile << fields[4].GetUInt32(); // orientation
- outfile << ", ";
- //sLog.outDebug("model1");
- outfile << fields[5].GetUInt32(); // model1
- outfile << ", ";
- //sLog.outDebug("model2");
- outfile << fields[6].GetUInt32(); // model2
- outfile << ", ";
- //sLog.outDebug("waittime");
- outfile << fields[7].GetUInt16(); // waittime
- outfile << ", ";
- //sLog.outDebug("emote");
- outfile << fields[8].GetUInt32(); // emote
- outfile << ", ";
- //sLog.outDebug("spell");
- outfile << fields[9].GetUInt32(); // spell
- outfile << ", ";
- //sLog.outDebug("text1");
- const char *tmpChar = fields[10].GetString();
- if( !tmpChar )
- {
- outfile << "NULL"; // text1
- }
- else
- {
- outfile << "'";
- outfile << tmpChar; // text1
- outfile << "'";
- }
- outfile << ", ";
- //sLog.outDebug("text2");
- tmpChar = fields[11].GetString();
- if( !tmpChar )
- {
- outfile << "NULL"; // text2
- }
- else
- {
- outfile << "'";
- outfile << tmpChar; // text2
- outfile << "'";
- }
- outfile << ", ";
- //sLog.outDebug("text3");
- tmpChar = fields[12].GetString();
- if( !tmpChar )
- {
- outfile << "NULL"; // text3
- }
- else
- {
- outfile << "'";
- outfile << tmpChar; // text3
- outfile << "'";
- }
- outfile << ", ";
- //sLog.outDebug("text4");
- tmpChar = fields[13].GetString();
- if( !tmpChar )
- {
- outfile << "NULL"; // text4
- }
- else
- {
- outfile << "'";
- outfile << tmpChar; // text4
- outfile << "'";
- }
- outfile << ", ";
- //sLog.outDebug("text5");
- tmpChar = fields[14].GetString();
- if( !tmpChar )
- {
- outfile << "NULL"; // text5
- }
- else
- {
- outfile << "'";
- outfile << tmpChar; // text5
- outfile << "'";
- }
- outfile << ");\n ";
-
- } while( result->NextRow() );
- delete result;
-
- PSendSysMessage(LANG_WAYPOINT_EXPORTED);
- }
- else
- {
- PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
- outfile << GetMangosString(LANG_WAYPOINT_NOTHINGTOEXPORT);
- }
- outfile.close();
-
- return true;
- }
- if(show == "import")
- {
- PSendSysMessage("DEBUG: wp import, GUID: %u", lowguid);
-
- std::string line;
- std::ifstream infile (arg_str);
- if (infile.is_open())
- {
- while (! infile.eof() )
- {
- getline (infile,line);
- //cout << line << endl;
- QueryResult *result = WorldDatabase.PQuery(line.c_str());
- delete result;
- }
- infile.close();
- }
- PSendSysMessage(LANG_WAYPOINT_IMPORTED);
-
- return true;
- }
-
- // Create creature - npc that has the waypoint
- Creature* npcCreature = NULL;
-
- /* FIXME: impossible withput entry
- if(lowguid)
- npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
- */
-
- // attempt check creature existance by DB
- if(!npcCreature)
- {
- if(!objmgr.GetCreatureData(lowguid))
- {
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
- return true;
- }
- }
-
const char *text = arg_str;
if( text == 0 )
{
// show_str check for present in list of correct values, no sql injection possible
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s=NULL WHERE id='%u' AND point='%u'",
- show_str, lowguid, point);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s=NULL WHERE id='%u' AND point='%u'",
+ show_str, pathid, point);
}
else
{
// show_str check for present in list of correct values, no sql injection possible
std::string text2 = text;
WorldDatabase.escape_string(text2);
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s='%s' WHERE id='%u' AND point='%u'",
- show_str, text2.c_str(), lowguid, point);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s='%s' WHERE id='%u' AND point='%u'",
+ show_str, text2.c_str(), pathid, point);
}
+
+ PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
- if(npcCreature)
- {
- npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
- npcCreature->GetMotionMaster()->Initialize();
- if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
- {
- npcCreature->setDeathState(JUST_DIED);
- npcCreature->RemoveCorpse();
- npcCreature->Respawn();
- }
- }
- PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
-
return true;
}
-/**
- * .wp show info | on | off
- *
- * info -> User has selected a visual waypoint before
- *
- * info <GUID> <WPNUM> -> User did not select a visual waypoint and
- * provided the GUID of the NPC and the number of
- * the waypoint.
- *
- * on -> User has selected an NPC; all visual waypoints for this
- * NPC are added to the world
- *
- * on <GUID> -> User did not select an NPC - instead the GUID of the
- * NPC is provided. All visual waypoints for this NPC
- * are added from the world.
- *
- * off -> User has selected an NPC; all visual waypoints for this
- * NPC are removed from the world.
- *
- * on <GUID> -> User did not select an NPC - instead the GUID of the
- * NPC is provided. All visual waypoints for this NPC
- * are removed from the world.
- *
- *
- */
+
bool ChatHandler::HandleWpShowCommand(const char* args)
{
sLog.outDebug("DEBUG: HandleWpShowCommand");
@@ -2679,20 +2737,16 @@
// second arg: GUID (optional, if a creature is selected)
char* guid_str = strtok((char*)NULL, " ");
sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
- //if (!guid_str) {
- // return false;
- //}
-
- // Did user provide a GUID
- // or did the user select a creature?
- // -> variable lowguid is filled with the GUID
+
+ uint32 pathid = 0;
+ Creature* target = getSelectedCreature();
uint32 lowguid = 0;
- Unit* target = getSelectedCreature();
- // Did player provide a GUID?
+
+ // Did player provide a PathID?
if (!guid_str)
{
sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str");
- // No GUID provided
+ // No PathID provided
// -> Player must have selected a creature
if(!target)
@@ -2700,20 +2754,20 @@
SendSysMessage(LANG_SELECT_CREATURE);
return true;
}
- lowguid = target->GetGUIDLow();
- }
+ pathid = target->GetWaypointPath();
+ }
else
{
- sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided");
- // GUID provided
+ sLog.outDebug("DEBUG: HandleWpShowCommand: PathID provided");
+ // PathID provided
// Warn if player also selected a creature
// -> Creature selection is ignored <-
if(target)
{
SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
}
- lowguid = atoi((char*)guid_str);
- }
+ pathid = atoi((char*)guid_str);
+ }
sLog.outDebug("DEBUG: HandleWpShowCommand: danach");
@@ -2722,114 +2776,71 @@
Creature* pCreature = NULL;
- sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u", lowguid);
+ sLog.outDebug("DEBUG: HandleWpShowCommand: PathID: %u", pathid);
+
+ sLog.outDebug("DEBUG: HandleWpShowCommand: wpshow - show: %s", show_str);
- /* imposiible without entry
- if(lowguid)
- pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
- */
-
- sLog.outDebug("DEBUG: HandleWpShowCommand: Habe creature: %ld", pCreature );
- // attempt check creature existance by DB
- if(!pCreature)
- {
- if(!objmgr.GetCreatureData(lowguid))
- {
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
- return true;
- }
- }
-
- sLog.outDebug("DEBUG: HandleWpShowCommand: wpshow - show: %s", show_str);
//PSendSysMessage("wpshow - show: %s", show);
// Show info for the selected waypoint
if(show == "info")
- {
- PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
-
- // Check if the user did specify a visual waypoint
- if( pCreature->GetEntry() != VISUAL_WAYPOINT )
+ {
+
+ // Check if the user did specify a visual waypoint
+ if( target->GetEntry() != VISUAL_WAYPOINT )
{
PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
return true;
}
- //PSendSysMessage("wp on, GUID: %u", lowguid);
-
- //pCreature->GetPositionX();
-
- QueryResult *result =
- WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE wpguid = %u",
- pCreature->GetGUID() );
- if(!result)
+ QueryResult *result = WorldDatabase.PQuery( "SELECT id, point, delay, move_flag, event_id, event_chance FROM waypoint_data WHERE wpguid = %u", target->GetGUIDLow());
+
+ if(!result)
{
- // Since we compare float values, we have to deal with
- // some difficulties.
- // Here we search for all waypoints that only differ in one from 1 thousand
- // (0.001) - There is no other way to compare C++ floats with mySQL floats
- // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
- 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 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)
- {
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
- return true;
- }
+ SendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM);
+ return true;
}
- do
+
+ SendSysMessage("DEBUG: wp show info:");
+
+ do
{
Field *fields = result->Fetch();
- uint32 creGUID = fields[0].GetUInt32();
- uint32 point = fields[1].GetUInt32();
- int waittime = fields[2].GetUInt32();
- uint32 emote = fields[3].GetUInt32();
- uint32 spell = fields[4].GetUInt32();
- const char * text1 = fields[5].GetString();
- const char * text2 = fields[6].GetString();
- const char * text3 = fields[7].GetString();
- const char * text4 = fields[8].GetString();
- const char * text5 = fields[9].GetString();
- uint32 model1 = fields[10].GetUInt32();
- uint32 model2 = fields[11].GetUInt32();
+ pathid = fields[0].GetUInt32();
+ uint32 point = fields[1].GetUInt32();
+ uint32 delay = fields[2].GetUInt32();
+ uint32 flag = fields[3].GetUInt32();
+ uint32 ev_id = fields[4].GetUInt32();
+ uint32 ev_chance = fields[5].GetUInt32();
- // Get the creature for which we read the waypoint
- Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
+ PSendSysMessage("Show info: for current point: %u, Path ID: %u", point, pathid);
+ PSendSysMessage("Show info: delay: %u", delay);
+ PSendSysMessage("Show info: Move flag: %u", flag);
+ PSendSysMessage("Show info: Waypoint event: %u", ev_id);
+ PSendSysMessage("Show info: Event chance: %u", ev_chance);
+ }while( result->NextRow() );
- PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
- PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
- PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
- PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
- PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
- PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
- PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 1, text1);
- PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 2, text2);
- PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 3, text3);
- PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 4, text4);
- PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 5, text5);
-
- }while( result->NextRow() );
- // Cleanup memory
+ // Cleanup memory
delete result;
return true;
}
if(show == "on")
- {
- PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid);
-
- QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid);
- if(!result)
+ {
+ QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM waypoint_data WHERE id = '%u'", pathid);
+
+ if(!result)
{
- PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
+ PSendSysMessage("Path no found.", pathid);
return true;
}
- // Delete all visuals for this NPC
- QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid);
- if(result2)
+
+ PSendSysMessage("DEBUG: wp on, PathID: %u", pathid);
+
+ // Delete all visuals for this NPC
+ QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM waypoint_data WHERE id = '%u' and wpguid <> 0", pathid);
+
+ if(result2)
{
bool hasError = false;
do
@@ -2852,8 +2863,10 @@
}
}while( result2->NextRow() );
- delete result2;
- if( hasError )
+
+ delete result2;
+
+ if( hasError )
{
PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
@@ -2882,19 +2895,25 @@
delete result;
return false;
}
- wpCreature->SetVisibility(VISIBILITY_OFF);
- sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u");
+
+ sLog.outDebug("DEBUG: UPDATE waypoint_data 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);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), pathid, point);
wpCreature->SaveToDB();
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), chr->GetInstanceId());
MapManager::Instance().GetMap(wpCreature->GetMapId(), wpCreature)->Add(wpCreature);
- //MapManager::Instance().GetMap(wpCreature->GetMapId())->Add(wpCreature);
+ if(target)
+ {
+ wpCreature->SetDisplayId(target->GetDisplayId());
+ wpCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5);
+ }
+ //MapManager::Instance().GetMap(wpCreature->GetMapId())->Add(wpCreature);
}while( result->NextRow() );
- // Cleanup memory
+ SendSysMessage("Showing the current creature's path.");
+ // Cleanup memory
delete result;
return true;
}
@@ -2903,10 +2922,10 @@
{
PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid);
- QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid);
+ QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM waypoint_data WHERE point='1' AND id = '%u'",pathid);
if(!result)
{
- PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
+ PSendSysMessage(LANG_WAYPOINT_NOTFOUND, pathid);
return true;
}
@@ -2931,7 +2950,13 @@
pCreature->SaveToDB();
pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), chr->GetInstanceId());
MapManager::Instance().GetMap(pCreature->GetMapId(), pCreature)->Add(pCreature);
- //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
+
+ if(target)
+ {
+ pCreature->SetDisplayId(target->GetDisplayId());
+ pCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5);
+ }
+ //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
// Cleanup memory
delete result;
@@ -2940,9 +2965,9 @@
if(show == "last")
{
- PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid);
+ PSendSysMessage("DEBUG: wp last, PathID: %u", pathid);
- QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
+ QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM waypoint_data WHERE id = '%u'",pathid);
if( result )
{
Maxpoint = (*result)[0].GetUInt32();
@@ -2952,10 +2977,10 @@
else
Maxpoint = 0;
- result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid);
+ result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM waypoint_data WHERE point ='%u' AND id = '%u'",Maxpoint, pathid);
if(!result)
{
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid);
+ PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, pathid);
return true;
}
Field *fields = result->Fetch();
@@ -2979,7 +3004,13 @@
pCreature->SaveToDB();
pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), chr->GetInstanceId());
MapManager::Instance().GetMap(pCreature->GetMapId(), pCreature)->Add(pCreature);
- //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
+
+ if(target)
+ {
+ pCreature->SetDisplayId(target->GetDisplayId());
+ pCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5);
+ }
+ //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
// Cleanup memory
delete result;
return true;
@@ -2987,7 +3018,7 @@
if(show == "off")
{
- QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT);
+ QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%u'", 1);
if(!result)
{
SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND);
@@ -3018,7 +3049,7 @@
}
}while(result->NextRow());
// set "wpguid" column to "empty" - no visual waypoint spawned
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0'");
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '0'");
if( hasError )
{
Index: src/game/Level3.cpp
===================================================================
--- src/game/Level3.cpp (revision 5687)
+++ src/game/Level3.cpp (working copy)
@@ -108,7 +108,8 @@
HandleReloadQuestEndScriptsCommand("a");
HandleReloadQuestStartScriptsCommand("a");
HandleReloadSpellScriptsCommand("a");
- SendGlobalSysMessage("DB tables `*_scripts` reloaded.");
+ HandleReloadWaypointScriptsCommand("a");
+ SendGlobalSysMessage("DB tables `*_scripts` reloaded.");
return true;
}
@@ -125,7 +126,8 @@
HandleReloadSpellScriptTargetCommand("a");
HandleReloadSpellTeleportCommand("a");
HandleReloadSpellThreatsCommand("a");
- return true;
+ HandleReloadWaypointScriptsCommand("a");
+ return true;
}
bool ChatHandler::HandleReloadAreaTriggerTavernCommand(const char*)
@@ -435,6 +437,25 @@
return true;
}
+bool ChatHandler::HandleReloadWaypointScriptsCommand(const char* arg)
+{
+ if(sWorld.IsScriptScheduled())
+ {
+ SendSysMessage("DB scripts used currently, please attempt reload later.");
+ return true;
+ }
+
+ if(*arg!='a')
+ sLog.outString( "Re-Loading Scripts from `quest_start_scripts`...");
+
+ objmgr.LoadWaypointScripts();
+
+ if(*arg!='a')
+ SendGlobalSysMessage("DB table `quest_start_scripts` reloaded.");
+
+ return true;
+}
+
bool ChatHandler::HandleReloadSpellScriptsCommand(const char* arg)
{
if(sWorld.IsScriptScheduled())
Index: src/game/Object.cpp
===================================================================
--- src/game/Object.cpp (revision 5687)
+++ src/game/Object.cpp (working copy)
@@ -525,9 +525,54 @@
{
if(!target)
return;
+
+ bool reset = false;
+ uint32 oldflags = 0;
+ bool IsActivateToQuest = false;
+
+ Creature const* pThis = static_cast<Creature const*>(this);
+ /*
+ if(GetTypeId() == TYPEID_UNIT && pThis->isTagged && (pThis->loot.gold || pThis->loot.items.size()))
+ {
+ // Let's see if we're the tagger or not.
+ oldflags = m_uint32Values[UNIT_DYNAMIC_FLAGS];
+ uint32 Flags = m_uint32Values[UNIT_DYNAMIC_FLAGS];
+ uint32 oldFlags = 0;
- bool IsActivateToQuest = false;
- if (updatetype == UPDATETYPE_CREATE_OBJECT || updatetype == UPDATETYPE_CREATE_OBJECT2)
+ if(pThis->TaggerGuid == target->GetGUID())
+
+ {
+ // Our target is our tagger.
+ oldFlags = 4;
+
+ if(Flags & 4)
+ Flags &= ~oldFlags;
+
+ if(!(Flags & 1))
+ Flags |= 1;
+ }
+ else
+ {
+ // Target is not the tagger.
+ oldFlags = 1;
+
+ if(!(Flags & 4))
+ Flags |= 4;
+
+ if(Flags & 1)
+ Flags &= ~oldFlags;
+ }
+
+ m_uint32Values[UNIT_DYNAMIC_FLAGS] = Flags;
+
+ updateMask->SetBit(UNIT_DYNAMIC_FLAGS);
+
+
+
+ reset = true;
+ }*/
+
+ if (updatetype == UPDATETYPE_CREATE_OBJECT || updatetype == UPDATETYPE_CREATE_OBJECT2)
{
if (isType(TYPE_GAMEOBJECT) && !((GameObject*)this)->IsTransport())
{
@@ -584,14 +629,15 @@
{
*data << (m_uint32Values[ index ] & ~UNIT_FLAG_NOT_SELECTABLE);
}
- else
- {
- // send in current format (float as float, uint32 as uint32)
+
+ else
+
+ // send in current format (float as float, uint32 as uint32)
*data << m_uint32Values[ index ];
}
}
}
- }
+
else if(isType(TYPE_GAMEOBJECT)) // gameobject case
{
for( uint16 index = 0; index < m_valuesCount; index ++ )
@@ -635,6 +681,12 @@
}
}
}
+
+//if(reset && GetTypeId() == TYPEID_UNIT)
+ //m_uint32Values[UNIT_DYNAMIC_FLAGS] = oldflags;
+
+
+
}
void Object::ClearUpdateMask(bool remove)
Index: src/game/ObjectAccessor.cpp
===================================================================
--- src/game/ObjectAccessor.cpp (revision 5687)
+++ src/game/ObjectAccessor.cpp (working copy)
@@ -35,6 +35,7 @@
#include "GridNotifiersImpl.h"
#include "Opcodes.h"
#include "ObjectDefines.h"
+#include "WaypointMovementGenerator.h"
#include <cmath>
@@ -561,16 +562,24 @@
ObjectAccessor::Update(uint32 diff)
{
{
- typedef std::multimap<uint32, Player *> CreatureLocationHolderType;
+ typedef std::multimap<uint32, Unit *> CreatureLocationHolderType;
CreatureLocationHolderType creature_locations;
//TODO: Player guard
HashMapHolder<Player>::MapType& playerMap = HashMapHolder<Player>::GetContainer();
- for(HashMapHolder<Player>::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter)
+
+ for(HashMapHolder<Player>::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter)
{
if(iter->second->IsInWorld()) iter->second->Update(diff);
creature_locations.insert( CreatureLocationHolderType::value_type(iter->second->GetMapId(), iter->second) );
}
-
+
+ WaypointMovementGenerator<Creature>::ActiveCreatureList& WpMap = WaypointMovementGenerator<Creature>::GetContainer();
+
+ for(WaypointMovementGenerator<Creature>::ActiveCreatureList::iterator iter = WpMap.begin(); iter != WpMap.end(); ++iter)
+ {
+ creature_locations.insert( CreatureLocationHolderType::value_type(iter->second->GetMapId(), iter->second) );
+ }
+
Map *map;
MaNGOS::ObjectUpdater updater(diff);
@@ -586,7 +595,7 @@
for(CreatureLocationHolderType::iterator iter=creature_locations.begin(); iter != creature_locations.end(); ++iter)
{
- Player *player = (*iter).second;
+ Unit *player = (*iter).second;
map = MapManager::Instance().GetMap((*iter).first, player);
CellPair standing_cell(MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()));
Index: src/game/ObjectAccessor.h
===================================================================
--- src/game/ObjectAccessor.h (revision 5687)
+++ src/game/ObjectAccessor.h (working copy)
@@ -24,6 +24,7 @@
#include "zthread/FastMutex.h"
#include "Utilities/HashMap.h"
#include "Policies/ThreadingModel.h"
+#include "WaypointMovementGenerator.h"
#include "ByteBuffer.h"
#include "UpdateData.h"
@@ -48,25 +49,27 @@
public:
typedef HM_NAMESPACE::hash_map< uint64, T* > MapType;
- typedef ZThread::FastMutex LockType;
+ typedef ZThread::FastMutex LockType;
typedef MaNGOS::GeneralLock<LockType > Guard;
static void Insert(T* o) { m_objectMap[o->GetGUID()] = o; }
- static void Remove(T* o)
+
+ static void Remove(T* o)
{
Guard guard(i_lock);
typename MapType::iterator itr = m_objectMap.find(o->GetGUID());
if (itr != m_objectMap.end())
m_objectMap.erase(itr);
}
- static T* Find(uint64 guid)
+
+ static T* Find(uint64 guid)
{
typename MapType::iterator itr = m_objectMap.find(guid);
return (itr != m_objectMap.end()) ? itr->second : NULL;
}
static MapType& GetContainer() { return m_objectMap; }
-
+
static LockType* GetLock() { return &i_lock; }
private:
@@ -89,8 +92,8 @@
public:
typedef HM_NAMESPACE::hash_map<uint64, Corpse* > Player2CorpsesMapType;
typedef HM_NAMESPACE::hash_map<Player*, UpdateData>::value_type UpdateDataValueType;
-
- template<class T> static T* GetObjectInWorld(uint64 guid, T* /*fake*/)
+
+ template<class T> static T* GetObjectInWorld(uint64 guid, T* /*fake*/)
{
return HashMapHolder<T>::Find(guid);
}
@@ -140,7 +143,8 @@
static Creature* GetCreature(WorldObject const &, uint64);
static Creature* GetCreatureOrPet(WorldObject const &, uint64);
static Unit* GetUnit(WorldObject const &, uint64);
- static Pet* GetPet(Unit const &, uint64 guid) { return GetPet(guid); }
+ static Creature* GetSqlIdCreature(uint32);
+ static Pet* GetPet(Unit const &, uint64 guid) { return GetPet(guid); }
static Player* GetPlayer(Unit const &, uint64 guid) { return FindPlayer(guid); }
static GameObject* GetGameObject(WorldObject const &, uint64);
static DynamicObject* GetDynamicObject(Unit const &, uint64);
@@ -149,8 +153,8 @@
static Player* FindPlayer(uint64);
Player* FindPlayerByName(const char *name) ;
-
- HashMapHolder<Player>::MapType& GetPlayers()
+
+ HashMapHolder<Player>::MapType& GetPlayers()
{
return HashMapHolder<Player>::GetContainer();
}
Index: src/game/ObjectMgr.cpp
===================================================================
--- src/game/ObjectMgr.cpp (revision 5687)
+++ src/game/ObjectMgr.cpp (working copy)
@@ -37,6 +37,7 @@
#include "GameEvent.h"
#include "Spell.h"
#include "Chat.h"
+#include "WaypointMovementGenerator.h"
INSTANTIATE_SINGLETON_1(ObjectMgr);
@@ -45,6 +46,7 @@
ScriptMapMap sSpellScripts;
ScriptMapMap sGameObjectScripts;
ScriptMapMap sEventScripts;
+ScriptMapMap sWaypointScripts;
ObjectMgr::ObjectMgr()
{
@@ -658,6 +660,26 @@
}
}
+void ObjectMgr::LoadCreatureFormations()
+{
+
+ sCreatureFormation.Load();
+
+ sLog.outString( ">> Loaded %u creature formations", sCreatureFormation.RecordCount );
+ sLog.outString();
+
+ for(uint32 i = 1; i < sCreatureFormation.MaxEntry; ++i)
+ {
+
+ CreatureFormation const* formation = sCreatureFormation.LookupEntry<CreatureFormation>(i);
+ if(!formation)
+ continue;
+
+ if(mCreatureDataMap.find(formation->follower)==mCreatureDataMap.end())
+ sLog.outErrorDb("Creature (GUID: %u) does not exist but has a record in `creature_formation`",formation->follower);
+ }
+}
+
EquipmentInfo const* ObjectMgr::GetEquipmentInfo(uint32 entry)
{
return sEquipmentStorage.LookupEntry<EquipmentInfo>(entry);
@@ -808,6 +830,13 @@
cell_guids.creatures.erase(guid);
}
+void ObjectMgr::LoadWaypointData()
+{
+ sWaypointStore.Load();
+
+ sLog.outString(">> Loaded %u waypoints\n\n", sWaypointStore.GetRecordsCount() );
+}
+
void ObjectMgr::LoadGameobjects()
{
uint32 count = 0;
@@ -3290,6 +3319,18 @@
}
}
+void ObjectMgr::LoadWaypointScripts()
+{
+ objmgr.LoadScripts(sWaypointScripts, "waypoint_scripts");
+
+ for(ScriptMapMap::const_iterator itr = sWaypointScripts.begin(); itr != sWaypointScripts.end(); ++itr)
+ {
+ QueryResult *query = WorldDatabase.PQuery("SELECT * FROM `waypoint_scripts` WHERE `event_id` = %u", itr->first);
+ if(!query || !query->GetRowCount())
+ sLog.outErrorDb("There is no waypoint which links to the waypoint script %u", itr->first);
+ }
+}
+
void ObjectMgr::LoadItemTexts()
{
QueryResult *result = CharacterDatabase.PQuery("SELECT id, text FROM item_text");
Index: src/game/ObjectMgr.h
===================================================================
--- src/game/ObjectMgr.h (revision 5687)
+++ src/game/ObjectMgr.h (working copy)
@@ -45,6 +45,7 @@
extern SQLStorage sCreatureStorage;
extern SQLStorage sCreatureDataAddonStorage;
+extern SQLStorage sCreatureFormation;
extern SQLStorage sCreatureInfoAddonStorage;
extern SQLStorage sCreatureModelStorage;
extern SQLStorage sEquipmentStorage;
@@ -81,6 +82,7 @@
extern ScriptMapMap sSpellScripts;
extern ScriptMapMap sGameObjectScripts;
extern ScriptMapMap sEventScripts;
+extern ScriptMapMap sWaypointScripts;
struct AreaTrigger
{
@@ -256,7 +258,12 @@
return sCreatureInfoAddonStorage.LookupEntry<CreatureDataAddon>(entry);
}
- static ItemPrototype const* GetItemPrototype(uint32 id) { return sItemStorage.LookupEntry<ItemPrototype>(id); }
+ static CreatureFormation const *GetFormation( uint32 lowguid )
+ {
+ return sCreatureFormation.LookupEntry<CreatureFormation>(lowguid);
+ }
+
+ static ItemPrototype const* GetItemPrototype(uint32 id) { return sItemStorage.LookupEntry<ItemPrototype>(id); }
static InstanceTemplate const* GetInstanceTemplate(uint32 map)
{
@@ -409,6 +416,7 @@
void LoadQuestStartScripts();
void LoadEventScripts();
void LoadSpellScripts();
+ void LoadWaypointScripts();
bool LoadMangosStrings();
void LoadMangosStringLocales();
@@ -419,7 +427,9 @@
void LoadCreatureRespawnTimes();
void LoadCreatureAddons();
void LoadCreatureModelInfo();
- void LoadEquipmentTemplates();
+ void LoadWaypointData();
+ void LoadCreatureFormations();
+ void LoadEquipmentTemplates();
void LoadGameObjectLocales();
void LoadGameobjects();
void LoadGameobjectRespawnTimes();
@@ -693,8 +703,7 @@
MangosStringLocaleMap mMangosStringLocaleMap;
RespawnTimes mCreatureRespawnTimes;
RespawnTimes mGORespawnTimes;
-
- typedef std::vector<uint32> GuildBankTabPriceMap;
+ typedef std::vector<uint32> GuildBankTabPriceMap;
GuildBankTabPriceMap mGuildBankTabPrice;
};
Index: src/game/TargetedMovementGenerator.cpp
===================================================================
--- src/game/TargetedMovementGenerator.cpp (revision 5687)
+++ src/game/TargetedMovementGenerator.cpp (working copy)
@@ -92,10 +92,22 @@
{
if(!&owner)
return;
+
owner.SetUnitMovementFlag(MOVEMENT_FLAG_RUN);
+
_setTargetLocation(owner);
}
+void
+TargetedMovementGenerator<Creature>::Initialize(Creature &owner)
+{
+ if(!&owner)
+ return;
+
+ owner.SetUnitMovementFlag(MOVEMENT_FLAG_RUN);
+ _setTargetLocation(owner);
+}
+
template<class T>
void
TargetedMovementGenerator<T>::Finalize(T &owner)
@@ -192,7 +204,7 @@
template void TargetedMovementGenerator<Player>::_setTargetLocation(Player &);
template void TargetedMovementGenerator<Creature>::_setTargetLocation(Creature &);
template void TargetedMovementGenerator<Player>::Initialize(Player &);
-template void TargetedMovementGenerator<Creature>::Initialize(Creature &);
+//template void TargetedMovementGenerator<Creature>::Initialize(Creature &);
template void TargetedMovementGenerator<Player>::Finalize(Player &);
template void TargetedMovementGenerator<Creature>::Finalize(Creature &);
template void TargetedMovementGenerator<Player>::Reset(Player &);
Index: src/game/Unit.cpp
===================================================================
--- src/game/Unit.cpp (revision 5687)
+++ src/game/Unit.cpp (working copy)
@@ -442,7 +442,7 @@
// remove affects from attacker at any non-DoT damage (including 0 damage)
if( damagetype != DOT)
- {
+ {
RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
@@ -474,7 +474,7 @@
if(!spellProto || spellProto->Mechanic != MECHANIC_ROOT)
pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_ROOT, damage);
- if(pVictim->GetTypeId() != TYPEID_PLAYER)
+ if(pVictim->GetTypeId() != TYPEID_PLAYER)
{
//pVictim->SetInFront(this);
// no xp,health if type 8 /critters/
@@ -9623,11 +9623,6 @@
// send explicit stop packet
SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(),0, GetUnitMovementFlags(), 0);
-
- // update position and orientation;
- WorldPacket data;
- BuildHeartBeatMsg(&data);
- SendMessageToSet(&data,false);
}
bool Unit::IsStandState() const
Index: src/game/WaypointMovementGenerator.cpp
===================================================================
--- src/game/WaypointMovementGenerator.cpp (revision 5687)
+++ src/game/WaypointMovementGenerator.cpp (working copy)
@@ -16,295 +16,396 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/*
-creature_movement Table
-alter table creature_movement add `text1` varchar(255) default NULL;
-alter table creature_movement add `text2` varchar(255) default NULL;
-alter table creature_movement add `text3` varchar(255) default NULL;
-alter table creature_movement add `text4` varchar(255) default NULL;
-alter table creature_movement add `text5` varchar(255) default NULL;
-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';
-
-*/
-
+//Basic header
#include <ctime>
#include "WaypointMovementGenerator.h"
+//Accessors
+#include "Database/DatabaseEnv.h"
#include "ObjectMgr.h"
+#include "World.h"
+//Creature-specific headers
#include "Creature.h"
-#include "DestinationHolderImp.h"
#include "CreatureAI.h"
+//Player-Specific
+#include "Player.h"
+//Visual
+#include "ProgressBar.h"
+#include "MapManager.h"
+#include "CreatureAI.h"
-#include <cassert>
+WaypointStore sWaypointStore;
-//-----------------------------------------------//
-void
-WaypointMovementGenerator<Creature>::LoadPath(Creature &c)
+void WaypointStore::Free()
{
- 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 FROM creature_movement WHERE id = '%u' ORDER BY point", c.GetDBTableGUIDLow());
- /*
- if( result ) {
- sLog.outDebug("DEBUG: Number of hits: %d", result->GetRowCount());
- } else {
- sLog.outDebug("DEBUG: Nothing found");
+ wpdata.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
}
- */
- if( result )
+ records = (*result)[0].GetUInt32();
+ delete result;
+
+
+ result = WorldDatabase.PQuery("SELECT `id`,`point`,`position_x`,`position_y`,`position_z`,`move_flag`,`delay`,`event_id`,`event_chance` FROM `waypoint_data` ORDER BY `id`, `point`");
+ if(!result)
{
- unsigned int count = 0;
- const unsigned int sz = result->GetRowCount();
- i_path.Resize( sz );
- i_delays.resize( sz );
- i_wpBehaviour.resize( sz );
+ sLog.outErrorDb("The table `creature_addon` is empty or corrupted");
+ return;
+ }
- do
- {
- //sLog.outDebug("DEBUG: _load");
- Field *fields = result->Fetch();
- i_path[count].x = fields[0].GetFloat();
- i_path[count].y = fields[1].GetFloat();
- i_path[count].z = fields[2].GetFloat();
- float orientation = fields[3].GetFloat();
- uint32 model1 = fields[4].GetUInt32();
- uint32 model2 = fields[5].GetUInt32();
- i_delays[count] = fields[6].GetUInt16();
- uint32 emote = fields[7].GetUInt32();
- uint32 spell = fields[8].GetUInt32();
- std::string text1 = fields[9].GetCppString();
- std::string text2 = fields[10].GetCppString();
- std::string text3 = fields[11].GetCppString();
- std::string text4 = fields[12].GetCppString();
- std::string text5 = fields[13].GetCppString();
+ WaypointPath* path_data;
+ uint32 total_records = result->GetRowCount();
- if( (emote != 0) || (spell != 0)
- || !text1.empty() || !text2.empty() || !text3.empty() || !text4.empty() || !text5.empty()
- || (model1 != 0) || (model2 != 0) || (orientation != 100))
- {
- WaypointBehavior *tmpWPB = new WaypointBehavior;
+ 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 && id != 0)
+ path_data = new WaypointPath;
+
+ float x,y,z;
+ x = fields[2].GetFloat();
+ y = fields[3].GetFloat();
+ z = fields[4].GetFloat();
- // sLog.outDebug("DEBUG: _load --- Adding WaypointBehavior");
+ MaNGOS::NormalizeMapCoord(x);
+ MaNGOS::NormalizeMapCoord(y);
- tmpWPB->text[0] = text1;
- tmpWPB->text[1] = text2;
- tmpWPB->text[2] = text3;
- tmpWPB->text[3] = text4;
- tmpWPB->text[4] = text5;
- tmpWPB->orientation = orientation;
- tmpWPB->emote = emote;
- tmpWPB->spell = spell;
- tmpWPB->model1 = model1;
- tmpWPB->model2 = model2;
- tmpWPB->HasDone = false;
- i_wpBehaviour[count] = tmpWPB;
- }
- else
- {
- i_wpBehaviour[count] = NULL;
- }
+ 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)
+ wpdata[id] = path_data;
+
+ last_id = id;
- if(!MaNGOS::IsValidMapCoord(i_path[count].x,i_path[count].y))
- {
- sLog.outErrorDb("ERROR: Creature (guidlow %d,entry %d) have invalid coordinates in his waypoint %d (X: %d, Y: %d).",
- c.GetGUIDLow(),c.GetEntry(),count,i_path[count].x,i_path[count].y
- );
+ } while(result->NextRow()) ;
- // prevent invalid coordinates using
- MaNGOS::NormalizeMapCoord(i_path[count].x);
- MaNGOS::NormalizeMapCoord(i_path[count].y);
- i_path[count].z = MapManager::Instance ().GetBaseMap(c.GetMapId())->GetHeight(i_path[count].x,i_path[count].y, i_path[count].z);
- }
- // to prevent a misbehaviour inside "update"
- // update is alway 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
- if( count == (sz-1) )
- {
- if( i_wpBehaviour[count] != NULL )
- {
- i_wpBehaviour[count]->HasDone = true;
- }
- }
- //if( i_delays[count] < 30 /* millisecond */ )
- // i_delays[count] = (rand() % 5000);
- ++count;
+ delete result;
+}
- } while( result->NextRow() );
+void WaypointStore::UpdatePath(uint32 id)
+{
+
+ if(wpdata.find(id)!= wpdata.end())
+ wpdata[id]->clear();
+
+ QueryResult *result;
- delete result;
+ result = WorldDatabase.PQuery("SELECT `id`,`point`,`position_x`,`position_y`,`position_z`,`move_flag`,`delay`,`event_id`,`event_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;
- assert( sz == count );
- }
+ float x,y,z;
+ x = fields[2].GetFloat();
+ y = fields[3].GetFloat();
+ z = fields[4].GetFloat();
+
+ MaNGOS::NormalizeMapCoord(x);
+ MaNGOS::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());
+
+wpdata[id] = path_data;
+
+delete result;
}
+WaypointData* CreateWaypoint(uint32 id, float x, float y, float z, bool run, uint32 delay, uint32 event_id, uint8 event_chance)
+{
+ WaypointData *wp = new WaypointData;
+ wp->id = id;
+
+ MaNGOS::NormalizeMapCoord(x);
+ MaNGOS::NormalizeMapCoord(y);
+
+ wp->x = x;
+ wp->y = y;
+ wp->z = z;
+
+ wp->run = run;
+ wp->delay = delay;
+ wp->event_id = event_id;
+ wp->event_chance = event_chance;
+
+ return wp;
+}
+
+template<class T>
void
-WaypointMovementGenerator<Creature>::ClearWaypoints()
+WaypointMovementGenerator<T>::Initialize(T &u)
{
- for (std::vector<WaypointBehavior*>::iterator itr = i_wpBehaviour.begin(); itr != i_wpBehaviour.end(); ++itr)
- delete (*itr);
- i_wpBehaviour.clear();
+ i_currentNode = 0;
+ i_nextMoveTime.Reset(0);
+ u.StopMoving();
+ if(!path_id)
+ GeneratePathId(u);
+ waypoints = sWaypointStore.GetPath(path_id);
+ m_ActiveCreatureMap[u.GetGUID()] = &u;
}
void
-WaypointMovementGenerator<Creature>::Initialize()
+WaypointMovementGenerator<Creature>::Finalize(Creature &u)
{
- QueryResult *result = WorldDatabase.Query("SELECT distinct(id) as uniqueid FROM creature_movement");
+ WaypointMovementGenerator<T>::ActiveCreatureList::iterator itr = m_ActiveCreatureMap.find(u.GetGUID());
+ if (itr != m_ActiveCreatureMap.end())
+ m_ActiveCreatureMap.erase(itr);
+}
- if( result )
- {
- do
- {
- Field *fields = result->Fetch();
- si_waypointHolders.insert( fields[0].GetUInt32() );
- }
- while( result->NextRow() );
+void
+WaypointMovementGenerator<Player>::Finalize(Player &u)
+{
- delete result;
- }
}
+
+template<class T>
+void
+WaypointMovementGenerator<T>::Reset(T &u)
+{
+ u.StopMoving();
+
+ float x,y,z;
+ i_destinationHolder.GetLocationNow(x,y,z);
+
+
+ Traveller<T> traveller(u);
+ i_destinationHolder.GetDestination(x,y,z);
+ i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
+}
+
+template<class T>
+void
+WaypointMovementGenerator<T>::GeneratePathId(T &unit)
+{
+ path_id = 0;
+}
+
+void
+WaypointMovementGenerator<Creature>::GeneratePathId(Creature &unit)
+{
+ path_id = unit.GetWaypointPath();
+}
+
+
+template<class T>
+void
+WaypointMovementGenerator<T>::SetMoveFlag(T &unit, bool flag)
+
+{
+ //I wonder how that should even work for players, empty for now
+}
+
+void
+WaypointMovementGenerator<Creature>::SetMoveFlag(Creature &unit,bool flag)
+{
+ unit.SetUnitMovementFlag(flag);
+}
+
+template<class T>
+void
+WaypointMovementGenerator<T>::MovementInform(T &unit)
+{
+
+}
+
+void WaypointMovementGenerator<Creature>::MovementInform(Creature &unit)
+{
+ unit.AI()->MovementInform(path_id);
+}
+
+template<class T>
bool
-WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
+WaypointMovementGenerator<T>::Update(T &unit, const uint32 &diff)
{
- if(!&creature)
+ if(!&unit)
return true;
// Waypoint movement can be switched on/off
// This is quite handy for escort quests and other stuff
- if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED))
+ if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED))
return true;
- // prevent crash at empty waypoint path.
- if(i_path.Empty())
- {
+ // Clear the generator if the path doesn't exist
+ if(!waypoints || !waypoints->size())
return true;
- }
- CreatureTraveller traveller(creature);
+ if(((Creature*)&unit)->IsStoppedByEvent())
+ return true;
+
+ Traveller<T> traveller(unit);
- /*
- 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);
- if( creature.IsStopped() )
- {
- uint32 wpB = i_currentNode > 0 ? i_currentNode-1 : i_wpBehaviour.size()-1;
-
- if( i_wpBehaviour[wpB] != NULL )
- {
- struct WaypointBehavior *tmpBehavior = i_wpBehaviour[wpB];
-
- if (!tmpBehavior->HasDone)
+ if( i_nextMoveTime.Passed() )
+ {
+ if( unit.IsStopped() )
+ {
+ if(i_currentNode == waypoints->size() - 1) //If that's our last waypoint
{
- if(tmpBehavior->emote != 0)
- {
- creature.SetUInt32Value(UNIT_NPC_EMOTESTATE,tmpBehavior->emote);
- }
- //sLog.outDebug("DEBUG: tmpBehavior->text[0] TEST");
- if(!tmpBehavior->text[0].empty())
- {
- //sLog.outDebug("DEBUG: tmpBehavior->text[0] != \"\"");
- // Only one text is set
- if( tmpBehavior->text[1].empty() )
- {
- //sLog.outDebug("DEBUG: tmpBehavior->text[1] == NULL");
- creature.Say(tmpBehavior->text[0].c_str(), 0, 0);
- }
- else
- {
- // Select one from max 5 texts (0 and 1 laready checked)
- int i = 2;
- for( ; i < 5; ++i )
- if( tmpBehavior->text[i].empty() )
- break;
+ MovementInform(unit);
+
+ if(repeating) //If the movement is repeating
+ i_currentNode = 0; //Start moving all over again
+ else
+ return false; //Clear the waypoint movement
- //sLog.outDebug("DEBUG: tmpBehavior->text[i] == \"\": %d", i);
- //sLog.outDebug("DEBUG: rand() % (i): %d", rand() % (i));
+ }
+ else
+ i_currentNode++;
- creature.Say(tmpBehavior->text[rand() % i].c_str(), 0, 0);
- }
- }
- if(tmpBehavior->spell != 0)
- {
- //sLog.outDebug("DEBUG: wpSys - spell");
- creature.CastSpell(&creature,tmpBehavior->spell, false);
- }
- if (tmpBehavior->orientation !=100)
- {
- //sLog.outDebug("DEBUG: wpSys - orientation");
- creature.SetOrientation(tmpBehavior->orientation);
- }
- if(tmpBehavior->model1 != 0)
- {
- //sLog.outDebug("DEBUG: wpSys - model1");
- creature.SetDisplayId(tmpBehavior->model1);
- }
- tmpBehavior->HasDone = true;
- MovementInform(creature);
- } // HasDone == false
- } // wpBehaviour found
- } // i_creature.IsStopped()
-
- if( i_nextMoveTime.Passed() )
- {
- if( creature.IsStopped() )
+ ExecuteScript = false;
+ WaypointData* nextWP = *(waypoints->begin()+i_currentNode);
+ SetMoveFlag(unit, nextWP->run);
+ unit.addUnitState(UNIT_STAT_ROAMING);
+
+ if(((Creature*)&unit)->IsFollower())
+ {
+
+ uint32 guid = ((Creature*)&unit)->GetCreatureFormation()->leader;
+ uint32 entry = objmgr.GetCreatureData(guid)->id;
+
+ Creature* Leader = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(guid, entry, HIGHGUID_UNIT), (Creature*)NULL);
+
+ if(Leader)
+ {
+ dist = ((Creature*)&unit)->GetCreatureFormation()->offset_dist;
+ offset = ((Creature*)&unit)->GetCreatureFormation()->offset_angle;
+
+ if(dist && offset)
+ {
+ Map const* map = MapManager::Instance().GetBaseMap(unit.GetMapId());
+ float x,y,z,pathangle;
+ pathangle = atan2(Leader->GetPositionY()-nextWP->y,Leader->GetPositionX()-nextWP->x);
+
+ x = nextWP->x+cos(offset+pathangle)*dist;
+ y = nextWP->y+sin(offset+pathangle)*dist;
+ z = map->GetHeight(x,y,nextWP->z, false); // use .map base surface height
+ i_destinationHolder.SetDestination(traveller, x, y, z);
+ ((Creature*)&unit)->SetCoordsBeforeBattle(x,y,z);
+ Leader->SetLinkedtoFormation(true);
+ }
+ }
+ }
+ else
+ {
+ i_destinationHolder.SetDestination(traveller, nextWP->x, nextWP->y, nextWP->z);
+ ((Creature*)&unit)->SetCoordsBeforeBattle( nextWP->x, nextWP->y, nextWP->z);
+ }
+ i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
+ }
+ else
{
- assert( i_currentNode < i_path.Size() );
- creature.addUnitState(UNIT_STAT_ROAMING);
- const Path::PathNode &node(i_path(i_currentNode));
- i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
- 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];
- tmpBehavior->HasDone = false;
- if(tmpBehavior->model2 != 0)
- {
- creature.SetDisplayId(tmpBehavior->model2);
- }
- if (tmpBehavior->orientation !=100)
- {
- creature.SetOrientation(tmpBehavior->orientation);
- }
- creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
- }
- }
- else
- {
- creature.StopMoving();
- i_nextMoveTime.Reset(i_delays[i_currentNode]);
- ++i_currentNode;
- if( i_currentNode >= i_path.Size() )
- i_currentNode = 0;
- }
- }
- return true;
+ WaypointData* wp = *(waypoints->begin()+i_currentNode);
+
+ //Determine waittime
+ if(wp->delay)
+ i_nextMoveTime.Reset(wp->delay);
+ else
+ i_nextMoveTime.Reset(200); //Prevents some lag
+
+ if(wp->event_id && rand()%100 < wp->event_chance && !ExecuteScript)
+ {
+ sWorld.ScriptsStart(sWaypointScripts, wp->event_id, &unit, NULL);
+ ExecuteScript = true;
+ }
+
+ ((Creature*)&unit)->UpdateWaypointID(i_currentNode);
+
+ if(!((Creature*)&unit)->IsFollower())
+ {
+ if(!((Creature*)&unit)->isLinkedtoFormation())
+ ((Creature*)&unit)->clearUnitState(UNIT_STAT_MOVING);
+
+ }
+ else
+ {
+ uint32 guid = ((Creature*)&unit)->GetCreatureFormation()->leader;
+ uint32 entry = objmgr.GetCreatureData(guid)->id;
+
+ Creature* Leader = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(guid, entry, HIGHGUID_UNIT), (Creature*)NULL);
+
+ if(Leader)
+ {
+ if(((Creature*)&unit)->GetCurrentWaypointID() == Leader->GetCurrentWaypointID())
+ {
+ ((Creature*)&unit)->clearUnitState(UNIT_STAT_MOVING);
+ Leader->SetLinkedtoFormation(false);
+ }
+ else if(((Creature*)&unit)->GetCurrentWaypointID() == Leader->GetCurrentWaypointID()-1)
+ if(Leader->isLinkedtoFormation())
+ {
+ ((Creature*)&unit)->clearUnitState(UNIT_STAT_MOVING);
+ }
+ }
+ }
+ }
+ }
+ return true;
}
-void WaypointMovementGenerator<Creature>::MovementInform(Creature &unit)
-{
- if(unit.AI())
- unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
-}
+template <class T> HM_NAMESPACE::hash_map< uint64, T* > WaypointMovementGenerator<T>::m_ActiveCreatureMap;
-std::set<uint32> WaypointMovementGenerator<Creature>::si_waypointHolders;
+template void WaypointMovementGenerator<Player>::Initialize(Player &);
+template void WaypointMovementGenerator<Creature>::Initialize(Creature &);
+template void WaypointMovementGenerator<Player>::Reset(Player &);
+template void WaypointMovementGenerator<Creature>::Reset(Creature &);
+template bool WaypointMovementGenerator<Player>::Update(Player &, const uint32 &);
+template bool WaypointMovementGenerator<Creature>::Update(Creature &, const uint32 &);
+template void WaypointMovementGenerator<Player>::GeneratePathId(Player &);
+template void WaypointMovementGenerator<Player>::MovementInform(Player &);
+template void WaypointMovementGenerator<Player>::SetMoveFlag(Player &, bool flag);
//----------------------------------------------------//
void
Index: src/game/WaypointMovementGenerator.h
===================================================================
--- src/game/WaypointMovementGenerator.h (revision 5687)
+++ src/game/WaypointMovementGenerator.h (working copy)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ * Copyright (C) 2005,2006,2007 MaNGOS <http://www.mangosproject.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
@@ -25,31 +25,57 @@
* packets for the players.
*/
+class Player;
+
+//Movement classes
#include "MovementGenerator.h"
#include "DestinationHolder.h"
#include "Path.h"
#include "Traveller.h"
+#include "FollowerReference.h"
-#include "Player.h"
-
-#include <vector>
-#include <set>
-
#define FLIGHT_TRAVEL_UPDATE 100
#define VISUAL_WAYPOINT 1
-struct WaypointBehavior
+struct WaypointData
{
- uint32 emote;
- uint32 spell;
- std::string text[5];
- float orientation;
- uint32 model1;
- uint32 model2;
- bool HasDone;
+ uint32 id;
+ float x,y,z;
+ bool run;
+ uint32 delay;
+ uint32 event_id;
+ uint8 event_chance;
};
+typedef std::vector<WaypointData*> WaypointPath;
+typedef HM_NAMESPACE::hash_map<uint32, WaypointPath*> waypoint_map;
+
+WaypointData* CreateWaypoint(uint32 id, float x, float y, float z, bool run, uint32 delay, uint32 event_id, uint8 event_chance);
+
+class WaypointStore
+{
+ private :
+ waypoint_map wpdata;
+ uint32 records;
+
+ public:
+ void UpdatePath(uint32 id);
+ void Load();
+ void Free();
+
+ WaypointPath* GetPath(uint32 id)
+ {
+ if(wpdata.find(id) != wpdata.end())
+ return wpdata[id];
+ else return 0;
+ }
+
+ inline uint32 GetRecordsCount() { return records; }
+};
+
+extern WaypointStore sWaypointStore;
+
template<class T>
class MANGOS_DLL_SPEC PathMovementBase
{
@@ -59,67 +85,78 @@
inline bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); }
- // template pattern, not defined .. override required
void LoadPath(T &);
void ReloadPath(T &);
uint32 GetCurrentNode() const { return i_currentNode; }
+ void Finalize(T &);
+
protected:
uint32 i_currentNode;
DestinationHolder< Traveller<T> > i_destinationHolder;
Path 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>
-class MANGOS_DLL_SPEC WaypointMovementGenerator;
-template<>
-class MANGOS_DLL_SPEC WaypointMovementGenerator<Creature>
-: public MovementGeneratorMedium< Creature, WaypointMovementGenerator<Creature> >,
-public PathMovementBase<Creature>
+class MANGOS_DLL_SPEC WaypointMovementGenerator
+ : public MovementGeneratorMedium< T, WaypointMovementGenerator<T> >
{
- TimeTracker i_nextMoveTime;
- std::vector<uint32> i_delays;
- std::vector<WaypointBehavior *> i_wpBehaviour;
public:
- WaypointMovementGenerator(Creature &) : i_nextMoveTime(0) {}
- ~WaypointMovementGenerator() { ClearWaypoints(); }
- void Initialize(Creature &u)
+ WaypointMovementGenerator(T &, uint32 _path_id = 0, bool _repeating = true) :
+ i_nextMoveTime(0), path_id(_path_id), repeating(_repeating), custom_path(false) {}
+ ~WaypointMovementGenerator()
+ {
+ if(custom_path)
+ {
+ for(WaypointPath::iterator itr = waypoints->begin(); itr!= waypoints->end();)
+ {
+ delete (*itr);
+ itr = waypoints->erase(itr);
+ }
+ delete waypoints;
+ }
+ }
+ typedef HM_NAMESPACE::hash_map< uint64, T* > ActiveCreatureList;
+
+ void Initialize(T &);
+ void Finalize(T &);
+ static ActiveCreatureList& GetContainer(){return m_ActiveCreatureMap;}
+
+ void UseCustomPath(uint32 custom_id, WaypointPath *data)
{
- i_nextMoveTime.Reset(0); // TODO: check the lower bound (0 is probably too small)
- u.StopMoving();
- LoadPath(u);
+ cucstom_path = true;
+ path_id = custom_id;
+ waypoints = data;
}
- void Finalize(Creature &) {}
- void Reset(Creature &u) { ReloadPath(u); }
- bool Update(Creature &u, const uint32 &diff);
- void MovementInform(Creature &);
+ void MovementInform(T &);
+ void GeneratePathId(T &);
+ void SetMoveFlag(T &, bool flag); //Will change it to real type once we have real movement types ...
+ void Reset(T &);
+ bool Update(T &, const uint32 &);
MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; }
-
- // now path movement implmementation
- void LoadPath(Creature &c);
- void ReloadPath(Creature &c) { ClearWaypoints(); LoadPath(c); }
-
- // statics
- static void Initialize(void);
+
private:
- void ClearWaypoints();
- static std::set<uint32> si_waypointHolders;
-};
+ uint32 i_currentNode;
+ DestinationHolder< Traveller<T> > i_destinationHolder;
+ TimeTracker i_nextMoveTime;
+ WaypointPath *waypoints;
+ uint32 path_id;
+ bool repeating, custom_path, ExecuteScript;
+ float offset;
+ float dist;
+ static ActiveCreatureList m_ActiveCreatureMap;
+ };
/** FlightPathMovementGenerator generates movement of the player for the paths
* and hence generates ground and activities for the player.
*/
+
class MANGOS_DLL_SPEC FlightPathMovementGenerator
-: public MovementGeneratorMedium< Player, FlightPathMovementGenerator >,
-public PathMovementBase<Player>
+ : public MovementGeneratorMedium< Player, FlightPathMovementGenerator >,
+ public PathMovementBase<Player>
{
uint32 i_pathId;
std::vector<uint32> i_mapIds;
@@ -142,4 +179,5 @@
void SetCurrentNodeAfterTeleport();
void SkipCurrentNode() { ++i_currentNode; }
};
+
#endif
Index: src/game/World.cpp
===================================================================
--- src/game/World.cpp (revision 5687)
+++ src/game/World.cpp (working copy)
@@ -790,7 +790,13 @@
sLog.outString( "Loading BattleMasters..." );
objmgr.LoadBattleMastersEntry();
- ///- Handle outdated emails (delete/return)
+ sLog.outString( "Loading Waypoint Data..." );
+ objmgr.LoadWaypointData();
+
+ sLog.outString( "Loading Creature Formations..." );
+ objmgr.LoadCreatureFormations();
+
+ ///- Handle outdated emails (delete/return)
sLog.outString( "Returning old mails..." );
objmgr.ReturnOrDeleteOldMails(false);
@@ -801,6 +807,7 @@
objmgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadGameObjectScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data)
+ objmgr.LoadWaypointScripts();
sLog.outString( "Initializing Scripts..." );
if(!LoadScriptingModule())
@@ -839,7 +846,6 @@
///- Initilize static helper structures
AIRegistry::Initialize();
- WaypointMovementGenerator<Creature>::Initialize();
Player::InitVisibleBits();
RedZone::Initialize();
@@ -1177,7 +1183,7 @@
sLog.outError("SCRIPT_COMMAND_TALK call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
break;
}
- if(step.script->datalong > 2)
+ if(step.script->datalong > 3)
{
sLog.outError("SCRIPT_COMMAND_TALK invalid chat type (%u), skipping.",step.script->datalong);
break;
@@ -1185,7 +1191,7 @@
uint64 unit_target = target!=NULL ? target->GetGUID() : 0;
- //datalong 0=normal say, datalong 1=whisper, datalong 2=yell
+ //datalong 0=normal say, datalong 1=whisper, datalong 2=yell, datalong 3=textemote
switch(step.script->datalong)
{
case 0: // SAY
@@ -1202,7 +1208,11 @@
case 2: // YELL
((Creature *)source)->Yell(step.script->datatext.c_str(), 0, unit_target);
break;
- default:
+ case 3: // TEXTEMOTE
+ ((Creature *)source)->TextEmote(step.script->datatext.c_str(),0);
+ break;
+
+ default:
break; // must be already checked at load
}
break;
@@ -1580,8 +1590,28 @@
break;
}
+ case SCRIPT_START_PATH:
+ {
+ if(!source)
+ {
+ sLog.outError("SCRIPT_COMMAND_EMOTE call for NULL creature.");
+ break;
+ }
- default:
+ if(source->GetTypeId()!=TYPEID_UNIT)
+ {
+ sLog.outError("SCRIPT_COMMAND_EMOTE call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
+ break;
+ }
+
+ ((Creature*)source)->LoadPath(step.script->datalong);
+ ((Creature*)source)->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
+ ((Creature*)source)->GetMotionMaster()->Initialize();
+
+ break;
+ }
+
+ default:
sLog.outError("Unknown script command %u called.",step.script->command);
break;
}
Index: src/game/World.h
===================================================================
--- src/game/World.h (revision 5687)
+++ src/game/World.h (working copy)
@@ -203,7 +203,7 @@
#define SCRIPT_COMMAND_TEMP_SUMMON_CREATURE 10
#define SCRIPT_COMMAND_OPEN_DOOR 11
#define SCRIPT_COMMAND_CLOSE_DOOR 12
-
+#define SCRIPT_START_PATH 14
/// CLI related stuff, define here to prevent cyclic dependancies
typedef int(* pPrintf)(const char*,...);
Index: src/shared/Database/SQLStorage.cpp
===================================================================
--- src/shared/Database/SQLStorage.cpp (revision 5687)
+++ src/shared/Database/SQLStorage.cpp (working copy)
@@ -28,9 +28,10 @@
#endif
const char CreatureInfofmt[]="iiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiliiiiiiiiiiiiiiiisiilliis";
-const char CreatureDataAddonInfofmt[]="iiiiiis";
+const char CreatureDataAddonInfofmt[]="iiiiiiis";
+const char CreatureDataFormationInfofmt[]="iiff";
const char CreatureModelfmt[]="iffii";
-const char CreatureInfoAddonInfofmt[]="iiiiiis";
+const char CreatureInfoAddonInfofmt[]="iiiiiiis";
const char EquipmentInfofmt[]="iiiiiiiiii";
const char GameObjectInfofmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis";
const char ItemPrototypefmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifsiiiii";
@@ -40,6 +41,7 @@
SQLStorage sCreatureStorage(CreatureInfofmt,"entry","creature_template");
SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon");
+SQLStorage sCreatureFormation(CreatureDataFormationInfofmt,"follower","creature_formations");
SQLStorage sCreatureModelStorage(CreatureModelfmt,"modelid","creature_model_info");
SQLStorage sCreatureInfoAddonStorage(CreatureInfoAddonInfofmt,"entry","creature_template_addon");
SQLStorage sEquipmentStorage(EquipmentInfofmt,"entry","creature_equip_template");
Index: win/VC90/game.vcproj
===================================================================
--- win/VC90/game.vcproj (revision 5687)
+++ win/VC90/game.vcproj (working copy)
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="9.00"
+ Version="9,00"
Name="game"
ProjectGUID="{1DC6C4DA-A028-41F3-877D-D5400C594F88}"
RootNamespace="game"