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 */
// 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
virtual void HandleKillPlayer(Player* player, 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)
{
@ -199,19 +199,10 @@ void BattleGroundAB::HandleAreaTrigger(Player* source, uint32 trigger)
else
source->LeaveBattleground();
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:
// sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", trigger);
// source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", trigger);
break;
return false;
}
return true;
}
/* type: 0-neutral, 1-contested, 3-occupied

View file

@ -173,7 +173,7 @@ class BattleGroundAB : public BattleGround
void AddPlayer(Player* plr) override;
virtual void StartingEventOpenDoors() 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;
void EndBattleGround(Team winner) override;
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player) override;

View file

@ -350,7 +350,7 @@ void BattleGroundAV::EndBattleGround(Team 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.
switch (trigger)
@ -368,19 +368,10 @@ void BattleGroundAV::HandleAreaTrigger(Player* source, uint32 trigger)
else
source->LeaveBattleground();
break;
case 3326:
case 3327:
case 3328:
case 3329:
case 3330:
case 3331:
// source->Unmount();
break;
default:
DEBUG_LOG("BattleGroundAV: WARNING: Unhandled AreaTrigger in Battleground: %u", trigger);
// source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", trigger);
break;
return false;
}
return true;
}
void BattleGroundAV::UpdatePlayerScore(Player* source, uint32 type, uint32 value)

View file

@ -339,8 +339,8 @@ class BattleGroundAV : public BattleGround
virtual void StartingEventOpenDoors() override;
// world states
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;
/*general stuff*/

View file

@ -96,32 +96,6 @@ bool BattleGroundBE::HandlePlayerUnderMap(Player* player)
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)
{
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
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;
void RemovePlayer(Player* plr, ObjectGuid guid) override;
void HandleAreaTrigger(Player* source, uint32 trigger) override;
virtual void FillInitialWorldStates(WorldPacket& d, uint32& count) override;
void HandleKillPlayer(Player* player, Player* killer) 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;
}
void BattleGroundEY::HandleAreaTrigger(Player* source, uint32 trigger)
bool BattleGroundEY::HandleAreaTrigger(Player* source, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
return false;
if (!source->IsAlive()) // hack code, must be removed later
return;
return false;
switch (trigger)
{
@ -324,7 +324,10 @@ void BattleGroundEY::HandleAreaTrigger(Player* source, uint32 trigger)
if (m_towerOwner[NODE_DRAENEI_RUINS] == source->GetTeam())
EventPlayerCapturedFlag(source, NODE_DRAENEI_RUINS);
break;
default:
return false;
}
return true;
}
void BattleGroundEY::Reset()

View file

@ -264,7 +264,7 @@ class BattleGroundEY : public BattleGround
void RemovePlayer(Player* plr, ObjectGuid guid) override;
bool HandleEvent(uint32 eventId, 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;
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player) override;

View file

@ -33,6 +33,8 @@
#include "BattleGround.h"
#include "ace/Recursive_Thread_Mutex.h"
#include <mutex>
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

View file

@ -97,41 +97,9 @@ bool BattleGroundNA::HandlePlayerUnderMap(Player* player)
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)
{
FillInitialWorldState(data, count, 0xa0f, GetAlivePlayersCountByTeam(ALLIANCE));
FillInitialWorldState(data, count, 0xa10, GetAlivePlayersCountByTeam(HORDE));
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;
void RemovePlayer(Player* plr, ObjectGuid guid) override;
void HandleAreaTrigger(Player* source, uint32 trigger) override;
virtual void FillInitialWorldStates(WorldPacket& d, uint32& count) override;
void HandleKillPlayer(Player* player, Player* killer) override;
bool HandlePlayerUnderMap(Player* plr) override;

View file

@ -96,42 +96,9 @@ bool BattleGroundRL::HandlePlayerUnderMap(Player* player)
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)
{
FillInitialWorldState(data, count, 0xbb8, GetAlivePlayersCountByTeam(ALLIANCE));
FillInitialWorldState(data, count, 0xbb9, GetAlivePlayersCountByTeam(HORDE));
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;
void RemovePlayer(Player* plr, ObjectGuid guid) override;
void HandleAreaTrigger(Player* source, uint32 trigger) override;
void HandleKillPlayer(Player* player, Player* killer) 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]);
}
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.
if (GetStatus() != STATUS_IN_PROGRESS)
return;
return false;
// uint32 SpellId = 0;
// uint64 buff_guid = 0;
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
if (m_FlagState[TEAM_INDEX_HORDE] && !m_FlagState[TEAM_INDEX_ALLIANCE])
if (GetHordeFlagCarrierGuid() == source->GetObjectGuid())
@ -510,16 +501,10 @@ void BattleGroundWS::HandleAreaTrigger(Player* source, uint32 trigger)
if (GetAllianceFlagCarrierGuid() == source->GetObjectGuid())
EventPlayerCapturedFlag(source);
break;
case 3649: // unk1
case 3688: // unk2
case 4628: // unk3
case 4629: // unk4
break;
default:
sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", trigger);
source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", trigger);
break;
return false;
}
return true;
}
void BattleGroundWS::Reset()

