mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 16:37:01 +00:00
Mant more cmangos Cata commits applied
Commit:
This commit is contained in:
parent
6db0ba8ae9
commit
8cac2f42db
51 changed files with 964 additions and 270 deletions
|
|
@ -64,8 +64,19 @@ typedef ACE_SHLIB_HANDLE MANGOS_LIBRARY_HANDLE;
|
||||||
# define MANGOS_EXPORT __declspec(dllexport)
|
# define MANGOS_EXPORT __declspec(dllexport)
|
||||||
# define MANGOS_IMPORT __cdecl
|
# define MANGOS_IMPORT __cdecl
|
||||||
#else // PLATFORM != PLATFORM_WINDOWS
|
#else // PLATFORM != PLATFORM_WINDOWS
|
||||||
|
# include <dlfcn.h>
|
||||||
|
typedef void* MANGOS_LIBRARY_HANDLE;
|
||||||
|
# define MANGOS_LOAD_LIBRARY(libname) dlopen(libname, RTLD_LAZY)
|
||||||
|
# define MANGOS_CLOSE_LIBRARY(hlib) dlclose(hlib)
|
||||||
|
# define MANGOS_GET_PROC_ADDR(hlib, name) dlsym(hlib, name)
|
||||||
# define MANGOS_EXPORT export
|
# define MANGOS_EXPORT export
|
||||||
# if defined(__APPLE_CC__) && defined(BIG_ENDIAN)
|
# if PLATFORM == PLATFORM_APPLE
|
||||||
|
# define MANGOS_SCRIPT_SUFFIX ".dylib"
|
||||||
|
# else
|
||||||
|
# define MANGOS_SCRIPT_SUFFIX ".so"
|
||||||
|
# endif
|
||||||
|
# define MANGOS_SCRIPT_PREFIX "lib"
|
||||||
|
# if defined(__APPLE_CC__) && defined(BIG_ENDIAN) // TODO:: more work to do with byte order. Have to be rechecked after boost integration.
|
||||||
# if (defined (__ppc__) || defined (__powerpc__))
|
# if (defined (__ppc__) || defined (__powerpc__))
|
||||||
# define MANGOS_IMPORT __attribute__ ((longcall))
|
# define MANGOS_IMPORT __attribute__ ((longcall))
|
||||||
# else
|
# else
|
||||||
|
|
|
||||||
|
|
@ -326,14 +326,7 @@ void BattleGround::Update(uint32 diff)
|
||||||
}
|
}
|
||||||
else if (m_PrematureCountDownTimer < diff)
|
else if (m_PrematureCountDownTimer < diff)
|
||||||
{
|
{
|
||||||
// time's up!
|
EndBattleGround(GetPrematureWinner());
|
||||||
Team winner = TEAM_NONE;
|
|
||||||
if (GetPlayersCountByTeam(ALLIANCE) >= GetMinPlayersPerTeam())
|
|
||||||
winner = ALLIANCE;
|
|
||||||
else if (GetPlayersCountByTeam(HORDE) >= GetMinPlayersPerTeam())
|
|
||||||
winner = HORDE;
|
|
||||||
|
|
||||||
EndBattleGround(winner);
|
|
||||||
m_PrematureCountDown = false;
|
m_PrematureCountDown = false;
|
||||||
}
|
}
|
||||||
else if (!sBattleGroundMgr.isTesting())
|
else if (!sBattleGroundMgr.isTesting())
|
||||||
|
|
@ -1483,6 +1476,19 @@ void BattleGround::DoorOpen(ObjectGuid guid)
|
||||||
sLog.outError("BattleGround: Door %s not found! - doors will be closed.", guid.GetString().c_str());
|
sLog.outError("BattleGround: Door %s not found! - doors will be closed.", guid.GetString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Team BattleGround::GetPrematureWinner()
|
||||||
|
{
|
||||||
|
uint32 hordePlayers = GetPlayersCountByTeam(HORDE);
|
||||||
|
uint32 alliancePlayers = GetPlayersCountByTeam(ALLIANCE);
|
||||||
|
|
||||||
|
if (hordePlayers > alliancePlayers)
|
||||||
|
return HORDE;
|
||||||
|
if (alliancePlayers > hordePlayers)
|
||||||
|
return ALLIANCE;
|
||||||
|
|
||||||
|
return TEAM_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
void BattleGround::OnObjectDBLoad(Creature* creature)
|
void BattleGround::OnObjectDBLoad(Creature* creature)
|
||||||
{
|
{
|
||||||
const BattleGroundEventIdx eventId = sBattleGroundMgr.GetCreatureEventIndex(creature->GetGUIDLow());
|
const BattleGroundEventIdx eventId = sBattleGroundMgr.GetCreatureEventIndex(creature->GetGUIDLow());
|
||||||
|
|
|
||||||
|
|
@ -550,6 +550,8 @@ class BattleGround
|
||||||
void DoorOpen(ObjectGuid guid);
|
void DoorOpen(ObjectGuid guid);
|
||||||
void DoorClose(ObjectGuid guid);
|
void DoorClose(ObjectGuid guid);
|
||||||
|
|
||||||
|
virtual Team GetPrematureWinner();
|
||||||
|
|
||||||
virtual bool HandlePlayerUnderMap(Player* /*plr*/) { return false; }
|
virtual bool HandlePlayerUnderMap(Player* /*plr*/) { return false; }
|
||||||
|
|
||||||
// since arenas can be AvA or Hvh, we have to get the "temporary" team of a player
|
// since arenas can be AvA or Hvh, we have to get the "temporary" team of a player
|
||||||
|
|
|
||||||
|
|
@ -543,3 +543,18 @@ bool BattleGroundAB::IsAllNodesControlledByTeam(Team team) const
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Team BattleGroundAB::GetPrematureWinner()
|
||||||
|
{
|
||||||
|
int32 hordeScore = m_TeamScores[TEAM_INDEX_HORDE];
|
||||||
|
int32 allianceScore = m_TeamScores[TEAM_INDEX_ALLIANCE];
|
||||||
|
|
||||||
|
if (hordeScore > allianceScore)
|
||||||
|
return HORDE;
|
||||||
|
if (allianceScore > hordeScore)
|
||||||
|
return ALLIANCE;
|
||||||
|
|
||||||
|
// If the values are equal, fall back to number of players on each team
|
||||||
|
return BattleGround::GetPrematureWinner();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,8 @@ class BattleGroundAB : public BattleGround
|
||||||
/* achievement req. */
|
/* achievement req. */
|
||||||
bool IsAllNodesControlledByTeam(Team team) const override;
|
bool IsAllNodesControlledByTeam(Team team) const override;
|
||||||
bool IsTeamScores500Disadvantage(Team team) const { return m_TeamScores500Disadvantage[GetTeamIndexByTeamId(team)]; }
|
bool IsTeamScores500Disadvantage(Team team) const { return m_TeamScores500Disadvantage[GetTeamIndexByTeamId(team)]; }
|
||||||
|
|
||||||
|
virtual Team GetPrematureWinner() override;
|
||||||
private:
|
private:
|
||||||
/* Gameobject spawning/despawning */
|
/* Gameobject spawning/despawning */
|
||||||
void _CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay);
|
void _CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay);
|
||||||
|
|
|
||||||
|
|
@ -823,3 +823,17 @@ void BattleGroundAV::Reset()
|
||||||
|
|
||||||
InitNode(BG_AV_NODES_SNOWFALL_GRAVE, BG_AV_TEAM_NEUTRAL, false); // give snowfall neutral owner
|
InitNode(BG_AV_NODES_SNOWFALL_GRAVE, BG_AV_TEAM_NEUTRAL, false); // give snowfall neutral owner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Team BattleGroundAV::GetPrematureWinner()
|
||||||
|
{
|
||||||
|
int32 hordeScore = m_TeamScores[TEAM_INDEX_HORDE];
|
||||||
|
int32 allianceScore = m_TeamScores[TEAM_INDEX_ALLIANCE];
|
||||||
|
|
||||||
|
if (hordeScore > allianceScore)
|
||||||
|
return HORDE;
|
||||||
|
if (allianceScore > hordeScore)
|
||||||
|
return ALLIANCE;
|
||||||
|
|
||||||
|
// If the values are equal, fall back to number of players on each team
|
||||||
|
return BattleGround::GetPrematureWinner();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -359,6 +359,8 @@ class BattleGroundAV : public BattleGround
|
||||||
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* plr) override;
|
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* plr) override;
|
||||||
|
|
||||||
static BattleGroundAVTeamIndex GetAVTeamIndexByTeamId(Team team) { return BattleGroundAVTeamIndex(GetTeamIndexByTeamId(team)); }
|
static BattleGroundAVTeamIndex GetAVTeamIndexByTeamId(Team team) { return BattleGroundAVTeamIndex(GetTeamIndexByTeamId(team)); }
|
||||||
|
|
||||||
|
virtual Team GetPrematureWinner() override;
|
||||||
private:
|
private:
|
||||||
/* Nodes occupying */
|
/* Nodes occupying */
|
||||||
void EventPlayerAssaultsPoint(Player* player, BG_AV_Nodes node);
|
void EventPlayerAssaultsPoint(Player* player, BG_AV_Nodes node);
|
||||||
|
|
|
||||||
|
|
@ -401,18 +401,6 @@ void BattleGroundEY::HandleKillPlayer(Player* player, Player* killer)
|
||||||
|
|
||||||
void BattleGroundEY::EventPlayerDroppedFlag(Player* source)
|
void BattleGroundEY::EventPlayerDroppedFlag(Player* source)
|
||||||
{
|
{
|
||||||
if (GetStatus() != STATUS_IN_PROGRESS)
|
|
||||||
{
|
|
||||||
// if not running, do not cast things at the dropper player, neither send unnecessary messages
|
|
||||||
// just take off the aura
|
|
||||||
if (IsFlagPickedUp() && GetFlagCarrierGuid() == source->GetObjectGuid())
|
|
||||||
{
|
|
||||||
ClearFlagCarrier();
|
|
||||||
source->RemoveAurasDueToSpell(EY_NETHERSTORM_FLAG_SPELL);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsFlagPickedUp())
|
if (!IsFlagPickedUp())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -421,6 +409,13 @@ void BattleGroundEY::EventPlayerDroppedFlag(Player* source)
|
||||||
|
|
||||||
ClearFlagCarrier();
|
ClearFlagCarrier();
|
||||||
source->RemoveAurasDueToSpell(EY_NETHERSTORM_FLAG_SPELL);
|
source->RemoveAurasDueToSpell(EY_NETHERSTORM_FLAG_SPELL);
|
||||||
|
|
||||||
|
if (GetStatus() != STATUS_IN_PROGRESS)
|
||||||
|
{
|
||||||
|
// do not cast auras or send messages after match has ended
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_flagState = EY_FLAG_STATE_ON_GROUND;
|
m_flagState = EY_FLAG_STATE_ON_GROUND;
|
||||||
m_flagRespawnTimer = EY_FLAG_RESPAWN_TIME;
|
m_flagRespawnTimer = EY_FLAG_RESPAWN_TIME;
|
||||||
source->CastSpell(source, SPELL_RECENTLY_DROPPED_FLAG, true);
|
source->CastSpell(source, SPELL_RECENTLY_DROPPED_FLAG, true);
|
||||||
|
|
@ -429,12 +424,12 @@ void BattleGroundEY::EventPlayerDroppedFlag(Player* source)
|
||||||
if (source->GetTeam() == ALLIANCE)
|
if (source->GetTeam() == ALLIANCE)
|
||||||
{
|
{
|
||||||
UpdateWorldState(WORLD_STATE_EY_NETHERSTORM_FLAG_STATE_ALLIANCE, 1);
|
UpdateWorldState(WORLD_STATE_EY_NETHERSTORM_FLAG_STATE_ALLIANCE, 1);
|
||||||
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL);
|
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, nullptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UpdateWorldState(WORLD_STATE_EY_NETHERSTORM_FLAG_STATE_HORDE, 1);
|
UpdateWorldState(WORLD_STATE_EY_NETHERSTORM_FLAG_STATE_HORDE, 1);
|
||||||
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, NULL);
|
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -625,3 +620,17 @@ bool BattleGroundEY::IsAllNodesControlledByTeam(Team team) const
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Team BattleGroundEY::GetPrematureWinner()
|
||||||
|
{
|
||||||
|
int32 hordeScore = m_TeamScores[TEAM_INDEX_HORDE];
|
||||||
|
int32 allianceScore = m_TeamScores[TEAM_INDEX_ALLIANCE];
|
||||||
|
|
||||||
|
if (hordeScore > allianceScore)
|
||||||
|
return HORDE;
|
||||||
|
if (allianceScore > hordeScore)
|
||||||
|
return ALLIANCE;
|
||||||
|
|
||||||
|
// If the values are equal, fall back to number of players on each team
|
||||||
|
return BattleGround::GetPrematureWinner();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -284,6 +284,8 @@ class BattleGroundEY : public BattleGround
|
||||||
/* achievement req. */
|
/* achievement req. */
|
||||||
bool IsAllNodesControlledByTeam(Team team) const override;
|
bool IsAllNodesControlledByTeam(Team team) const override;
|
||||||
|
|
||||||
|
virtual Team GetPrematureWinner() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// process capture events
|
// process capture events
|
||||||
void ProcessCaptureEvent(GameObject* go, uint32 towerId, Team team, uint32 newWorldState, uint32 message);
|
void ProcessCaptureEvent(GameObject* go, uint32 towerId, Team team, uint32 newWorldState, uint32 message);
|
||||||
|
|
|
||||||
|
|
@ -652,3 +652,17 @@ void BattleGroundWS::FillInitialWorldStates(WorldPacket& data, uint32& count)
|
||||||
FillInitialWorldState(data, count, BG_WS_TIME_ENABLED, WORLD_STATE_ADD);
|
FillInitialWorldState(data, count, BG_WS_TIME_ENABLED, WORLD_STATE_ADD);
|
||||||
FillInitialWorldState(data, count, BG_WS_TIME_REMAINING, GetRemainingTimeInMinutes());
|
FillInitialWorldState(data, count, BG_WS_TIME_REMAINING, GetRemainingTimeInMinutes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Team BattleGroundWS::GetPrematureWinner()
|
||||||
|
{
|
||||||
|
int32 hordeScore = m_TeamScores[TEAM_INDEX_HORDE];
|
||||||
|
int32 allianceScore = m_TeamScores[TEAM_INDEX_ALLIANCE];
|
||||||
|
|
||||||
|
if (hordeScore > allianceScore)
|
||||||
|
return HORDE;
|
||||||
|
if (allianceScore > hordeScore)
|
||||||
|
return ALLIANCE;
|
||||||
|
|
||||||
|
// If the values are equal, fall back to number of players on each team
|
||||||
|
return BattleGround::GetPrematureWinner();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,8 @@ class BattleGroundWS : public BattleGround
|
||||||
ObjectGuid const& GetDroppedFlagGuid(Team team) const { return m_DroppedFlagGuid[GetTeamIndexByTeamId(team)];}
|
ObjectGuid const& GetDroppedFlagGuid(Team team) const { return m_DroppedFlagGuid[GetTeamIndexByTeamId(team)];}
|
||||||
virtual void FillInitialWorldStates(WorldPacket& data, uint32& count) override;
|
virtual void FillInitialWorldStates(WorldPacket& data, uint32& count) override;
|
||||||
|
|
||||||
|
virtual Team GetPrematureWinner() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ObjectGuid m_flagCarrierAlliance;
|
ObjectGuid m_flagCarrierAlliance;
|
||||||
ObjectGuid m_flagCarrierHorde;
|
ObjectGuid m_flagCarrierHorde;
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@
|
||||||
#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
|
#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
|
||||||
#include "MoveMap.h" // for mmap manager
|
#include "MoveMap.h" // for mmap manager
|
||||||
#include "PathFinder.h" // for mmap commands
|
#include "PathFinder.h" // for mmap commands
|
||||||
|
#include "movement/MoveSplineInit.h"
|
||||||
|
|
||||||
static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] =
|
static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] =
|
||||||
{
|
{
|
||||||
|
|
@ -2919,24 +2920,21 @@ inline void UnsummonVisualWaypoints(Player const* player, ObjectGuid ownerGuid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Add a waypoint to a creature
|
||||||
* Add a waypoint to a creature.
|
* .wp add [dbGuid] [pathId] [source]
|
||||||
*
|
*
|
||||||
* The user can either select an npc or provide its GUID.
|
* The user can either select an npc or provide its dbGuid.
|
||||||
|
* Also the user can specify pathId and source if wanted.
|
||||||
*
|
*
|
||||||
* The user can even select a visual waypoint - then the new waypoint
|
* The user can even select a visual waypoint - then the new waypoint
|
||||||
* is placed *after* the selected one - this makes insertion of new
|
* is placed *after* the selected one - this makes insertion of new
|
||||||
* waypoints possible.
|
* waypoints possible.
|
||||||
*
|
*
|
||||||
* eg:
|
* .wp add [pathId] [source]
|
||||||
* .wp add 12345
|
* -> adds a waypoint to the currently selected creature, to path pathId in source-storage
|
||||||
* -> adds a waypoint to the npc with the GUID 12345
|
|
||||||
*
|
*
|
||||||
* .wp add
|
* .wp add guid [pathId] [source]
|
||||||
* -> adds a waypoint to the currently selected creature
|
* -> if no npc is selected, expect the creature provided with guid argument
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param args if the user did not provide a GUID, it is NULL
|
|
||||||
*
|
*
|
||||||
* @return true - command did succeed, false - something went wrong
|
* @return true - command did succeed, false - something went wrong
|
||||||
*/
|
*/
|
||||||
|
|
@ -3082,24 +3080,39 @@ bool ChatHandler::HandleWpAddCommand(char* args)
|
||||||
} // HandleWpAddCommand
|
} // HandleWpAddCommand
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* .wp modify emote | spell | text | del | move | add
|
* .wp modify waittime | scriptid | orientation | del | move [dbGuid, id] [value]
|
||||||
*
|
*
|
||||||
* add -> add a WP after the selected visual waypoint
|
* waittime <Delay>
|
||||||
* User must select a visual waypoint and then issue ".wp modify add"
|
|
||||||
*
|
|
||||||
* emote <emoteID>
|
|
||||||
* User has selected a visual waypoint before.
|
* User has selected a visual waypoint before.
|
||||||
* <emoteID> is added to this waypoint. Everytime the
|
* Delay <Delay> is added to this waypoint. Everytime the
|
||||||
* NPC comes to this waypoint, the emote is called.
|
* NPC comes to this waypoint, it will wait Delay millieseconds.
|
||||||
*
|
*
|
||||||
* emote <GUID> <WPNUM> <emoteID>
|
* waittime <DBGuid> <WPNUM> <Delay>
|
||||||
* User has not selected visual waypoint before.
|
* User has not selected visual waypoint before.
|
||||||
* For the waypoint <WPNUM> for the NPC with <GUID>
|
* For the waypoint <WPNUM> for the NPC with <DBGuid>
|
||||||
* an emote <emoteID> is added.
|
* an delay Delay is added to this waypoint
|
||||||
* Everytime the NPC comes to this waypoint, the emote is called.
|
* Everytime the NPC comes to this waypoint, it will wait Delay millieseconds.
|
||||||
*
|
*
|
||||||
|
* scriptid <scriptId>
|
||||||
|
* User has selected a visual waypoint before.
|
||||||
|
* <scriptId> is added to this waypoint. Everytime the
|
||||||
|
* NPC comes to this waypoint, the DBScript scriptId is executed.
|
||||||
*
|
*
|
||||||
* info <GUID> <WPNUM> -> User did not select a visual waypoint and
|
* scriptid <DBGuid> <WPNUM> <scriptId>
|
||||||
|
* User has not selected visual waypoint before.
|
||||||
|
* For the waypoint <WPNUM> for the NPC with <DBGuid>
|
||||||
|
* an emote <scriptId> is added.
|
||||||
|
* Everytime the NPC comes to this waypoint, the DBScript scriptId is executed.
|
||||||
|
*
|
||||||
|
* orientation [DBGuid, WpNum] <Orientation>
|
||||||
|
* Set the orientation of the selected waypoint or waypoint given with DbGuid/ WpId
|
||||||
|
* to the value of <Orientation>.
|
||||||
|
*
|
||||||
|
* del [DBGuid, WpId]
|
||||||
|
* Remove the selected waypoint or waypoint given with DbGuid/ WpId.
|
||||||
|
*
|
||||||
|
* move [DBGuid, WpId]
|
||||||
|
* Move the selected waypoint or waypoint given with DbGuid/ WpId to player's current positiion.
|
||||||
*/
|
*/
|
||||||
bool ChatHandler::HandleWpModifyCommand(char* args)
|
bool ChatHandler::HandleWpModifyCommand(char* args)
|
||||||
{
|
{
|
||||||
|
|
@ -3303,29 +3316,19 @@ bool ChatHandler::HandleWpModifyCommand(char* args)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* .wp show info | on | off
|
* .wp show info | on | off | first | last [dbGuid] [pathId [wpOrigin] ]
|
||||||
*
|
*
|
||||||
* info -> User has selected a visual waypoint before
|
* info -> User has selected a visual waypoint before
|
||||||
*
|
*
|
||||||
* info <GUID> <WPNUM> -> User did not select a visual waypoint and
|
|
||||||
* provided the GUID of the NPC and the number of
|
|
||||||
* the waypoint.
|
|
||||||
*
|
|
||||||
* on -> User has selected an NPC; all visual waypoints for this
|
* on -> User has selected an NPC; all visual waypoints for this
|
||||||
* NPC are added to the world
|
* NPC are added to the world
|
||||||
*
|
*
|
||||||
* on <GUID> -> User did not select an NPC - instead the GUID of the
|
* on <dbGuid> -> User did not select an NPC - instead the dbGuid of the
|
||||||
* NPC is provided. All visual waypoints for this NPC
|
* NPC is provided. All visual waypoints for this NPC
|
||||||
* are added from the world.
|
* are added from the world.
|
||||||
*
|
*
|
||||||
* off -> User has selected an NPC; all visual waypoints for this
|
* off -> User has selected an NPC; all visual waypoints for this
|
||||||
* NPC are removed from the world.
|
* NPC are removed from the world.
|
||||||
*
|
|
||||||
* on <GUID> -> User did not select an NPC - instead the GUID of the
|
|
||||||
* NPC is provided. All visual waypoints for this NPC
|
|
||||||
* are removed from the world.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
bool ChatHandler::HandleWpShowCommand(char* args)
|
bool ChatHandler::HandleWpShowCommand(char* args)
|
||||||
{
|
{
|
||||||
|
|
@ -5071,20 +5074,53 @@ bool ChatHandler::HandleMmapPathCommand(char* args)
|
||||||
char* para = strtok(args, " ");
|
char* para = strtok(args, " ");
|
||||||
|
|
||||||
bool useStraightPath = false;
|
bool useStraightPath = false;
|
||||||
if (para && strcmp(para, "true") == 0)
|
bool followPath = false;
|
||||||
|
bool unitToPlayer = false;
|
||||||
|
if (para)
|
||||||
|
{
|
||||||
|
if (strcmp(para, "go") == 0)
|
||||||
|
{
|
||||||
|
followPath = true;
|
||||||
|
para = strtok(nullptr, " ");
|
||||||
|
if (para && strcmp(para, "straight") == 0)
|
||||||
useStraightPath = true;
|
useStraightPath = true;
|
||||||
|
}
|
||||||
|
else if (strcmp(para, "straight") == 0)
|
||||||
|
useStraightPath = true;
|
||||||
|
else if (strcmp(para, "to_me") == 0)
|
||||||
|
unitToPlayer = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PSendSysMessage("Use '.mmap path go' to move on target.");
|
||||||
|
PSendSysMessage("Use '.mmap path straight' to generate straight path.");
|
||||||
|
PSendSysMessage("Use '.mmap path to_me' to generate path from the target to you.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit* destinationUnit;
|
||||||
|
Unit* originUnit;
|
||||||
|
if (unitToPlayer)
|
||||||
|
{
|
||||||
|
destinationUnit = player;
|
||||||
|
originUnit = target;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
destinationUnit = target;
|
||||||
|
originUnit = player;
|
||||||
|
}
|
||||||
|
|
||||||
// unit locations
|
// unit locations
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
player->GetPosition(x, y, z);
|
destinationUnit->GetPosition(x, y, z);
|
||||||
|
|
||||||
// path
|
// path
|
||||||
PathFinder path(target);
|
PathFinder path(originUnit);
|
||||||
path.setUseStrightPath(useStraightPath);
|
path.setUseStrightPath(useStraightPath);
|
||||||
path.calculate(x, y, z);
|
path.calculate(x, y, z);
|
||||||
|
|
||||||
PointsArray pointPath = path.getPath();
|
PointsArray pointPath = path.getPath();
|
||||||
PSendSysMessage("%s's path to %s:", target->GetName(), player->GetName());
|
PSendSysMessage("%s's path to %s:", originUnit->GetName(), destinationUnit->GetName());
|
||||||
PSendSysMessage("Building %s", useStraightPath ? "StraightPath" : "SmoothPath");
|
PSendSysMessage("Building %s", useStraightPath ? "StraightPath" : "SmoothPath");
|
||||||
PSendSysMessage("length " SIZEFMTD " type %u", pointPath.size(), path.getPathType());
|
PSendSysMessage("length " SIZEFMTD " type %u", pointPath.size(), path.getPathType());
|
||||||
|
|
||||||
|
|
@ -5099,13 +5135,15 @@ bool ChatHandler::HandleMmapPathCommand(char* args)
|
||||||
if (!player->isGameMaster())
|
if (!player->isGameMaster())
|
||||||
PSendSysMessage("Enable GM mode to see the path points.");
|
PSendSysMessage("Enable GM mode to see the path points.");
|
||||||
|
|
||||||
// this entry visible only to GM's with "gm on"
|
|
||||||
static const uint32 WAYPOINT_NPC_ENTRY = 1;
|
|
||||||
Creature* wp = NULL;
|
|
||||||
for (uint32 i = 0; i < pointPath.size(); ++i)
|
for (uint32 i = 0; i < pointPath.size(); ++i)
|
||||||
|
player->SummonCreature(VISUAL_WAYPOINT, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000);
|
||||||
|
|
||||||
|
if (followPath)
|
||||||
{
|
{
|
||||||
wp = player->SummonCreature(WAYPOINT_NPC_ENTRY, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000);
|
Movement::MoveSplineInit init(*player);
|
||||||
// TODO: make creature not sink/fall
|
init.MovebyPath(pointPath);
|
||||||
|
init.SetWalk(false);
|
||||||
|
init.Launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -2302,7 +2302,7 @@ bool ChatHandler::HandleLearnAllCommand(char* /*args*/)
|
||||||
int loop = 0;
|
int loop = 0;
|
||||||
while (strcmp(allSpellList[loop], "0"))
|
while (strcmp(allSpellList[loop], "0"))
|
||||||
{
|
{
|
||||||
uint32 spell = atol((char*)allSpellList[loop++]);
|
uint32 spell = std::stoul((char*)allSpellList[loop++]);
|
||||||
|
|
||||||
if (m_session->GetPlayer()->HasSpell(spell))
|
if (m_session->GetPlayer()->HasSpell(spell))
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -2345,7 +2345,7 @@ bool ChatHandler::HandleLearnAllGMCommand(char* /*args*/)
|
||||||
uint16 gmSpellIter = 0;
|
uint16 gmSpellIter = 0;
|
||||||
while (strcmp(gmSpellList[gmSpellIter], "0"))
|
while (strcmp(gmSpellList[gmSpellIter], "0"))
|
||||||
{
|
{
|
||||||
uint32 spell = atol((char*)gmSpellList[gmSpellIter++]);
|
uint32 spell = std::stoul((char*)gmSpellList[gmSpellIter++]);
|
||||||
|
|
||||||
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
|
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
|
||||||
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, m_session->GetPlayer()))
|
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, m_session->GetPlayer()))
|
||||||
|
|
|
||||||
|
|
@ -354,7 +354,7 @@ bool ChatHandler::HandleDebugGetLootRecipientCommand(char* /*args*/)
|
||||||
|
|
||||||
bool ChatHandler::HandleDebugSendQuestInvalidMsgCommand(char* args)
|
bool ChatHandler::HandleDebugSendQuestInvalidMsgCommand(char* args)
|
||||||
{
|
{
|
||||||
uint32 msg = atol(args);
|
uint32 msg = std::stoul(args);
|
||||||
m_session->GetPlayer()->SendCanTakeQuestResponse(msg);
|
m_session->GetPlayer()->SendCanTakeQuestResponse(msg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ PathFinder::PathFinder(const Unit* owner) :
|
||||||
DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::PathInfo for %u \n", m_sourceUnit->GetGUIDLow());
|
DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::PathInfo for %u \n", m_sourceUnit->GetGUIDLow());
|
||||||
|
|
||||||
uint32 mapId = m_sourceUnit->GetMapId();
|
uint32 mapId = m_sourceUnit->GetMapId();
|
||||||
if (MMAP::MMapFactory::IsPathfindingEnabled(mapId))
|
if (MMAP::MMapFactory::IsPathfindingEnabled(mapId, owner))
|
||||||
{
|
{
|
||||||
MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager();
|
MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager();
|
||||||
m_navMesh = mmap->GetNavMesh(mapId);
|
m_navMesh = mmap->GetNavMesh(mapId);
|
||||||
|
|
|
||||||
|
|
@ -1810,18 +1810,27 @@ void Creature::SetLootStatus(CreatureLootStatus status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true if this creature is tapped by the player or by a member of his group.
|
// simple tap system return true if player or his group tapped the creature
|
||||||
bool Creature::IsTappedBy(Player const* player) const
|
// TODO:: this is semi correct. For group situation need more work but its not a big issue
|
||||||
|
bool Creature::IsTappedBy(Player* plr) const
|
||||||
{
|
{
|
||||||
if (player == GetOriginalLootRecipient())
|
if (Player* recipient = GetLootRecipient())
|
||||||
|
{
|
||||||
|
if (recipient == plr)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Group const* playerGroup = player->GetGroup();
|
if (Group* grp = recipient->GetGroup())
|
||||||
if (!playerGroup || playerGroup != GetGroupLootRecipient()) // if we dont have a group we arent the recipient
|
{
|
||||||
return false; // if creature doesnt have group bound it means it was solo killed by someone else
|
if (Group* plrGroup = plr->GetGroup())
|
||||||
|
{
|
||||||
|
if (plrGroup == grp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
SpellEntry const* Creature::ReachWithSpellAttack(Unit* pVictim)
|
SpellEntry const* Creature::ReachWithSpellAttack(Unit* pVictim)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ enum CreatureFlagsExtra
|
||||||
CREATURE_EXTRA_FLAG_MMAP_FORCE_DISABLE = 0x00004000, // creature is forced to NOT use MMaps
|
CREATURE_EXTRA_FLAG_MMAP_FORCE_DISABLE = 0x00004000, // creature is forced to NOT use MMaps
|
||||||
CREATURE_EXTRA_FLAG_WALK_IN_WATER = 0x00008000, // creature is forced to walk in water even it can swim
|
CREATURE_EXTRA_FLAG_WALK_IN_WATER = 0x00008000, // creature is forced to walk in water even it can swim
|
||||||
CREATURE_EXTRA_FLAG_HAVE_NO_SWIM_ANIMATION = 0x00010000, // we have to not set "swim" animation or creature will have "no animation"
|
CREATURE_EXTRA_FLAG_HAVE_NO_SWIM_ANIMATION = 0x00010000, // we have to not set "swim" animation or creature will have "no animation"
|
||||||
|
CREATURE_EXTRA_FLAG_NO_MELEE = 0x00020000, // creature can't melee
|
||||||
};
|
};
|
||||||
|
|
||||||
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
|
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
|
||||||
|
|
@ -561,7 +562,7 @@ class Creature : public Unit
|
||||||
bool IsImmuneToSpell(SpellEntry const* spellInfo, bool castOnSelf) override;
|
bool IsImmuneToSpell(SpellEntry const* spellInfo, bool castOnSelf) override;
|
||||||
bool IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index, bool castOnSelf) const override;
|
bool IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index, bool castOnSelf) const override;
|
||||||
void SetLootStatus(CreatureLootStatus status);
|
void SetLootStatus(CreatureLootStatus status);
|
||||||
bool IsTappedBy(Player const* player) const;
|
bool IsTappedBy(Player* plr) const;
|
||||||
|
|
||||||
bool IsElite() const
|
bool IsElite() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,10 @@ GameObject::GameObject() : WorldObject(),
|
||||||
m_groupLootTimer = 0;
|
m_groupLootTimer = 0;
|
||||||
m_groupLootId = 0;
|
m_groupLootId = 0;
|
||||||
m_lootGroupRecipientId = 0;
|
m_lootGroupRecipientId = 0;
|
||||||
|
|
||||||
|
m_isInUse = false;
|
||||||
|
m_reStockTimer = 0;
|
||||||
|
m_despawnTimer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObject::~GameObject()
|
GameObject::~GameObject()
|
||||||
|
|
@ -1951,6 +1955,7 @@ void GameObject::SetLootRecipient(Unit* pUnit)
|
||||||
{
|
{
|
||||||
m_lootRecipientGuid.Clear();
|
m_lootRecipientGuid.Clear();
|
||||||
m_lootGroupRecipientId = 0;
|
m_lootGroupRecipientId = 0;
|
||||||
|
ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); // needed to be sure tapping status is updated
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1964,6 +1969,8 @@ void GameObject::SetLootRecipient(Unit* pUnit)
|
||||||
// set group for group existed case including if player will leave group at loot time
|
// set group for group existed case including if player will leave group at loot time
|
||||||
if (Group* group = player->GetGroup())
|
if (Group* group = player->GetGroup())
|
||||||
{ m_lootGroupRecipientId = group->GetId(); }
|
{ m_lootGroupRecipientId = group->GetId(); }
|
||||||
|
|
||||||
|
ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); // needed to be sure tapping status is updated
|
||||||
}
|
}
|
||||||
|
|
||||||
float GameObject::GetObjectBoundingRadius() const
|
float GameObject::GetObjectBoundingRadius() const
|
||||||
|
|
@ -2402,6 +2409,15 @@ float GameObject::GetInteractionDistance()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameObject::SetInUse(bool use)
|
||||||
|
{
|
||||||
|
m_isInUse = use;
|
||||||
|
if (use)
|
||||||
|
SetGoState(GO_STATE_ACTIVE);
|
||||||
|
else
|
||||||
|
SetGoState(GO_STATE_READY);
|
||||||
|
}
|
||||||
|
|
||||||
uint32 GameObject::GetScriptId()
|
uint32 GameObject::GetScriptId()
|
||||||
{
|
{
|
||||||
return sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, -int32(GetGUIDLow())) ? sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, -int32(GetGUIDLow())) : sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, GetEntry());
|
return sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, -int32(GetGUIDLow())) ? sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, -int32(GetGUIDLow())) : sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, GetEntry());
|
||||||
|
|
|
||||||
|
|
@ -749,6 +749,8 @@ class GameObject : public WorldObject
|
||||||
|
|
||||||
void AddUniqueUse(Player* player);
|
void AddUniqueUse(Player* player);
|
||||||
void AddUse() { ++m_useTimes; }
|
void AddUse() { ++m_useTimes; }
|
||||||
|
bool IsInUse() const { return m_isInUse; }
|
||||||
|
void SetInUse(bool use);
|
||||||
|
|
||||||
uint32 GetUseCount() const { return m_useTimes; }
|
uint32 GetUseCount() const { return m_useTimes; }
|
||||||
uint32 GetUniqueUseCount() const { return m_UniqueUsers.size(); }
|
uint32 GetUniqueUseCount() const { return m_UniqueUsers.size(); }
|
||||||
|
|
|
||||||
|
|
@ -800,7 +800,7 @@ bool Object::LoadValues(const char* data)
|
||||||
int index;
|
int index;
|
||||||
for (iter = tokens.begin(), index = 0; index < m_valuesCount; ++iter, ++index)
|
for (iter = tokens.begin(), index = 0; index < m_valuesCount; ++iter, ++index)
|
||||||
{
|
{
|
||||||
m_uint32Values[index] = atol((*iter).c_str());
|
m_uint32Values[index] = std::stoul((*iter).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1119,6 +1119,16 @@ void Object::MarkForClientUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Object::ForceValuesUpdateAtIndex(uint32 index)
|
||||||
|
{
|
||||||
|
m_changedValues[index] = true;
|
||||||
|
if (m_inWorld && !m_objectUpdated)
|
||||||
|
{
|
||||||
|
AddToClientUpdateList();
|
||||||
|
m_objectUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WorldObject::WorldObject() :
|
WorldObject::WorldObject() :
|
||||||
#ifdef ENABLE_ELUNA
|
#ifdef ENABLE_ELUNA
|
||||||
elunaEvents(NULL),
|
elunaEvents(NULL),
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,7 @@ class Object
|
||||||
void SetGuidValue(uint16 index, ObjectGuid const& value) { SetUInt64Value(index, value.GetRawValue()); }
|
void SetGuidValue(uint16 index, ObjectGuid const& value) { SetUInt64Value(index, value.GetRawValue()); }
|
||||||
void SetStatFloatValue(uint16 index, float value);
|
void SetStatFloatValue(uint16 index, float value);
|
||||||
void SetStatInt32Value(uint16 index, int32 value);
|
void SetStatInt32Value(uint16 index, int32 value);
|
||||||
|
void ForceValuesUpdateAtIndex(uint32 index);
|
||||||
|
|
||||||
void ApplyModUInt32Value(uint16 index, int32 val, bool apply);
|
void ApplyModUInt32Value(uint16 index, int32 val, bool apply);
|
||||||
void ApplyModInt32Value(uint16 index, int32 val, bool apply);
|
void ApplyModInt32Value(uint16 index, int32 val, bool apply);
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ void PlayerTaxi::LoadTaxiMask(const char* data)
|
||||||
(index < TaxiMaskSize) && (iter != tokens.end()); ++iter, ++index)
|
(index < TaxiMaskSize) && (iter != tokens.end()); ++iter, ++index)
|
||||||
{
|
{
|
||||||
// load and set bits only for existing taxi nodes
|
// load and set bits only for existing taxi nodes
|
||||||
m_taximask[index] = sTaxiNodesMask[index] & uint8(atol((*iter).c_str()));
|
m_taximask[index] = sTaxiNodesMask[index] & uint8(std::stoul((*iter).c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,7 +218,7 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, Team
|
||||||
|
|
||||||
for (Tokens::iterator iter = tokens.begin(); iter != tokens.end(); ++iter)
|
for (Tokens::iterator iter = tokens.begin(); iter != tokens.end(); ++iter)
|
||||||
{
|
{
|
||||||
uint32 node = uint32(atol(iter->c_str()));
|
uint32 node = std::stoul(iter->c_str());
|
||||||
AddTaxiDestination(node);
|
AddTaxiDestination(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2358,23 +2358,7 @@ GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameo
|
||||||
{
|
{
|
||||||
if (uint32(go->GetGoType()) == gameobject_type || gameobject_type == MAX_GAMEOBJECT_TYPE)
|
if (uint32(go->GetGoType()) == gameobject_type || gameobject_type == MAX_GAMEOBJECT_TYPE)
|
||||||
{
|
{
|
||||||
float maxdist;
|
float maxdist = go->GetInteractionDistance();
|
||||||
switch (go->GetGoType())
|
|
||||||
{
|
|
||||||
// TODO: find out how the client calculates the maximal usage distance to spellless working
|
|
||||||
// gameobjects like guildbanks and mailboxes - 10.0 is a just an abitrary choosen number
|
|
||||||
case GAMEOBJECT_TYPE_GUILD_BANK:
|
|
||||||
case GAMEOBJECT_TYPE_MAILBOX:
|
|
||||||
maxdist = 10.0f;
|
|
||||||
break;
|
|
||||||
case GAMEOBJECT_TYPE_FISHINGHOLE:
|
|
||||||
maxdist = 20.0f + CONTACT_DISTANCE; // max spell range
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
maxdist = INTERACTION_DISTANCE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (go->IsWithinDistInMap(this, maxdist) && go->isSpawned())
|
if (go->IsWithinDistInMap(this, maxdist) && go->isSpawned())
|
||||||
return go;
|
return go;
|
||||||
|
|
||||||
|
|
@ -5543,6 +5527,10 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
|
||||||
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
SkillStatusData& skillStatus = itr->second;
|
||||||
|
if (skillStatus.uState == SKILL_DELETED)
|
||||||
|
return false;
|
||||||
|
|
||||||
uint16 field = itr->second.pos / 2;
|
uint16 field = itr->second.pos / 2;
|
||||||
uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
|
uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
|
||||||
|
|
||||||
|
|
@ -15349,7 +15337,7 @@ void Player::_LoadIntoDataField(const char* data, uint32 startOffset, uint32 cou
|
||||||
uint32 index;
|
uint32 index;
|
||||||
for (iter = tokens.begin(), index = 0; index < count; ++iter, ++index)
|
for (iter = tokens.begin(), index = 0; index < count; ++iter, ++index)
|
||||||
{
|
{
|
||||||
m_uint32Values[startOffset + index] = atol((*iter).c_str());
|
m_uint32Values[startOffset + index] = std::stoul((*iter).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2075,6 +2075,9 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
|
||||||
|
|
||||||
// This seems to reduce the victims time until next attack if your attack was parried
|
// This seems to reduce the victims time until next attack if your attack was parried
|
||||||
if (damageInfo->TargetState == VICTIMSTATE_PARRY)
|
if (damageInfo->TargetState == VICTIMSTATE_PARRY)
|
||||||
|
{
|
||||||
|
if (pVictim->GetTypeId() != TYPEID_UNIT ||
|
||||||
|
!(((Creature*)pVictim)->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_PARRY_HASTEN))
|
||||||
{
|
{
|
||||||
// Get attack timers
|
// Get attack timers
|
||||||
float offtime = float(pVictim->getAttackTimer(OFF_ATTACK));
|
float offtime = float(pVictim->getAttackTimer(OFF_ATTACK));
|
||||||
|
|
@ -2109,6 +2112,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Call default DealDamage
|
// Call default DealDamage
|
||||||
CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->attackType, damageInfo->hitOutCome);
|
CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->attackType, damageInfo->hitOutCome);
|
||||||
|
|
@ -10736,9 +10740,9 @@ void CharmInfo::LoadPetActionBar(const std::string& data)
|
||||||
for (iter = tokens.begin(), index = ACTION_BAR_INDEX_START; index < ACTION_BAR_INDEX_END; ++iter, ++index)
|
for (iter = tokens.begin(), index = ACTION_BAR_INDEX_START; index < ACTION_BAR_INDEX_END; ++iter, ++index)
|
||||||
{
|
{
|
||||||
// use unsigned cast to avoid sign negative format use at long-> ActiveStates (int) conversion
|
// use unsigned cast to avoid sign negative format use at long-> ActiveStates (int) conversion
|
||||||
uint8 type = (uint8)atol((*iter).c_str());
|
uint8 type = (uint8)std::stoul((*iter).c_str());
|
||||||
++iter;
|
++iter;
|
||||||
uint32 action = atol((*iter).c_str());
|
uint32 action = std::stoul((*iter).c_str());
|
||||||
|
|
||||||
PetActionBar[index].SetActionAndType(action, ActiveStates(type));
|
PetActionBar[index].SetActionAndType(action, ActiveStates(type));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -791,6 +791,7 @@ class MovementInfo
|
||||||
void ChangeOrientation(float o) { pos.o = o; }
|
void ChangeOrientation(float o) { pos.o = o; }
|
||||||
void ChangePosition(float x, float y, float z, float o) { pos.x = x; pos.y = y; pos.z = z; pos.o = o; }
|
void ChangePosition(float x, float y, float z, float o) { pos.x = x; pos.y = y; pos.z = z; pos.o = o; }
|
||||||
void UpdateTime(uint32 _time) { time = _time; }
|
void UpdateTime(uint32 _time) { time = _time; }
|
||||||
|
uint32 GetTime(){ return time; }
|
||||||
|
|
||||||
struct JumpInfo
|
struct JumpInfo
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -469,7 +469,8 @@ enum SummonPropGroup
|
||||||
SUMMON_PROP_GROUP_FRIENDLY = 1,
|
SUMMON_PROP_GROUP_FRIENDLY = 1,
|
||||||
SUMMON_PROP_GROUP_PETS = 2,
|
SUMMON_PROP_GROUP_PETS = 2,
|
||||||
SUMMON_PROP_GROUP_CONTROLLABLE = 3,
|
SUMMON_PROP_GROUP_CONTROLLABLE = 3,
|
||||||
SUMMON_PROP_GROUP_VEHICLE = 4
|
SUMMON_PROP_GROUP_VEHICLE = 4,
|
||||||
|
SUMMON_PROP_GROUP_UNCONTROLLABLE_VEHICLE = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
// SummonProperties.dbc, col 2 == FactionId (m_faction)
|
// SummonProperties.dbc, col 2 == FactionId (m_faction)
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
|
||||||
m_muteTime(mute_time), _player(NULL), m_Socket(sock), _security(sec), _accountId(id), m_expansion(expansion), _logoutTime(0),
|
m_muteTime(mute_time), _player(NULL), m_Socket(sock), _security(sec), _accountId(id), m_expansion(expansion), _logoutTime(0),
|
||||||
m_inQueue(false), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_playerSave(false),
|
m_inQueue(false), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_playerSave(false),
|
||||||
m_sessionDbcLocale(sWorld.GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(sObjectMgr.GetIndexForLocale(locale)),
|
m_sessionDbcLocale(sWorld.GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(sObjectMgr.GetIndexForLocale(locale)),
|
||||||
m_latency(0), m_tutorialState(TUTORIALDATA_UNCHANGED)
|
m_latency(0), m_clientTimeDelay(0), m_tutorialState(TUTORIALDATA_UNCHANGED)
|
||||||
{
|
{
|
||||||
if (sock)
|
if (sock)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -462,6 +462,7 @@ class WorldSession
|
||||||
m_latency = latency;
|
m_latency = latency;
|
||||||
}
|
}
|
||||||
void SetClientTimeDelay(uint32 delay) { m_clientTimeDelay = delay; }
|
void SetClientTimeDelay(uint32 delay) { m_clientTimeDelay = delay; }
|
||||||
|
void ResetClientTimeDelay() { m_clientTimeDelay = 0; }
|
||||||
uint32 getDialogStatus(Player* pPlayer, Object* questgiver, uint32 defstatus);
|
uint32 getDialogStatus(Player* pPlayer, Object* questgiver, uint32 defstatus);
|
||||||
|
|
||||||
public: // opcodes handlers
|
public: // opcodes handlers
|
||||||
|
|
@ -1015,10 +1016,10 @@ class WorldSession
|
||||||
LocaleConstant m_sessionDbcLocale;
|
LocaleConstant m_sessionDbcLocale;
|
||||||
int m_sessionDbLocaleIndex;
|
int m_sessionDbLocaleIndex;
|
||||||
uint32 m_latency;
|
uint32 m_latency;
|
||||||
|
uint32 m_clientTimeDelay;
|
||||||
AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES];
|
AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES];
|
||||||
uint32 m_Tutorials[8];
|
uint32 m_Tutorials[8];
|
||||||
TutorialDataState m_tutorialState;
|
TutorialDataState m_tutorialState;
|
||||||
uint32 m_clientTimeDelay;
|
|
||||||
AddonsList m_addonsList;
|
AddonsList m_addonsList;
|
||||||
ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue;
|
ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1051,17 +1051,18 @@ int WorldSocket::HandlePing(WorldPacket& recvPacket)
|
||||||
|
|
||||||
// critical section
|
// critical section
|
||||||
{
|
{
|
||||||
ACE_GUARD_RETURN(LockType, Guard, m_SessionLock, -1);
|
|
||||||
|
|
||||||
if (m_Session)
|
if (m_Session)
|
||||||
|
{
|
||||||
m_Session->SetLatency(latency);
|
m_Session->SetLatency(latency);
|
||||||
|
m_Session->ResetClientTimeDelay();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sLog.outError("WorldSocket::HandlePing: peer sent CMSG_PING, "
|
sLog.outError("WorldSocket::HandlePing: peer sent CMSG_PING, "
|
||||||
"but is not authenticated or got recently kicked,"
|
"but is not authenticated or got recently kicked,"
|
||||||
" address = %s",
|
" address = %s",
|
||||||
GetRemoteAddress().c_str());
|
GetRemoteAddress().c_str());
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ GridMap::GridMap()
|
||||||
m_gridGetHeight = &GridMap::getHeightFromFlat;
|
m_gridGetHeight = &GridMap::getHeightFromFlat;
|
||||||
m_V9 = NULL;
|
m_V9 = NULL;
|
||||||
m_V8 = NULL;
|
m_V8 = NULL;
|
||||||
|
memset(m_holes, 0, sizeof(m_holes));
|
||||||
|
|
||||||
// Liquid data
|
// Liquid data
|
||||||
m_liquidType = 0;
|
m_liquidType = 0;
|
||||||
|
|
@ -205,6 +206,16 @@ bool GridMap::loadHeightData(FILE* in, uint32 offset, uint32 /*size*/)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GridMap::loadHolesData(FILE* in, uint32 offset, uint32 size)
|
||||||
|
{
|
||||||
|
if (fseek(in, offset, SEEK_SET) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fread(&m_holes, sizeof(m_holes), 1, in) != 1)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GridMap::loadGridMapLiquidData(FILE* in, uint32 offset, uint32 /*size*/)
|
bool GridMap::loadGridMapLiquidData(FILE* in, uint32 offset, uint32 /*size*/)
|
||||||
{
|
{
|
||||||
GridMapLiquidHeader header;
|
GridMapLiquidHeader header;
|
||||||
|
|
@ -255,10 +266,22 @@ float GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const
|
||||||
return m_gridHeight;
|
return m_gridHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GridMap::isHole(int row, int col) const
|
||||||
|
{
|
||||||
|
int cellRow = row / 8; // 8 squares per cell
|
||||||
|
int cellCol = col / 8;
|
||||||
|
int holeRow = row % 8 / 2;
|
||||||
|
int holeCol = (col - (cellCol * 8)) / 2;
|
||||||
|
|
||||||
|
uint16 hole = m_holes[cellRow][cellCol];
|
||||||
|
|
||||||
|
return (hole & holetab_h[holeCol] & holetab_v[holeRow]) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
float GridMap::getHeightFromFloat(float x, float y) const
|
float GridMap::getHeightFromFloat(float x, float y) const
|
||||||
{
|
{
|
||||||
if (!m_V8 || !m_V9)
|
if (!m_V8 || !m_V9)
|
||||||
return m_gridHeight;
|
return INVALID_HEIGHT_VALUE;
|
||||||
|
|
||||||
x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
|
x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
|
||||||
y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
|
y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
|
||||||
|
|
@ -270,6 +293,9 @@ float GridMap::getHeightFromFloat(float x, float y) const
|
||||||
x_int &= (MAP_RESOLUTION - 1);
|
x_int &= (MAP_RESOLUTION - 1);
|
||||||
y_int &= (MAP_RESOLUTION - 1);
|
y_int &= (MAP_RESOLUTION - 1);
|
||||||
|
|
||||||
|
if (isHole(x_int, y_int))
|
||||||
|
return INVALID_HEIGHT_VALUE;
|
||||||
|
|
||||||
// Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid
|
// Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid
|
||||||
// +--------------> X
|
// +--------------> X
|
||||||
// | h1-------h2 Coordinates is:
|
// | h1-------h2 Coordinates is:
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ class GridMap
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
uint16 m_holes[16][16];
|
||||||
uint32 m_flags;
|
uint32 m_flags;
|
||||||
|
|
||||||
// Area data
|
// Area data
|
||||||
|
|
@ -163,6 +164,8 @@ class GridMap
|
||||||
bool loadAreaData(FILE* in, uint32 offset, uint32 size);
|
bool loadAreaData(FILE* in, uint32 offset, uint32 size);
|
||||||
bool loadHeightData(FILE* in, uint32 offset, uint32 size);
|
bool loadHeightData(FILE* in, uint32 offset, uint32 size);
|
||||||
bool loadGridMapLiquidData(FILE* in, uint32 offset, uint32 size);
|
bool loadGridMapLiquidData(FILE* in, uint32 offset, uint32 size);
|
||||||
|
bool loadHolesData(FILE* in, uint32 offset, uint32 size);
|
||||||
|
bool isHole(int row, int col) const;
|
||||||
|
|
||||||
// Get height functions and pointers
|
// Get height functions and pointers
|
||||||
typedef float(GridMap::*pGetHeightPtr)(float x, float y) const;
|
typedef float(GridMap::*pGetHeightPtr)(float x, float y) const;
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,6 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recv_data)
|
||||||
DEBUG_LOG("WORLD: Received opcode CMSG_WHO");
|
DEBUG_LOG("WORLD: Received opcode CMSG_WHO");
|
||||||
// recv_data.hexlike();
|
// recv_data.hexlike();
|
||||||
|
|
||||||
uint32 clientcount = 0;
|
|
||||||
|
|
||||||
uint32 level_min, level_max, racemask, classmask, zones_count, str_count;
|
uint32 level_min, level_max, racemask, classmask, zones_count, str_count;
|
||||||
uint32 zoneids[10]; // 10 is client limit
|
uint32 zoneids[10]; // 10 is client limit
|
||||||
std::string player_name, guild_name;
|
std::string player_name, guild_name;
|
||||||
|
|
@ -149,9 +147,12 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recv_data)
|
||||||
bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_WHO_LIST);
|
bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_WHO_LIST);
|
||||||
AccountTypes gmLevelInWhoList = (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_WHO_LIST);
|
AccountTypes gmLevelInWhoList = (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_WHO_LIST);
|
||||||
|
|
||||||
|
uint32 matchcount = 0;
|
||||||
|
uint32 displaycount = 0;
|
||||||
|
|
||||||
WorldPacket data(SMSG_WHO, 50); // guess size
|
WorldPacket data(SMSG_WHO, 50); // guess size
|
||||||
data << uint32(clientcount); // clientcount place holder, listed count
|
data << uint32(matchcount); // clientcount place holder, listed count
|
||||||
data << uint32(clientcount); // clientcount place holder, online count
|
data << uint32(displaycount); // clientcount place holder, online count
|
||||||
|
|
||||||
// TODO: Guard Player map
|
// TODO: Guard Player map
|
||||||
HashMapHolder<Player>::MapType& m = sObjectAccessor.GetPlayers();
|
HashMapHolder<Player>::MapType& m = sObjectAccessor.GetPlayers();
|
||||||
|
|
@ -250,6 +251,8 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recv_data)
|
||||||
if (!s_show)
|
if (!s_show)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
++displaycount;
|
||||||
|
|
||||||
data << pname; // player name
|
data << pname; // player name
|
||||||
data << gname; // guild name
|
data << gname; // guild name
|
||||||
data << uint32(lvl); // player level
|
data << uint32(lvl); // player level
|
||||||
|
|
@ -257,15 +260,13 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recv_data)
|
||||||
data << uint32(race); // player race
|
data << uint32(race); // player race
|
||||||
data << uint8(gender); // player gender
|
data << uint8(gender); // player gender
|
||||||
data << uint32(pzoneid); // player zone id
|
data << uint32(pzoneid); // player zone id
|
||||||
|
|
||||||
// 50 is maximum player count sent to client
|
|
||||||
if ((++clientcount) == 50)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 count = m.size();
|
if (sWorld.getConfig(CONFIG_UINT32_MAX_WHOLIST_RETURNS) && matchcount > sWorld.getConfig(CONFIG_UINT32_MAX_WHOLIST_RETURNS))
|
||||||
data.put(0, clientcount); // insert right count, listed count
|
matchcount = sWorld.getConfig(CONFIG_UINT32_MAX_WHOLIST_RETURNS);
|
||||||
data.put(4, count > 50 ? count : clientcount); // insert right count, online count
|
|
||||||
|
data.put(0, displaycount); // insert right count, count displayed
|
||||||
|
data.put(4, matchcount); // insert right count, count of matches
|
||||||
|
|
||||||
SendPacket(&data);
|
SendPacket(&data);
|
||||||
DEBUG_LOG("WORLD: Send SMSG_WHO Message");
|
DEBUG_LOG("WORLD: Send SMSG_WHO Message");
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include "GridMap.h"
|
#include "GridMap.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
#include "Creature.h"
|
||||||
|
|
||||||
#include "MoveMap.h"
|
#include "MoveMap.h"
|
||||||
#include "MoveMapSharedDefines.h"
|
#include "MoveMapSharedDefines.h"
|
||||||
|
|
@ -65,10 +66,30 @@ namespace MMAP
|
||||||
delete[] mapList;
|
delete[] mapList;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MMapFactory::IsPathfindingEnabled(uint32 mapId)
|
bool MMapFactory::IsPathfindingEnabled(uint32 mapId, const Unit* unit = nullptr)
|
||||||
{
|
{
|
||||||
return sWorld.getConfig(CONFIG_BOOL_MMAP_ENABLED)
|
if (!sWorld.getConfig(CONFIG_BOOL_MMAP_ENABLED))
|
||||||
&& g_mmapDisabledIds->find(mapId) == g_mmapDisabledIds->end();
|
return false;
|
||||||
|
|
||||||
|
if (unit)
|
||||||
|
{
|
||||||
|
// always use mmaps for players
|
||||||
|
if (unit->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (IsPathfindingForceDisabled(unit))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (IsPathfindingForceEnabled(unit))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// always use mmaps for pets of players (can still be disabled by extra-flag for pet creature)
|
||||||
|
if (unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->IsPet() && unit->GetOwner() &&
|
||||||
|
unit->GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_mmapDisabledIds->find(mapId) == g_mmapDisabledIds->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMapFactory::clear()
|
void MMapFactory::clear()
|
||||||
|
|
@ -80,6 +101,34 @@ namespace MMAP
|
||||||
g_MMapManager = NULL;
|
g_MMapManager = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MMapFactory::IsPathfindingForceEnabled(const Unit* unit)
|
||||||
|
{
|
||||||
|
if (const Creature* pCreature = dynamic_cast<const Creature*>(unit))
|
||||||
|
{
|
||||||
|
if (const CreatureInfo* pInfo = pCreature->GetCreatureInfo())
|
||||||
|
{
|
||||||
|
if (pInfo->ExtraFlags & CREATURE_EXTRA_FLAG_MMAP_FORCE_ENABLE)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MMapFactory::IsPathfindingForceDisabled(const Unit* unit)
|
||||||
|
{
|
||||||
|
if (const Creature* pCreature = dynamic_cast<const Creature*>(unit))
|
||||||
|
{
|
||||||
|
if (const CreatureInfo* pInfo = pCreature->GetCreatureInfo())
|
||||||
|
{
|
||||||
|
if (pInfo->ExtraFlags & CREATURE_EXTRA_FLAG_MMAP_FORCE_DISABLE)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// ######################## MMapManager ########################
|
// ######################## MMapManager ########################
|
||||||
MMapManager::~MMapManager()
|
MMapManager::~MMapManager()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@
|
||||||
#include "../../dep/recastnavigation/Detour/Include/DetourNavMesh.h"
|
#include "../../dep/recastnavigation/Detour/Include/DetourNavMesh.h"
|
||||||
#include "../../dep/recastnavigation/Detour/Include/DetourNavMeshQuery.h"
|
#include "../../dep/recastnavigation/Detour/Include/DetourNavMeshQuery.h"
|
||||||
|
|
||||||
|
class Unit;
|
||||||
|
|
||||||
// memory management
|
// memory management
|
||||||
inline void* dtCustomAlloc(int size, dtAllocHint /*hint*/)
|
inline void* dtCustomAlloc(int size, dtAllocHint /*hint*/)
|
||||||
{
|
{
|
||||||
|
|
@ -107,7 +109,9 @@ namespace MMAP
|
||||||
static MMapManager* createOrGetMMapManager();
|
static MMapManager* createOrGetMMapManager();
|
||||||
static void clear();
|
static void clear();
|
||||||
static void preventPathfindingOnMaps(const char* ignoreMapIds);
|
static void preventPathfindingOnMaps(const char* ignoreMapIds);
|
||||||
static bool IsPathfindingEnabled(uint32 mapId);
|
static bool IsPathfindingEnabled(uint32 mapId, const Unit* unit);
|
||||||
|
static bool IsPathfindingForceEnabled(const Unit* unit);
|
||||||
|
static bool IsPathfindingForceDisabled(const Unit* unit);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@
|
||||||
#include "MapPersistentStateMgr.h"
|
#include "MapPersistentStateMgr.h"
|
||||||
#include "ObjectMgr.h"
|
#include "ObjectMgr.h"
|
||||||
|
|
||||||
|
#define MOVEMENT_PACKET_TIME_DELAY 0
|
||||||
|
|
||||||
void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recv_data*/)
|
void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recv_data*/)
|
||||||
{
|
{
|
||||||
DEBUG_LOG("WORLD: got MSG_MOVE_WORLDPORT_ACK.");
|
DEBUG_LOG("WORLD: got MSG_MOVE_WORLDPORT_ACK.");
|
||||||
|
|
@ -595,7 +597,9 @@ bool WorldSession::VerifyMovementInfo(MovementInfo const& movementInfo, ObjectGu
|
||||||
|
|
||||||
void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo)
|
void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo)
|
||||||
{
|
{
|
||||||
movementInfo.UpdateTime(WorldTimer::getMSTime());
|
if (m_clientTimeDelay == 0)
|
||||||
|
m_clientTimeDelay = WorldTimer::getMSTime() - movementInfo.GetTime();
|
||||||
|
movementInfo.UpdateTime(movementInfo.GetTime() + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY);
|
||||||
|
|
||||||
Unit* mover = _player->GetMover();
|
Unit* mover = _player->GetMover();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -702,7 +702,7 @@ void ScriptMgr::LoadScripts(ScriptMapMapName& scripts, const char* tablename)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCRIPT_COMMAND_SEND_AI_EVENT_AROUND: // 35
|
case SCRIPT_COMMAND_SEND_AI_EVENT: // 35
|
||||||
{
|
{
|
||||||
if (tmp.sendAIEvent.eventType >= MAXIMAL_AI_EVENT_EVENTAI)
|
if (tmp.sendAIEvent.eventType >= MAXIMAL_AI_EVENT_EVENTAI)
|
||||||
{
|
{
|
||||||
|
|
@ -717,7 +717,7 @@ void ScriptMgr::LoadScripts(ScriptMapMapName& scripts, const char* tablename)
|
||||||
{
|
{
|
||||||
if (tmp.moveDynamic.maxDist < tmp.moveDynamic.minDist)
|
if (tmp.moveDynamic.maxDist < tmp.moveDynamic.minDist)
|
||||||
{
|
{
|
||||||
sLog.outErrorDb("Table `%s` has invalid min-dist (datalong2 = %u) less than max-dist (datalon = %u) in SCRIPT_COMMAND_MOVE_DYNAMIC for script id %u", tablename, tmp.moveDynamic.minDist, tmp.moveDynamic.maxDist, tmp.id);
|
sLog.outErrorDb("Table `%s` has invalid min-dist (datalong2 = %u) less than max-dist (datalong = %u) in SCRIPT_COMMAND_MOVE_DYNAMIC for script id %u", tablename, tmp.moveDynamic.minDist, tmp.moveDynamic.maxDist, tmp.id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -736,7 +736,36 @@ void ScriptMgr::LoadScripts(ScriptMapMapName& scripts, const char* tablename)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCRIPT_COMMAND_CHANGE_ENTRY: // 39
|
case SCRIPT_COMMAND_SET_FLY: // 39
|
||||||
|
case SCRIPT_COMMAND_DESPAWN_GO: // 40
|
||||||
|
case SCRIPT_COMMAND_RESPAWN: // 41
|
||||||
|
break;
|
||||||
|
case SCRIPT_COMMAND_SET_EQUIPMENT_SLOTS: // 42
|
||||||
|
{
|
||||||
|
if (tmp.textId[0] < 0 || tmp.textId[1] < 0 || tmp.textId[2] < 0)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("Table `%s` has invalid equipment slot (dataint = %u, dataint2 = %u, dataint3 = %u) in SCRIPT_COMMAND_SET_EQUIPMENT_SLOTS for script id %u", tablename, tmp.textId[0], tmp.textId[1], tmp.textId[2], tmp.id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCRIPT_COMMAND_RESET_GO: // 43
|
||||||
|
break;
|
||||||
|
case SCRIPT_COMMAND_UPDATE_TEMPLATE: // 44
|
||||||
|
{
|
||||||
|
if (!sCreatureStorage.LookupEntry<CreatureInfo>(tmp.updateTemplate.newTemplate))
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("Table `%s` uses nonexistent creature entry %u in SCRIPT_COMMAND_UPDATE_TEMPLATE for script id %u.", tablename, tmp.updateTemplate.newTemplate, tmp.id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tmp.updateTemplate.newFactionTeam != 0 && tmp.updateTemplate.newFactionTeam != 1)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("Table `%s` uses nonexistent faction team %u in SCRIPT_COMMAND_UPDATE_TEMPLATE for script id %u.", tablename, tmp.updateTemplate.newFactionTeam, tmp.id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCRIPT_COMMAND_CHANGE_ENTRY: // 45
|
||||||
{
|
{
|
||||||
if (tmp.changeEntry.creatureEntry && !ObjectMgr::GetCreatureTemplate(tmp.changeEntry.creatureEntry))
|
if (tmp.changeEntry.creatureEntry && !ObjectMgr::GetCreatureTemplate(tmp.changeEntry.creatureEntry))
|
||||||
{
|
{
|
||||||
|
|
@ -1048,15 +1077,24 @@ bool ScriptAction::GetScriptProcessTargets(WorldObject* pOrigSource, WorldObject
|
||||||
|
|
||||||
if (m_script->IsCreatureBuddy())
|
if (m_script->IsCreatureBuddy())
|
||||||
{
|
{
|
||||||
Creature* pCreatureBuddy = NULL;
|
Creature* pCreatureBuddy = nullptr;
|
||||||
|
|
||||||
|
if (m_script->data_flags & SCRIPT_FLAG_BUDDY_IS_DESPAWNED)
|
||||||
|
{
|
||||||
|
MaNGOS::AllCreaturesOfEntryInRangeCheck u_check(pSearcher, m_script->buddyEntry, m_script->searchRadiusOrGuid);
|
||||||
|
MaNGOS::CreatureLastSearcher<MaNGOS::AllCreaturesOfEntryInRangeCheck> searcher(pCreatureBuddy, u_check);
|
||||||
|
Cell::VisitGridObjects(pSearcher, searcher, m_script->searchRadiusOrGuid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*pSearcher, m_script->buddyEntry, true, false, m_script->searchRadiusOrGuid, true);
|
MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*pSearcher, m_script->buddyEntry, true, false, m_script->searchRadiusOrGuid, true);
|
||||||
MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(pCreatureBuddy, u_check);
|
MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(pCreatureBuddy, u_check);
|
||||||
|
|
||||||
if (m_script->data_flags & SCRIPT_FLAG_BUDDY_IS_PET)
|
if (m_script->data_flags & SCRIPT_FLAG_BUDDY_IS_PET)
|
||||||
{ Cell::VisitWorldObjects(pSearcher, searcher, m_script->searchRadiusOrGuid); }
|
Cell::VisitWorldObjects(pSearcher, searcher, m_script->searchRadiusOrGuid);
|
||||||
else // Normal Creature
|
else // Normal Creature
|
||||||
{ Cell::VisitGridObjects(pSearcher, searcher, m_script->searchRadiusOrGuid); }
|
Cell::VisitGridObjects(pSearcher, searcher, m_script->searchRadiusOrGuid);
|
||||||
|
}
|
||||||
|
|
||||||
pBuddy = pCreatureBuddy;
|
pBuddy = pCreatureBuddy;
|
||||||
|
|
||||||
|
|
@ -1894,55 +1932,80 @@ bool ScriptAction::HandleScriptStep()
|
||||||
}
|
}
|
||||||
return terminateResult;
|
return terminateResult;
|
||||||
}
|
}
|
||||||
case SCRIPT_COMMAND_SEND_AI_EVENT_AROUND: // 35
|
case SCRIPT_COMMAND_SEND_AI_EVENT: // 35
|
||||||
{
|
{
|
||||||
if (LogIfNotCreature(pSource))
|
if (LogIfNotCreature(pSource))
|
||||||
return false;
|
return false;
|
||||||
if (LogIfNotUnit(pTarget))
|
if (LogIfNotUnit(pTarget))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// if radius is provided send AI event around
|
||||||
|
if (m_script->sendAIEvent.radius)
|
||||||
((Creature*)pSource)->AI()->SendAIEventAround(AIEventType(m_script->sendAIEvent.eventType), (Unit*)pTarget, 0, float(m_script->sendAIEvent.radius));
|
((Creature*)pSource)->AI()->SendAIEventAround(AIEventType(m_script->sendAIEvent.eventType), (Unit*)pTarget, 0, float(m_script->sendAIEvent.radius));
|
||||||
|
// else if no radius and target is creature send AI event to target
|
||||||
|
else if (pTarget->GetTypeId() == TYPEID_UNIT)
|
||||||
|
((Creature*)pSource)->AI()->SendAIEvent(AIEventType(m_script->sendAIEvent.eventType), nullptr, (Creature*)pTarget);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCRIPT_COMMAND_TURN_TO: // 36
|
case SCRIPT_COMMAND_TURN_TO: // 36
|
||||||
{
|
{
|
||||||
if (LogIfNotUnit(pSource))
|
if (LogIfNotCreature(pSource))
|
||||||
{ break; }
|
return false;
|
||||||
|
Creature* pCSource = static_cast<Creature*>(pSource);
|
||||||
|
if (!pTarget)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, command _SET_FACING (%u): No target found.", m_table, m_script->id, m_script->command);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (m_script->turnTo.targetId)
|
||||||
|
{
|
||||||
|
float x, y, z, o;
|
||||||
|
if (pCSource->GetMotionMaster()->empty() || !pCSource->GetMotionMaster()->top()->GetResetPosition(*pCSource, x, y, z, o))
|
||||||
|
pCSource->GetRespawnCoord(x, y, z, &o);
|
||||||
|
pCSource->SetFacingTo(o);
|
||||||
|
|
||||||
((Unit*)pSource)->SetFacingTo(pSource->GetAngle(pTarget));
|
if (m_script->data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL && !pCSource->IsInCombat())
|
||||||
|
pCSource->SetTargetGuid(ObjectGuid());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pCSource->SetFacingToObject(pTarget);
|
||||||
|
if (m_script->data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL && !LogIfNotUnit(pTarget) && !pCSource->IsInCombat())
|
||||||
|
pCSource->SetTargetGuid(pTarget->GetObjectGuid());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCRIPT_COMMAND_MOVE_DYNAMIC: // 37
|
case SCRIPT_COMMAND_MOVE_DYNAMIC: // 37
|
||||||
{
|
{
|
||||||
//if (LogIfNotCreature(pSource))
|
if (LogIfNotCreature(pSource))
|
||||||
// return false;
|
return false;
|
||||||
//if (LogIfNotUnit(pTarget))
|
if (LogIfNotUnit(pTarget))
|
||||||
// return false;
|
return false;
|
||||||
|
|
||||||
//float x, y, z;
|
float x, y, z;
|
||||||
//if (m_script->moveDynamic.maxDist == 0) // Move to pTarget
|
if (m_script->moveDynamic.maxDist == 0) // Move to pTarget
|
||||||
//{
|
{
|
||||||
// if (pTarget == pSource)
|
if (pTarget == pSource)
|
||||||
// {
|
{
|
||||||
// sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, _MOVE_DYNAMIC called with maxDist == 0, but resultingSource == resultingTarget (== %s)", m_table, m_script->id, pSource->GetGuidStr().c_str());
|
sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, _MOVE_DYNAMIC called with maxDist == 0, but resultingSource == resultingTarget (== %s)", m_table, m_script->id, pSource->GetGuidStr().c_str());
|
||||||
// break;
|
break;
|
||||||
// }
|
}
|
||||||
// pTarget->GetContactPoint(pSource, x, y, z);
|
pTarget->GetContactPoint(pSource, x, y, z);
|
||||||
//}
|
}
|
||||||
//else // Calculate position
|
else // Calculate position
|
||||||
//{
|
{
|
||||||
// float orientation;
|
float orientation;
|
||||||
// if (m_script->data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL)
|
if (m_script->data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL)
|
||||||
// orientation = pSource->GetOrientation() + m_script->o + 2 * M_PI_F;
|
orientation = pSource->GetOrientation() + m_script->o + 2 * M_PI_F;
|
||||||
// else
|
else
|
||||||
// orientation = m_script->o;
|
orientation = m_script->o;
|
||||||
|
|
||||||
// pSource->GetRandomPoint(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), m_script->moveDynamic.maxDist, x, y, z,
|
pSource->GetRandomPoint(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), m_script->moveDynamic.maxDist, x, y, z,
|
||||||
// m_script->moveDynamic.minDist, (orientation == 0.0f ? NULL : &orientation));
|
m_script->moveDynamic.minDist, (orientation == 0.0f ? nullptr : &orientation));
|
||||||
// z = std::max(z, pTarget->GetPositionZ());
|
z = std::max(z, pTarget->GetPositionZ());
|
||||||
// pSource->UpdateAllowedPositionZ(x, y, z);
|
pSource->UpdateAllowedPositionZ(x, y, z);
|
||||||
//}
|
}
|
||||||
//((Creature*)pSource)->GetMotionMaster()->MovePoint(1, x, y, z);
|
((Creature*)pSource)->GetMotionMaster()->MovePoint(1, x, y, z);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCRIPT_COMMAND_SEND_MAIL: // 38
|
case SCRIPT_COMMAND_SEND_MAIL: // 38
|
||||||
|
|
@ -1962,7 +2025,98 @@ bool ScriptAction::HandleScriptStep()
|
||||||
MailDraft(m_script->sendMail.mailTemplateId).SendMailTo(static_cast<Player*>(pTarget), sender, MAIL_CHECK_MASK_HAS_BODY, deliverDelay);
|
MailDraft(m_script->sendMail.mailTemplateId).SendMailTo(static_cast<Player*>(pTarget), sender, MAIL_CHECK_MASK_HAS_BODY, deliverDelay);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCRIPT_COMMAND_CHANGE_ENTRY: // 39
|
case SCRIPT_COMMAND_SET_FLY: // 39
|
||||||
|
{
|
||||||
|
if (LogIfNotCreature(pSource))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// enable / disable the fly anim flag
|
||||||
|
if (m_script->data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL)
|
||||||
|
{
|
||||||
|
if (m_script->fly.fly)
|
||||||
|
pSource->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_FLY_ANIM);
|
||||||
|
else
|
||||||
|
pSource->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_FLY_ANIM);
|
||||||
|
}
|
||||||
|
|
||||||
|
((Creature*)pSource)->SetLevitate(!!m_script->fly.fly);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCRIPT_COMMAND_DESPAWN_GO: // 40
|
||||||
|
{
|
||||||
|
if (LogIfNotGameObject(pTarget))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ToDo: Change this to pGo->ForcedDespawn() when function is implemented!
|
||||||
|
((GameObject*)pTarget)->SetLootState(GO_JUST_DEACTIVATED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCRIPT_COMMAND_RESPAWN: // 41
|
||||||
|
{
|
||||||
|
if (LogIfNotCreature(pTarget))
|
||||||
|
break;
|
||||||
|
|
||||||
|
((Creature*)pTarget)->Respawn();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCRIPT_COMMAND_SET_EQUIPMENT_SLOTS: // 42
|
||||||
|
{
|
||||||
|
if (LogIfNotCreature(pSource))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Creature* pCSource = static_cast<Creature*>(pSource);
|
||||||
|
// reset default
|
||||||
|
if (m_script->setEquipment.resetDefault)
|
||||||
|
{
|
||||||
|
pCSource->LoadEquipment(pCSource->GetCreatureInfo()->EquipmentTemplateId, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// main hand
|
||||||
|
if (m_script->textId[0] >= 0)
|
||||||
|
pCSource->SetVirtualItem(VIRTUAL_ITEM_SLOT_0, m_script->textId[0]);
|
||||||
|
|
||||||
|
// off hand
|
||||||
|
if (m_script->textId[1] >= 0)
|
||||||
|
pCSource->SetVirtualItem(VIRTUAL_ITEM_SLOT_1, m_script->textId[1]);
|
||||||
|
|
||||||
|
// ranged
|
||||||
|
if (m_script->textId[2] >= 0)
|
||||||
|
pCSource->SetVirtualItem(VIRTUAL_ITEM_SLOT_2, m_script->textId[2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCRIPT_COMMAND_RESET_GO: // 43
|
||||||
|
{
|
||||||
|
if (LogIfNotGameObject(pTarget))
|
||||||
|
break;
|
||||||
|
|
||||||
|
GameObject* pGoTarget = static_cast<GameObject*>(pTarget);
|
||||||
|
switch (pGoTarget->GetGoType())
|
||||||
|
{
|
||||||
|
case GAMEOBJECT_TYPE_DOOR:
|
||||||
|
case GAMEOBJECT_TYPE_BUTTON:
|
||||||
|
pGoTarget->ResetDoorOrButton();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, command %u failed for gameobject(buddyEntry: %u). Gameobject is not a door or button", m_table, m_script->id, m_script->command, m_script->buddyEntry);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCRIPT_COMMAND_UPDATE_TEMPLATE: // 44
|
||||||
|
{
|
||||||
|
if (LogIfNotCreature(pSource))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Creature* pCSource = static_cast<Creature*>(pSource);
|
||||||
|
|
||||||
|
if (pCSource->GetEntry() != m_script->updateTemplate.newTemplate)
|
||||||
|
pCSource->UpdateEntry(m_script->updateTemplate.newTemplate, m_script->updateTemplate.newFactionTeam ? HORDE : ALLIANCE);
|
||||||
|
else
|
||||||
|
sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, command %u failed. Source already has specified creature entry.", m_table, m_script->id, m_script->command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCRIPT_COMMAND_CHANGE_ENTRY: // 45
|
||||||
{
|
{
|
||||||
if (LogIfNotCreature(pSource))
|
if (LogIfNotCreature(pSource))
|
||||||
{ break; }
|
{ break; }
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ enum DBScriptCommand // resSource, resTar
|
||||||
SCRIPT_COMMAND_XP_USER = 33, // source or target with Player, datalong = bool (0=off, 1=on)
|
SCRIPT_COMMAND_XP_USER = 33, // source or target with Player, datalong = bool (0=off, 1=on)
|
||||||
SCRIPT_COMMAND_TERMINATE_COND = 34, // datalong = condition_id, datalong2 = if != 0 then quest_id of quest that will be failed for player's group if the script is terminated
|
SCRIPT_COMMAND_TERMINATE_COND = 34, // datalong = condition_id, datalong2 = if != 0 then quest_id of quest that will be failed for player's group if the script is terminated
|
||||||
// data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL terminate when condition is false ELSE terminate when condition is true
|
// data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL terminate when condition is false ELSE terminate when condition is true
|
||||||
SCRIPT_COMMAND_SEND_AI_EVENT_AROUND = 35, // resSource = Creature, resTarget = Unit
|
SCRIPT_COMMAND_SEND_AI_EVENT = 35, // resSource = Creature, resTarget = Unit
|
||||||
// datalong = AIEventType
|
// datalong = AIEventType
|
||||||
// datalong2 = radius
|
// datalong2 = radius
|
||||||
SCRIPT_COMMAND_TURN_TO = 36, // resSource = Unit, resTarget = Unit/none
|
SCRIPT_COMMAND_TURN_TO = 36, // resSource = Unit, resTarget = Unit/none
|
||||||
|
|
@ -145,8 +145,20 @@ enum DBScriptCommand // resSource, resTar
|
||||||
SCRIPT_COMMAND_SEND_MAIL = 38, // resSource WorldObject, can be NULL, resTarget Player
|
SCRIPT_COMMAND_SEND_MAIL = 38, // resSource WorldObject, can be NULL, resTarget Player
|
||||||
// datalong: Send mailTemplateId from resSource (if provided) to player resTarget
|
// datalong: Send mailTemplateId from resSource (if provided) to player resTarget
|
||||||
// datalong2: AlternativeSenderEntry. Use as sender-Entry
|
// datalong2: AlternativeSenderEntry. Use as sender-Entry
|
||||||
|
SCRIPT_COMMAND_SET_FLY = 39, // resSource = Creature
|
||||||
|
// datalong = bool 0=off, 1=on
|
||||||
|
// data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL set/unset byte flag UNIT_BYTE1_FLAG_FLY_ANIM
|
||||||
// dataint1: Delay (>= 0) in Seconds
|
// dataint1: Delay (>= 0) in Seconds
|
||||||
SCRIPT_COMMAND_CHANGE_ENTRY = 39, // resSource = Creature, datalong=creature entry
|
SCRIPT_COMMAND_DESPAWN_GO = 40, // resTarget = GameObject
|
||||||
|
SCRIPT_COMMAND_RESPAWN = 41, // resSource = Creature. Requires SCRIPT_FLAG_BUDDY_IS_DESPAWNED to find dead or despawned targets
|
||||||
|
SCRIPT_COMMAND_SET_EQUIPMENT_SLOTS = 42, // resSource = Creature
|
||||||
|
// datalong = resetDefault: bool 0=false, 1=true
|
||||||
|
// dataint = main hand slot; dataint2 = off hand slot; dataint3 = ranged slot
|
||||||
|
SCRIPT_COMMAND_RESET_GO = 43, // resTarget = GameObject
|
||||||
|
SCRIPT_COMMAND_UPDATE_TEMPLATE = 44, // resSource = Creature
|
||||||
|
// datalong = new Creature entry
|
||||||
|
// datalong2 = Alliance(0) Horde(1), other values throw error
|
||||||
|
SCRIPT_COMMAND_CHANGE_ENTRY = 45, // resSource = Creature, datalong=creature entry
|
||||||
// dataint1 = entry
|
// dataint1 = entry
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -161,8 +173,9 @@ enum ScriptInfoDataFlags
|
||||||
SCRIPT_FLAG_COMMAND_ADDITIONAL = 0x08, // command dependend
|
SCRIPT_FLAG_COMMAND_ADDITIONAL = 0x08, // command dependend
|
||||||
SCRIPT_FLAG_BUDDY_BY_GUID = 0x10, // take the buddy by guid
|
SCRIPT_FLAG_BUDDY_BY_GUID = 0x10, // take the buddy by guid
|
||||||
SCRIPT_FLAG_BUDDY_IS_PET = 0x20, // buddy is a pet
|
SCRIPT_FLAG_BUDDY_IS_PET = 0x20, // buddy is a pet
|
||||||
|
SCRIPT_FLAG_BUDDY_IS_DESPAWNED = 0X40, // buddy is dead or despawned
|
||||||
};
|
};
|
||||||
#define MAX_SCRIPT_FLAG_VALID (2 * SCRIPT_FLAG_BUDDY_IS_PET - 1)
|
#define MAX_SCRIPT_FLAG_VALID (2 * SCRIPT_FLAG_BUDDY_IS_DESPAWNED - 1)
|
||||||
|
|
||||||
struct ScriptInfo
|
struct ScriptInfo
|
||||||
{
|
{
|
||||||
|
|
@ -371,7 +384,7 @@ struct ScriptInfo
|
||||||
uint32 failQuest; // datalong2
|
uint32 failQuest; // datalong2
|
||||||
} terminateCond;
|
} terminateCond;
|
||||||
|
|
||||||
struct // SCRIPT_COMMAND_SEND_AI_EVENT_AROUND (35)
|
struct // SCRIPT_COMMAND_SEND_AI_EVENT (35)
|
||||||
{
|
{
|
||||||
uint32 eventType; // datalong
|
uint32 eventType; // datalong
|
||||||
uint32 radius; // datalong2
|
uint32 radius; // datalong2
|
||||||
|
|
@ -395,7 +408,30 @@ struct ScriptInfo
|
||||||
uint32 altSender; // datalong2;
|
uint32 altSender; // datalong2;
|
||||||
} sendMail;
|
} sendMail;
|
||||||
|
|
||||||
struct // SCRIPT_COMMAND_MORPH_TO_ENTRY_OR_MODEL (23)
|
struct // SCRIPT_COMMAND_SET_FLY (39)
|
||||||
|
{
|
||||||
|
uint32 fly; // datalong
|
||||||
|
uint32 empty; // datalong2
|
||||||
|
} fly;
|
||||||
|
|
||||||
|
// datalong unsed // SCRIPT_COMMAND_DESPAWN_GO (40)
|
||||||
|
// datalong unsed // SCRIPT_COMMAND_RESPAWN (41)
|
||||||
|
|
||||||
|
struct // SCRIPT_COMMAND_SET_EQUIPMENT_SLOTS (42)
|
||||||
|
{
|
||||||
|
uint32 resetDefault; // datalong
|
||||||
|
uint32 empty; // datalong2
|
||||||
|
} setEquipment;
|
||||||
|
|
||||||
|
// datalong unsed // SCRIPT_COMMAND_RESET_GO (43)
|
||||||
|
|
||||||
|
struct // SCRIPT_COMMAND_UPDATE_TEMPLATE (44)
|
||||||
|
{
|
||||||
|
uint32 newTemplate; // datalong
|
||||||
|
uint32 newFactionTeam; // datalong2
|
||||||
|
} updateTemplate;
|
||||||
|
|
||||||
|
struct // SCRIPT_COMMAND_MORPH_TO_ENTRY_OR_MODEL (45)
|
||||||
{
|
{
|
||||||
uint32 creatureEntry; // datalong
|
uint32 creatureEntry; // datalong
|
||||||
uint32 empty1; // datalong2
|
uint32 empty1; // datalong2
|
||||||
|
|
@ -443,6 +479,8 @@ struct ScriptInfo
|
||||||
case SCRIPT_COMMAND_CLOSE_DOOR:
|
case SCRIPT_COMMAND_CLOSE_DOOR:
|
||||||
case SCRIPT_COMMAND_ACTIVATE_OBJECT:
|
case SCRIPT_COMMAND_ACTIVATE_OBJECT:
|
||||||
case SCRIPT_COMMAND_GO_LOCK_STATE:
|
case SCRIPT_COMMAND_GO_LOCK_STATE:
|
||||||
|
case SCRIPT_COMMAND_DESPAWN_GO:
|
||||||
|
case SCRIPT_COMMAND_RESET_GO:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -464,6 +502,7 @@ struct ScriptInfo
|
||||||
case SCRIPT_COMMAND_TERMINATE_COND:
|
case SCRIPT_COMMAND_TERMINATE_COND:
|
||||||
case SCRIPT_COMMAND_TURN_TO:
|
case SCRIPT_COMMAND_TURN_TO:
|
||||||
case SCRIPT_COMMAND_MOVE_DYNAMIC:
|
case SCRIPT_COMMAND_MOVE_DYNAMIC:
|
||||||
|
case SCRIPT_COMMAND_SET_FLY:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -6154,24 +6154,29 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||||
case SPELL_EFFECT_LEAP:
|
case SPELL_EFFECT_LEAP:
|
||||||
case SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER:
|
case SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER:
|
||||||
{
|
{
|
||||||
float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellEffect->GetRadiusIndex()));
|
if (!m_caster || m_caster->IsTaxiFlying())
|
||||||
float fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
|
return SPELL_FAILED_NOT_ON_TAXI;
|
||||||
float fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
|
|
||||||
// teleport a bit above terrain level to avoid falling below it
|
|
||||||
float fz = m_caster->GetMap()->GetHeight(m_caster->GetPhaseMask(), fx, fy, m_caster->GetPositionZ());
|
|
||||||
if (fz <= INVALID_HEIGHT) // note: this also will prevent use effect in instances without vmaps height enabled
|
|
||||||
return SPELL_FAILED_TRY_AGAIN;
|
|
||||||
|
|
||||||
float caster_pos_z = m_caster->GetPositionZ();
|
// Blink has leap first and then removing of auras with root effect
|
||||||
// Control the caster to not climb or drop when +-fz > 8
|
// need further research with this
|
||||||
if (!(fz <= caster_pos_z + 8 && fz >= caster_pos_z - 8))
|
SpellEffectEntry const* spellEffect = m_spellInfo->GetSpellEffect(SpellEffectIndex(i));
|
||||||
return SPELL_FAILED_TRY_AGAIN;
|
if (!spellEffect)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (spellEffect->Effect != SPELL_EFFECT_LEAP)
|
||||||
|
{
|
||||||
|
if (m_caster->hasUnitState(UNIT_STAT_ROOT))
|
||||||
|
return SPELL_FAILED_ROOTED;
|
||||||
|
}
|
||||||
|
|
||||||
// not allow use this effect at battleground until battleground start
|
|
||||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
{
|
||||||
|
// not allow use this effect at battleground until battleground start
|
||||||
if (BattleGround const* bg = ((Player*)m_caster)->GetBattleGround())
|
if (BattleGround const* bg = ((Player*)m_caster)->GetBattleGround())
|
||||||
if (bg->GetStatus() != STATUS_IN_PROGRESS)
|
if (bg->GetStatus() != STATUS_IN_PROGRESS)
|
||||||
return SPELL_FAILED_TRY_AGAIN;
|
return SPELL_FAILED_TRY_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELL_EFFECT_STEAL_BENEFICIAL_BUFF:
|
case SPELL_EFFECT_STEAL_BENEFICIAL_BUFF:
|
||||||
|
|
|
||||||
|
|
@ -2976,7 +2976,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
||||||
{
|
{
|
||||||
//AreaTableEntry const* area = GetAreaEntryByAreaID(target->GetAreaId());
|
//AreaTableEntry const* area = GetAreaEntryByAreaID(target->GetAreaId());
|
||||||
|
|
||||||
//// Dalaran restricted flight zone (recheck before apply unmount)
|
//// Dalaran restricstruct boss_freyted flight zone (recheck before apply unmount)
|
||||||
//if (area && target->GetTypeId() == TYPEID_PLAYER && (area->flags & AREA_FLAG_CANNOT_FLY) &&
|
//if (area && target->GetTypeId() == TYPEID_PLAYER && (area->flags & AREA_FLAG_CANNOT_FLY) &&
|
||||||
// ((Player*)target)->IsFreeFlying() && !((Player*)target)->isGameMaster())
|
// ((Player*)target)->IsFreeFlying() && !((Player*)target)->isGameMaster())
|
||||||
//{
|
//{
|
||||||
|
|
|
||||||
|
|
@ -5384,14 +5384,13 @@ void Spell::EffectSummonType(SpellEffectEntry const* effect)
|
||||||
if (summon_prop->Group == SUMMON_PROP_GROUP_PETS && prop_id != 1562)
|
if (summon_prop->Group == SUMMON_PROP_GROUP_PETS && prop_id != 1562)
|
||||||
{
|
{
|
||||||
DoSummonPet(effect);
|
DoSummonPet(effect);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expected Amount: TODO - there are quite some exceptions (like totems, engineering dragonlings..)
|
// Expected Amount: TODO - there are quite some exceptions (like totems, engineering dragonlings..)
|
||||||
uint32 amount = damage > 0 ? damage : 1;
|
uint32 amount = damage > 0 ? damage : 1;
|
||||||
|
|
||||||
// basepoints of SUMMON_PROP_GROUP_VEHICLE is often a spellId, set amount to 1
|
// basepoints of SUMMON_PROP_GROUP_VEHICLE is often a spellId, set amount to 1
|
||||||
if (summon_prop->Group == SUMMON_PROP_GROUP_VEHICLE)
|
if (summon_prop->Group == SUMMON_PROP_GROUP_VEHICLE || summon_prop->Group == SUMMON_PROP_GROUP_UNCONTROLLABLE_VEHICLE || summon_prop->Group == SUMMON_PROP_GROUP_CONTROLLABLE)
|
||||||
amount = 1;
|
amount = 1;
|
||||||
|
|
||||||
// Get casting object
|
// Get casting object
|
||||||
|
|
@ -5552,6 +5551,7 @@ void Spell::EffectSummonType(SpellEffectEntry const* effect)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SUMMON_PROP_GROUP_VEHICLE:
|
case SUMMON_PROP_GROUP_VEHICLE:
|
||||||
|
case SUMMON_PROP_GROUP_UNCONTROLLABLE_VEHICLE:
|
||||||
{
|
{
|
||||||
summonResult = DoSummonVehicle(summonPositions, summon_prop, effect, level);
|
summonResult = DoSummonVehicle(summonPositions, summon_prop, effect, level);
|
||||||
break;
|
break;
|
||||||
|
|
@ -5750,17 +5750,30 @@ bool Spell::DoSummonGuardian(CreatureSummonPositions& list, SummonPropertiesEntr
|
||||||
if (m_duration > 0)
|
if (m_duration > 0)
|
||||||
spawnCreature->SetDuration(m_duration);
|
spawnCreature->SetDuration(m_duration);
|
||||||
|
|
||||||
|
CreatureInfo const* cInfo = spawnCreature->GetCreatureInfo();
|
||||||
|
|
||||||
// spawnCreature->SetName(""); // generated by client
|
// spawnCreature->SetName(""); // generated by client
|
||||||
spawnCreature->SetOwnerGuid(m_caster->GetObjectGuid());
|
spawnCreature->SetOwnerGuid(m_caster->GetObjectGuid());
|
||||||
spawnCreature->SetPowerType(POWER_MANA);
|
spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, cInfo->UnitFlags);
|
||||||
spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, spawnCreature->GetCreatureInfo()->NpcFlags);
|
spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, cInfo->NpcFlags);
|
||||||
|
spawnCreature->setFaction(m_caster->getFaction());
|
||||||
spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
|
spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
|
||||||
spawnCreature->SetCreatorGuid(m_caster->GetObjectGuid());
|
spawnCreature->SetCreatorGuid(m_caster->GetObjectGuid());
|
||||||
spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
||||||
|
|
||||||
spawnCreature->InitStatsForLevel(level, m_caster);
|
spawnCreature->InitStatsForLevel(level);
|
||||||
spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
|
|
||||||
|
if (CharmInfo* charmInfo = spawnCreature->GetCharmInfo())
|
||||||
|
{
|
||||||
|
charmInfo->SetPetNumber(pet_number, false);
|
||||||
|
|
||||||
|
if (spawnCreature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE))
|
||||||
|
charmInfo->SetReactState(REACT_PASSIVE);
|
||||||
|
else if ((cInfo->ExtraFlags & CREATURE_EXTRA_FLAG_NO_MELEE) || petType == PROTECTOR_PET)
|
||||||
|
charmInfo->SetReactState(REACT_DEFENSIVE);
|
||||||
|
else
|
||||||
|
charmInfo->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
}
|
||||||
|
|
||||||
m_caster->AddGuardian(spawnCreature);
|
m_caster->AddGuardian(spawnCreature);
|
||||||
}
|
}
|
||||||
|
|
@ -10721,24 +10734,159 @@ void Spell::EffectBlock(SpellEffectEntry const* /*effect*/)
|
||||||
|
|
||||||
void Spell::EffectLeapForward(SpellEffectEntry const* effect)
|
void Spell::EffectLeapForward(SpellEffectEntry const* effect)
|
||||||
{
|
{
|
||||||
if (unitTarget->IsTaxiFlying())
|
float dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->rangeIndex));
|
||||||
return;
|
const float IN_OR_UNDER_LIQUID_RANGE = 0.8f; // range to make player under liquid or on liquid surface from liquid level
|
||||||
|
|
||||||
if (m_spellInfo->rangeIndex == SPELL_RANGE_IDX_SELF_ONLY)
|
G3D::Vector3 prevPos, nextPos;
|
||||||
|
float orientation = unitTarget->GetOrientation();
|
||||||
|
|
||||||
|
prevPos.x = unitTarget->GetPositionX();
|
||||||
|
prevPos.y = unitTarget->GetPositionY();
|
||||||
|
prevPos.z = unitTarget->GetPositionZ();
|
||||||
|
|
||||||
|
float groundZ = prevPos.z;
|
||||||
|
|
||||||
|
// falling case
|
||||||
|
if (!unitTarget->GetMap()->GetHeightInRange(unitTarget->GetPhaseMask(), prevPos.x, prevPos.y, groundZ, 3.0f) && unitTarget->m_movementInfo.HasMovementFlag(MOVEFLAG_FALLING))
|
||||||
{
|
{
|
||||||
float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(effect->GetRadiusIndex()));
|
nextPos.x = prevPos.x + dist * cos(orientation);
|
||||||
|
nextPos.y = prevPos.y + dist * sin(orientation);
|
||||||
|
nextPos.z = prevPos.z - 2.0f; // little hack to avoid the impression to go up when teleporting instead of continue to fall. This value may need some tweak
|
||||||
|
|
||||||
// before caster
|
//
|
||||||
float fx, fy, fz;
|
GridMapLiquidData liquidData;
|
||||||
unitTarget->GetClosePoint(fx, fy, fz, unitTarget->GetObjectBoundingRadius(), dis);
|
if (unitTarget->GetMap()->GetTerrain()->IsInWater(nextPos.x, nextPos.y, nextPos.z, &liquidData))
|
||||||
float ox, oy, oz;
|
{
|
||||||
unitTarget->GetPosition(ox, oy, oz);
|
if (fabs(nextPos.z - liquidData.level) < 10.0f)
|
||||||
|
nextPos.z = liquidData.level - IN_OR_UNDER_LIQUID_RANGE;
|
||||||
if (unitTarget->GetMap()->GetHitPosition(ox, oy, oz + 0.5f, fx, fy, fz, unitTarget->GetPhaseMask(), -0.5f))
|
|
||||||
unitTarget->UpdateAllowedPositionZ(fx, fy, fz);
|
|
||||||
|
|
||||||
unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(), unitTarget == m_caster);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// fix z to ground if near of it
|
||||||
|
unitTarget->GetMap()->GetHeightInRange(unitTarget->GetPhaseMask(), nextPos.x, nextPos.y, nextPos.z, 10.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check any obstacle and fix coords
|
||||||
|
unitTarget->GetMap()->GetHitPosition(prevPos.x, prevPos.y, prevPos.z + 0.5f, nextPos.x, nextPos.y, nextPos.z, unitTarget->GetPhaseMask(), -0.5f);
|
||||||
|
|
||||||
|
// teleport
|
||||||
|
unitTarget->NearTeleportTo(nextPos.x, nextPos.y, nextPos.z, orientation, unitTarget == m_caster);
|
||||||
|
|
||||||
|
//sLog.outString("Falling BLINK!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix origin position if player was jumping and near of the ground but not in ground
|
||||||
|
if (fabs(prevPos.z - groundZ) > 0.5f)
|
||||||
|
prevPos.z = groundZ;
|
||||||
|
|
||||||
|
//check if in liquid
|
||||||
|
bool isPrevInLiquid = unitTarget->GetMap()->GetTerrain()->IsInWater(prevPos.x, prevPos.y, prevPos.z);
|
||||||
|
|
||||||
|
const float step = 2.0f; // step length before next check slope/edge/water
|
||||||
|
const float maxSlope = 50.0f; // 50(degree) max seem best value for walkable slope
|
||||||
|
const float MAX_SLOPE_IN_RADIAN = maxSlope / 180.0f * M_PI_F;
|
||||||
|
float nextZPointEstimation = 1.0f;
|
||||||
|
float destx = prevPos.x + dist * cos(orientation);
|
||||||
|
float desty = prevPos.y + dist * sin(orientation);
|
||||||
|
const uint32 numChecks = ceil(fabs(dist / step));
|
||||||
|
const float DELTA_X = (destx - prevPos.x) / numChecks;
|
||||||
|
const float DELTA_Y = (desty - prevPos.y) / numChecks;
|
||||||
|
|
||||||
|
for (uint32 i = 1; i < numChecks + 1; ++i)
|
||||||
|
{
|
||||||
|
// compute next point average position
|
||||||
|
nextPos.x = prevPos.x + DELTA_X;
|
||||||
|
nextPos.y = prevPos.y + DELTA_Y;
|
||||||
|
nextPos.z = prevPos.z + nextZPointEstimation;
|
||||||
|
|
||||||
|
bool isInLiquid = false;
|
||||||
|
bool isInLiquidTested = false;
|
||||||
|
bool isOnGround = false;
|
||||||
|
GridMapLiquidData liquidData;
|
||||||
|
|
||||||
|
// try fix height for next position
|
||||||
|
if (!unitTarget->GetMap()->GetHeightInRange(unitTarget->GetPhaseMask(), nextPos.x, nextPos.y, nextPos.z))
|
||||||
|
{
|
||||||
|
// we cant so test if we are on water
|
||||||
|
if (!unitTarget->GetMap()->GetTerrain()->IsInWater(nextPos.x, nextPos.y, nextPos.z, &liquidData))
|
||||||
|
{
|
||||||
|
// not in water and cannot get correct height, maybe flying?
|
||||||
|
//sLog.outString("Can't get height of point %u, point value %s", i, nextPos.toString().c_str());
|
||||||
|
nextPos = prevPos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isInLiquid = true;
|
||||||
|
isInLiquidTested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
isOnGround = true; // player is on ground
|
||||||
|
|
||||||
|
if (isInLiquid || (!isInLiquidTested && unitTarget->GetMap()->GetTerrain()->IsInWater(nextPos.x, nextPos.y, nextPos.z, &liquidData)))
|
||||||
|
{
|
||||||
|
if (!isPrevInLiquid && fabs(liquidData.level - prevPos.z) > 2.0f)
|
||||||
|
{
|
||||||
|
// on edge of water with difference a bit to high to continue
|
||||||
|
//sLog.outString("Ground vs liquid edge detected!");
|
||||||
|
nextPos = prevPos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((liquidData.level - IN_OR_UNDER_LIQUID_RANGE) > nextPos.z)
|
||||||
|
nextPos.z = prevPos.z; // we are under water so next z equal prev z
|
||||||
|
else
|
||||||
|
nextPos.z = liquidData.level - IN_OR_UNDER_LIQUID_RANGE; // we are on water surface, so next z equal liquid level
|
||||||
|
|
||||||
|
isInLiquid = true;
|
||||||
|
|
||||||
|
float ground = nextPos.z;
|
||||||
|
if (unitTarget->GetMap()->GetHeightInRange(unitTarget->GetPhaseMask(), nextPos.x, nextPos.y, ground))
|
||||||
|
{
|
||||||
|
if (nextPos.z < ground)
|
||||||
|
{
|
||||||
|
nextPos.z = ground;
|
||||||
|
isOnGround = true; // player is on ground of the water
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//unitTarget->SummonCreature(VISUAL_WAYPOINT, nextPos.x, nextPos.y, nextPos.z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000);
|
||||||
|
float hitZ = nextPos.z + 1.5f;
|
||||||
|
if (unitTarget->GetMap()->GetHitPosition(prevPos.x, prevPos.y, prevPos.z + 1.5f, nextPos.x, nextPos.y, hitZ, unitTarget->GetPhaseMask(), -1.0f))
|
||||||
|
{
|
||||||
|
//sLog.outString("Blink collision detected!");
|
||||||
|
nextPos = prevPos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isOnGround)
|
||||||
|
{
|
||||||
|
// project vector to get only positive value
|
||||||
|
float ac = fabs(prevPos.z - nextPos.z);
|
||||||
|
|
||||||
|
// compute slope (in radian)
|
||||||
|
float slope = atan(ac / step);
|
||||||
|
|
||||||
|
// check slope value
|
||||||
|
if (slope > MAX_SLOPE_IN_RADIAN)
|
||||||
|
{
|
||||||
|
//sLog.outString("bad slope detected! %4.2f max %4.2f, ac(%4.2f)", slope * 180 / M_PI_F, maxSlope, ac);
|
||||||
|
nextPos = prevPos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//sLog.outString("slope is ok! %4.2f max %4.2f, ac(%4.2f)", slope * 180 / M_PI_F, maxSlope, ac);
|
||||||
|
}
|
||||||
|
|
||||||
|
//sLog.outString("point %u is ok, coords %s", i, nextPos.toString().c_str());
|
||||||
|
nextZPointEstimation = (nextPos.z - prevPos.z) / 2.0f;
|
||||||
|
isPrevInLiquid = isInLiquid;
|
||||||
|
prevPos = nextPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
unitTarget->NearTeleportTo(nextPos.x, nextPos.y, nextPos.z, orientation, unitTarget == m_caster);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spell::EffectLeapBack(SpellEffectEntry const* effect)
|
void Spell::EffectLeapBack(SpellEffectEntry const* effect)
|
||||||
|
|
@ -10922,11 +11070,18 @@ void Spell::EffectPlayerPull(SpellEffectEntry const* effect)
|
||||||
if (!unitTarget)
|
if (!unitTarget)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float dist = unitTarget->GetDistance2d(m_caster);
|
float x, y, z;
|
||||||
if (damage && dist > damage)
|
m_caster->GetPosition(x, y, z);
|
||||||
dist = float(damage);
|
|
||||||
|
|
||||||
unitTarget->KnockBackFrom(m_caster, -dist, float(effect->EffectMiscValue) / 10);
|
// move back a bit
|
||||||
|
x = x - (0.6 * cos(m_caster->GetOrientation() + M_PI_F));
|
||||||
|
y = y - (0.6 * sin(m_caster->GetOrientation() + M_PI_F));
|
||||||
|
|
||||||
|
// Try to normalize Z coord because GetContactPoint do nothing with Z axis
|
||||||
|
unitTarget->UpdateAllowedPositionZ(x, y, z);
|
||||||
|
|
||||||
|
float speed = m_spellInfo->speed ? m_spellInfo->speed : 27.0f;
|
||||||
|
unitTarget->GetMotionMaster()->MoveJump(x, y, z, speed, 2.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spell::EffectDispelMechanic(SpellEffectEntry const* effect)
|
void Spell::EffectDispelMechanic(SpellEffectEntry const* effect)
|
||||||
|
|
|
||||||
|
|
@ -293,10 +293,13 @@ void WorldSession::HandleGameObjectUseOpcode(WorldPacket& recv_data)
|
||||||
if (!_player->IsSelfMover())
|
if (!_player->IsSelfMover())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GameObject* obj = GetPlayer()->GetMap()->GetGameObject(guid);
|
GameObject* obj = _player->GetMap()->GetGameObject(guid);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!obj->IsWithinDistInMap(_player, obj->GetInteractionDistance()))
|
||||||
|
return;
|
||||||
|
|
||||||
// Additional check preventing exploits (ie loot despawned chests)
|
// Additional check preventing exploits (ie loot despawned chests)
|
||||||
if (!obj->isSpawned())
|
if (!obj->isSpawned())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -635,6 +635,6 @@ void WaypointManager::CheckTextsExistance(std::set<int32>& ids)
|
||||||
{
|
{
|
||||||
for (WaypointPath::const_iterator pItr = pmItr->second.begin(); pItr != pmItr->second.end(); ++pItr)
|
for (WaypointPath::const_iterator pItr = pmItr->second.begin(); pItr != pmItr->second.end(); ++pItr)
|
||||||
if (pItr->second.behavior)
|
if (pItr->second.behavior)
|
||||||
CheckWPText(false, pmItr->first, pItr->first, pItr->second.behavior, ids);
|
CheckWPText(true, pmItr->first, pItr->first, pItr->second.behavior, ids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ class WaypointManager
|
||||||
|
|
||||||
WaypointPath* GetDefaultPath(uint32 entry, uint32 lowGuid, WaypointPathOrigin* wpOrigin = NULL)
|
WaypointPath* GetDefaultPath(uint32 entry, uint32 lowGuid, WaypointPathOrigin* wpOrigin = NULL)
|
||||||
{
|
{
|
||||||
WaypointPath* path = NULL;
|
WaypointPath* path = GetPath(lowGuid);
|
||||||
path = GetPath(lowGuid);
|
path = GetPath(lowGuid);
|
||||||
if (path && wpOrigin)
|
if (path && wpOrigin)
|
||||||
*wpOrigin = PATH_FROM_GUID;
|
*wpOrigin = PATH_FROM_GUID;
|
||||||
|
|
|
||||||
|
|
@ -531,6 +531,7 @@ void World::LoadConfigSettings(bool reload)
|
||||||
setConfig(CONFIG_BOOL_ADDON_CHANNEL, "AddonChannel", true);
|
setConfig(CONFIG_BOOL_ADDON_CHANNEL, "AddonChannel", true);
|
||||||
setConfig(CONFIG_BOOL_CLEAN_CHARACTER_DB, "CleanCharacterDB", true);
|
setConfig(CONFIG_BOOL_CLEAN_CHARACTER_DB, "CleanCharacterDB", true);
|
||||||
setConfig(CONFIG_BOOL_GRID_UNLOAD, "GridUnload", true);
|
setConfig(CONFIG_BOOL_GRID_UNLOAD, "GridUnload", true);
|
||||||
|
setConfig(CONFIG_UINT32_MAX_WHOLIST_RETURNS, "MaxWhoListReturns", 49);
|
||||||
|
|
||||||
std::string forceLoadGridOnMaps = sConfig.GetStringDefault("LoadAllGridsOnMaps", "");
|
std::string forceLoadGridOnMaps = sConfig.GetStringDefault("LoadAllGridsOnMaps", "");
|
||||||
if (!forceLoadGridOnMaps.empty())
|
if (!forceLoadGridOnMaps.empty())
|
||||||
|
|
|
||||||
|
|
@ -220,6 +220,8 @@ enum eConfigUInt32Values
|
||||||
CONFIG_UINT32_MIN_LEVEL_FOR_RAID,
|
CONFIG_UINT32_MIN_LEVEL_FOR_RAID,
|
||||||
CONFIG_UINT32_CREATURE_RESPAWN_AGGRO_DELAY,
|
CONFIG_UINT32_CREATURE_RESPAWN_AGGRO_DELAY,
|
||||||
CONFIG_UINT32_RANDOM_BG_RESET_HOUR,
|
CONFIG_UINT32_RANDOM_BG_RESET_HOUR,
|
||||||
|
CONFIG_UINT32_MAX_WHOLIST_RETURNS,
|
||||||
|
CONFIG_UINT32_VALUE_COUNT,
|
||||||
// Warden
|
// Warden
|
||||||
CONFIG_UINT32_WARDEN_CLIENT_RESPONSE_DELAY,
|
CONFIG_UINT32_WARDEN_CLIENT_RESPONSE_DELAY,
|
||||||
CONFIG_UINT32_WARDEN_CLIENT_CHECK_HOLDOFF,
|
CONFIG_UINT32_WARDEN_CLIENT_CHECK_HOLDOFF,
|
||||||
|
|
@ -227,8 +229,7 @@ enum eConfigUInt32Values
|
||||||
CONFIG_UINT32_WARDEN_CLIENT_BAN_DURATION,
|
CONFIG_UINT32_WARDEN_CLIENT_BAN_DURATION,
|
||||||
CONFIG_UINT32_WARDEN_NUM_MEM_CHECKS,
|
CONFIG_UINT32_WARDEN_NUM_MEM_CHECKS,
|
||||||
CONFIG_UINT32_WARDEN_NUM_OTHER_CHECKS,
|
CONFIG_UINT32_WARDEN_NUM_OTHER_CHECKS,
|
||||||
CONFIG_UINT32_WARDEN_DB_LOGLEVEL,
|
CONFIG_UINT32_WARDEN_DB_LOGLEVEL
|
||||||
CONFIG_UINT32_VALUE_COUNT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Configuration elements
|
/// Configuration elements
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,14 @@ enum
|
||||||
SPELL_MAGMASHACKLES = 19496,
|
SPELL_MAGMASHACKLES = 19496,
|
||||||
SPELL_ERUPTION_TRIGGER = 20482, // target script, dispel and permanent immune to banish anywhere on map
|
SPELL_ERUPTION_TRIGGER = 20482, // target script, dispel and permanent immune to banish anywhere on map
|
||||||
SPELL_ENRAGE_TRIGGER = 19515, // target script, effect dummy anywhere on map
|
SPELL_ENRAGE_TRIGGER = 19515, // target script, effect dummy anywhere on map
|
||||||
|
SPELL_ENRAGE = 19516,
|
||||||
|
|
||||||
// Add spells
|
// Add spells
|
||||||
|
SPELL_THRASH = 8876,
|
||||||
|
SPELL_IMMOLATE = 15733,
|
||||||
SPELL_ERUPTION = 19497,
|
SPELL_ERUPTION = 19497,
|
||||||
SPELL_MASSIVE_ERUPTION = 20483, // TODO possible on death
|
SPELL_MASSIVE_ERUPTION = 20483, // TODO possible on death
|
||||||
SPELL_IMMOLATE = 20294,
|
SPELL_SEPARATION_ANXIETY_BOSSGARR = 23492, // Used if separated too far from Garr
|
||||||
};
|
};
|
||||||
|
|
||||||
struct boss_garr : public CreatureScript
|
struct boss_garr : public CreatureScript
|
||||||
|
|
@ -184,6 +187,10 @@ struct mob_firesworn : public CreatureScript
|
||||||
mob_fireswornAI(Creature* pCreature) : ScriptedAI(pCreature)
|
mob_fireswornAI(Creature* pCreature) : ScriptedAI(pCreature)
|
||||||
{
|
{
|
||||||
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
|
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_THRASH, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_IMMOLATE, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptedInstance* m_pInstance;
|
ScriptedInstance* m_pInstance;
|
||||||
|
|
@ -199,6 +206,12 @@ struct mob_firesworn : public CreatureScript
|
||||||
m_bExploding = false;
|
m_bExploding = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JustReachedHome() override
|
||||||
|
{
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_THRASH, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_IMMOLATE, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
|
}
|
||||||
|
|
||||||
void DamageTaken(Unit* /*pDealer*/, uint32& uiDamage) override
|
void DamageTaken(Unit* /*pDealer*/, uint32& uiDamage) override
|
||||||
{
|
{
|
||||||
if (!m_bExploding && m_creature->HealthBelowPctDamaged(10, uiDamage))
|
if (!m_bExploding && m_creature->HealthBelowPctDamaged(10, uiDamage))
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,11 @@ enum
|
||||||
SPELL_EARTHQUAKE = 19798,
|
SPELL_EARTHQUAKE = 19798,
|
||||||
SPELL_ENRAGE = 19953,
|
SPELL_ENRAGE = 19953,
|
||||||
SPELL_GOLEMAGG_TRUST = 20553,
|
SPELL_GOLEMAGG_TRUST = 20553,
|
||||||
|
SPELL_DOUBLE_ATTACK = 18943,
|
||||||
|
|
||||||
// Core Rager
|
// Core Rager
|
||||||
EMOTE_LOW_HP = -1409002,
|
EMOTE_LOW_HP = -1409002,
|
||||||
|
SPELL_THRASH = 12787,
|
||||||
SPELL_MANGLE = 19820
|
SPELL_MANGLE = 19820
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -60,6 +62,7 @@ struct boss_golemagg : public CreatureScript
|
||||||
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
|
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
|
||||||
#if defined (WOTLK) || defined (CATA)
|
#if defined (WOTLK) || defined (CATA)
|
||||||
DoCastSpellIfCan(m_creature, SPELL_MAGMA_SPLASH, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
DoCastSpellIfCan(m_creature, SPELL_MAGMA_SPLASH, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_DOUBLE_ATTACK, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -185,6 +188,9 @@ struct mob_core_rager : public CreatureScript
|
||||||
mob_core_ragerAI(Creature* pCreature) : ScriptedAI(pCreature)
|
mob_core_ragerAI(Creature* pCreature) : ScriptedAI(pCreature)
|
||||||
{
|
{
|
||||||
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
|
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_THRASH, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptedInstance* m_pInstance;
|
ScriptedInstance* m_pInstance;
|
||||||
|
|
@ -208,6 +214,11 @@ struct mob_core_rager : public CreatureScript
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JustReachedHome() override
|
||||||
|
{
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_THRASH, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateAI(const uint32 uiDiff) override
|
void UpdateAI(const uint32 uiDiff) override
|
||||||
{
|
{
|
||||||
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
|
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ enum
|
||||||
EMOTE_INSECT_SWARM = -1533154,
|
EMOTE_INSECT_SWARM = -1533154,
|
||||||
EMOTE_CORPSE_SCARABS = -1533155,
|
EMOTE_CORPSE_SCARABS = -1533155,
|
||||||
|
|
||||||
|
SPELL_DOUBLE_ATTACK = 18943,
|
||||||
SPELL_IMPALE = 28783, // May be wrong spell id. Causes more dmg than I expect
|
SPELL_IMPALE = 28783, // May be wrong spell id. Causes more dmg than I expect
|
||||||
SPELL_IMPALE_H = 56090,
|
SPELL_IMPALE_H = 56090,
|
||||||
SPELL_LOCUSTSWARM = 28785, // This is a self buff that triggers the dmg debuff
|
SPELL_LOCUSTSWARM = 28785, // This is a self buff that triggers the dmg debuff
|
||||||
|
|
@ -82,6 +83,9 @@ struct boss_anubrekhan : public CreatureScript
|
||||||
m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
|
m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
|
||||||
m_introDialogue.InitializeDialogueHelper(m_pInstance);
|
m_introDialogue.InitializeDialogueHelper(m_pInstance);
|
||||||
m_bHasTaunted = false;
|
m_bHasTaunted = false;
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_DOUBLE_ATTACK, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptedInstance* m_pInstance;
|
ScriptedInstance* m_pInstance;
|
||||||
|
|
@ -135,6 +139,8 @@ struct boss_anubrekhan : public CreatureScript
|
||||||
{
|
{
|
||||||
if (m_pInstance)
|
if (m_pInstance)
|
||||||
m_pInstance->SetData(TYPE_ANUB_REKHAN, FAIL);
|
m_pInstance->SetData(TYPE_ANUB_REKHAN, FAIL);
|
||||||
|
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_DOUBLE_ATTACK, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* pWho) override
|
void MoveInLineOfSight(Unit* pWho) override
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ enum
|
||||||
EMOTE_BOSS_GENERIC_ENRAGED = -1000006,
|
EMOTE_BOSS_GENERIC_ENRAGED = -1000006,
|
||||||
EMOTE_DECIMATE = -1533152,
|
EMOTE_DECIMATE = -1533152,
|
||||||
|
|
||||||
|
SPELL_DOUBLE_ATTACK = 19818,
|
||||||
SPELL_MORTALWOUND = 54378, // old vanilla spell was 25646,
|
SPELL_MORTALWOUND = 54378, // old vanilla spell was 25646,
|
||||||
SPELL_DECIMATE = 28374,
|
SPELL_DECIMATE = 28374,
|
||||||
SPELL_DECIMATE_H = 54426,
|
SPELL_DECIMATE_H = 54426,
|
||||||
|
|
@ -66,6 +67,9 @@ struct boss_gluth : public CreatureScript
|
||||||
{
|
{
|
||||||
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
|
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
|
||||||
m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
|
m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_DOUBLE_ATTACK, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptedInstance* m_pInstance;
|
ScriptedInstance* m_pInstance;
|
||||||
|
|
@ -118,6 +122,8 @@ struct boss_gluth : public CreatureScript
|
||||||
{
|
{
|
||||||
if (m_pInstance)
|
if (m_pInstance)
|
||||||
m_pInstance->SetData(TYPE_GLUTH, FAIL);
|
m_pInstance->SetData(TYPE_GLUTH, FAIL);
|
||||||
|
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_DOUBLE_ATTACK, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustSummoned(Creature* pSummoned) override
|
void JustSummoned(Creature* pSummoned) override
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ enum
|
||||||
EMOTE_SPRAY = -1533148,
|
EMOTE_SPRAY = -1533148,
|
||||||
EMOTE_BOSS_GENERIC_FRENZY = -1000005,
|
EMOTE_BOSS_GENERIC_FRENZY = -1000005,
|
||||||
|
|
||||||
|
SPELL_DOUBLE_ATTACK = 19818,
|
||||||
|
|
||||||
SPELL_WEBWRAP = 28622,
|
SPELL_WEBWRAP = 28622,
|
||||||
SPELL_WEBWRAP_2 = 28673, // purpose unknown
|
SPELL_WEBWRAP_2 = 28673, // purpose unknown
|
||||||
|
|
||||||
|
|
@ -166,6 +168,9 @@ struct boss_maexxna : public CreatureScript
|
||||||
{
|
{
|
||||||
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
|
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
|
||||||
m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
|
m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_DOUBLE_ATTACK, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptedInstance* m_pInstance;
|
ScriptedInstance* m_pInstance;
|
||||||
|
|
@ -204,6 +209,8 @@ struct boss_maexxna : public CreatureScript
|
||||||
{
|
{
|
||||||
if (m_pInstance)
|
if (m_pInstance)
|
||||||
m_pInstance->SetData(TYPE_MAEXXNA, FAIL);
|
m_pInstance->SetData(TYPE_MAEXXNA, FAIL);
|
||||||
|
|
||||||
|
DoCastSpellIfCan(m_creature, SPELL_DOUBLE_ATTACK, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustSummoned(Creature* pSummoned) override
|
void JustSummoned(Creature* pSummoned) override
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,7 @@ struct boss_freya : public CreatureScript
|
||||||
|
|
||||||
uint32 m_uiEpilogueTimer;
|
uint32 m_uiEpilogueTimer;
|
||||||
uint32 m_uiBerserkTimer;
|
uint32 m_uiBerserkTimer;
|
||||||
|
uint32 m_uiDrainEldersTimer;
|
||||||
|
|
||||||
uint32 m_uiAlliesNatureTimer;
|
uint32 m_uiAlliesNatureTimer;
|
||||||
uint8 m_uiAlliesWaveCount;
|
uint8 m_uiAlliesWaveCount;
|
||||||
|
|
@ -244,6 +245,7 @@ struct boss_freya : public CreatureScript
|
||||||
m_uiUnstableEnergyTimer = 0;
|
m_uiUnstableEnergyTimer = 0;
|
||||||
m_uiIronRootsTimer = 0;
|
m_uiIronRootsTimer = 0;
|
||||||
m_uiGroundTremorTimer = 0;
|
m_uiGroundTremorTimer = 0;
|
||||||
|
m_uiDrainEldersTimer = 0;
|
||||||
|
|
||||||
// make the spawn spells random
|
// make the spawn spells random
|
||||||
std::random_shuffle(spawnSpellsVector.begin(), spawnSpellsVector.end());
|
std::random_shuffle(spawnSpellsVector.begin(), spawnSpellsVector.end());
|
||||||
|
|
@ -292,17 +294,26 @@ struct boss_freya : public CreatureScript
|
||||||
if (Creature* pElder = m_pInstance->GetSingleCreatureFromStorage(NPC_ELDER_BRIGHTLEAF))
|
if (Creature* pElder = m_pInstance->GetSingleCreatureFromStorage(NPC_ELDER_BRIGHTLEAF))
|
||||||
{
|
{
|
||||||
if (pElder->IsAlive())
|
if (pElder->IsAlive())
|
||||||
|
{
|
||||||
pElder->AI()->EnterEvadeMode();
|
pElder->AI()->EnterEvadeMode();
|
||||||
|
pElder->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (Creature* pElder = m_pInstance->GetSingleCreatureFromStorage(NPC_ELDER_IRONBRACH))
|
if (Creature* pElder = m_pInstance->GetSingleCreatureFromStorage(NPC_ELDER_IRONBRACH))
|
||||||
{
|
{
|
||||||
if (pElder->IsAlive())
|
if (pElder->IsAlive())
|
||||||
|
{
|
||||||
pElder->AI()->EnterEvadeMode();
|
pElder->AI()->EnterEvadeMode();
|
||||||
|
pElder->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (Creature* pElder = m_pInstance->GetSingleCreatureFromStorage(NPC_ELDER_STONEBARK))
|
if (Creature* pElder = m_pInstance->GetSingleCreatureFromStorage(NPC_ELDER_STONEBARK))
|
||||||
{
|
{
|
||||||
if (pElder->IsAlive())
|
if (pElder->IsAlive())
|
||||||
|
{
|
||||||
pElder->AI()->EnterEvadeMode();
|
pElder->AI()->EnterEvadeMode();
|
||||||
|
pElder->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -468,7 +479,7 @@ struct boss_freya : public CreatureScript
|
||||||
{
|
{
|
||||||
if (pElder->IsAlive())
|
if (pElder->IsAlive())
|
||||||
{
|
{
|
||||||
pElder->CastSpell(pElder, m_bIsRegularMode ? SPELL_BRIGHTLEAF_ESSENCE_CHANNEL : SPELL_BRIGHTLEAF_ESSENCE_CHANNEL_H, true);
|
pElder->CastSpell(pElder, m_bIsRegularMode ? SPELL_BRIGHTLEAF_ESSENCE_CHANNEL : SPELL_BRIGHTLEAF_ESSENCE_CHANNEL_H, false, NULL, NULL, m_creature->GetObjectGuid());
|
||||||
pElder->CastSpell(pElder, SPELL_FULL_HEAL, true);
|
pElder->CastSpell(pElder, SPELL_FULL_HEAL, true);
|
||||||
|
|
||||||
m_uiUnstableEnergyTimer = 25000;
|
m_uiUnstableEnergyTimer = 25000;
|
||||||
|
|
@ -479,7 +490,7 @@ struct boss_freya : public CreatureScript
|
||||||
{
|
{
|
||||||
if (pElder->IsAlive())
|
if (pElder->IsAlive())
|
||||||
{
|
{
|
||||||
pElder->CastSpell(pElder, m_bIsRegularMode ? SPELL_IRONBRANCH_ESSENCE_CHANNEL : SPELL_IRONBRANCH_ESSENCE_CHANNEL_H, true);
|
pElder->CastSpell(pElder, m_bIsRegularMode ? SPELL_IRONBRANCH_ESSENCE_CHANNEL : SPELL_IRONBRANCH_ESSENCE_CHANNEL_H, false, NULL, NULL, m_creature->GetObjectGuid());
|
||||||
pElder->CastSpell(pElder, SPELL_FULL_HEAL, true);
|
pElder->CastSpell(pElder, SPELL_FULL_HEAL, true);
|
||||||
|
|
||||||
m_uiIronRootsTimer = 60000;
|
m_uiIronRootsTimer = 60000;
|
||||||
|
|
@ -490,7 +501,7 @@ struct boss_freya : public CreatureScript
|
||||||
{
|
{
|
||||||
if (pElder->IsAlive())
|
if (pElder->IsAlive())
|
||||||
{
|
{
|
||||||
pElder->CastSpell(pElder, m_bIsRegularMode ? SPELL_STONEBARK_ESSEMCE_CHANNEL : SPELL_STONEBARK_ESSEMCE_CHANNEL_H, true);
|
pElder->CastSpell(pElder, m_bIsRegularMode ? SPELL_STONEBARK_ESSEMCE_CHANNEL : SPELL_STONEBARK_ESSEMCE_CHANNEL_H, false, NULL, NULL, m_creature->GetObjectGuid());
|
||||||
pElder->CastSpell(pElder, SPELL_FULL_HEAL, true);
|
pElder->CastSpell(pElder, SPELL_FULL_HEAL, true);
|
||||||
|
|
||||||
m_uiGroundTremorTimer = 10000;
|
m_uiGroundTremorTimer = 10000;
|
||||||
|
|
@ -507,6 +518,38 @@ struct boss_freya : public CreatureScript
|
||||||
DoScriptText(SAY_AGGRO, m_creature);
|
DoScriptText(SAY_AGGRO, m_creature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function that will drain elders after aggro
|
||||||
|
void DoDrainElders()
|
||||||
|
{
|
||||||
|
if (!m_pInstance)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Creature* pElder = m_pInstance->GetSingleCreatureFromStorage(NPC_ELDER_BRIGHTLEAF))
|
||||||
|
{
|
||||||
|
if (pElder->IsAlive())
|
||||||
|
{
|
||||||
|
pElder->CastSpell(pElder, SPELL_DRAINED_OF_POWER, true);
|
||||||
|
pElder->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Creature* pElder = m_pInstance->GetSingleCreatureFromStorage(NPC_ELDER_IRONBRACH))
|
||||||
|
{
|
||||||
|
if (pElder->IsAlive())
|
||||||
|
{
|
||||||
|
pElder->CastSpell(pElder, SPELL_DRAINED_OF_POWER, true);
|
||||||
|
pElder->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Creature* pElder = m_pInstance->GetSingleCreatureFromStorage(NPC_ELDER_STONEBARK))
|
||||||
|
{
|
||||||
|
if (pElder->IsAlive())
|
||||||
|
{
|
||||||
|
pElder->CastSpell(pElder, SPELL_DRAINED_OF_POWER, true);
|
||||||
|
pElder->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateAI(const uint32 uiDiff) override
|
void UpdateAI(const uint32 uiDiff) override
|
||||||
{
|
{
|
||||||
if (m_uiEpilogueTimer)
|
if (m_uiEpilogueTimer)
|
||||||
|
|
@ -540,6 +583,18 @@ struct boss_freya : public CreatureScript
|
||||||
m_uiBerserkTimer -= uiDiff;
|
m_uiBerserkTimer -= uiDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drain elders after hard mode aggro
|
||||||
|
if (m_uiDrainEldersTimer)
|
||||||
|
{
|
||||||
|
if (m_uiDrainEldersTimer <= uiDiff)
|
||||||
|
{
|
||||||
|
DoDrainElders();
|
||||||
|
m_uiDrainEldersTimer = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_uiDrainEldersTimer -= uiDiff;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_uiThreeAlliesTimer)
|
if (m_uiThreeAlliesTimer)
|
||||||
{
|
{
|
||||||
if (m_uiThreeAlliesTimer <= uiDiff)
|
if (m_uiThreeAlliesTimer <= uiDiff)
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,7 @@ bool DB2FileLoader::Load(const char *filename, const char *fmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE * f = fopen(filename, "rb");
|
FILE * f = fopen(filename, "rb");
|
||||||
if (!f)
|
if(!f)return false;
|
||||||
{ return false; }
|
|
||||||
|
|
||||||
if(fread(&header, 4, 1, f) != 1) // Signature
|
if(fread(&header, 4, 1, f) != 1) // Signature
|
||||||
{
|
{
|
||||||
|
|
@ -59,7 +58,7 @@ bool DB2FileLoader::Load(const char *filename, const char *fmt)
|
||||||
if(header != 0x32424457)
|
if(header != 0x32424457)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return false;
|
return false; //'WDB2'
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fread(&recordCount,4,1,f)!=1) // Number of records
|
if(fread(&recordCount,4,1,f)!=1) // Number of records
|
||||||
|
|
@ -153,13 +152,13 @@ bool DB2FileLoader::Load(const char *filename, const char *fmt)
|
||||||
|
|
||||||
fieldsOffset = new uint32[fieldCount];
|
fieldsOffset = new uint32[fieldCount];
|
||||||
fieldsOffset[0] = 0;
|
fieldsOffset[0] = 0;
|
||||||
for (uint32 i = 1; i < fieldCount; ++i)
|
for(uint32 i = 1; i < fieldCount; i++)
|
||||||
{
|
{
|
||||||
fieldsOffset[i] = fieldsOffset[i - 1];
|
fieldsOffset[i] = fieldsOffset[i - 1];
|
||||||
if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields
|
if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields
|
||||||
{ fieldsOffset[i] += 1; }
|
fieldsOffset[i] += 1;
|
||||||
else // 4 byte fields (int32/float/strings)
|
else // 4 byte fields (int32/float/strings)
|
||||||
{ fieldsOffset[i] += 4; }
|
fieldsOffset[i] += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = new unsigned char[recordSize*recordCount+stringSize];
|
data = new unsigned char[recordSize*recordCount+stringSize];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue