Update Waypoint System and Commands

Update Waypoint System and Commands
This commit is contained in:
Charles A Edwards 2016-08-30 11:15:20 +01:00 committed by Antz
parent 870b4dd0a4
commit 6ac38a0d65
48 changed files with 455 additions and 323 deletions

View file

@ -490,7 +490,7 @@ class BattleGround
/* Triggers handle */ /* Triggers handle */
// must be implemented in BG subclass // must be implemented in BG subclass
virtual void HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) {} virtual bool HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) { return false; }
// must be implemented in BG subclass if need AND call base class generic code // must be implemented in BG subclass if need AND call base class generic code
virtual void HandleKillPlayer(Player* player, Player* killer); virtual void HandleKillPlayer(Player* player, Player* killer);
virtual void HandleKillUnit(Creature* /*unit*/, Player* /*killer*/) {} virtual void HandleKillUnit(Creature* /*unit*/, Player* /*killer*/) {}

View file

@ -183,7 +183,7 @@ void BattleGroundAB::RemovePlayer(Player * /*plr*/, ObjectGuid /*guid*/)
{ {
} }
void BattleGroundAB::HandleAreaTrigger(Player* source, uint32 trigger) bool BattleGroundAB::HandleAreaTrigger(Player* source, uint32 trigger)
{ {
switch (trigger) switch (trigger)
{ {
@ -199,19 +199,10 @@ void BattleGroundAB::HandleAreaTrigger(Player* source, uint32 trigger)
else else
source->LeaveBattleground(); source->LeaveBattleground();
break; break;
case 3866: // Stables
case 3869: // Gold Mine
case 3867: // Farm
case 3868: // Lumber Mill
case 3870: // Black Smith
case 4020: // Unk1
case 4021: // Unk2
// break;
default: default:
// sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", trigger); return false;
// source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", trigger);
break;
} }
return true;
} }
/* type: 0-neutral, 1-contested, 3-occupied /* type: 0-neutral, 1-contested, 3-occupied

View file

@ -173,7 +173,7 @@ class BattleGroundAB : public BattleGround
void AddPlayer(Player* plr) override; void AddPlayer(Player* plr) override;
virtual void StartingEventOpenDoors() override; virtual void StartingEventOpenDoors() override;
void RemovePlayer(Player* plr, ObjectGuid guid) override; void RemovePlayer(Player* plr, ObjectGuid guid) override;
void HandleAreaTrigger(Player* source, uint32 trigger) override; bool HandleAreaTrigger(Player* source, uint32 trigger) override;
virtual void Reset() override; virtual void Reset() override;
void EndBattleGround(Team winner) override; void EndBattleGround(Team winner) override;
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player) override; virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player) override;

View file

@ -350,7 +350,7 @@ void BattleGroundAV::EndBattleGround(Team winner)
BattleGround::EndBattleGround(winner); BattleGround::EndBattleGround(winner);
} }
void BattleGroundAV::HandleAreaTrigger(Player* source, uint32 trigger) bool BattleGroundAV::HandleAreaTrigger(Player* source, uint32 trigger)
{ {
// this is wrong way to implement these things. On official it done by gameobject spell cast. // this is wrong way to implement these things. On official it done by gameobject spell cast.
switch (trigger) switch (trigger)
@ -368,19 +368,10 @@ void BattleGroundAV::HandleAreaTrigger(Player* source, uint32 trigger)
else else
source->LeaveBattleground(); source->LeaveBattleground();
break; break;
case 3326:
case 3327:
case 3328:
case 3329:
case 3330:
case 3331:
// source->Unmount();
break;
default: default:
DEBUG_LOG("BattleGroundAV: WARNING: Unhandled AreaTrigger in Battleground: %u", trigger); return false;
// source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", trigger);
break;
} }
return true;
} }
void BattleGroundAV::UpdatePlayerScore(Player* source, uint32 type, uint32 value) void BattleGroundAV::UpdatePlayerScore(Player* source, uint32 type, uint32 value)

View file

@ -339,8 +339,8 @@ class BattleGroundAV : public BattleGround
virtual void StartingEventOpenDoors() override; virtual void StartingEventOpenDoors() override;
// world states // world states
virtual void FillInitialWorldStates(WorldPacket& data, uint32& count) override; virtual void FillInitialWorldStates(WorldPacket& data, uint32& count) override;
void HandleAreaTrigger(Player* source, uint32 trigger) override; bool HandleAreaTrigger(Player* source, uint32 trigger) override;
virtual void Reset() override; virtual void Reset() override;
/*general stuff*/ /*general stuff*/

View file

@ -96,32 +96,6 @@ bool BattleGroundBE::HandlePlayerUnderMap(Player* player)
return true; return true;
} }
void BattleGroundBE::HandleAreaTrigger(Player* source, uint32 trigger)
{
// this is wrong way to implement these things. On official it done by gameobject spell cast.
if (GetStatus() != STATUS_IN_PROGRESS)
return;
// uint32 spellId = 0;
// uint64 buff_guid = 0;
switch (trigger)
{
case 4538: // buff trigger?
// buff_guid = -nonexistingStorage-[BG_BE_OBJECT_BUFF_1];
break;
case 4539: // buff trigger?
// buff_guid = -nonexistingStorage-[BG_BE_OBJECT_BUFF_2];
break;
default:
sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", trigger);
source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", trigger);
break;
}
// if (buff_guid)
// HandleTriggerBuff(buff_guid, source);
}
void BattleGroundBE::FillInitialWorldStates(WorldPacket& data, uint32& count) void BattleGroundBE::FillInitialWorldStates(WorldPacket& data, uint32& count)
{ {
FillInitialWorldState(data, count, 0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); FillInitialWorldState(data, count, 0x9f1, GetAlivePlayersCountByTeam(ALLIANCE));
@ -138,18 +112,3 @@ void BattleGroundBE::UpdatePlayerScore(Player* source, uint32 type, uint32 value
// there is nothing special in this score // there is nothing special in this score
BattleGround::UpdatePlayerScore(source, type, value); BattleGround::UpdatePlayerScore(source, type, value);
} }
/*
21:45:46 id:231310 [S2C] SMSG_INIT_WORLD_STATES (706 = 0x02C2) len: 86
0000: 32 02 00 00 76 0e 00 00 00 00 00 00 09 00 f3 09 | 2...v...........
0010: 00 00 01 00 00 00 f1 09 00 00 01 00 00 00 f0 09 | ................
0020: 00 00 02 00 00 00 d4 08 00 00 00 00 00 00 d8 08 | ................
0030: 00 00 00 00 00 00 d7 08 00 00 00 00 00 00 d6 08 | ................
0040: 00 00 00 00 00 00 d5 08 00 00 00 00 00 00 d3 08 | ................
0050: 00 00 00 00 00 00 | ......
spell 32724 - Gold Team
spell 32725 - Green Team
35774 Gold Team
35775 Green Team
*/

View file

@ -45,7 +45,6 @@ class BattleGroundBE : public BattleGround
virtual void StartingEventOpenDoors() override; virtual void StartingEventOpenDoors() override;
void RemovePlayer(Player* plr, ObjectGuid guid) override; void RemovePlayer(Player* plr, ObjectGuid guid) override;
void HandleAreaTrigger(Player* source, uint32 trigger) override;
virtual void FillInitialWorldStates(WorldPacket& d, uint32& count) override; virtual void FillInitialWorldStates(WorldPacket& d, uint32& count) override;
void HandleKillPlayer(Player* player, Player* killer) override; void HandleKillPlayer(Player* player, Player* killer) override;
bool HandlePlayerUnderMap(Player* plr) override; bool HandlePlayerUnderMap(Player* plr) override;

View file

@ -298,13 +298,13 @@ void BattleGroundEY::ProcessCaptureEvent(GameObject* go, uint32 towerId, Team te
m_towerOwner[towerId] = team; m_towerOwner[towerId] = team;
} }
void BattleGroundEY::HandleAreaTrigger(Player* source, uint32 trigger) bool BattleGroundEY::HandleAreaTrigger(Player* source, uint32 trigger)
{ {
if (GetStatus() != STATUS_IN_PROGRESS) if (GetStatus() != STATUS_IN_PROGRESS)
return; return false;
if (!source->IsAlive()) // hack code, must be removed later if (!source->IsAlive()) // hack code, must be removed later
return; return false;
switch (trigger) switch (trigger)
{ {
@ -324,7 +324,10 @@ void BattleGroundEY::HandleAreaTrigger(Player* source, uint32 trigger)
if (m_towerOwner[NODE_DRAENEI_RUINS] == source->GetTeam()) if (m_towerOwner[NODE_DRAENEI_RUINS] == source->GetTeam())
EventPlayerCapturedFlag(source, NODE_DRAENEI_RUINS); EventPlayerCapturedFlag(source, NODE_DRAENEI_RUINS);
break; break;
default:
return false;
} }
return true;
} }
void BattleGroundEY::Reset() void BattleGroundEY::Reset()

View file

@ -264,7 +264,7 @@ class BattleGroundEY : public BattleGround
void RemovePlayer(Player* plr, ObjectGuid guid) override; void RemovePlayer(Player* plr, ObjectGuid guid) override;
bool HandleEvent(uint32 eventId, GameObject* go) override; bool HandleEvent(uint32 eventId, GameObject* go) override;
void HandleGameObjectCreate(GameObject* go) override; void HandleGameObjectCreate(GameObject* go) override;
void HandleAreaTrigger(Player* source, uint32 trigger) override; bool HandleAreaTrigger(Player* source, uint32 trigger) override;
void HandleKillPlayer(Player* player, Player* killer) override; void HandleKillPlayer(Player* player, Player* killer) override;
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player) override; virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player) override;

View file

@ -33,6 +33,8 @@
#include "BattleGround.h" #include "BattleGround.h"
#include "ace/Recursive_Thread_Mutex.h" #include "ace/Recursive_Thread_Mutex.h"
#include <mutex>
typedef std::map<uint32, BattleGround*> BattleGroundSet; typedef std::map<uint32, BattleGround*> BattleGroundSet;
// this container can't be deque, because deque doesn't like removing the last element - if you remove it, it invalidates next iterator and crash appears // this container can't be deque, because deque doesn't like removing the last element - if you remove it, it invalidates next iterator and crash appears

View file

@ -97,41 +97,9 @@ bool BattleGroundNA::HandlePlayerUnderMap(Player* player)
return true; return true;
} }
void BattleGroundNA::HandleAreaTrigger(Player* source, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
// uint32 spellId = 0;
// uint64 buff_guid = 0;
switch (trigger)
{
case 4536: // buff trigger?
case 4537: // buff trigger?
break;
default:
sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", trigger);
source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", trigger);
break;
}
// if (buff_guid)
// HandleTriggerBuff(buff_guid, source);
}
void BattleGroundNA::FillInitialWorldStates(WorldPacket& data, uint32& count) void BattleGroundNA::FillInitialWorldStates(WorldPacket& data, uint32& count)
{ {
FillInitialWorldState(data, count, 0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); FillInitialWorldState(data, count, 0xa0f, GetAlivePlayersCountByTeam(ALLIANCE));
FillInitialWorldState(data, count, 0xa10, GetAlivePlayersCountByTeam(HORDE)); FillInitialWorldState(data, count, 0xa10, GetAlivePlayersCountByTeam(HORDE));
FillInitialWorldState(data, count, 0xa11, 1); FillInitialWorldState(data, count, 0xa11, 1);
} }
/*
20:12:14 id:036668 [S2C] SMSG_INIT_WORLD_STATES (706 = 0x02C2) len: 86
0000: 2f 02 00 00 72 0e 00 00 00 00 00 00 09 00 11 0a | /...r...........
0010: 00 00 01 00 00 00 0f 0a 00 00 00 00 00 00 10 0a | ................
0020: 00 00 00 00 00 00 d4 08 00 00 00 00 00 00 d8 08 | ................
0030: 00 00 00 00 00 00 d7 08 00 00 00 00 00 00 d6 08 | ................
0040: 00 00 00 00 00 00 d5 08 00 00 00 00 00 00 d3 08 | ................
0050: 00 00 00 00 00 00 | ......
*/

View file

@ -46,7 +46,6 @@ class BattleGroundNA : public BattleGround
virtual void StartingEventOpenDoors() override; virtual void StartingEventOpenDoors() override;
void RemovePlayer(Player* plr, ObjectGuid guid) override; void RemovePlayer(Player* plr, ObjectGuid guid) override;
void HandleAreaTrigger(Player* source, uint32 trigger) override;
virtual void FillInitialWorldStates(WorldPacket& d, uint32& count) override; virtual void FillInitialWorldStates(WorldPacket& d, uint32& count) override;
void HandleKillPlayer(Player* player, Player* killer) override; void HandleKillPlayer(Player* player, Player* killer) override;
bool HandlePlayerUnderMap(Player* plr) override; bool HandlePlayerUnderMap(Player* plr) override;

View file

@ -96,42 +96,9 @@ bool BattleGroundRL::HandlePlayerUnderMap(Player* player)
return true; return true;
} }
void BattleGroundRL::HandleAreaTrigger(Player* source, uint32 trigger)
{
// this is wrong way to implement these things. On official it done by gameobject spell cast.
if (GetStatus() != STATUS_IN_PROGRESS)
return;
// uint32 spellId = 0;
// uint64 buff_guid = 0;
switch (trigger)
{
case 4696: // buff trigger?
case 4697: // buff trigger?
break;
default:
sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", trigger);
source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", trigger);
break;
}
// if (buff_guid)
// HandleTriggerBuff(buff_guid, source);
}
void BattleGroundRL::FillInitialWorldStates(WorldPacket& data, uint32& count) void BattleGroundRL::FillInitialWorldStates(WorldPacket& data, uint32& count)
{ {
FillInitialWorldState(data, count, 0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); FillInitialWorldState(data, count, 0xbb8, GetAlivePlayersCountByTeam(ALLIANCE));
FillInitialWorldState(data, count, 0xbb9, GetAlivePlayersCountByTeam(HORDE)); FillInitialWorldState(data, count, 0xbb9, GetAlivePlayersCountByTeam(HORDE));
FillInitialWorldState(data, count, 0xbba, 1); FillInitialWorldState(data, count, 0xbba, 1);
} }
/*
Packet S->C, id 600, SMSG_INIT_WORLD_STATES (706), len 86
0000: 3C 02 00 00 80 0F 00 00 00 00 00 00 09 00 BA 0B | <...............
0010: 00 00 01 00 00 00 B9 0B 00 00 02 00 00 00 B8 0B | ................
0020: 00 00 00 00 00 00 D8 08 00 00 00 00 00 00 D7 08 | ................
0030: 00 00 00 00 00 00 D6 08 00 00 00 00 00 00 D5 08 | ................
0040: 00 00 00 00 00 00 D3 08 00 00 00 00 00 00 D4 08 | ................
0050: 00 00 00 00 00 00 | ......
*/

View file

@ -47,7 +47,6 @@ class BattleGroundRL : public BattleGround
virtual void StartingEventOpenDoors() override; virtual void StartingEventOpenDoors() override;
void RemovePlayer(Player* plr, ObjectGuid guid) override; void RemovePlayer(Player* plr, ObjectGuid guid) override;
void HandleAreaTrigger(Player* source, uint32 trigger) override;
void HandleKillPlayer(Player* player, Player* killer) override; void HandleKillPlayer(Player* player, Player* killer) override;
bool HandlePlayerUnderMap(Player* plr) override; bool HandlePlayerUnderMap(Player* plr) override;
}; };

View file

@ -483,23 +483,14 @@ void BattleGroundWS::UpdateTeamScore(Team team)
UpdateWorldState(BG_WS_FLAG_CAPTURES_HORDE, m_TeamScores[TEAM_INDEX_HORDE]); UpdateWorldState(BG_WS_FLAG_CAPTURES_HORDE, m_TeamScores[TEAM_INDEX_HORDE]);
} }
void BattleGroundWS::HandleAreaTrigger(Player* source, uint32 trigger) bool BattleGroundWS::HandleAreaTrigger(Player* source, uint32 trigger)
{ {
// this is wrong way to implement these things. On official it done by gameobject spell cast. // this is wrong way to implement these things. On official it done by gameobject spell cast.
if (GetStatus() != STATUS_IN_PROGRESS) if (GetStatus() != STATUS_IN_PROGRESS)
return; return false;
// uint32 SpellId = 0;
// uint64 buff_guid = 0;
switch (trigger) switch (trigger)
{ {
case 3686: // Alliance elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in BattleGround::Update().
case 3687: // Horde elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in BattleGround::Update().
case 3706: // Alliance elixir of regeneration spawn
case 3708: // Horde elixir of regeneration spawn
case 3707: // Alliance elixir of berserk spawn
case 3709: // Horde elixir of berserk spawn
break;
case 3646: // Alliance Flag spawn case 3646: // Alliance Flag spawn
if (m_FlagState[TEAM_INDEX_HORDE] && !m_FlagState[TEAM_INDEX_ALLIANCE]) if (m_FlagState[TEAM_INDEX_HORDE] && !m_FlagState[TEAM_INDEX_ALLIANCE])
if (GetHordeFlagCarrierGuid() == source->GetObjectGuid()) if (GetHordeFlagCarrierGuid() == source->GetObjectGuid())
@ -510,16 +501,10 @@ void BattleGroundWS::HandleAreaTrigger(Player* source, uint32 trigger)
if (GetAllianceFlagCarrierGuid() == source->GetObjectGuid()) if (GetAllianceFlagCarrierGuid() == source->GetObjectGuid())
EventPlayerCapturedFlag(source); EventPlayerCapturedFlag(source);
break; break;
case 3649: // unk1
case 3688: // unk2
case 4628: // unk3
case 4629: // unk4
break;
default: default:
sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", trigger); return false;
source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", trigger);
break;
} }
return true;
} }
void BattleGroundWS::Reset() void BattleGroundWS::Reset()

View file

@ -139,7 +139,7 @@ class BattleGroundWS : public BattleGround
virtual void EventPlayerCapturedFlag(Player* source) override; virtual void EventPlayerCapturedFlag(Player* source) override;
void RemovePlayer(Player* plr, ObjectGuid guid) override; void RemovePlayer(Player* plr, ObjectGuid guid) override;
void HandleAreaTrigger(Player* source, uint32 trigger) override; bool HandleAreaTrigger(Player* source, uint32 trigger) override;
void HandleKillPlayer(Player* player, Player* killer) override; void HandleKillPlayer(Player* player, Player* killer) override;
virtual void Reset() override; virtual void Reset() override;
void EndBattleGround(Team winner) override; void EndBattleGround(Team winner) override;

View file

@ -3140,7 +3140,7 @@ bool ChatHandler::HandleWpModifyCommand(char* args)
// Did user provide a GUID or did the user select a creature? // Did user provide a GUID or did the user select a creature?
Creature* targetCreature = getSelectedCreature(); // Expect a visual waypoint to be selected Creature* targetCreature = getSelectedCreature(); // Expect a visual waypoint to be selected
Creature* wpOwner = nullptr; // Who moves along the waypoint Creature* wpOwner; // Who moves along the waypoint
uint32 wpId = 0; uint32 wpId = 0;
WaypointPathOrigin wpSource = PATH_NO_PATH; WaypointPathOrigin wpSource = PATH_NO_PATH;
int32 wpPathId = 0; int32 wpPathId = 0;
@ -3393,8 +3393,8 @@ bool ChatHandler::HandleWpShowCommand(char* args)
} }
} }
Creature* wpOwner = NULL; ///< Npc that is moving Creature* wpOwner; ///< Npc that is moving
TemporarySummonWaypoint* wpTarget = NULL; // Define here for wp-info command TemporarySummonWaypoint* wpTarget = nullptr; // Define here for wp-info command
// Show info for the selected waypoint (Step one: get moving npc) // Show info for the selected waypoint (Step one: get moving npc)
if (subCmd == "info") if (subCmd == "info")
@ -3431,7 +3431,7 @@ bool ChatHandler::HandleWpShowCommand(char* args)
wpOwner = targetCreature; wpOwner = targetCreature;
// Get the path // Get the path
WaypointPath* wpPath = NULL; WaypointPath* wpPath = nullptr;
if (wpOrigin != PATH_NO_PATH) // Might have been provided by param if (wpOrigin != PATH_NO_PATH) // Might have been provided by param
wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin); wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin);
else else
@ -3538,65 +3538,112 @@ bool ChatHandler::HandleWpShowCommand(char* args)
return false; return false;
} }
/// [Guid if no selected unit] <filename> [pathId [wpOrigin] ]
bool ChatHandler::HandleWpExportCommand(char* args) bool ChatHandler::HandleWpExportCommand(char* args)
{ {
if (!*args) if (!*args)
return false; return false;
// Next arg is: <GUID> <ARGUMENT> Creature* wpOwner;
WaypointPathOrigin wpOrigin = PATH_NO_PATH;
int32 wpPathId = 0;
// Did user provide a GUID if (Creature* targetCreature = getSelectedCreature())
// or did the user select a creature?
// -> variable lowguid is filled with the GUID of the NPC
uint32 lowguid = 0;
Creature* target = getSelectedCreature();
char* arg_str = NULL;
if (target)
{ {
if (target->GetEntry() != VISUAL_WAYPOINT) // Check if the user did specify a visual waypoint
lowguid = target->GetGUIDLow(); if (targetCreature->GetEntry() == VISUAL_WAYPOINT && targetCreature->GetSubtype() == CREATURE_SUBTYPE_TEMPORARY_SUMMON)
else
{ {
QueryResult* result = WorldDatabase.PQuery("SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow()); TemporarySummonWaypoint* wpTarget = dynamic_cast<TemporarySummonWaypoint*>(targetCreature);
if (!result) if (!wpTarget)
{ {
PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow()); PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
return true; SetSentErrorMessage(true);
return false;
} }
Field* fields = result->Fetch();
lowguid = fields[0].GetUInt32();;
delete result;
}
arg_str = strtok(args, " "); // Who moves along this waypoint?
wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid());
if (!wpOwner)
{
PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str());
SetSentErrorMessage(true);
return false;
}
wpOrigin = (WaypointPathOrigin)wpTarget->GetPathOrigin();
wpPathId = wpTarget->GetPathId();
}
else // normal creature selected
wpOwner = targetCreature;
} }
else else
{ {
// user provided <GUID> uint32 dbGuid;
char* guid_str = strtok(args, " "); if (!ExtractUInt32(&args, dbGuid))
if (!guid_str)
{ {
SendSysMessage(LANG_WAYPOINT_NOGUID); PSendSysMessage(LANG_WAYPOINT_NOGUID);
SetSentErrorMessage(true);
return false; return false;
} }
lowguid = atoi((char*)guid_str);
arg_str = strtok((char*)NULL, " "); CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid);
if (!data)
{
PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid);
SetSentErrorMessage(true);
return false;
}
if (m_session->GetPlayer()->GetMapId() != data->mapid)
{
PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, dbGuid);
SetSentErrorMessage(true);
return false;
}
wpOwner = m_session->GetPlayer()->GetMap()->GetAnyTypeCreature(data->GetObjectGuid(dbGuid));
if (!wpOwner)
{
PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid);
SetSentErrorMessage(true);
return false;
}
} }
if (!arg_str) // wpOwner is now known, in case of export by visual waypoint also the to be exported path
char* export_str = ExtractLiteralArg(&args);
if (!export_str)
{ {
PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export"); PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export");
SetSentErrorMessage(true);
return false; return false;
} }
PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid); if (wpOrigin == PATH_NO_PATH) // No WP selected, Extract optional arguments
{
if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source
{
uint32 src = (uint32)PATH_NO_PATH;
if (ExtractOptUInt32(&args, src, src))
wpOrigin = (WaypointPathOrigin)src;
else // pathId provided but no destination
{
if (wpPathId != 0)
wpOrigin = PATH_FROM_ENTRY; // Multiple Paths must only be assigned by entry
}
}
QueryResult* result = WorldDatabase.PQuery( if (wpOrigin == PATH_NO_PATH)
// 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, textid1, textid2, textid3, textid4, textid5, id FROM creature_movement WHERE id = '%u' ORDER BY point", lowguid); if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
if (WaypointMovementGenerator<Creature> const* wpMMGen = dynamic_cast<WaypointMovementGenerator<Creature> const*>(wpOwner->GetMotionMaster()->GetCurrent()))
wpMMGen->GetPathInformation(wpPathId, wpOrigin);
if (wpOrigin == PATH_NO_PATH)
sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpOrigin);
}
}
if (!result) WaypointPath const* wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin);
if (!wpPath || wpPath->empty())
{ {
PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT); PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
SetSentErrorMessage(true); SetSentErrorMessage(true);
@ -3604,51 +3651,44 @@ bool ChatHandler::HandleWpExportCommand(char* args)
} }
std::ofstream outfile; std::ofstream outfile;
outfile.open(arg_str); outfile.open(export_str);
do std::string table;
char const* key_field;
uint32 key;
switch (wpOrigin)
{ {
Field* fields = result->Fetch(); case PATH_FROM_ENTRY: key = wpOwner->GetEntry(); key_field = "entry"; table = "creature_movement_template"; break;
case PATH_FROM_GUID: key = wpOwner->GetGUIDLow(); key_field = "id"; table = "creature_movement"; break;
outfile << "INSERT INTO creature_movement "; case PATH_FROM_EXTERNAL: key = wpOwner->GetEntry(); key_field = "entry"; table = sWaypointMgr.GetExternalWPTable(); break;
outfile << "(id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5) VALUES "; case PATH_NO_PATH:
return false;
outfile << "( "; }
outfile << fields[15].GetUInt32(); // id
outfile << ", "; outfile << "DELETE FROM " << table << " WHERE " << key_field << "=" << key << ";\n";
outfile << fields[0].GetUInt32(); // point if (wpOrigin != PATH_FROM_EXTERNAL)
outfile << ", "; outfile << "INSERT INTO " << table << " (" << key_field << ", point, position_x, position_y, position_z, orientation, waittime, script_id) VALUES\n";
outfile << fields[1].GetFloat(); // position_x else
outfile << ", "; outfile << "INSERT INTO " << table << " (" << key_field << ", point, position_x, position_y, position_z, orientation, waittime) VALUES\n";
outfile << fields[2].GetFloat(); // position_y
outfile << ", "; WaypointPath::const_iterator itr = wpPath->begin();
outfile << fields[3].GetUInt32(); // position_z uint32 countDown = wpPath->size();
outfile << ", "; for (; itr != wpPath->end(); ++itr, --countDown)
outfile << fields[4].GetUInt32(); // orientation {
outfile << ", "; outfile << "(" << key << ",";
outfile << fields[5].GetUInt32(); // model1 outfile << itr->first << ",";
outfile << ", "; outfile << itr->second.x << ",";
outfile << fields[6].GetUInt32(); // model2 outfile << itr->second.y << ",";
outfile << ", "; outfile << itr->second.z << ",";
outfile << fields[7].GetUInt16(); // waittime outfile << itr->second.orientation << ",";
outfile << ", "; outfile << itr->second.delay << ",";
outfile << fields[8].GetUInt32(); // emote if (wpOrigin != PATH_FROM_EXTERNAL) // Only for normal waypoints
outfile << ", "; outfile << itr->second.script_id << ")";
outfile << fields[9].GetUInt32(); // spell if (countDown > 1)
outfile << ", "; outfile << ",\n";
outfile << fields[10].GetUInt32(); // textid1 else
outfile << ", "; outfile << ";\n";
outfile << fields[11].GetUInt32(); // textid2
outfile << ", ";
outfile << fields[12].GetUInt32(); // textid3
outfile << ", ";
outfile << fields[13].GetUInt32(); // textid4
outfile << ", ";
outfile << fields[14].GetUInt32(); // textid5
outfile << ");\n ";
} }
while (result->NextRow());
delete result;
PSendSysMessage(LANG_WAYPOINT_EXPORTED); PSendSysMessage(LANG_WAYPOINT_EXPORTED);
outfile.close(); outfile.close();
@ -3656,33 +3696,6 @@ bool ChatHandler::HandleWpExportCommand(char* args)
return true; return true;
} }
bool ChatHandler::HandleWpImportCommand(char* args)
{
if (!*args)
return false;
char* arg_str = strtok(args, " ");
if (!arg_str)
return false;
std::string line;
std::ifstream infile(arg_str);
if (infile.is_open())
{
while (! infile.eof())
{
getline(infile, line);
// cout << line << endl;
QueryResult* result = WorldDatabase.Query(line.c_str());
delete result;
}
infile.close();
}
PSendSysMessage(LANG_WAYPOINT_IMPORTED);
return true;
}
// rename characters // rename characters
bool ChatHandler::HandleCharacterRenameCommand(char* args) bool ChatHandler::HandleCharacterRenameCommand(char* args)
{ {

View file

@ -59,8 +59,10 @@ void MotionMaster::Initialize()
if (m_owner->GetTypeId() == TYPEID_UNIT && !m_owner->hasUnitState(UNIT_STAT_CONTROLLED)) if (m_owner->GetTypeId() == TYPEID_UNIT && !m_owner->hasUnitState(UNIT_STAT_CONTROLLED))
{ {
MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)m_owner); MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)m_owner);
push(movement == NULL ? &si_idleMovement : movement); push(movement == nullptr ? &si_idleMovement : movement);
top()->Initialize(*m_owner); top()->Initialize(*m_owner);
if (top()->GetMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
(static_cast<WaypointMovementGenerator<Creature>*>(top()))->InitializeWaypointPath(*((Creature*)(m_owner)), 0, PATH_NO_PATH, 0, 0);
} }
else else
push(&si_idleMovement); push(&si_idleMovement);
@ -376,20 +378,22 @@ void MotionMaster::MoveFleeing(Unit* enemy, uint32 time)
} }
} }
void MotionMaster::MoveWaypoint() void MotionMaster::MoveWaypoint(int32 id /*=0*/, uint32 source /*=0==PATH_NO_PATH*/, uint32 initialDelay /*=0*/, uint32 overwriteEntry /*=0*/)
{ {
if (m_owner->GetTypeId() == TYPEID_UNIT) if (m_owner->GetTypeId() == TYPEID_UNIT)
{ {
if (GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) if (GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
{ {
sLog.outError("Creature %s (Entry %u) attempt to MoveWaypoint() but creature is already using waypoint", m_owner->GetGuidStr().c_str(), m_owner->GetEntry()); sLog.outError("%s attempt to MoveWaypoint() but is already using waypoint", m_owner->GetGuidStr().c_str());
return; return;
} }
Creature* creature = (Creature*)m_owner; Creature* creature = (Creature*)m_owner;
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature %s (Entry %u) start MoveWaypoint()", m_owner->GetGuidStr().c_str(), m_owner->GetEntry()); DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s start MoveWaypoint()", m_owner->GetGuidStr().c_str());
Mutate(new WaypointMovementGenerator<Creature>(*creature)); WaypointMovementGenerator<Creature>* newWPMMgen = new WaypointMovementGenerator<Creature>(*creature);
Mutate(newWPMMgen);
newWPMMgen->InitializeWaypointPath(*creature, id, (WaypointPathOrigin)source, initialDelay, overwriteEntry);
} }
else else
{ {
@ -469,6 +473,16 @@ void MotionMaster::propagateSpeedChange()
} }
} }
bool MotionMaster::SetNextWaypoint(uint32 pointId)
{
for (Impl::container_type::reverse_iterator rItr = Impl::c.rbegin(); rItr != Impl::c.rend(); ++rItr)
{
if ((*rItr)->GetMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
return (static_cast<WaypointMovementGenerator<Creature>*>(*rItr))->SetNextWaypoint(pointId);
}
return false;
}
uint32 MotionMaster::getLastReachedWaypoint() const uint32 MotionMaster::getLastReachedWaypoint() const
{ {
for (Impl::container_type::const_reverse_iterator rItr = Impl::c.rbegin(); rItr != Impl::c.rend(); ++rItr) for (Impl::container_type::const_reverse_iterator rItr = Impl::c.rbegin(); rItr != Impl::c.rend(); ++rItr)
@ -487,6 +501,18 @@ MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const
return top()->GetMovementGeneratorType(); return top()->GetMovementGeneratorType();
} }
void MotionMaster::GetWaypointPathInformation(std::ostringstream& oss) const
{
for (Impl::container_type::const_reverse_iterator rItr = Impl::c.rbegin(); rItr != Impl::c.rend(); ++rItr)
{
if ((*rItr)->GetMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
{
static_cast<WaypointMovementGenerator<Creature>*>(*rItr)->GetPathInformation(oss);
return;
}
}
}
bool MotionMaster::GetDestination(float& x, float& y, float& z) bool MotionMaster::GetDestination(float& x, float& y, float& z)
{ {
if (m_owner->movespline->Finalized()) if (m_owner->movespline->Finalized())

View file

@ -55,6 +55,10 @@ enum MovementGeneratorType
TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h (alt.second part of flee for assistance) TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h (alt.second part of flee for assistance)
FOLLOW_MOTION_TYPE = 14, // TargetedMovementGenerator.h FOLLOW_MOTION_TYPE = 14, // TargetedMovementGenerator.h
EFFECT_MOTION_TYPE = 15, EFFECT_MOTION_TYPE = 15,
EXTERNAL_WAYPOINT_MOVE = 256, // Only used in CreatureAI::MovementInform when a waypoint is reached. The pathId >= 0 is added as additonal value
EXTERNAL_WAYPOINT_MOVE_START = 512, // Only used in CreatureAI::MovementInform when a waypoint is started. The pathId >= 0 is added as additional value
EXTERNAL_WAYPOINT_FINISHED_LAST = 1024, // Only used in CreatureAI::MovementInform when the waittime of the last wp is finished The pathId >= 0 is added as additional value
}; };
enum MMCleanFlag enum MMCleanFlag
@ -113,7 +117,7 @@ class MotionMaster : private std::stack<MovementGenerator*>
void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true); void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true);
void MoveSeekAssistance(float x, float y, float z); void MoveSeekAssistance(float x, float y, float z);
void MoveSeekAssistanceDistract(uint32 timer); void MoveSeekAssistanceDistract(uint32 timer);
void MoveWaypoint(); void MoveWaypoint(int32 id = 0, uint32 source = 0, uint32 initialDelay = 0, uint32 overwriteEntry = 0);
void MoveTaxiFlight(uint32 path, uint32 pathnode); void MoveTaxiFlight(uint32 path, uint32 pathnode);
void MoveDistract(uint32 timeLimit); void MoveDistract(uint32 timeLimit);
void MoveJump(float x, float y, float z, float horizontalSpeed, float max_height, uint32 id = 0); void MoveJump(float x, float y, float z, float horizontalSpeed, float max_height, uint32 id = 0);
@ -124,7 +128,9 @@ class MotionMaster : private std::stack<MovementGenerator*>
MovementGeneratorType GetCurrentMovementGeneratorType() const; MovementGeneratorType GetCurrentMovementGeneratorType() const;
void propagateSpeedChange(); void propagateSpeedChange();
bool SetNextWaypoint(uint32 pointId);
uint32 getLastReachedWaypoint() const; uint32 getLastReachedWaypoint() const;
void GetWaypointPathInformation(std::ostringstream& oss) const;
bool GetDestination(float& x, float& y, float& z); bool GetDestination(float& x, float& y, float& z);

View file

@ -77,6 +77,14 @@ void WaypointMovementGenerator<Creature>::Initialize(Creature& creature)
creature.clearUnitState(UNIT_STAT_WAYPOINT_PAUSED); creature.clearUnitState(UNIT_STAT_WAYPOINT_PAUSED);
} }
void WaypointMovementGenerator<Creature>::InitializeWaypointPath(Creature& u, int32 id, WaypointPathOrigin wpSource, uint32 initialDelay, uint32 overwriteEntry)
{
LoadPath(u, id, wpSource, overwriteEntry);
i_nextMoveTime.Reset(initialDelay);
// Start moving if possible
StartMove(u);
}
void WaypointMovementGenerator<Creature>::Finalize(Creature& creature) void WaypointMovementGenerator<Creature>::Finalize(Creature& creature)
{ {
creature.clearUnitState(UNIT_STAT_ROAMING | UNIT_STAT_ROAMING_MOVE); creature.clearUnitState(UNIT_STAT_ROAMING | UNIT_STAT_ROAMING_MOVE);
@ -156,6 +164,15 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
} }
// Inform script // Inform script
if (creature.AI())
{
uint32 type = WAYPOINT_MOTION_TYPE;
if (m_PathOrigin == PATH_FROM_EXTERNAL && m_pathId > 0)
type = EXTERNAL_WAYPOINT_MOVE + m_pathId;
creature.AI()->MovementInform(type, i_currentNode);
}
// Wait delay ms
Stop(node.delay); Stop(node.delay);
} }
@ -182,9 +199,25 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature& creature)
if (m_isArrivalDone) if (m_isArrivalDone)
{ {
bool reachedLast = false;
++currPoint; ++currPoint;
if (currPoint == i_path->end()) if (currPoint == i_path->end())
{
reachedLast = true;
currPoint = i_path->begin(); currPoint = i_path->begin();
}
// Inform AI
if (creature.AI() && m_PathOrigin == PATH_FROM_EXTERNAL && m_pathId > 0)
{
if (!reachedLast)
creature.AI()->MovementInform(EXTERNAL_WAYPOINT_MOVE_START + m_pathId, currPoint->first);
else
creature.AI()->MovementInform(EXTERNAL_WAYPOINT_FINISHED_LAST + m_pathId, currPoint->first);
if (creature.IsDead() || !creature.IsInWorld()) // Might have happened with above calls
return;
}
i_currentNode = currPoint->first; i_currentNode = currPoint->first;
} }
@ -238,6 +271,20 @@ bool WaypointMovementGenerator<Creature>::Update(Creature& creature, const uint3
return true; return true;
} }
bool WaypointMovementGenerator<Creature>::Stopped(Creature& u)
{
return !i_nextMoveTime.Passed() || u.hasUnitState(UNIT_STAT_WAYPOINT_PAUSED);
}
bool WaypointMovementGenerator<Creature>::CanMove(int32 diff, Creature& u)
{
i_nextMoveTime.Update(diff);
if (i_nextMoveTime.Passed() && u.hasUnitState(UNIT_STAT_WAYPOINT_PAUSED))
i_nextMoveTime.Reset(1);
return i_nextMoveTime.Passed() && !u.hasUnitState(UNIT_STAT_WAYPOINT_PAUSED);
}
bool WaypointMovementGenerator<Creature>::GetResetPosition(Creature&, float& x, float& y, float& z, float& o) const bool WaypointMovementGenerator<Creature>::GetResetPosition(Creature&, float& x, float& y, float& z, float& o) const
{ {
// prevent a crash at empty waypoint path. // prevent a crash at empty waypoint path.
@ -280,18 +327,10 @@ bool WaypointMovementGenerator<Creature>::GetResetPosition(Creature&, float& x,
return true; return true;
} }
bool WaypointMovementGenerator<Creature>::Stopped(Creature& u) void WaypointMovementGenerator<Creature>::GetPathInformation(std::ostringstream& oss) const
{ {
return !i_nextMoveTime.Passed() || u.hasUnitState(UNIT_STAT_WAYPOINT_PAUSED); oss << "WaypointMovement: Last Reached WP: " << m_lastReachedWaypoint << " ";
} oss << "(Loaded path " << m_pathId << " from " << WaypointManager::GetOriginString(m_PathOrigin) << ")\n";
bool WaypointMovementGenerator<Creature>::CanMove(int32 diff, Creature& u)
{
i_nextMoveTime.Update(diff);
if (i_nextMoveTime.Passed() && u.hasUnitState(UNIT_STAT_WAYPOINT_PAUSED))
i_nextMoveTime.Reset(1);
return i_nextMoveTime.Passed() && !u.hasUnitState(UNIT_STAT_WAYPOINT_PAUSED);
} }
void WaypointMovementGenerator<Creature>::AddToWaypointPauseTime(int32 waitTimeDiff) void WaypointMovementGenerator<Creature>::AddToWaypointPauseTime(int32 waitTimeDiff)
@ -304,6 +343,26 @@ void WaypointMovementGenerator<Creature>::AddToWaypointPauseTime(int32 waitTimeD
} }
} }
bool WaypointMovementGenerator<Creature>::SetNextWaypoint(uint32 pointId)
{
if (!i_path || i_path->empty())
return false;
WaypointPath::const_iterator currPoint = i_path->find(pointId);
if (currPoint == i_path->end())
return false;
// Allow Moving with next tick
// Handle allow movement this way to not interact with PAUSED state.
// If this function is called while PAUSED, it will move properly when unpaused.
i_nextMoveTime.Reset(1);
m_isArrivalDone = false;
// Set the point
i_currentNode = pointId;
return true;
}
//----------------------------------------------------// //----------------------------------------------------//
uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const
{ {

View file

@ -37,6 +37,8 @@
#include "ObjectGuid.h" #include "ObjectGuid.h"
#include "World.h" #include "World.h"
#include <mutex>
#include <cmath> #include <cmath>
#define CLASS_LOCK MaNGOS::ClassLevelLockable<ObjectAccessor, ACE_Thread_Mutex> #define CLASS_LOCK MaNGOS::ClassLevelLockable<ObjectAccessor, ACE_Thread_Mutex>

View file

@ -40,6 +40,8 @@
#include "Player.h" #include "Player.h"
#include "Corpse.h" #include "Corpse.h"
#include <mutex>
#include <set> #include <set>
#include <list> #include <list>

View file

@ -9568,7 +9568,7 @@ bool Unit::SelectHostileTarget()
// check if currently selected target is reachable // check if currently selected target is reachable
// NOTE: path alrteady generated from AttackStart() // NOTE: path alrteady generated from AttackStart()
if (!GetMotionMaster()->operator->()->IsReachable()) if (!GetMotionMaster()->GetCurrent()->IsReachable())
{ {
// remove all taunts // remove all taunts
RemoveSpellsCausingAura(SPELL_AURA_MOD_TAUNT); RemoveSpellsCausingAura(SPELL_AURA_MOD_TAUNT);

View file

@ -58,6 +58,8 @@
#include "Auth/HMACSHA1.h" #include "Auth/HMACSHA1.h"
#include "zlib.h" #include "zlib.h"
#include <mutex>
// select opcodes appropriate for processing in Map::Update context for current session state // select opcodes appropriate for processing in Map::Update context for current session state
static bool MapSessionFilterHelper(WorldSession* session, OpcodeHandler const& opHandle) static bool MapSessionFilterHelper(WorldSession* session, OpcodeHandler const& opHandle)
{ {

View file

@ -37,6 +37,8 @@
#include "Item.h" #include "Item.h"
#include "LFGMgr.h" #include "LFGMgr.h"
#include <mutex>
struct ItemPrototype; struct ItemPrototype;
struct AuctionEntry; struct AuctionEntry;
struct AuctionHouseEntry; struct AuctionHouseEntry;

View file

@ -742,7 +742,6 @@ ChatCommand* ChatHandler::getCommandTable()
{ "add", SEC_GAMEMASTER, false, &ChatHandler::HandleWpAddCommand, "", NULL }, { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleWpAddCommand, "", NULL },
{ "modify", SEC_GAMEMASTER, false, &ChatHandler::HandleWpModifyCommand, "", NULL }, { "modify", SEC_GAMEMASTER, false, &ChatHandler::HandleWpModifyCommand, "", NULL },
{ "export", SEC_ADMINISTRATOR, false, &ChatHandler::HandleWpExportCommand, "", NULL }, { "export", SEC_ADMINISTRATOR, false, &ChatHandler::HandleWpExportCommand, "", NULL },
{ "import", SEC_ADMINISTRATOR, false, &ChatHandler::HandleWpImportCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL } { NULL, 0, false, NULL, "", NULL }
}; };

View file

@ -566,7 +566,6 @@ class ChatHandler
bool HandleWpModifyCommand(char* args); bool HandleWpModifyCommand(char* args);
bool HandleWpShowCommand(char* args); bool HandleWpShowCommand(char* args);
bool HandleWpExportCommand(char* args); bool HandleWpExportCommand(char* args);
bool HandleWpImportCommand(char* args);
bool HandleHelpCommand(char* args); bool HandleHelpCommand(char* args);
bool HandleCommandsCommand(char* args); bool HandleCommandsCommand(char* args);

View file

@ -30,6 +30,8 @@
#include "Platform/Define.h" #include "Platform/Define.h"
#include "Policies/Singleton.h" #include "Policies/Singleton.h"
#include <mutex>
#define max_ge_check_delay 86400 // 1 day in seconds #define max_ge_check_delay 86400 // 1 day in seconds
class Creature; class Creature;

View file

@ -36,6 +36,8 @@
#include "Policies/Singleton.h" #include "Policies/Singleton.h"
#include "Util.h" #include "Util.h"
#include <mutex>
char const* MAP_MAGIC = "MAPS"; char const* MAP_MAGIC = "MAPS";
char const* MAP_VERSION_MAGIC = "c1.4"; char const* MAP_VERSION_MAGIC = "c1.4";
char const* MAP_AREA_MAGIC = "AREA"; char const* MAP_AREA_MAGIC = "AREA";

View file

@ -35,6 +35,8 @@
#include <bitset> #include <bitset>
#include <list> #include <list>
#include <mutex>
class Creature; class Creature;
class Unit; class Unit;
class WorldPacket; class WorldPacket;

View file

@ -38,6 +38,8 @@
#include "ObjectGuid.h" #include "ObjectGuid.h"
#include "PoolManager.h" #include "PoolManager.h"
#include <mutex>
struct InstanceTemplate; struct InstanceTemplate;
struct MapEntry; struct MapEntry;
struct MapDifficultyEntry; struct MapDifficultyEntry;

View file

@ -779,8 +779,8 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data)
if (BattleGround* bg = player->GetBattleGround()) if (BattleGround* bg = player->GetBattleGround())
{ {
bg->HandleAreaTrigger(player, Trigger_ID); if (bg->HandleAreaTrigger(player, Trigger_ID))
return; return;
} }
else if (OutdoorPvP* outdoorPvP = sOutdoorPvPMgr.GetScript(player->GetCachedZoneId())) else if (OutdoorPvP* outdoorPvP = sOutdoorPvPMgr.GetScript(player->GetCachedZoneId()))
{ {

View file

@ -2852,6 +2852,11 @@ uint32 GetScriptIdsCount()
return sScriptMgr.GetScriptIdsCount(); return sScriptMgr.GetScriptIdsCount();
} }
void SetExternalWaypointTable(char const* tableName)
{
sWaypointMgr.SetExternalWPTable(tableName);
}
bool AddWaypointFromExternal(uint32 entry, int32 pathId, uint32 pointId, float x, float y, float z, float o, uint32 waittime) bool AddWaypointFromExternal(uint32 entry, int32 pathId, uint32 pointId, float x, float y, float z, float o, uint32 waittime)
{ {
return sWaypointMgr.AddExternalNode(entry, pathId, pointId, x, y, z, o, waittime); return sWaypointMgr.AddExternalNode(entry, pathId, pointId, x, y, z, o, waittime);

View file

@ -29,7 +29,8 @@
#include "Policies/Singleton.h" #include "Policies/Singleton.h"
#include "ObjectGuid.h" #include "ObjectGuid.h"
#include "DBCEnums.h" #include "DBCEnums.h"
#include <ace/Atomic_Op.h> //#include <ace/Atomic_Op.h> <- delete this if the #include below works
#include <atomic>
struct AreaTriggerEntry; struct AreaTriggerEntry;
struct SpellEntry; struct SpellEntry;
@ -614,6 +615,9 @@ class ScriptMgr
void LoadEventIdScripts(); void LoadEventIdScripts();
void LoadSpellIdScripts(); void LoadSpellIdScripts();
uint32 GetAreaTriggerScriptId(uint32 triggerId) const;
uint32 GetEventIdScriptId(uint32 eventId) const;
bool ReloadScriptBinding(); bool ReloadScriptBinding();
const char* GetScriptName(uint32 id) const const char* GetScriptName(uint32 id) const
@ -707,6 +711,14 @@ bool StartEvents_Event(Map* map, uint32 id, Object* source, Object* target, bool
#define sScriptMgr MaNGOS::Singleton<ScriptMgr>::Instance() #define sScriptMgr MaNGOS::Singleton<ScriptMgr>::Instance()
MANGOS_DLL_SPEC uint32 GetAreaTriggerScriptId(uint32 triggerId);
MANGOS_DLL_SPEC uint32 GetEventIdScriptId(uint32 eventId);
MANGOS_DLL_SPEC uint32 GetScriptId(const char* name);
MANGOS_DLL_SPEC char const* GetScriptName(uint32 id);
MANGOS_DLL_SPEC uint32 GetScriptIdsCount();
MANGOS_DLL_SPEC void SetExternalWaypointTable(char const* tableName);
MANGOS_DLL_SPEC bool AddWaypointFromExternal(uint32 entry, int32 pathId, uint32 pointId, float x, float y, float z, float o, uint32 waittime);
uint32 GetScriptId(const char* name); uint32 GetScriptId(const char* name);
char const* GetScriptName(uint32 id); char const* GetScriptName(uint32 id);
uint32 GetScriptIdsCount(); uint32 GetScriptIdsCount();

View file

@ -112,6 +112,7 @@ void WaypointManager::Load()
{ {
barRow.step(); barRow.step();
Field* fields = result->Fetch(); Field* fields = result->Fetch();
uint32 id = fields[0].GetUInt32(); uint32 id = fields[0].GetUInt32();
uint32 point = fields[1].GetUInt32(); uint32 point = fields[1].GetUInt32();
@ -126,7 +127,7 @@ void WaypointManager::Load()
if (cData->movementType != WAYPOINT_MOTION_TYPE) if (cData->movementType != WAYPOINT_MOTION_TYPE)
creatureNoMoveType.insert(id); creatureNoMoveType.insert(id);
WaypointPath& path = m_pathMap[id]; WaypointPath& path = m_pathTemplateMap[id << 8];
WaypointNode& node = path[point]; WaypointNode& node = path[point];
node.x = fields[2].GetFloat(); node.x = fields[2].GetFloat();
@ -391,12 +392,16 @@ void WaypointManager::Load()
void WaypointManager::Unload() void WaypointManager::Unload()
{ {
for (WaypointPathMap::iterator itr = m_pathMap.begin(); itr != m_pathMap.end(); ++itr) for (WaypointPathMap::iterator itr = m_pathMap.begin(); itr != m_pathMap.end(); ++itr)
_clearPath(itr->second); { _clearPath(itr->second); }
m_pathMap.clear(); m_pathMap.clear();
for (WaypointPathMap::iterator itr = m_pathTemplateMap.begin(); itr != m_pathTemplateMap.end(); ++itr) for (WaypointPathMap::iterator itr = m_pathTemplateMap.begin(); itr != m_pathTemplateMap.end(); ++itr)
_clearPath(itr->second); { _clearPath(itr->second); }
m_pathTemplateMap.clear(); m_pathTemplateMap.clear();
for (WaypointPathMap::iterator itr = m_externalPathTemplateMap.begin(); itr != m_externalPathTemplateMap.end(); ++itr)
{ _clearPath(itr->second); }
m_externalPathTemplateMap.clear();
} }
void WaypointManager::_clearPath(WaypointPath& path) void WaypointManager::_clearPath(WaypointPath& path)

View file

@ -110,8 +110,8 @@ class WaypointManager
// Helper function to get a path provided the required information // Helper function to get a path provided the required information
WaypointPath* GetPathFromOrigin(uint32 entry, uint32 lowGuid, int32 pathId, WaypointPathOrigin wpOrigin) WaypointPath* GetPathFromOrigin(uint32 entry, uint32 lowGuid, int32 pathId, WaypointPathOrigin wpOrigin)
{ {
WaypointPathMap* wpMap = NULL; WaypointPathMap* wpMap;
uint32 key = 0; uint32 key;
switch (wpOrigin) switch (wpOrigin)
{ {
@ -121,19 +121,19 @@ class WaypointManager
break; break;
case PATH_FROM_ENTRY: case PATH_FROM_ENTRY:
if (pathId >= 0xFF || pathId < 0) if (pathId >= 0xFF || pathId < 0)
return NULL; return nullptr;
key = (entry << 8) + pathId; key = (entry << 8) + pathId;
wpMap = &m_pathTemplateMap; wpMap = &m_pathTemplateMap;
break; break;
case PATH_FROM_EXTERNAL: case PATH_FROM_EXTERNAL:
if (pathId >= 0xFF || pathId < 0) if (pathId >= 0xFF || pathId < 0)
return NULL; return nullptr;
key = (entry << 8) + pathId; key = (entry << 8) + pathId;
wpMap = &m_externalPathTemplateMap; wpMap = &m_externalPathTemplateMap;
break; break;
case PATH_NO_PATH: case PATH_NO_PATH:
default: default:
return NULL; return nullptr;
} }
WaypointPathMap::iterator find = wpMap->find(key); WaypointPathMap::iterator find = wpMap->find(key);
return find != wpMap->end() ? &find->second : NULL; return find != wpMap->end() ? &find->second : NULL;
@ -197,6 +197,6 @@ class WaypointManager
#define sWaypointMgr MaNGOS::Singleton<WaypointManager>::Instance() #define sWaypointMgr MaNGOS::Singleton<WaypointManager>::Instance()
/// Accessor for Scripting library /// Accessor for Scripting library
MANGOS_DLL_SPEC bool AddWaypointFromExternal(uint32 entry, int32 pathId, uint32 pointId, float x, float y, float z, float o, uint32 waittime); bool AddWaypointFromExternal(uint32 entry, int32 pathId, uint32 pointId, float x, float y, float z, float o, uint32 waittime);
#endif #endif

View file

@ -32,6 +32,8 @@
#include <iomanip> #include <iomanip>
#include <limits> #include <limits>
#include <unordered_map>
using G3D::Vector3; using G3D::Vector3;
namespace VMAP namespace VMAP

View file

@ -30,6 +30,8 @@
#include "Platform/Define.h" #include "Platform/Define.h"
#include <G3D/Vector3.h> #include <G3D/Vector3.h>
#include <unordered_map>
//=========================================================== //===========================================================
#define MAP_FILENAME_EXTENSION2 ".vmtree" #define MAP_FILENAME_EXTENSION2 ".vmtree"

View file

@ -367,7 +367,12 @@ enum
SAY_AT_CLOSE = -1000326, SAY_AT_CLOSE = -1000326,
QUEST_GYROMAST_REV = 2078, QUEST_GYROMAST_REV = 2078,
NPC_GELKAK = 6667, NPC_GELKAK = 6667,
FACTION_HOSTILE = 14 FACTION_HOSTILE = 14,
TEXT_ID_THRESH_DEFAULT = 718,
TEXT_ID_KEY_READY = 758,
GOSSIP_ITEM_TURN_KEY = -3000115,
}; };
#define GOSSIP_ITEM_INSERT_KEY "[PH] Insert key" #define GOSSIP_ITEM_INSERT_KEY "[PH] Insert key"
@ -416,10 +421,12 @@ struct npc_threshwackonator : public CreatureScript
{ {
if (pPlayer->GetQuestStatus(QUEST_GYROMAST_REV) == QUEST_STATUS_INCOMPLETE) if (pPlayer->GetQuestStatus(QUEST_GYROMAST_REV) == QUEST_STATUS_INCOMPLETE)
{ {
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_INSERT_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TURN_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
pPlayer->SEND_GOSSIP_MENU(TEXT_ID_KEY_READY, pCreature->GetObjectGuid());
} }
else
pPlayer->SEND_GOSSIP_MENU(TEXT_ID_THRESH_DEFAULT, pCreature->GetObjectGuid());
pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid());
return true; return true;
} }

View file

@ -33,6 +33,7 @@ npc_captured_beryl_sorcerer
npc_nexus_drake_hatchling npc_nexus_drake_hatchling
npc_scourged_flamespitter npc_scourged_flamespitter
npc_bonker_togglevolt npc_bonker_togglevolt
npc_jenny
EndContentData */ EndContentData */
#include "precompiled.h" #include "precompiled.h"
@ -1128,6 +1129,119 @@ struct npc_bonker_togglevolt : public CreatureScript
} }
}; };
/*######
## npc_jenny
######*/
enum
{
SPELL_CREATES_CARRIED = 46340,
SPELL_DROP_CRATE = 46342,
SPELL_JENNY_CREDIT = 46358,
NPC_FEZZIX = 25849,
QUEST_ID_LOADER_UP = 11881,
};
struct npc_jenny : public CreatureScript
{
npc_jenny() : CreatureScript("npc_jenny") {}
struct npc_jennyAI : public FollowerAI
{
npc_jennyAI(Creature* pCreature) : FollowerAI(pCreature)
{
m_bFollowStarted = false;
m_bEventComplete = false;
Reset();
}
bool m_bEventComplete;
bool m_bFollowStarted;
uint32 m_uiDropDelayTimer;
void Reset() override
{
m_uiDropDelayTimer = 0;
}
void AttackedBy(Unit* pAttacker) override
{
if (!m_uiDropDelayTimer)
{
if (DoCastSpellIfCan(m_creature, SPELL_DROP_CRATE) == CAST_OK)
{
m_creature->RemoveAuraHolderFromStack(SPELL_CREATES_CARRIED);
m_uiDropDelayTimer = 10000;
// check if all crates are dropped
if (!m_creature->HasAura(SPELL_CREATES_CARRIED))
{
FollowerAI::JustDied(pAttacker);
m_creature->ForcedDespawn();
}
}
}
}
void AttackStart(Unit* pWho) override { }
void MoveInLineOfSight(Unit* pWho) override
{
if (m_bEventComplete)
return;
if (pWho->GetEntry() == NPC_FEZZIX && m_creature->IsWithinDistInMap(pWho, 10.0f))
{
if (DoCastSpellIfCan(m_creature, SPELL_JENNY_CREDIT) == CAST_OK)
{
SetFollowComplete(true);
float fX, fY, fZ;
pWho->GetContactPoint(m_creature, fX, fY, fZ);
m_creature->GetMotionMaster()->MovePoint(0, fX, fY, fZ);
m_creature->ForcedDespawn(15000);
m_bEventComplete = true;
}
}
}
void UpdateFollowerAI(const uint32 uiDiff)
{
if (!m_bFollowStarted)
{
if (Player* pSummoner = m_creature->GetCharmerOrOwnerPlayerOrPlayerItself())
{
StartFollow(pSummoner, pSummoner->getFaction(), GetQuestTemplateStore(QUEST_ID_LOADER_UP));
if (DoCastSpellIfCan(m_creature, SPELL_CREATES_CARRIED) == CAST_OK)
m_bFollowStarted = true;
}
}
if (m_uiDropDelayTimer)
{
if (m_uiDropDelayTimer <= uiDiff)
m_uiDropDelayTimer = 0;
else
m_uiDropDelayTimer -= uiDiff;
}
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
return;
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new npc_jennyAI(pCreature);
}
};
void AddSC_borean_tundra() void AddSC_borean_tundra()
{ {
Script* s; Script* s;
@ -1146,6 +1260,8 @@ void AddSC_borean_tundra()
s->RegisterSelf(); s->RegisterSelf();
s = new npc_bonker_togglevolt(); s = new npc_bonker_togglevolt();
s->RegisterSelf(); s->RegisterSelf();
s = new npc_jenny();
s->RegisterSelf();
s = new spell_throw_wolf_batt(); s = new spell_throw_wolf_batt();
s->RegisterSelf(); s->RegisterSelf();

View file

@ -88,6 +88,7 @@
#include <queue> #include <queue>
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#include <unordered_map>
#include "Utilities/Errors.h" #include "Utilities/Errors.h"
#include "LockedQueue/LockedQueue.h" #include "LockedQueue/LockedQueue.h"

View file

@ -24,6 +24,11 @@
#include "Config.h" #include "Config.h"
#include <ace/Configuration_Import_Export.h> #include <ace/Configuration_Import_Export.h>
#include <mutex>
#include <unordered_map>
#include <string>
#include <fstream>
#include "Policies/Singleton.h" #include "Policies/Singleton.h"

View file

@ -28,6 +28,10 @@
#include "Common/Common.h" #include "Common/Common.h"
#include <Policies/Singleton.h> #include <Policies/Singleton.h>
#include "Platform/Define.h" #include "Platform/Define.h"
#include <mutex>
#include <string>
#include <unordered_map>
class ACE_Configuration_Heap; class ACE_Configuration_Heap;

View file

@ -29,6 +29,8 @@
#include "LockedQueue/LockedQueue.h" #include "LockedQueue/LockedQueue.h"
#include "Threading/Threading.h" #include "Threading/Threading.h"
#include <mutex>
class Database; class Database;
class SqlOperation; class SqlOperation;
class SqlConnection; class SqlConnection;

View file

@ -32,6 +32,8 @@
#include <queue> #include <queue>
#include "Utilities/Callback.h" #include "Utilities/Callback.h"
#include <mutex>
/// ---- BASE --- /// ---- BASE ---
class Database; class Database;

View file

@ -28,6 +28,8 @@
#include "Common/Common.h" #include "Common/Common.h"
#include "Policies/Singleton.h" #include "Policies/Singleton.h"
#include <mutex>
class Config; class Config;
class ByteBuffer; class ByteBuffer;

View file

@ -67,23 +67,11 @@ else()
target_link_libraries(${EXECUTABLE_NAME} ACE) target_link_libraries(${EXECUTABLE_NAME} ACE)
endif() endif()
target_link_libraries(${EXECUTABLE_NAME} g3dlite vmap detour recast zlib shared)
set(EXECUTABLE_LINK_FLAGS "")
if(UNIX) if(UNIX)
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") target_link_libraries(${EXECUTABLE_NAME} rt)
set(EXECUTABLE_LINK_FLAGS "-Wl,--no-as-needed -lrt -pthread ${EXECUTABLE_LINK_FLAGS}")
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
set(EXECUTABLE_LINK_FLAGS "-Wl,--no-as-needed -ldl -pthread -lrt ${EXECUTABLE_LINK_FLAGS}")
endif()
endif() endif()
if(APPLE) target_link_libraries(${EXECUTABLE_NAME} g3dlite vmap detour recast zlib shared)
set(EXECUTABLE_LINK_FLAGS "-framework CoreServices ${EXECUTABLE_LINK_FLAGS}")
endif()
set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS "${EXECUTABLE_LINK_FLAGS}")
#Output the compiled exes to build/bin/$(Configuration)/tools directory on windows by default #Output the compiled exes to build/bin/$(Configuration)/tools directory on windows by default
if(WIN32) if(WIN32)

View file

@ -47,22 +47,20 @@ else()
target_link_libraries(${EXECUTABLE_NAME} ACE) target_link_libraries(${EXECUTABLE_NAME} ACE)
endif() endif()
if(UNIX)
target_link_libraries(${EXECUTABLE_NAME} rt dl)
endif()
target_link_libraries(${EXECUTABLE_NAME} vmap g3dlite zlib) target_link_libraries(${EXECUTABLE_NAME} vmap g3dlite zlib)
set(EXECUTABLE_LINK_FLAGS "") set(EXECUTABLE_LINK_FLAGS "")
if(UNIX) if(UNIX)
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") if(CMAKE_C_COMPILER MATCHES "clang" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
set(EXECUTABLE_LINK_FLAGS "-Wl,--no-as-needed -lrt -pthread ${EXECUTABLE_LINK_FLAGS}") set(EXECUTABLE_LINK_FLAGS "-pthread${EXECUTABLE_LINK_FLAGS}")
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
set(EXECUTABLE_LINK_FLAGS "-Wl,--no-as-needed -ldl -pthread -lrt ${EXECUTABLE_LINK_FLAGS}")
endif() endif()
endif() endif()
if(APPLE)
set(EXECUTABLE_LINK_FLAGS "-framework CoreServices ${EXECUTABLE_LINK_FLAGS}")
endif()
set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS "${EXECUTABLE_LINK_FLAGS}") set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS "${EXECUTABLE_LINK_FLAGS}")
#Output the compiled exes to build/bin/$(Configuration)/tools directory on windows by default #Output the compiled exes to build/bin/$(Configuration)/tools directory on windows by default