View file

@ -139,7 +139,7 @@ class BattleGroundWS : public BattleGround
virtual void EventPlayerCapturedFlag(Player* source) 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;
virtual void Reset() 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?
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;
WaypointPathOrigin wpSource = PATH_NO_PATH;
int32 wpPathId = 0;
@ -3393,8 +3393,8 @@ bool ChatHandler::HandleWpShowCommand(char* args)
}
}
Creature* wpOwner = NULL; ///< Npc that is moving
TemporarySummonWaypoint* wpTarget = NULL; // Define here for wp-info command
Creature* wpOwner; ///< Npc that is moving
TemporarySummonWaypoint* wpTarget = nullptr; // Define here for wp-info command
// Show info for the selected waypoint (Step one: get moving npc)
if (subCmd == "info")
@ -3431,7 +3431,7 @@ bool ChatHandler::HandleWpShowCommand(char* args)
wpOwner = targetCreature;
// Get the path
WaypointPath* wpPath = NULL;
WaypointPath* wpPath = nullptr;
if (wpOrigin != PATH_NO_PATH) // Might have been provided by param
wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin);
else
@ -3538,65 +3538,112 @@ bool ChatHandler::HandleWpShowCommand(char* args)
return false;
}
/// [Guid if no selected unit] <filename> [pathId [wpOrigin] ]
bool ChatHandler::HandleWpExportCommand(char* args)
{
if (!*args)
return false;
// Next arg is: <GUID> <ARGUMENT>
Creature* wpOwner;
WaypointPathOrigin wpOrigin = PATH_NO_PATH;
int32 wpPathId = 0;
// 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;
Creature* target = getSelectedCreature();
char* arg_str = NULL;
if (target)
if (Creature* targetCreature = getSelectedCreature())
{
if (target->GetEntry() != VISUAL_WAYPOINT)
lowguid = target->GetGUIDLow();
else
// Check if the user did specify a visual waypoint
if (targetCreature->GetEntry() == VISUAL_WAYPOINT && targetCreature->GetSubtype() == CREATURE_SUBTYPE_TEMPORARY_SUMMON)
{
QueryResult* result = WorldDatabase.PQuery("SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow());
if (!result)
TemporarySummonWaypoint* wpTarget = dynamic_cast<TemporarySummonWaypoint*>(targetCreature);
if (!wpTarget)
{
PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
return true;
PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
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
{
// user provided <GUID>
char* guid_str = strtok(args, " ");
if (!guid_str)
uint32 dbGuid;
if (!ExtractUInt32(&args, dbGuid))
{
SendSysMessage(LANG_WAYPOINT_NOGUID);
PSendSysMessage(LANG_WAYPOINT_NOGUID);
SetSentErrorMessage(true);
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");
SetSentErrorMessage(true);
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(
// 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 (wpOrigin == PATH_NO_PATH)
{
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);
SetSentErrorMessage(true);
@ -3604,51 +3651,44 @@ bool ChatHandler::HandleWpExportCommand(char* args)
}
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();
outfile << "INSERT INTO creature_movement ";
outfile << "(id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5) VALUES ";
outfile << "( ";
outfile << fields[15].GetUInt32(); // id
outfile << ", ";
outfile << fields[0].GetUInt32(); // point
outfile << ", ";
outfile << fields[1].GetFloat(); // position_x
outfile << ", ";
outfile << fields[2].GetFloat(); // position_y
outfile << ", ";
outfile << fields[3].GetUInt32(); // position_z
outfile << ", ";
outfile << fields[4].GetUInt32(); // orientation
outfile << ", ";
outfile << fields[5].GetUInt32(); // model1
outfile << ", ";
outfile << fields[6].GetUInt32(); // model2
outfile << ", ";
outfile << fields[7].GetUInt16(); // waittime
outfile << ", ";
outfile << fields[8].GetUInt32(); // emote
outfile << ", ";
outfile << fields[9].GetUInt32(); // spell
outfile << ", ";
outfile << fields[10].GetUInt32(); // textid1
outfile << ", ";
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 ";
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;
case PATH_FROM_EXTERNAL: key = wpOwner->GetEntry(); key_field = "entry"; table = sWaypointMgr.GetExternalWPTable(); break;
case PATH_NO_PATH:
return false;
}
outfile << "DELETE FROM " << table << " WHERE " << key_field << "=" << key << ";\n";
if (wpOrigin != PATH_FROM_EXTERNAL)
outfile << "INSERT INTO " << table << " (" << key_field << ", point, position_x, position_y, position_z, orientation, waittime, script_id) VALUES\n";
else
outfile << "INSERT INTO " << table << " (" << key_field << ", point, position_x, position_y, position_z, orientation, waittime) VALUES\n";
WaypointPath::const_iterator itr = wpPath->begin();
uint32 countDown = wpPath->size();
for (; itr != wpPath->end(); ++itr, --countDown)
{
outfile << "(" << key << ",";
outfile << itr->first << ",";
outfile << itr->second.x << ",";
outfile << itr->second.y << ",";
outfile << itr->second.z << ",";
outfile << itr->second.orientation << ",";
outfile << itr->second.delay << ",";
if (wpOrigin != PATH_FROM_EXTERNAL) // Only for normal waypoints
outfile << itr->second.script_id << ")";
if (countDown > 1)
outfile << ",\n";
else
outfile << ";\n";
}
while (result->NextRow());
delete result;
PSendSysMessage(LANG_WAYPOINT_EXPORTED);
outfile.close();
@ -3656,33 +3696,6 @@ bool ChatHandler::HandleWpExportCommand(char* args)
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
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))
{
MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)m_owner);
push(movement == NULL ? &si_idleMovement : movement);
push(movement == nullptr ? &si_idleMovement : movement);
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
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 (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;
}
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());
Mutate(new WaypointMovementGenerator<Creature>(*creature));
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s start MoveWaypoint()", m_owner->GetGuidStr().c_str());
WaypointMovementGenerator<Creature>* newWPMMgen = new WaypointMovementGenerator<Creature>(*creature);
Mutate(newWPMMgen);
newWPMMgen->InitializeWaypointPath(*creature, id, (WaypointPathOrigin)source, initialDelay, overwriteEntry);
}
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
{
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();
}
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)
{
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)
FOLLOW_MOTION_TYPE = 14, // TargetedMovementGenerator.h
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
@ -113,7 +117,7 @@ class MotionMaster : private std::stack<MovementGenerator*>
void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true);
void MoveSeekAssistance(float x, float y, float z);
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 MoveDistract(uint32 timeLimit);
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;
void propagateSpeedChange();
bool SetNextWaypoint(uint32 pointId);
uint32 getLastReachedWaypoint() const;
void GetWaypointPathInformation(std::ostringstream& oss) const;
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);
}
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)
{
creature.clearUnitState(UNIT_STAT_ROAMING | UNIT_STAT_ROAMING_MOVE);
@ -156,6 +164,15 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
}
// 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);
}
@ -182,9 +199,25 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature& creature)
if (m_isArrivalDone)
{
bool reachedLast = false;
++currPoint;
if (currPoint == i_path->end())
{
reachedLast = true;
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;
}
@ -238,6 +271,20 @@ bool WaypointMovementGenerator<Creature>::Update(Creature& creature, const uint3
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
{
// prevent a crash at empty waypoint path.
@ -280,18 +327,10 @@ bool WaypointMovementGenerator<Creature>::GetResetPosition(Creature&, float& x,
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);
}
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);
oss << "WaypointMovement: Last Reached WP: " << m_lastReachedWaypoint << " ";
oss << "(Loaded path " << m_pathId << " from " << WaypointManager::GetOriginString(m_PathOrigin) << ")\n";
}
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
{

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2852,6 +2852,11 @@ uint32 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)
{
return sWaypointMgr.AddExternalNode(entry, pathId, pointId, x, y, z, o, waittime);

View file

@ -29,7 +29,8 @@
#include "Policies/Singleton.h"
#include "ObjectGuid.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 SpellEntry;
@ -614,6 +615,9 @@ class ScriptMgr
void LoadEventIdScripts();
void LoadSpellIdScripts();
uint32 GetAreaTriggerScriptId(uint32 triggerId) const;
uint32 GetEventIdScriptId(uint32 eventId) const;
bool ReloadScriptBinding();
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()
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);
char const* GetScriptName(uint32 id);
uint32 GetScriptIdsCount();

View file

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

View file

@ -110,8 +110,8 @@ class WaypointManager
// Helper function to get a path provided the required information
WaypointPath* GetPathFromOrigin(uint32 entry, uint32 lowGuid, int32 pathId, WaypointPathOrigin wpOrigin)
{
WaypointPathMap* wpMap = NULL;
uint32 key = 0;
WaypointPathMap* wpMap;
uint32 key;
switch (wpOrigin)
{
@ -121,19 +121,19 @@ class WaypointManager
break;
case PATH_FROM_ENTRY:
if (pathId >= 0xFF || pathId < 0)
return NULL;
return nullptr;
key = (entry << 8) + pathId;
wpMap = &m_pathTemplateMap;
break;
case PATH_FROM_EXTERNAL:
if (pathId >= 0xFF || pathId < 0)
return NULL;
return nullptr;
key = (entry << 8) + pathId;
wpMap = &m_externalPathTemplateMap;
break;
case PATH_NO_PATH:
default:
return NULL;
return nullptr;
}
WaypointPathMap::iterator find = wpMap->find(key);
return find != wpMap->end() ? &find->second : NULL;
@ -197,6 +197,6 @@ class WaypointManager
#define sWaypointMgr MaNGOS::Singleton<WaypointManager>::Instance()
/// 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

View file

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

View file

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

View file

@ -367,7 +367,12 @@ enum
SAY_AT_CLOSE = -1000326,
QUEST_GYROMAST_REV = 2078,
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"
@ -416,10 +421,12 @@ struct npc_threshwackonator : public CreatureScript
{
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;
}

View file

@ -33,6 +33,7 @@ npc_captured_beryl_sorcerer
npc_nexus_drake_hatchling
npc_scourged_flamespitter
npc_bonker_togglevolt
npc_jenny
EndContentData */
#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()
{
Script* s;
@ -1146,6 +1260,8 @@ void AddSC_borean_tundra()
s->RegisterSelf();
s = new npc_bonker_togglevolt();
s->RegisterSelf();
s = new npc_jenny();
s->RegisterSelf();
s = new spell_throw_wolf_batt();
s->RegisterSelf();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -67,23 +67,11 @@ else()
target_link_libraries(${EXECUTABLE_NAME} ACE)
endif()
target_link_libraries(${EXECUTABLE_NAME} g3dlite vmap detour recast zlib shared)
set(EXECUTABLE_LINK_FLAGS "")
if(UNIX)
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
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()
target_link_libraries(${EXECUTABLE_NAME} rt)
endif()
if(APPLE)
set(EXECUTABLE_LINK_FLAGS "-framework CoreServices ${EXECUTABLE_LINK_FLAGS}")
endif()
set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS "${EXECUTABLE_LINK_FLAGS}")
target_link_libraries(${EXECUTABLE_NAME} g3dlite vmap detour recast zlib shared)
#Output the compiled exes to build/bin/$(Configuration)/tools directory on windows by default
if(WIN32)

View file

@ -47,22 +47,20 @@ else()
target_link_libraries(${EXECUTABLE_NAME} ACE)
endif()
if(UNIX)
target_link_libraries(${EXECUTABLE_NAME} rt dl)
endif()
target_link_libraries(${EXECUTABLE_NAME} vmap g3dlite zlib)
set(EXECUTABLE_LINK_FLAGS "")
if(UNIX)
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
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}")
if(CMAKE_C_COMPILER MATCHES "clang" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
set(EXECUTABLE_LINK_FLAGS "-pthread${EXECUTABLE_LINK_FLAGS}")
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}")
#Output the compiled exes to build/bin/$(Configuration)/tools directory on windows by default