mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 04:37:00 +00:00
Many, many cmangos Cata commits applied
The following commits were either applied or found not to be applicable:
This commit is contained in:
parent
32a26f44c7
commit
a800f3b1ad
100 changed files with 2385 additions and 1305 deletions
|
|
@ -213,32 +213,32 @@ BattleGround::BattleGround()
|
|||
m_MapId = 0;
|
||||
m_Map = NULL;
|
||||
|
||||
m_TeamStartLocX[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamStartLocX[BG_TEAM_HORDE] = 0;
|
||||
m_TeamStartLocX[TEAM_INDEX_ALLIANCE] = 0;
|
||||
m_TeamStartLocX[TEAM_INDEX_HORDE] = 0;
|
||||
|
||||
m_TeamStartLocY[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamStartLocY[BG_TEAM_HORDE] = 0;
|
||||
m_TeamStartLocY[TEAM_INDEX_ALLIANCE] = 0;
|
||||
m_TeamStartLocY[TEAM_INDEX_HORDE] = 0;
|
||||
|
||||
m_TeamStartLocZ[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamStartLocZ[BG_TEAM_HORDE] = 0;
|
||||
m_TeamStartLocZ[TEAM_INDEX_ALLIANCE] = 0;
|
||||
m_TeamStartLocZ[TEAM_INDEX_HORDE] = 0;
|
||||
|
||||
m_TeamStartLocO[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamStartLocO[BG_TEAM_HORDE] = 0;
|
||||
m_TeamStartLocO[TEAM_INDEX_ALLIANCE] = 0;
|
||||
m_TeamStartLocO[TEAM_INDEX_HORDE] = 0;
|
||||
|
||||
m_ArenaTeamIds[BG_TEAM_ALLIANCE] = 0;
|
||||
m_ArenaTeamIds[BG_TEAM_HORDE] = 0;
|
||||
m_ArenaTeamIds[TEAM_INDEX_ALLIANCE] = 0;
|
||||
m_ArenaTeamIds[TEAM_INDEX_HORDE] = 0;
|
||||
|
||||
m_ArenaTeamRatingChanges[BG_TEAM_ALLIANCE] = 0;
|
||||
m_ArenaTeamRatingChanges[BG_TEAM_HORDE] = 0;
|
||||
m_ArenaTeamRatingChanges[TEAM_INDEX_ALLIANCE] = 0;
|
||||
m_ArenaTeamRatingChanges[TEAM_INDEX_HORDE] = 0;
|
||||
|
||||
m_BgRaids[BG_TEAM_ALLIANCE] = NULL;
|
||||
m_BgRaids[BG_TEAM_HORDE] = NULL;
|
||||
m_BgRaids[TEAM_INDEX_ALLIANCE] = NULL;
|
||||
m_BgRaids[TEAM_INDEX_HORDE] = NULL;
|
||||
|
||||
m_PlayersCount[BG_TEAM_ALLIANCE] = 0;
|
||||
m_PlayersCount[BG_TEAM_HORDE] = 0;
|
||||
m_PlayersCount[TEAM_INDEX_ALLIANCE] = 0;
|
||||
m_PlayersCount[TEAM_INDEX_HORDE] = 0;
|
||||
|
||||
m_TeamScores[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamScores[BG_TEAM_HORDE] = 0;
|
||||
m_TeamScores[TEAM_INDEX_ALLIANCE] = 0;
|
||||
m_TeamScores[TEAM_INDEX_HORDE] = 0;
|
||||
|
||||
m_PrematureCountDown = false;
|
||||
m_PrematureCountDownTimer = 0;
|
||||
|
|
@ -459,6 +459,14 @@ void BattleGround::Update(uint32 diff)
|
|||
/*********************************************************/
|
||||
/*** BATTLEGROUND ENDING SYSTEM ***/
|
||||
/*********************************************************/
|
||||
if (GetStatus() == STATUS_IN_PROGRESS && isArena())
|
||||
{
|
||||
// after 45 minutes without one team losing, the arena closes with no winner and -16 rating change for both
|
||||
if (m_StartTime > uint32(m_StartDelayTimes[BG_STARTING_EVENT_FIRST] + ARENA_FORCED_DRAW))
|
||||
{
|
||||
EndBattleGround(TEAM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetStatus() == STATUS_WAIT_LEAVE)
|
||||
{
|
||||
|
|
@ -485,7 +493,7 @@ void BattleGround::Update(uint32 diff)
|
|||
|
||||
void BattleGround::SetTeamStartLoc(Team team, float X, float Y, float Z, float O)
|
||||
{
|
||||
BattleGroundTeamIndex teamIdx = GetTeamIndexByTeamId(team);
|
||||
PvpTeamIndex teamIdx = GetTeamIndexByTeamId(team);
|
||||
m_TeamStartLocX[teamIdx] = X;
|
||||
m_TeamStartLocY[teamIdx] = Y;
|
||||
m_TeamStartLocZ[teamIdx] = Z;
|
||||
|
|
@ -1322,18 +1330,20 @@ void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player* plr, ObjectGuid plr_gu
|
|||
}
|
||||
|
||||
// This method should be called when player logs into running battleground
|
||||
void BattleGround::EventPlayerLoggedIn(Player* player, ObjectGuid plr_guid)
|
||||
void BattleGround::EventPlayerLoggedIn(Player* player)
|
||||
{
|
||||
ObjectGuid playerGuid = player->GetObjectGuid();
|
||||
|
||||
// player is correct pointer
|
||||
for (OfflineQueue::iterator itr = m_OfflineQueue.begin(); itr != m_OfflineQueue.end(); ++itr)
|
||||
{
|
||||
if (*itr == plr_guid)
|
||||
if (*itr == playerGuid)
|
||||
{
|
||||
m_OfflineQueue.erase(itr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_Players[plr_guid].OfflineRemoveTime = 0;
|
||||
m_Players[playerGuid].OfflineRemoveTime = 0;
|
||||
PlayerAddedToBGCheckIfBGIsRunning(player);
|
||||
// if battleground is starting, then add preparation aura
|
||||
// we don't have to do that, because preparation aura isn't removed when player logs out
|
||||
|
|
@ -1783,7 +1793,7 @@ WorldSafeLocsEntry const* BattleGround::GetClosestGraveYard(Player* player)
|
|||
|
||||
bool BattleGround::IsTeamScoreInRange(Team team, uint32 minScore, uint32 maxScore) const
|
||||
{
|
||||
BattleGroundTeamIndex team_idx = GetTeamIndexByTeamId(team);
|
||||
PvpTeamIndex team_idx = GetTeamIndexByTeamId(team);
|
||||
uint32 score = (m_TeamScores[team_idx] < 0) ? 0 : uint32(m_TeamScores[team_idx]);
|
||||
return score >= minScore && score <= maxScore;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,13 +112,14 @@ enum BattleGroundTimeIntervals
|
|||
{
|
||||
RESURRECTION_INTERVAL = 30000, // ms
|
||||
INVITATION_REMIND_TIME = 20000, // ms
|
||||
INVITE_ACCEPT_WAIT_TIME = 40000, // ms
|
||||
INVITE_ACCEPT_WAIT_TIME = 60000, // ms
|
||||
TIME_TO_AUTOREMOVE = 120000, // ms
|
||||
MAX_OFFLINE_TIME = 300, // secs
|
||||
RESPAWN_ONE_DAY = 86400, // secs
|
||||
RESPAWN_IMMEDIATELY = 0, // secs
|
||||
BUFF_RESPAWN_TIME = 180, // secs
|
||||
ARENA_SPAWN_BUFF_OBJECTS = 90000, // ms - 90sec after start
|
||||
ARENA_FORCED_DRAW = 2700000, // ms - 45min after start
|
||||
BATTLEGROUND_COUNTDOWN_MAX = 120, // secs
|
||||
ARENA_COUNTDOWN_MAX = 60, // secs
|
||||
};
|
||||
|
|
@ -212,14 +213,6 @@ enum BattleGroundType
|
|||
TYPE_ARENA = 4
|
||||
};
|
||||
|
||||
enum BattleGroundTeamIndex
|
||||
{
|
||||
BG_TEAM_ALLIANCE = 0,
|
||||
BG_TEAM_HORDE = 1
|
||||
};
|
||||
|
||||
#define BG_TEAMS_COUNT 2
|
||||
|
||||
enum BattleGroundStartingEvents
|
||||
{
|
||||
BG_STARTING_EVENT_NONE = 0x00,
|
||||
|
|
@ -432,7 +425,7 @@ class BattleGround
|
|||
void SetTeamStartLoc(Team team, float X, float Y, float Z, float O);
|
||||
void GetTeamStartLoc(Team team, float& X, float& Y, float& Z, float& O) const
|
||||
{
|
||||
BattleGroundTeamIndex idx = GetTeamIndexByTeamId(team);
|
||||
PvpTeamIndex idx = GetTeamIndexByTeamId(team);
|
||||
X = m_TeamStartLocX[idx];
|
||||
Y = m_TeamStartLocY[idx];
|
||||
Z = m_TeamStartLocZ[idx];
|
||||
|
|
@ -477,7 +470,7 @@ class BattleGround
|
|||
|
||||
virtual void UpdatePlayerScore(Player* Source, uint32 type, uint32 value);
|
||||
|
||||
static BattleGroundTeamIndex GetTeamIndexByTeamId(Team team) { return team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; }
|
||||
static PvpTeamIndex GetTeamIndexByTeamId(Team team) { return team == ALLIANCE ? TEAM_INDEX_ALLIANCE : TEAM_INDEX_HORDE; }
|
||||
uint32 GetPlayersCountByTeam(Team team) const { return m_PlayersCount[GetTeamIndexByTeamId(team)]; }
|
||||
uint32 GetAlivePlayersCountByTeam(Team team) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases
|
||||
void UpdatePlayersCountByTeam(Team team, bool remove)
|
||||
|
|
@ -518,7 +511,7 @@ class BattleGround
|
|||
virtual void EventPlayerDroppedFlag(Player* /*player*/) {}
|
||||
virtual void EventPlayerClickedOnFlag(Player* /*player*/, GameObject* /*target_obj*/) {}
|
||||
virtual void EventPlayerCapturedFlag(Player* /*player*/) {}
|
||||
void EventPlayerLoggedIn(Player* player, ObjectGuid plr_guid);
|
||||
void EventPlayerLoggedIn(Player* player);
|
||||
void EventPlayerLoggedOut(Player* player);
|
||||
|
||||
/* Death related */
|
||||
|
|
@ -563,11 +556,11 @@ class BattleGround
|
|||
Team GetPlayerTeam(ObjectGuid guid);
|
||||
uint32 GetRemainingTime() const { return m_EndTime; }
|
||||
static Team GetOtherTeam(Team team) { return team ? ((team == ALLIANCE) ? HORDE : ALLIANCE) : TEAM_NONE; }
|
||||
static BattleGroundTeamIndex GetOtherTeamIndex(BattleGroundTeamIndex teamIdx) { return teamIdx == BG_TEAM_ALLIANCE ? BG_TEAM_HORDE : BG_TEAM_ALLIANCE; }
|
||||
static PvpTeamIndex GetOtherTeamIndex(PvpTeamIndex teamIdx) { return teamIdx == TEAM_INDEX_ALLIANCE ? TEAM_INDEX_HORDE : TEAM_INDEX_ALLIANCE; }
|
||||
bool IsPlayerInBattleGround(ObjectGuid guid);
|
||||
|
||||
/* virtual score-array - get's used in bg-subclasses */
|
||||
int32 m_TeamScores[BG_TEAMS_COUNT];
|
||||
int32 m_TeamScores[PVP_TEAM_COUNT];
|
||||
|
||||
struct EventObjects
|
||||
{
|
||||
|
|
@ -640,15 +633,15 @@ class BattleGround
|
|||
uint32 m_InvitedHorde;
|
||||
|
||||
/* Raid Group */
|
||||
Group* m_BgRaids[BG_TEAMS_COUNT]; // 0 - alliance, 1 - horde
|
||||
Group* m_BgRaids[PVP_TEAM_COUNT]; // 0 - alliance, 1 - horde
|
||||
|
||||
/* Players count by team */
|
||||
uint32 m_PlayersCount[BG_TEAMS_COUNT];
|
||||
uint32 m_PlayersCount[PVP_TEAM_COUNT];
|
||||
|
||||
/* Arena team ids by team */
|
||||
uint32 m_ArenaTeamIds[BG_TEAMS_COUNT];
|
||||
uint32 m_ArenaTeamIds[PVP_TEAM_COUNT];
|
||||
|
||||
int32 m_ArenaTeamRatingChanges[BG_TEAMS_COUNT];
|
||||
int32 m_ArenaTeamRatingChanges[PVP_TEAM_COUNT];
|
||||
|
||||
/* Limits */
|
||||
uint32 m_LevelMin;
|
||||
|
|
@ -661,10 +654,10 @@ class BattleGround
|
|||
/* Start location */
|
||||
uint32 m_MapId;
|
||||
BattleGroundMap* m_Map;
|
||||
float m_TeamStartLocX[BG_TEAMS_COUNT];
|
||||
float m_TeamStartLocY[BG_TEAMS_COUNT];
|
||||
float m_TeamStartLocZ[BG_TEAMS_COUNT];
|
||||
float m_TeamStartLocO[BG_TEAMS_COUNT];
|
||||
float m_TeamStartLocX[PVP_TEAM_COUNT];
|
||||
float m_TeamStartLocY[PVP_TEAM_COUNT];
|
||||
float m_TeamStartLocZ[PVP_TEAM_COUNT];
|
||||
float m_TeamStartLocO[PVP_TEAM_COUNT];
|
||||
};
|
||||
|
||||
// helper functions for world state list fill
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ void BattleGroundAB::Update(uint32 diff)
|
|||
|
||||
if (GetStatus() == STATUS_IN_PROGRESS)
|
||||
{
|
||||
int team_points[BG_TEAMS_COUNT] = { 0, 0 };
|
||||
int team_points[PVP_TEAM_COUNT] = { 0, 0 };
|
||||
|
||||
for (uint8 node = 0; node < BG_AB_NODES_MAX; ++node)
|
||||
{
|
||||
|
|
@ -100,13 +100,13 @@ void BattleGroundAB::Update(uint32 diff)
|
|||
}
|
||||
}
|
||||
|
||||
for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
|
||||
for (uint8 team = 0; team < PVP_TEAM_COUNT; ++team)
|
||||
if (m_Nodes[node] == team + BG_AB_NODE_TYPE_OCCUPIED)
|
||||
++team_points[team];
|
||||
}
|
||||
|
||||
// Accumulate points
|
||||
for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
|
||||
for (uint8 team = 0; team < PVP_TEAM_COUNT; ++team)
|
||||
{
|
||||
int points = team_points[team];
|
||||
if (!points)
|
||||
|
|
@ -120,17 +120,17 @@ void BattleGroundAB::Update(uint32 diff)
|
|||
m_ReputationScoreTics[team] += BG_AB_TickPoints[points];
|
||||
if (m_ReputationScoreTics[team] >= m_ReputationTics)
|
||||
{
|
||||
(team == BG_TEAM_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE);
|
||||
(team == TEAM_INDEX_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE);
|
||||
m_ReputationScoreTics[team] -= m_ReputationTics;
|
||||
}
|
||||
if (m_honorScoreTicks[team] >= m_honorTicks)
|
||||
{
|
||||
RewardHonorToTeam(GetBonusHonorFromKill(1), (team == BG_TEAM_ALLIANCE) ? ALLIANCE : HORDE);
|
||||
RewardHonorToTeam(GetBonusHonorFromKill(1), (team == TEAM_INDEX_ALLIANCE) ? ALLIANCE : HORDE);
|
||||
m_honorScoreTicks[team] -= m_honorTicks;
|
||||
}
|
||||
if (!m_IsInformedNearVictory && m_TeamScores[team] > BG_AB_WARNING_NEAR_VICTORY_SCORE)
|
||||
{
|
||||
if (team == BG_TEAM_ALLIANCE)
|
||||
if (team == TEAM_INDEX_ALLIANCE)
|
||||
SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
||||
else
|
||||
SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
||||
|
|
@ -140,24 +140,24 @@ void BattleGroundAB::Update(uint32 diff)
|
|||
|
||||
if (m_TeamScores[team] > BG_AB_MAX_TEAM_SCORE)
|
||||
m_TeamScores[team] = BG_AB_MAX_TEAM_SCORE;
|
||||
if (team == BG_TEAM_ALLIANCE)
|
||||
if (team == TEAM_INDEX_ALLIANCE)
|
||||
UpdateWorldState(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[team]);
|
||||
if (team == BG_TEAM_HORDE)
|
||||
if (team == TEAM_INDEX_HORDE)
|
||||
UpdateWorldState(BG_AB_OP_RESOURCES_HORDE, m_TeamScores[team]);
|
||||
|
||||
// update achievement flags
|
||||
// we increased m_TeamScores[team] so we just need to check if it is 500 more than other teams resources
|
||||
// horde will be a bit disadvantaged, but we can assume that points aren't updated for both team in same Update() call
|
||||
uint8 otherTeam = (team + 1) % BG_TEAMS_COUNT;
|
||||
uint8 otherTeam = (team + 1) % PVP_TEAM_COUNT;
|
||||
if (m_TeamScores[team] > m_TeamScores[otherTeam] + 500)
|
||||
m_TeamScores500Disadvantage[otherTeam] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Test win condition
|
||||
if (m_TeamScores[BG_TEAM_ALLIANCE] >= BG_AB_MAX_TEAM_SCORE)
|
||||
if (m_TeamScores[TEAM_INDEX_ALLIANCE] >= BG_AB_MAX_TEAM_SCORE)
|
||||
EndBattleGround(ALLIANCE);
|
||||
if (m_TeamScores[BG_TEAM_HORDE] >= BG_AB_MAX_TEAM_SCORE)
|
||||
if (m_TeamScores[TEAM_INDEX_HORDE] >= BG_AB_MAX_TEAM_SCORE)
|
||||
EndBattleGround(HORDE);
|
||||
}
|
||||
}
|
||||
|
|
@ -277,8 +277,8 @@ void BattleGroundAB::FillInitialWorldStates(WorldPacket& data, uint32& count)
|
|||
// Team scores
|
||||
FillInitialWorldState(data, count, BG_AB_OP_RESOURCES_MAX, BG_AB_MAX_TEAM_SCORE);
|
||||
FillInitialWorldState(data, count, BG_AB_OP_RESOURCES_WARNING, BG_AB_WARNING_NEAR_VICTORY_SCORE);
|
||||
FillInitialWorldState(data, count, BG_AB_OP_RESOURCES_ALLY, m_TeamScores[BG_TEAM_ALLIANCE]);
|
||||
FillInitialWorldState(data, count, BG_AB_OP_RESOURCES_HORDE, m_TeamScores[BG_TEAM_HORDE]);
|
||||
FillInitialWorldState(data, count, BG_AB_OP_RESOURCES_ALLY, m_TeamScores[TEAM_INDEX_ALLIANCE]);
|
||||
FillInitialWorldState(data, count, BG_AB_OP_RESOURCES_HORDE, m_TeamScores[TEAM_INDEX_HORDE]);
|
||||
|
||||
// other unknown
|
||||
FillInitialWorldState(data, count, 0x745, 0x2); // 37 1861 unk
|
||||
|
|
@ -333,7 +333,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player* source, GameObject* target
|
|||
return;
|
||||
BG_AB_Nodes node = BG_AB_Nodes(event);
|
||||
|
||||
BattleGroundTeamIndex teamIndex = GetTeamIndexByTeamId(source->GetTeam());
|
||||
PvpTeamIndex teamIndex = GetTeamIndexByTeamId(source->GetTeam());
|
||||
|
||||
// Check if player really could use this banner, not cheated
|
||||
if (!(m_Nodes[node] == 0 || teamIndex == m_Nodes[node] % 2))
|
||||
|
|
@ -376,7 +376,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player* source, GameObject* target
|
|||
_SendNodeUpdate(node);
|
||||
m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
|
||||
|
||||
if (teamIndex == BG_TEAM_ALLIANCE)
|
||||
if (teamIndex == TEAM_INDEX_ALLIANCE)
|
||||
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED, CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node));
|
||||
else
|
||||
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED, CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node));
|
||||
|
|
@ -391,14 +391,14 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player* source, GameObject* target
|
|||
_CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true);
|
||||
_SendNodeUpdate(node);
|
||||
m_NodeTimers[node] = 0;
|
||||
_NodeOccupied(node, (teamIndex == BG_TEAM_ALLIANCE) ? ALLIANCE : HORDE);
|
||||
_NodeOccupied(node, (teamIndex == TEAM_INDEX_ALLIANCE) ? ALLIANCE : HORDE);
|
||||
|
||||
if (teamIndex == BG_TEAM_ALLIANCE)
|
||||
if (teamIndex == TEAM_INDEX_ALLIANCE)
|
||||
SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED, CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node));
|
||||
else
|
||||
SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED, CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node));
|
||||
}
|
||||
sound = (teamIndex == BG_TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
|
||||
sound = (teamIndex == TEAM_INDEX_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
|
||||
}
|
||||
// If node is occupied, change to enemy-contested
|
||||
else
|
||||
|
|
@ -411,18 +411,18 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player* source, GameObject* target
|
|||
_SendNodeUpdate(node);
|
||||
m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
|
||||
|
||||
if (teamIndex == BG_TEAM_ALLIANCE)
|
||||
if (teamIndex == TEAM_INDEX_ALLIANCE)
|
||||
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED, CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node));
|
||||
else
|
||||
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED, CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node));
|
||||
|
||||
sound = (teamIndex == BG_TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
|
||||
sound = (teamIndex == TEAM_INDEX_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
|
||||
}
|
||||
|
||||
// If node is occupied again, send "X has taken the Y" msg.
|
||||
if (m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED)
|
||||
{
|
||||
if (teamIndex == BG_TEAM_ALLIANCE)
|
||||
if (teamIndex == TEAM_INDEX_ALLIANCE)
|
||||
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN, CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, LANG_BG_ALLY, _GetNodeNameId(node));
|
||||
else
|
||||
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN, CHAT_MSG_BG_SYSTEM_HORDE, NULL, LANG_BG_HORDE, _GetNodeNameId(node));
|
||||
|
|
@ -435,7 +435,7 @@ void BattleGroundAB::Reset()
|
|||
// call parent's class reset
|
||||
BattleGround::Reset();
|
||||
|
||||
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
|
||||
for (uint8 i = 0; i < PVP_TEAM_COUNT; ++i)
|
||||
{
|
||||
m_TeamScores[i] = 0;
|
||||
m_lastTick[i] = 0;
|
||||
|
|
@ -477,7 +477,7 @@ void BattleGroundAB::EndBattleGround(Team winner)
|
|||
|
||||
WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player)
|
||||
{
|
||||
BattleGroundTeamIndex teamIndex = GetTeamIndexByTeamId(player->GetTeam());
|
||||
PvpTeamIndex teamIndex = GetTeamIndexByTeamId(player->GetTeam());
|
||||
|
||||
// Is there any occupied node for this team?
|
||||
std::vector<uint8> nodes;
|
||||
|
|
|
|||
|
|
@ -153,6 +153,10 @@ class BattleGroundABScore : public BattleGroundScore
|
|||
public:
|
||||
BattleGroundABScore(): BasesAssaulted(0), BasesDefended(0) {};
|
||||
virtual ~BattleGroundABScore() {};
|
||||
|
||||
uint32 GetAttr1() const { return BasesAssaulted; }
|
||||
uint32 GetAttr2() const { return BasesDefended; }
|
||||
|
||||
uint32 BasesAssaulted;
|
||||
uint32 BasesDefended;
|
||||
};
|
||||
|
|
@ -207,13 +211,13 @@ class BattleGroundAB : public BattleGround
|
|||
uint8 m_prevNodes[BG_AB_NODES_MAX]; // used for performant wordlstate-updating
|
||||
BG_AB_BannerTimer m_BannerTimers[BG_AB_NODES_MAX];
|
||||
uint32 m_NodeTimers[BG_AB_NODES_MAX];
|
||||
uint32 m_lastTick[BG_TEAMS_COUNT];
|
||||
uint32 m_honorScoreTicks[BG_TEAMS_COUNT];
|
||||
uint32 m_ReputationScoreTics[BG_TEAMS_COUNT];
|
||||
uint32 m_lastTick[PVP_TEAM_COUNT];
|
||||
uint32 m_honorScoreTicks[PVP_TEAM_COUNT];
|
||||
uint32 m_ReputationScoreTics[PVP_TEAM_COUNT];
|
||||
bool m_IsInformedNearVictory;
|
||||
uint32 m_honorTicks;
|
||||
uint32 m_ReputationTics;
|
||||
// need for achievements
|
||||
bool m_TeamScores500Disadvantage[BG_TEAMS_COUNT];
|
||||
bool m_TeamScores500Disadvantage[PVP_TEAM_COUNT];
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ void BattleGroundAV::HandleKillUnit(Creature* creature, Player* killer)
|
|||
return;
|
||||
RewardReputationToTeam(BG_AV_FACTION_H, m_RepCaptain, HORDE);
|
||||
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), HORDE);
|
||||
UpdateScore(BG_TEAM_ALLIANCE, (-1) * BG_AV_RES_CAPTAIN);
|
||||
UpdateScore(TEAM_INDEX_ALLIANCE, (-1) * BG_AV_RES_CAPTAIN);
|
||||
// spawn destroyed aura
|
||||
SpawnEvent(BG_AV_NodeEventCaptainDead_A, 0, true);
|
||||
break;
|
||||
|
|
@ -87,7 +87,7 @@ void BattleGroundAV::HandleKillUnit(Creature* creature, Player* killer)
|
|||
return;
|
||||
RewardReputationToTeam(BG_AV_FACTION_A, m_RepCaptain, ALLIANCE);
|
||||
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), ALLIANCE);
|
||||
UpdateScore(BG_TEAM_HORDE, (-1) * BG_AV_RES_CAPTAIN);
|
||||
UpdateScore(TEAM_INDEX_HORDE, (-1) * BG_AV_RES_CAPTAIN);
|
||||
// spawn destroyed aura
|
||||
SpawnEvent(BG_AV_NodeEventCaptainDead_H, 0, true);
|
||||
break;
|
||||
|
|
@ -211,10 +211,10 @@ void BattleGroundAV::HandleQuestComplete(uint32 questid, Player* player)
|
|||
RewardReputationToTeam((player->GetTeam() == ALLIANCE) ? BG_AV_FACTION_A : BG_AV_FACTION_H, reputation, player->GetTeam());
|
||||
}
|
||||
|
||||
void BattleGroundAV::UpdateScore(BattleGroundTeamIndex teamIdx, int32 points)
|
||||
void BattleGroundAV::UpdateScore(PvpTeamIndex teamIdx, int32 points)
|
||||
{
|
||||
// note: to remove reinforcements points must be negative, for adding reinforcements points must be positive
|
||||
MANGOS_ASSERT(teamIdx == BG_TEAM_ALLIANCE || teamIdx == BG_TEAM_HORDE);
|
||||
MANGOS_ASSERT(teamIdx == TEAM_INDEX_ALLIANCE || teamIdx == TEAM_INDEX_HORDE);
|
||||
m_TeamScores[teamIdx] += points; // m_TeamScores is int32 - so no problems here
|
||||
|
||||
if (points < 0)
|
||||
|
|
@ -223,17 +223,17 @@ void BattleGroundAV::UpdateScore(BattleGroundTeamIndex teamIdx, int32 points)
|
|||
{
|
||||
m_TeamScores[teamIdx] = 0;
|
||||
// other team will win:
|
||||
EndBattleGround((teamIdx == BG_TEAM_ALLIANCE) ? HORDE : ALLIANCE);
|
||||
EndBattleGround((teamIdx == TEAM_INDEX_ALLIANCE) ? HORDE : ALLIANCE);
|
||||
}
|
||||
else if (!m_IsInformedNearLose[teamIdx] && m_TeamScores[teamIdx] < BG_AV_SCORE_NEAR_LOSE)
|
||||
{
|
||||
SendMessageToAll((teamIdx == BG_TEAM_HORDE) ? LANG_BG_AV_H_NEAR_LOSE : LANG_BG_AV_A_NEAR_LOSE, CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
||||
SendMessageToAll((teamIdx == TEAM_INDEX_HORDE) ? LANG_BG_AV_H_NEAR_LOSE : LANG_BG_AV_A_NEAR_LOSE, CHAT_MSG_BG_SYSTEM_NEUTRAL);
|
||||
PlaySoundToAll(BG_AV_SOUND_NEAR_LOSE);
|
||||
m_IsInformedNearLose[teamIdx] = true;
|
||||
}
|
||||
}
|
||||
// must be called here, else it could display a negative value
|
||||
UpdateWorldState(((teamIdx == BG_TEAM_HORDE) ? BG_AV_Horde_Score : BG_AV_Alliance_Score), m_TeamScores[teamIdx]);
|
||||
UpdateWorldState(((teamIdx == TEAM_INDEX_HORDE) ? BG_AV_Horde_Score : BG_AV_Alliance_Score), m_TeamScores[teamIdx]);
|
||||
}
|
||||
|
||||
void BattleGroundAV::Update(uint32 diff)
|
||||
|
|
@ -251,7 +251,7 @@ void BattleGroundAV::Update(uint32 diff)
|
|||
m_Mine_Timer[mine] -= diff;
|
||||
if (m_Mine_Timer[mine] <= 0)
|
||||
{
|
||||
UpdateScore(BattleGroundTeamIndex(m_Mine_Owner[mine]), WORLD_STATE_ADD);
|
||||
UpdateScore(PvpTeamIndex(m_Mine_Owner[mine]), WORLD_STATE_ADD);
|
||||
m_Mine_Timer[mine] = BG_AV_MINE_TICK_TIMER;
|
||||
}
|
||||
|
||||
|
|
@ -296,18 +296,18 @@ void BattleGroundAV::AddPlayer(Player* plr)
|
|||
void BattleGroundAV::EndBattleGround(Team winner)
|
||||
{
|
||||
// calculate bonuskills for both teams:
|
||||
uint32 tower_survived[BG_TEAMS_COUNT] = {0, 0};
|
||||
uint32 graves_owned[BG_TEAMS_COUNT] = {0, 0};
|
||||
uint32 mines_owned[BG_TEAMS_COUNT] = {0, 0};
|
||||
uint32 tower_survived[PVP_TEAM_COUNT] = {0, 0};
|
||||
uint32 graves_owned[PVP_TEAM_COUNT] = {0, 0};
|
||||
uint32 mines_owned[PVP_TEAM_COUNT] = {0, 0};
|
||||
// towers all not destroyed:
|
||||
for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i)
|
||||
if (m_Nodes[i].State == POINT_CONTROLLED)
|
||||
if (m_Nodes[i].TotalOwner == BG_AV_TEAM_ALLIANCE)
|
||||
++tower_survived[BG_TEAM_ALLIANCE];
|
||||
++tower_survived[TEAM_INDEX_ALLIANCE];
|
||||
for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i)
|
||||
if (m_Nodes[i].State == POINT_CONTROLLED)
|
||||
if (m_Nodes[i].TotalOwner == BG_AV_TEAM_HORDE)
|
||||
++tower_survived[BG_TEAM_HORDE];
|
||||
++tower_survived[TEAM_INDEX_HORDE];
|
||||
|
||||
// graves all controlled
|
||||
for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i)
|
||||
|
|
@ -319,9 +319,9 @@ void BattleGroundAV::EndBattleGround(Team winner)
|
|||
++mines_owned[m_Mine_Owner[i]];
|
||||
|
||||
// now we have the values give the honor/reputation to the teams:
|
||||
Team team[BG_TEAMS_COUNT] = { ALLIANCE, HORDE };
|
||||
uint32 faction[BG_TEAMS_COUNT] = { BG_AV_FACTION_A, BG_AV_FACTION_H };
|
||||
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
|
||||
Team team[PVP_TEAM_COUNT] = { ALLIANCE, HORDE };
|
||||
uint32 faction[PVP_TEAM_COUNT] = { BG_AV_FACTION_A, BG_AV_FACTION_H };
|
||||
for (uint8 i = 0; i < PVP_TEAM_COUNT; ++i)
|
||||
{
|
||||
if (tower_survived[i])
|
||||
{
|
||||
|
|
@ -417,8 +417,8 @@ void BattleGroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node)
|
|||
DEBUG_LOG("BattleGroundAV: player destroyed point node %i", node);
|
||||
|
||||
MANGOS_ASSERT(m_Nodes[node].Owner != BG_AV_TEAM_NEUTRAL)
|
||||
BattleGroundTeamIndex ownerTeamIdx = BattleGroundTeamIndex(m_Nodes[node].Owner);
|
||||
Team ownerTeam = ownerTeamIdx == BG_TEAM_ALLIANCE ? ALLIANCE : HORDE;
|
||||
PvpTeamIndex ownerTeamIdx = PvpTeamIndex(m_Nodes[node].Owner);
|
||||
Team ownerTeam = ownerTeamIdx == TEAM_INDEX_ALLIANCE ? ALLIANCE : HORDE;
|
||||
|
||||
// despawn banner
|
||||
DestroyNode(node);
|
||||
|
|
@ -531,7 +531,7 @@ void BattleGroundAV::EventPlayerDefendsPoint(Player* player, BG_AV_Nodes node)
|
|||
{
|
||||
MANGOS_ASSERT(GetStatus() == STATUS_IN_PROGRESS);
|
||||
|
||||
BattleGroundTeamIndex teamIdx = GetTeamIndexByTeamId(player->GetTeam());
|
||||
PvpTeamIndex teamIdx = GetTeamIndexByTeamId(player->GetTeam());
|
||||
|
||||
if (m_Nodes[node].Owner == BattleGroundAVTeamIndex(teamIdx) || m_Nodes[node].State != POINT_ASSAULTED)
|
||||
return;
|
||||
|
|
@ -559,7 +559,7 @@ void BattleGroundAV::EventPlayerDefendsPoint(Player* player, BG_AV_Nodes node)
|
|||
{
|
||||
SendYell2ToAll(LANG_BG_AV_TOWER_DEFENDED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0),
|
||||
GetNodeName(node),
|
||||
(teamIdx == BG_TEAM_ALLIANCE) ? LANG_BG_ALLY : LANG_BG_HORDE);
|
||||
(teamIdx == TEAM_INDEX_ALLIANCE) ? LANG_BG_ALLY : LANG_BG_HORDE);
|
||||
UpdatePlayerScore(player, SCORE_TOWERS_DEFENDED, 1);
|
||||
PlaySoundToAll(BG_AV_SOUND_BOTH_TOWER_DEFEND);
|
||||
}
|
||||
|
|
@ -567,17 +567,17 @@ void BattleGroundAV::EventPlayerDefendsPoint(Player* player, BG_AV_Nodes node)
|
|||
{
|
||||
SendYell2ToAll(LANG_BG_AV_GRAVE_DEFENDED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0),
|
||||
GetNodeName(node),
|
||||
(teamIdx == BG_TEAM_ALLIANCE) ? LANG_BG_ALLY : LANG_BG_HORDE);
|
||||
(teamIdx == TEAM_INDEX_ALLIANCE) ? LANG_BG_ALLY : LANG_BG_HORDE);
|
||||
UpdatePlayerScore(player, SCORE_GRAVEYARDS_DEFENDED, 1);
|
||||
// update the statistic for the defending player
|
||||
PlaySoundToAll((teamIdx == BG_TEAM_ALLIANCE) ? BG_AV_SOUND_ALLIANCE_GOOD : BG_AV_SOUND_HORDE_GOOD);
|
||||
PlaySoundToAll((teamIdx == TEAM_INDEX_ALLIANCE) ? BG_AV_SOUND_ALLIANCE_GOOD : BG_AV_SOUND_HORDE_GOOD);
|
||||
}
|
||||
}
|
||||
|
||||
void BattleGroundAV::EventPlayerAssaultsPoint(Player* player, BG_AV_Nodes node)
|
||||
{
|
||||
// TODO implement quest 7101, 7081
|
||||
BattleGroundTeamIndex teamIdx = GetTeamIndexByTeamId(player->GetTeam());
|
||||
PvpTeamIndex teamIdx = GetTeamIndexByTeamId(player->GetTeam());
|
||||
DEBUG_LOG("BattleGroundAV: player assaults node %i", node);
|
||||
if (m_Nodes[node].Owner == BattleGroundAVTeamIndex(teamIdx) || BattleGroundAVTeamIndex(teamIdx) == m_Nodes[node].TotalOwner)
|
||||
return;
|
||||
|
|
@ -590,19 +590,19 @@ void BattleGroundAV::EventPlayerAssaultsPoint(Player* player, BG_AV_Nodes node)
|
|||
{
|
||||
SendYell2ToAll(LANG_BG_AV_TOWER_ASSAULTED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0),
|
||||
GetNodeName(node),
|
||||
(teamIdx == BG_TEAM_ALLIANCE) ? LANG_BG_ALLY : LANG_BG_HORDE);
|
||||
(teamIdx == TEAM_INDEX_ALLIANCE) ? LANG_BG_ALLY : LANG_BG_HORDE);
|
||||
UpdatePlayerScore(player, SCORE_TOWERS_ASSAULTED, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendYell2ToAll(LANG_BG_AV_GRAVE_ASSAULTED, LANG_UNIVERSAL, GetSingleCreatureGuid(BG_AV_HERALD, 0),
|
||||
GetNodeName(node),
|
||||
(teamIdx == BG_TEAM_ALLIANCE) ? LANG_BG_ALLY : LANG_BG_HORDE);
|
||||
(teamIdx == TEAM_INDEX_ALLIANCE) ? LANG_BG_ALLY : LANG_BG_HORDE);
|
||||
// update the statistic for the assaulting player
|
||||
UpdatePlayerScore(player, SCORE_GRAVEYARDS_ASSAULTED, 1);
|
||||
}
|
||||
|
||||
PlaySoundToAll((teamIdx == BG_TEAM_ALLIANCE) ? BG_AV_SOUND_ALLIANCE_ASSAULTS : BG_AV_SOUND_HORDE_ASSAULTS);
|
||||
PlaySoundToAll((teamIdx == TEAM_INDEX_ALLIANCE) ? BG_AV_SOUND_ALLIANCE_ASSAULTS : BG_AV_SOUND_HORDE_ASSAULTS);
|
||||
}
|
||||
|
||||
void BattleGroundAV::FillInitialWorldStates(WorldPacket& data, uint32& count)
|
||||
|
|
@ -623,8 +623,8 @@ void BattleGroundAV::FillInitialWorldStates(WorldPacket& data, uint32& count)
|
|||
if (m_Nodes[BG_AV_NODES_SNOWFALL_GRAVE].Owner == BG_AV_TEAM_NEUTRAL) // cause neutral teams aren't handled generic
|
||||
FillInitialWorldState(data, count, AV_SNOWFALL_N, WORLD_STATE_ADD);
|
||||
|
||||
FillInitialWorldState(data, count, BG_AV_Alliance_Score, m_TeamScores[BG_TEAM_ALLIANCE]);
|
||||
FillInitialWorldState(data, count, BG_AV_Horde_Score, m_TeamScores[BG_TEAM_HORDE]);
|
||||
FillInitialWorldState(data, count, BG_AV_Alliance_Score, m_TeamScores[TEAM_INDEX_ALLIANCE]);
|
||||
FillInitialWorldState(data, count, BG_AV_Horde_Score, m_TeamScores[TEAM_INDEX_HORDE]);
|
||||
if (GetStatus() == STATUS_IN_PROGRESS) // only if game is running the teamscores are displayed
|
||||
{
|
||||
FillInitialWorldState(data, count, BG_AV_SHOW_A_SCORE, WORLD_STATE_ADD);
|
||||
|
|
@ -718,7 +718,7 @@ uint32 BattleGroundAV::GetNodeName(BG_AV_Nodes node) const
|
|||
}
|
||||
}
|
||||
|
||||
void BattleGroundAV::AssaultNode(BG_AV_Nodes node, BattleGroundTeamIndex teamIdx)
|
||||
void BattleGroundAV::AssaultNode(BG_AV_Nodes node, PvpTeamIndex teamIdx)
|
||||
{
|
||||
MANGOS_ASSERT(m_Nodes[node].TotalOwner != BattleGroundAVTeamIndex(teamIdx));
|
||||
MANGOS_ASSERT(m_Nodes[node].Owner != BattleGroundAVTeamIndex(teamIdx));
|
||||
|
|
@ -758,7 +758,7 @@ void BattleGroundAV::InitNode(BG_AV_Nodes node, BattleGroundAVTeamIndex teamIdx,
|
|||
m_ActiveEvents[node + BG_AV_NODES_MAX] = teamIdx * BG_AV_MAX_GRAVETYPES;
|
||||
}
|
||||
|
||||
void BattleGroundAV::DefendNode(BG_AV_Nodes node, BattleGroundTeamIndex teamIdx)
|
||||
void BattleGroundAV::DefendNode(BG_AV_Nodes node, PvpTeamIndex teamIdx)
|
||||
{
|
||||
MANGOS_ASSERT(m_Nodes[node].TotalOwner == BattleGroundAVTeamIndex(teamIdx));
|
||||
MANGOS_ASSERT(m_Nodes[node].Owner != BattleGroundAVTeamIndex(teamIdx));
|
||||
|
|
@ -785,7 +785,7 @@ void BattleGroundAV::Reset()
|
|||
m_RepSurviveTower = (isBGWeekend) ? BG_AV_REP_SURVIVING_TOWER_HOLIDAY : BG_AV_REP_SURVIVING_TOWER;
|
||||
m_RepOwnedMine = (isBGWeekend) ? BG_AV_REP_OWNED_MINE_HOLIDAY : BG_AV_REP_OWNED_MINE;
|
||||
|
||||
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
|
||||
for (uint8 i = 0; i < PVP_TEAM_COUNT; ++i)
|
||||
{
|
||||
for (uint8 j = 0; j < 9; ++j) // 9 quests getting tracked
|
||||
m_Team_QuestStatus[i][j] = 0;
|
||||
|
|
|
|||
|
|
@ -208,13 +208,13 @@ enum BG_AV_WorldStates
|
|||
AV_SNOWFALL_N = 1966,
|
||||
};
|
||||
|
||||
// special version with more wide values range that BattleGroundTeamIndex
|
||||
// BattleGroundAVTeamIndex <- BattleGroundTeamIndex cast safe
|
||||
// BattleGroundAVTeamIndex -> BattleGroundTeamIndex cast safe and array with BG_TEAMS_COUNT elements must checked != BG_AV_TEAM_NEUTRAL before used
|
||||
// special version with more wide values range that PvpTeamIndex
|
||||
// BattleGroundAVTeamIndex <- PvpTeamIndex cast safe
|
||||
// BattleGroundAVTeamIndex -> PvpTeamIndex cast safe and array with PVP_TEAM_COUNT elements must checked != BG_AV_TEAM_NEUTRAL before used
|
||||
enum BattleGroundAVTeamIndex
|
||||
{
|
||||
BG_AV_TEAM_ALLIANCE = BG_TEAM_ALLIANCE,
|
||||
BG_AV_TEAM_HORDE = BG_TEAM_HORDE,
|
||||
BG_AV_TEAM_ALLIANCE = TEAM_INDEX_ALLIANCE,
|
||||
BG_AV_TEAM_HORDE = TEAM_INDEX_HORDE,
|
||||
BG_AV_TEAM_NEUTRAL = 2, // this is the neutral owner of snowfall
|
||||
};
|
||||
|
||||
|
|
@ -311,6 +311,13 @@ class BattleGroundAVScore : public BattleGroundScore
|
|||
public:
|
||||
BattleGroundAVScore() : GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), SecondaryObjectives(0) {};
|
||||
virtual ~BattleGroundAVScore() {};
|
||||
|
||||
uint32 GetAttr1() const { return GraveyardsAssaulted; }
|
||||
uint32 GetAttr2() const { return GraveyardsDefended; }
|
||||
uint32 GetAttr3() const { return TowersAssaulted; }
|
||||
uint32 GetAttr4() const { return TowersDefended; }
|
||||
uint32 GetAttr5() const { return SecondaryObjectives; }
|
||||
|
||||
uint32 GraveyardsAssaulted;
|
||||
uint32 GraveyardsDefended;
|
||||
uint32 TowersAssaulted;
|
||||
|
|
@ -337,7 +344,7 @@ class BattleGroundAV : public BattleGround
|
|||
virtual void Reset() override;
|
||||
|
||||
/*general stuff*/
|
||||
void UpdateScore(BattleGroundTeamIndex teamIdx, int32 points);
|
||||
void UpdateScore(PvpTeamIndex teamIdx, int32 points);
|
||||
void UpdatePlayerScore(Player* source, uint32 type, uint32 value) override;
|
||||
|
||||
/*handle stuff*/ // these are functions which get called from extern scripts
|
||||
|
|
@ -358,10 +365,10 @@ class BattleGroundAV : public BattleGround
|
|||
void EventPlayerDefendsPoint(Player* player, BG_AV_Nodes node);
|
||||
void EventPlayerDestroyedPoint(BG_AV_Nodes node);
|
||||
|
||||
void AssaultNode(BG_AV_Nodes node, BattleGroundTeamIndex teamIdx);
|
||||
void AssaultNode(BG_AV_Nodes node, PvpTeamIndex teamIdx);
|
||||
void DestroyNode(BG_AV_Nodes node);
|
||||
void InitNode(BG_AV_Nodes node, BattleGroundAVTeamIndex teamIdx, bool tower);
|
||||
void DefendNode(BG_AV_Nodes node, BattleGroundTeamIndex teamIdx);
|
||||
void DefendNode(BG_AV_Nodes node, PvpTeamIndex teamIdx);
|
||||
|
||||
void PopulateNode(BG_AV_Nodes node);
|
||||
|
||||
|
|
@ -378,7 +385,7 @@ class BattleGroundAV : public BattleGround
|
|||
void UpdateNodeWorldState(BG_AV_Nodes node);
|
||||
|
||||
/*variables */
|
||||
uint32 m_Team_QuestStatus[BG_TEAMS_COUNT][9]; // [x][y] x=team y=questcounter
|
||||
uint32 m_Team_QuestStatus[PVP_TEAM_COUNT][9]; // [x][y] x=team y=questcounter
|
||||
|
||||
BG_AV_NodeInfo m_Nodes[BG_AV_NODES_MAX];
|
||||
|
||||
|
|
@ -388,7 +395,7 @@ class BattleGroundAV : public BattleGround
|
|||
int32 m_Mine_Timer[BG_AV_MAX_MINES];
|
||||
uint32 m_Mine_Reclaim_Timer[BG_AV_MAX_MINES];
|
||||
|
||||
bool m_IsInformedNearLose[BG_TEAMS_COUNT];
|
||||
bool m_IsInformedNearLose[PVP_TEAM_COUNT];
|
||||
|
||||
uint32 m_HonorMapComplete;
|
||||
uint32 m_RepTowerDestruction;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,28 @@ void BattleGroundEY::Update(uint32 diff)
|
|||
else
|
||||
m_flagRespawnTimer -= diff;
|
||||
}
|
||||
|
||||
// workaround for Fel Reaver Ruins flag capture needed on 3.3.5 only
|
||||
// the original areatrigger (4514) is covered by a bigger one (4515) and is not triggered on client side
|
||||
if (IsFlagPickedUp())
|
||||
{
|
||||
if (m_felReaverFlagTimer < diff)
|
||||
{
|
||||
Player* flagCarrier = sObjectMgr.GetPlayer(GetFlagCarrierGuid());
|
||||
if (flagCarrier)
|
||||
{
|
||||
if (m_towerOwner[NODE_FEL_REAVER_RUINS] == flagCarrier->GetTeam())
|
||||
{
|
||||
// coords and range taken from DBC of areatrigger (4514)
|
||||
if (flagCarrier->GetDistance(2044.0f, 1729.729f, 1190.03f) <= 3.0f)
|
||||
EventPlayerCapturedFlag(flagCarrier, NODE_FEL_REAVER_RUINS);
|
||||
}
|
||||
}
|
||||
m_felReaverFlagTimer = EY_FEL_REAVER_FLAG_UPDATE_TIME;
|
||||
}
|
||||
else
|
||||
m_felReaverFlagTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
void BattleGroundEY::StartingEventOpenDoors()
|
||||
|
|
@ -85,7 +107,7 @@ void BattleGroundEY::StartingEventOpenDoors()
|
|||
|
||||
void BattleGroundEY::AddPoints(Team team, uint32 points)
|
||||
{
|
||||
BattleGroundTeamIndex team_index = GetTeamIndexByTeamId(team);
|
||||
PvpTeamIndex team_index = GetTeamIndexByTeamId(team);
|
||||
m_TeamScores[team_index] += points;
|
||||
m_honorScoreTicks[team_index] += points;
|
||||
if (m_honorScoreTicks[team_index] >= m_honorTicks)
|
||||
|
|
@ -231,7 +253,7 @@ void BattleGroundEY::ProcessCaptureEvent(GameObject* go, uint32 towerId, Team te
|
|||
SendMessageToAll(message, CHAT_MSG_BG_SYSTEM_ALLIANCE);
|
||||
|
||||
// spawn gameobjects
|
||||
SpawnEvent(towerId, BG_TEAM_ALLIANCE, true);
|
||||
SpawnEvent(towerId, TEAM_INDEX_ALLIANCE, true);
|
||||
}
|
||||
else if (team == HORDE)
|
||||
{
|
||||
|
|
@ -242,7 +264,7 @@ void BattleGroundEY::ProcessCaptureEvent(GameObject* go, uint32 towerId, Team te
|
|||
SendMessageToAll(message, CHAT_MSG_BG_SYSTEM_HORDE);
|
||||
|
||||
// spawn gameobjects
|
||||
SpawnEvent(towerId, BG_TEAM_HORDE, true);
|
||||
SpawnEvent(towerId, TEAM_INDEX_HORDE, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -310,15 +332,15 @@ void BattleGroundEY::Reset()
|
|||
// call parent's class reset
|
||||
BattleGround::Reset();
|
||||
|
||||
m_TeamScores[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamScores[BG_TEAM_HORDE] = 0;
|
||||
m_TeamScores[TEAM_INDEX_ALLIANCE] = 0;
|
||||
m_TeamScores[TEAM_INDEX_HORDE] = 0;
|
||||
|
||||
m_towersAlliance = 0;
|
||||
m_towersHorde = 0;
|
||||
|
||||
m_honorTicks = BattleGroundMgr::IsBGWeekend(GetTypeID()) ? EY_WEEKEND_HONOR_INTERVAL : EY_NORMAL_HONOR_INTERVAL;
|
||||
m_honorScoreTicks[BG_TEAM_ALLIANCE] = 0;
|
||||
m_honorScoreTicks[BG_TEAM_HORDE] = 0;
|
||||
m_honorScoreTicks[TEAM_INDEX_ALLIANCE] = 0;
|
||||
m_honorScoreTicks[TEAM_INDEX_HORDE] = 0;
|
||||
|
||||
m_flagState = EY_FLAG_STATE_ON_BASE;
|
||||
m_flagCarrier.Clear();
|
||||
|
|
@ -326,6 +348,7 @@ void BattleGroundEY::Reset()
|
|||
|
||||
m_flagRespawnTimer = 0;
|
||||
m_resourceUpdateTimer = 0;
|
||||
m_felReaverFlagTimer = 0;
|
||||
|
||||
m_towerWorldState[NODE_BLOOD_ELF_TOWER] = WORLD_STATE_EY_BLOOD_ELF_TOWER_NEUTRAL;
|
||||
m_towerWorldState[NODE_FEL_REAVER_RUINS] = WORLD_STATE_EY_FEL_REAVER_RUINS_NEUTRAL;
|
||||
|
|
@ -512,8 +535,8 @@ void BattleGroundEY::FillInitialWorldStates(WorldPacket& data, uint32& count)
|
|||
FillInitialWorldState(data, count, WORLD_STATE_EY_TOWER_COUNT_ALLIANCE, m_towersAlliance);
|
||||
FillInitialWorldState(data, count, WORLD_STATE_EY_TOWER_COUNT_HORDE, m_towersHorde);
|
||||
|
||||
FillInitialWorldState(data, count, WORLD_STATE_EY_RESOURCES_ALLIANCE, m_TeamScores[BG_TEAM_ALLIANCE]);
|
||||
FillInitialWorldState(data, count, WORLD_STATE_EY_RESOURCES_HORDE, m_TeamScores[BG_TEAM_HORDE]);
|
||||
FillInitialWorldState(data, count, WORLD_STATE_EY_RESOURCES_ALLIANCE, m_TeamScores[TEAM_INDEX_ALLIANCE]);
|
||||
FillInitialWorldState(data, count, WORLD_STATE_EY_RESOURCES_HORDE, m_TeamScores[TEAM_INDEX_HORDE]);
|
||||
|
||||
// tower world states
|
||||
FillInitialWorldState(data, count, WORLD_STATE_EY_BLOOD_ELF_TOWER_ALLIANCE, m_towerOwner[NODE_BLOOD_ELF_TOWER] == ALLIANCE);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class BattleGround;
|
|||
|
||||
#define EY_FLAG_RESPAWN_TIME (10 * IN_MILLISECONDS) //10 seconds
|
||||
#define EY_RESOURCES_UPDATE_TIME (2 * IN_MILLISECONDS) //2 seconds
|
||||
#define EY_FEL_REAVER_FLAG_UPDATE_TIME (1 * IN_MILLISECONDS) //1 second
|
||||
|
||||
enum EYWorldStates
|
||||
{
|
||||
|
|
@ -305,9 +306,10 @@ class BattleGroundEY : public BattleGround
|
|||
ObjectGuid m_towers[EY_NODES_MAX];
|
||||
|
||||
uint32 m_honorTicks;
|
||||
uint32 m_honorScoreTicks[BG_TEAMS_COUNT];
|
||||
uint32 m_honorScoreTicks[PVP_TEAM_COUNT];
|
||||
|
||||
uint32 m_flagRespawnTimer;
|
||||
uint32 m_resourceUpdateTimer;
|
||||
uint32 m_felReaverFlagTimer;
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ INSTANTIATE_SINGLETON_1(BattleGroundMgr);
|
|||
|
||||
BattleGroundQueue::BattleGroundQueue()
|
||||
{
|
||||
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
|
||||
for (uint8 i = 0; i < PVP_TEAM_COUNT; ++i)
|
||||
{
|
||||
for (uint8 j = 0; j < MAX_BATTLEGROUND_BRACKETS; ++j)
|
||||
{
|
||||
|
|
@ -175,7 +175,7 @@ GroupQueueInfo* BattleGroundQueue::AddGroup(Player* leader, Group* grp, BattleGr
|
|||
// compute index (if group is premade or joined a rated match) to queues
|
||||
uint32 index = 0;
|
||||
if (!isRated && !isPremade)
|
||||
index += BG_TEAMS_COUNT; // BG_QUEUE_PREMADE_* -> BG_QUEUE_NORMAL_*
|
||||
index += PVP_TEAM_COUNT; // BG_QUEUE_PREMADE_* -> BG_QUEUE_NORMAL_*
|
||||
|
||||
if (ginfo->GroupTeam == HORDE)
|
||||
++index; // BG_QUEUE_*_ALLIANCE -> BG_QUEUE_*_HORDE
|
||||
|
|
@ -260,16 +260,16 @@ GroupQueueInfo* BattleGroundQueue::AddGroup(Player* leader, Group* grp, BattleGr
|
|||
void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BattleGroundBracketId bracket_id)
|
||||
{
|
||||
uint32 timeInQueue = WorldTimer::getMSTimeDiff(ginfo->JoinTime, WorldTimer::getMSTime());
|
||||
uint8 team_index = BG_TEAM_ALLIANCE; // default set to BG_TEAM_ALLIANCE - or non rated arenas!
|
||||
uint8 team_index = TEAM_INDEX_ALLIANCE; // default set to TEAM_INDEX_ALLIANCE - or non rated arenas!
|
||||
if (ginfo->arenaType == ARENA_TYPE_NONE)
|
||||
{
|
||||
if (ginfo->GroupTeam == HORDE)
|
||||
team_index = BG_TEAM_HORDE;
|
||||
team_index = TEAM_INDEX_HORDE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ginfo->IsRated)
|
||||
team_index = BG_TEAM_HORDE; // for rated arenas use BG_TEAM_HORDE
|
||||
team_index = TEAM_INDEX_HORDE; // for rated arenas use TEAM_INDEX_HORDE
|
||||
}
|
||||
|
||||
// store pointer to arrayindex of player that was added first
|
||||
|
|
@ -287,16 +287,16 @@ void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* g
|
|||
|
||||
uint32 BattleGroundQueue::GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BattleGroundBracketId bracket_id)
|
||||
{
|
||||
uint8 team_index = BG_TEAM_ALLIANCE; // default set to BG_TEAM_ALLIANCE - or non rated arenas!
|
||||
uint8 team_index = TEAM_INDEX_ALLIANCE; // default set to TEAM_INDEX_ALLIANCE - or non rated arenas!
|
||||
if (ginfo->arenaType == ARENA_TYPE_NONE)
|
||||
{
|
||||
if (ginfo->GroupTeam == HORDE)
|
||||
team_index = BG_TEAM_HORDE;
|
||||
team_index = TEAM_INDEX_HORDE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ginfo->IsRated)
|
||||
team_index = BG_TEAM_HORDE; // for rated arenas use BG_TEAM_HORDE
|
||||
team_index = TEAM_INDEX_HORDE; // for rated arenas use TEAM_INDEX_HORDE
|
||||
}
|
||||
// check if there is enought values(we always add values > 0)
|
||||
if (m_WaitTimes[team_index][bracket_id][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME - 1])
|
||||
|
|
@ -526,13 +526,13 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BattleGroundBracketId
|
|||
uint32 aliCount = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE].size();
|
||||
// index to queue which group is current
|
||||
uint32 aliIndex = 0;
|
||||
for (; aliIndex < aliCount && m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree); ++aliIndex)
|
||||
for (; aliIndex < aliCount && m_SelectionPools[TEAM_INDEX_ALLIANCE].AddGroup((*Ali_itr), aliFree); ++aliIndex)
|
||||
++Ali_itr;
|
||||
// the same thing for horde
|
||||
GroupsQueueType::const_iterator Horde_itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].begin();
|
||||
uint32 hordeCount = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].size();
|
||||
uint32 hordeIndex = 0;
|
||||
for (; hordeIndex < hordeCount && m_SelectionPools[BG_TEAM_HORDE].AddGroup((*Horde_itr), hordeFree); ++hordeIndex)
|
||||
for (; hordeIndex < hordeCount && m_SelectionPools[TEAM_INDEX_HORDE].AddGroup((*Horde_itr), hordeFree); ++hordeIndex)
|
||||
++Horde_itr;
|
||||
|
||||
// if ofc like BG queue invitation is set in config, then we are happy
|
||||
|
|
@ -548,45 +548,45 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BattleGroundBracketId
|
|||
*/
|
||||
|
||||
// At first we need to compare free space in bg and our selection pool
|
||||
int32 diffAli = aliFree - int32(m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount());
|
||||
int32 diffHorde = hordeFree - int32(m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount());
|
||||
while (abs(diffAli - diffHorde) > 1 && (m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() > 0 || m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() > 0))
|
||||
int32 diffAli = aliFree - int32(m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount());
|
||||
int32 diffHorde = hordeFree - int32(m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount());
|
||||
while (abs(diffAli - diffHorde) > 1 && (m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount() > 0 || m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount() > 0))
|
||||
{
|
||||
// each cycle execution we need to kick at least 1 group
|
||||
if (diffAli < diffHorde)
|
||||
{
|
||||
// kick alliance group, add to pool new group if needed
|
||||
if (m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffHorde - diffAli))
|
||||
if (m_SelectionPools[TEAM_INDEX_ALLIANCE].KickGroup(diffHorde - diffAli))
|
||||
{
|
||||
for (; aliIndex < aliCount && m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*Ali_itr), (aliFree >= diffHorde) ? aliFree - diffHorde : 0); ++aliIndex)
|
||||
for (; aliIndex < aliCount && m_SelectionPools[TEAM_INDEX_ALLIANCE].AddGroup((*Ali_itr), (aliFree >= diffHorde) ? aliFree - diffHorde : 0); ++aliIndex)
|
||||
++Ali_itr;
|
||||
}
|
||||
// if ali selection is already empty, then kick horde group, but if there are less horde than ali in bg - break;
|
||||
if (!m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())
|
||||
if (!m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount())
|
||||
{
|
||||
if (aliFree <= diffHorde + 1)
|
||||
break;
|
||||
m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffHorde - diffAli);
|
||||
m_SelectionPools[TEAM_INDEX_HORDE].KickGroup(diffHorde - diffAli);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// kick horde group, add to pool new group if needed
|
||||
if (m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffAli - diffHorde))
|
||||
if (m_SelectionPools[TEAM_INDEX_HORDE].KickGroup(diffAli - diffHorde))
|
||||
{
|
||||
for (; hordeIndex < hordeCount && m_SelectionPools[BG_TEAM_HORDE].AddGroup((*Horde_itr), (hordeFree >= diffAli) ? hordeFree - diffAli : 0); ++hordeIndex)
|
||||
for (; hordeIndex < hordeCount && m_SelectionPools[TEAM_INDEX_HORDE].AddGroup((*Horde_itr), (hordeFree >= diffAli) ? hordeFree - diffAli : 0); ++hordeIndex)
|
||||
++Horde_itr;
|
||||
}
|
||||
if (!m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount())
|
||||
if (!m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount())
|
||||
{
|
||||
if (hordeFree <= diffAli + 1)
|
||||
break;
|
||||
m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffAli - diffHorde);
|
||||
m_SelectionPools[TEAM_INDEX_ALLIANCE].KickGroup(diffAli - diffHorde);
|
||||
}
|
||||
}
|
||||
// count diffs after small update
|
||||
diffAli = aliFree - int32(m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount());
|
||||
diffHorde = hordeFree - int32(m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount());
|
||||
diffAli = aliFree - int32(m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount());
|
||||
diffHorde = hordeFree - int32(m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -610,12 +610,12 @@ bool BattleGroundQueue::CheckPremadeMatch(BattleGroundBracketId bracket_id, uint
|
|||
|
||||
if (ali_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].end() && horde_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].end())
|
||||
{
|
||||
m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*ali_group), MaxPlayersPerTeam);
|
||||
m_SelectionPools[BG_TEAM_HORDE].AddGroup((*horde_group), MaxPlayersPerTeam);
|
||||
m_SelectionPools[TEAM_INDEX_ALLIANCE].AddGroup((*ali_group), MaxPlayersPerTeam);
|
||||
m_SelectionPools[TEAM_INDEX_HORDE].AddGroup((*horde_group), MaxPlayersPerTeam);
|
||||
// add groups/players from normal queue to size of bigger group
|
||||
uint32 maxPlayers = std::max(m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount(), m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount());
|
||||
uint32 maxPlayers = std::max(m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount(), m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount());
|
||||
GroupsQueueType::const_iterator itr;
|
||||
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
|
||||
for (uint8 i = 0; i < PVP_TEAM_COUNT; ++i)
|
||||
{
|
||||
for (itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++itr)
|
||||
{
|
||||
|
|
@ -633,7 +633,7 @@ bool BattleGroundQueue::CheckPremadeMatch(BattleGroundBracketId bracket_id, uint
|
|||
// if first is invited to BG and seconds timer expired, but we can ignore it, because players have only 80 seconds to click to enter bg
|
||||
// and when they click or after 80 seconds the queue info is removed from queue
|
||||
uint32 time_before = WorldTimer::getMSTime() - sWorld.getConfig(CONFIG_UINT32_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH);
|
||||
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
|
||||
for (uint8 i = 0; i < PVP_TEAM_COUNT; ++i)
|
||||
{
|
||||
if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].empty())
|
||||
{
|
||||
|
|
@ -653,8 +653,8 @@ bool BattleGroundQueue::CheckPremadeMatch(BattleGroundBracketId bracket_id, uint
|
|||
// this method tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam
|
||||
bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BattleGroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers)
|
||||
{
|
||||
GroupsQueueType::const_iterator itr_team[BG_TEAMS_COUNT];
|
||||
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
|
||||
GroupsQueueType::const_iterator itr_team[PVP_TEAM_COUNT];
|
||||
for (uint8 i = 0; i < PVP_TEAM_COUNT; ++i)
|
||||
{
|
||||
itr_team[i] = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin();
|
||||
for (; itr_team[i] != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++(itr_team[i]))
|
||||
|
|
@ -668,43 +668,43 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BattleGround
|
|||
}
|
||||
}
|
||||
// try to invite same number of players - this cycle may cause longer wait time even if there are enough players in queue, but we want ballanced bg
|
||||
uint32 j = BG_TEAM_ALLIANCE;
|
||||
if (m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() < m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())
|
||||
j = BG_TEAM_HORDE;
|
||||
uint32 j = TEAM_INDEX_ALLIANCE;
|
||||
if (m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount() < m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount())
|
||||
j = TEAM_INDEX_HORDE;
|
||||
if (sWorld.getConfig(CONFIG_UINT32_BATTLEGROUND_INVITATION_TYPE) != 0
|
||||
&& m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= minPlayers && m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= minPlayers)
|
||||
&& m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount() >= minPlayers && m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount() >= minPlayers)
|
||||
{
|
||||
// we will try to invite more groups to team with less players indexed by j
|
||||
++(itr_team[j]); // this will not cause a crash, because for cycle above reached break;
|
||||
for (; itr_team[j] != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + j].end(); ++(itr_team[j]))
|
||||
{
|
||||
if (!(*(itr_team[j]))->IsInvitedToBGInstanceGUID)
|
||||
if (!m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % BG_TEAMS_COUNT].GetPlayerCount()))
|
||||
if (!m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % PVP_TEAM_COUNT].GetPlayerCount()))
|
||||
break;
|
||||
}
|
||||
// do not allow to start bg with more than 2 players more on 1 faction
|
||||
if (abs((int32)(m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() - m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())) > 2)
|
||||
if (abs((int32)(m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount() - m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount())) > 2)
|
||||
return false;
|
||||
}
|
||||
// allow 1v0 if debug bg
|
||||
if (sBattleGroundMgr.isTesting() && bg_template->isBattleGround() && (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()))
|
||||
if (sBattleGroundMgr.isTesting() && bg_template->isBattleGround() && (m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount() || m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount()))
|
||||
return true;
|
||||
// return true if there are enough players in selection pools - enable to work .debug bg command correctly
|
||||
return m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= minPlayers;
|
||||
return m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount() >= minPlayers;
|
||||
}
|
||||
|
||||
// this method will check if we can invite players to same faction skirmish match
|
||||
bool BattleGroundQueue::CheckSkirmishForSameFaction(BattleGroundBracketId bracket_id, uint32 minPlayersPerTeam)
|
||||
{
|
||||
if (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() < minPlayersPerTeam && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() < minPlayersPerTeam)
|
||||
if (m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount() < minPlayersPerTeam && m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount() < minPlayersPerTeam)
|
||||
return false;
|
||||
BattleGroundTeamIndex teamIdx = BG_TEAM_ALLIANCE;
|
||||
BattleGroundTeamIndex otherTeamIdx = BG_TEAM_HORDE;
|
||||
PvpTeamIndex teamIdx = TEAM_INDEX_ALLIANCE;
|
||||
PvpTeamIndex otherTeamIdx = TEAM_INDEX_HORDE;
|
||||
Team otherTeamId = HORDE;
|
||||
if (m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() == minPlayersPerTeam)
|
||||
if (m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount() == minPlayersPerTeam)
|
||||
{
|
||||
teamIdx = BG_TEAM_HORDE;
|
||||
otherTeamIdx = BG_TEAM_ALLIANCE;
|
||||
teamIdx = TEAM_INDEX_HORDE;
|
||||
otherTeamIdx = TEAM_INDEX_ALLIANCE;
|
||||
otherTeamId = ALLIANCE;
|
||||
}
|
||||
// clear other team's selection
|
||||
|
|
@ -782,16 +782,16 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BattleGroundBracketI
|
|||
// and iterator is invalid
|
||||
|
||||
// clear selection pools
|
||||
m_SelectionPools[BG_TEAM_ALLIANCE].Init();
|
||||
m_SelectionPools[BG_TEAM_HORDE].Init();
|
||||
m_SelectionPools[TEAM_INDEX_ALLIANCE].Init();
|
||||
m_SelectionPools[TEAM_INDEX_HORDE].Init();
|
||||
|
||||
// call a function that does the job for us
|
||||
FillPlayersToBG(bg, bracket_id);
|
||||
|
||||
// now everything is set, invite players
|
||||
for (GroupsQueueType::const_iterator citr = m_SelectionPools[BG_TEAM_ALLIANCE].SelectedGroups.begin(); citr != m_SelectionPools[BG_TEAM_ALLIANCE].SelectedGroups.end(); ++citr)
|
||||
for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_INDEX_ALLIANCE].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_INDEX_ALLIANCE].SelectedGroups.end(); ++citr)
|
||||
InviteGroupToBG((*citr), bg, (*citr)->GroupTeam);
|
||||
for (GroupsQueueType::const_iterator citr = m_SelectionPools[BG_TEAM_HORDE].SelectedGroups.begin(); citr != m_SelectionPools[BG_TEAM_HORDE].SelectedGroups.end(); ++citr)
|
||||
for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_INDEX_HORDE].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_INDEX_HORDE].SelectedGroups.end(); ++citr)
|
||||
InviteGroupToBG((*citr), bg, (*citr)->GroupTeam);
|
||||
|
||||
if (!bg->HasFreeSlots())
|
||||
|
|
@ -853,8 +853,8 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BattleGroundBracketI
|
|||
}
|
||||
}
|
||||
|
||||
m_SelectionPools[BG_TEAM_ALLIANCE].Init();
|
||||
m_SelectionPools[BG_TEAM_HORDE].Init();
|
||||
m_SelectionPools[TEAM_INDEX_ALLIANCE].Init();
|
||||
m_SelectionPools[TEAM_INDEX_HORDE].Init();
|
||||
|
||||
if (bg_template->isBattleGround())
|
||||
{
|
||||
|
|
@ -869,14 +869,14 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BattleGroundBracketI
|
|||
return;
|
||||
}
|
||||
// invite those selection pools
|
||||
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
|
||||
for (GroupsQueueType::const_iterator citr = m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.end(); ++citr)
|
||||
for (uint8 i = 0; i < PVP_TEAM_COUNT; ++i)
|
||||
for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_INDEX_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_INDEX_ALLIANCE + i].SelectedGroups.end(); ++citr)
|
||||
InviteGroupToBG((*citr), bg2, (*citr)->GroupTeam);
|
||||
// start bg
|
||||
bg2->StartBattleGround();
|
||||
// clear structures
|
||||
m_SelectionPools[BG_TEAM_ALLIANCE].Init();
|
||||
m_SelectionPools[BG_TEAM_HORDE].Init();
|
||||
m_SelectionPools[TEAM_INDEX_ALLIANCE].Init();
|
||||
m_SelectionPools[TEAM_INDEX_HORDE].Init();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -896,8 +896,8 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BattleGroundBracketI
|
|||
}
|
||||
|
||||
// invite those selection pools
|
||||
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
|
||||
for (GroupsQueueType::const_iterator citr = m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.end(); ++citr)
|
||||
for (uint8 i = 0; i < PVP_TEAM_COUNT; ++i)
|
||||
for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_INDEX_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_INDEX_ALLIANCE + i].SelectedGroups.end(); ++citr)
|
||||
InviteGroupToBG((*citr), bg2, (*citr)->GroupTeam);
|
||||
// start bg
|
||||
bg2->StartBattleGround();
|
||||
|
|
@ -942,7 +942,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BattleGroundBracketI
|
|||
|
||||
// we need to find 2 teams which will play next game
|
||||
|
||||
GroupsQueueType::iterator itr_team[BG_TEAMS_COUNT];
|
||||
GroupsQueueType::iterator itr_team[PVP_TEAM_COUNT];
|
||||
|
||||
// optimalization : --- we dont need to use selection_pools - each update we select max 2 groups
|
||||
|
||||
|
|
@ -967,40 +967,40 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BattleGroundBracketI
|
|||
// if we don't have, we must try to continue search in same queue
|
||||
// tmp variables are correctly set
|
||||
// this code isn't much userfriendly - but it is supposed to continue search for mathing group in HORDE queue
|
||||
if (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() == 0 && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount())
|
||||
if (m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount() == 0 && m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount())
|
||||
{
|
||||
itr_team[BG_TEAM_ALLIANCE] = itr_team[BG_TEAM_HORDE];
|
||||
++itr_team[BG_TEAM_ALLIANCE];
|
||||
for (; itr_team[BG_TEAM_ALLIANCE] != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].end(); ++(itr_team[BG_TEAM_ALLIANCE]))
|
||||
itr_team[TEAM_INDEX_ALLIANCE] = itr_team[TEAM_INDEX_HORDE];
|
||||
++itr_team[TEAM_INDEX_ALLIANCE];
|
||||
for (; itr_team[TEAM_INDEX_ALLIANCE] != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].end(); ++(itr_team[TEAM_INDEX_ALLIANCE]))
|
||||
{
|
||||
if (!(*itr_team[BG_TEAM_ALLIANCE])->IsInvitedToBGInstanceGUID
|
||||
&& (((*itr_team[BG_TEAM_ALLIANCE])->ArenaTeamRating >= arenaMinRating && (*itr_team[BG_TEAM_ALLIANCE])->ArenaTeamRating <= arenaMaxRating)
|
||||
|| (*itr_team[BG_TEAM_ALLIANCE])->JoinTime < discardTime))
|
||||
if (!(*itr_team[TEAM_INDEX_ALLIANCE])->IsInvitedToBGInstanceGUID
|
||||
&& (((*itr_team[TEAM_INDEX_ALLIANCE])->ArenaTeamRating >= arenaMinRating && (*itr_team[TEAM_INDEX_ALLIANCE])->ArenaTeamRating <= arenaMaxRating)
|
||||
|| (*itr_team[TEAM_INDEX_ALLIANCE])->JoinTime < discardTime))
|
||||
{
|
||||
m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*itr_team[BG_TEAM_ALLIANCE]), MaxPlayersPerTeam);
|
||||
m_SelectionPools[TEAM_INDEX_ALLIANCE].AddGroup((*itr_team[TEAM_INDEX_ALLIANCE]), MaxPlayersPerTeam);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// this code isn't much userfriendly - but it is supposed to continue search for mathing group in ALLIANCE queue
|
||||
if (m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() == 0 && m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())
|
||||
if (m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount() == 0 && m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount())
|
||||
{
|
||||
itr_team[BG_TEAM_HORDE] = itr_team[BG_TEAM_ALLIANCE];
|
||||
++itr_team[BG_TEAM_HORDE];
|
||||
for (; itr_team[BG_TEAM_HORDE] != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].end(); ++(itr_team[BG_TEAM_HORDE]))
|
||||
itr_team[TEAM_INDEX_HORDE] = itr_team[TEAM_INDEX_ALLIANCE];
|
||||
++itr_team[TEAM_INDEX_HORDE];
|
||||
for (; itr_team[TEAM_INDEX_HORDE] != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].end(); ++(itr_team[TEAM_INDEX_HORDE]))
|
||||
{
|
||||
if (!(*itr_team[BG_TEAM_HORDE])->IsInvitedToBGInstanceGUID
|
||||
&& (((*itr_team[BG_TEAM_HORDE])->ArenaTeamRating >= arenaMinRating && (*itr_team[BG_TEAM_HORDE])->ArenaTeamRating <= arenaMaxRating)
|
||||
|| (*itr_team[BG_TEAM_HORDE])->JoinTime < discardTime))
|
||||
if (!(*itr_team[TEAM_INDEX_HORDE])->IsInvitedToBGInstanceGUID
|
||||
&& (((*itr_team[TEAM_INDEX_HORDE])->ArenaTeamRating >= arenaMinRating && (*itr_team[TEAM_INDEX_HORDE])->ArenaTeamRating <= arenaMaxRating)
|
||||
|| (*itr_team[TEAM_INDEX_HORDE])->JoinTime < discardTime))
|
||||
{
|
||||
m_SelectionPools[BG_TEAM_HORDE].AddGroup((*itr_team[BG_TEAM_HORDE]), MaxPlayersPerTeam);
|
||||
m_SelectionPools[TEAM_INDEX_HORDE].AddGroup((*itr_team[TEAM_INDEX_HORDE]), MaxPlayersPerTeam);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we have 2 teams, then start new arena and invite players!
|
||||
if (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount())
|
||||
if (m_SelectionPools[TEAM_INDEX_ALLIANCE].GetPlayerCount() && m_SelectionPools[TEAM_INDEX_HORDE].GetPlayerCount())
|
||||
{
|
||||
BattleGround* arena = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, bracketEntry, arenaType, true);
|
||||
if (!arena)
|
||||
|
|
@ -1009,28 +1009,28 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BattleGroundBracketI
|
|||
return;
|
||||
}
|
||||
|
||||
(*(itr_team[BG_TEAM_ALLIANCE]))->OpponentsTeamRating = (*(itr_team[BG_TEAM_HORDE]))->ArenaTeamRating;
|
||||
DEBUG_LOG("setting oposite teamrating for team %u to %u", (*(itr_team[BG_TEAM_ALLIANCE]))->ArenaTeamId, (*(itr_team[BG_TEAM_ALLIANCE]))->OpponentsTeamRating);
|
||||
(*(itr_team[BG_TEAM_HORDE]))->OpponentsTeamRating = (*(itr_team[BG_TEAM_ALLIANCE]))->ArenaTeamRating;
|
||||
DEBUG_LOG("setting oposite teamrating for team %u to %u", (*(itr_team[BG_TEAM_HORDE]))->ArenaTeamId, (*(itr_team[BG_TEAM_HORDE]))->OpponentsTeamRating);
|
||||
(*(itr_team[TEAM_INDEX_ALLIANCE]))->OpponentsTeamRating = (*(itr_team[TEAM_INDEX_HORDE]))->ArenaTeamRating;
|
||||
DEBUG_LOG("setting oposite teamrating for team %u to %u", (*(itr_team[TEAM_INDEX_ALLIANCE]))->ArenaTeamId, (*(itr_team[TEAM_INDEX_ALLIANCE]))->OpponentsTeamRating);
|
||||
(*(itr_team[TEAM_INDEX_HORDE]))->OpponentsTeamRating = (*(itr_team[TEAM_INDEX_ALLIANCE]))->ArenaTeamRating;
|
||||
DEBUG_LOG("setting oposite teamrating for team %u to %u", (*(itr_team[TEAM_INDEX_HORDE]))->ArenaTeamId, (*(itr_team[TEAM_INDEX_HORDE]))->OpponentsTeamRating);
|
||||
// now we must move team if we changed its faction to another faction queue, because then we will spam log by errors in Queue::RemovePlayer
|
||||
if ((*(itr_team[BG_TEAM_ALLIANCE]))->GroupTeam != ALLIANCE)
|
||||
if ((*(itr_team[TEAM_INDEX_ALLIANCE]))->GroupTeam != ALLIANCE)
|
||||
{
|
||||
// add to alliance queue
|
||||
m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].push_front(*(itr_team[BG_TEAM_ALLIANCE]));
|
||||
m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].push_front(*(itr_team[TEAM_INDEX_ALLIANCE]));
|
||||
// erase from horde queue
|
||||
m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].erase(itr_team[BG_TEAM_ALLIANCE]);
|
||||
itr_team[BG_TEAM_ALLIANCE] = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].begin();
|
||||
m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].erase(itr_team[TEAM_INDEX_ALLIANCE]);
|
||||
itr_team[TEAM_INDEX_ALLIANCE] = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].begin();
|
||||
}
|
||||
if ((*(itr_team[BG_TEAM_HORDE]))->GroupTeam != HORDE)
|
||||
if ((*(itr_team[TEAM_INDEX_HORDE]))->GroupTeam != HORDE)
|
||||
{
|
||||
m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].push_front(*(itr_team[BG_TEAM_HORDE]));
|
||||
m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].erase(itr_team[BG_TEAM_HORDE]);
|
||||
itr_team[BG_TEAM_HORDE] = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].begin();
|
||||
m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].push_front(*(itr_team[TEAM_INDEX_HORDE]));
|
||||
m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].erase(itr_team[TEAM_INDEX_HORDE]);
|
||||
itr_team[TEAM_INDEX_HORDE] = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].begin();
|
||||
}
|
||||
|
||||
InviteGroupToBG(*(itr_team[BG_TEAM_ALLIANCE]), arena, ALLIANCE);
|
||||
InviteGroupToBG(*(itr_team[BG_TEAM_HORDE]), arena, HORDE);
|
||||
InviteGroupToBG(*(itr_team[TEAM_INDEX_ALLIANCE]), arena, ALLIANCE);
|
||||
InviteGroupToBG(*(itr_team[TEAM_INDEX_HORDE]), arena, HORDE);
|
||||
|
||||
DEBUG_LOG("Starting rated arena match!");
|
||||
|
||||
|
|
|
|||
|
|
@ -134,12 +134,12 @@ class BattleGroundQueue
|
|||
};
|
||||
|
||||
// one selection pool for horde, other one for alliance
|
||||
SelectionPool m_SelectionPools[BG_TEAMS_COUNT];
|
||||
SelectionPool m_SelectionPools[PVP_TEAM_COUNT];
|
||||
|
||||
bool InviteGroupToBG(GroupQueueInfo* ginfo, BattleGround* bg, Team side);
|
||||
uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME];
|
||||
uint32 m_WaitTimeLastPlayer[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS];
|
||||
uint32 m_SumOfWaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS];
|
||||
uint32 m_WaitTimes[PVP_TEAM_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME];
|
||||
uint32 m_WaitTimeLastPlayer[PVP_TEAM_COUNT][MAX_BATTLEGROUND_BRACKETS];
|
||||
uint32 m_SumOfWaitTimes[PVP_TEAM_COUNT][MAX_BATTLEGROUND_BRACKETS];
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -48,52 +48,52 @@ void BattleGroundWS::Update(uint32 diff)
|
|||
|
||||
if (GetStatus() == STATUS_IN_PROGRESS)
|
||||
{
|
||||
if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN)
|
||||
if (m_FlagState[TEAM_INDEX_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN)
|
||||
{
|
||||
m_FlagsTimer[BG_TEAM_ALLIANCE] -= diff;
|
||||
m_FlagsTimer[TEAM_INDEX_ALLIANCE] -= diff;
|
||||
|
||||
if (m_FlagsTimer[BG_TEAM_ALLIANCE] < 0)
|
||||
if (m_FlagsTimer[TEAM_INDEX_ALLIANCE] < 0)
|
||||
{
|
||||
m_FlagsTimer[BG_TEAM_ALLIANCE] = 0;
|
||||
m_FlagsTimer[TEAM_INDEX_ALLIANCE] = 0;
|
||||
RespawnFlag(ALLIANCE, true);
|
||||
}
|
||||
}
|
||||
if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND)
|
||||
if (m_FlagState[TEAM_INDEX_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND)
|
||||
{
|
||||
m_FlagsDropTimer[BG_TEAM_ALLIANCE] -= diff;
|
||||
m_FlagsDropTimer[TEAM_INDEX_ALLIANCE] -= diff;
|
||||
|
||||
if (m_FlagsDropTimer[BG_TEAM_ALLIANCE] < 0)
|
||||
if (m_FlagsDropTimer[TEAM_INDEX_ALLIANCE] < 0)
|
||||
{
|
||||
m_FlagsDropTimer[BG_TEAM_ALLIANCE] = 0;
|
||||
m_FlagsDropTimer[TEAM_INDEX_ALLIANCE] = 0;
|
||||
RespawnDroppedFlag(ALLIANCE);
|
||||
}
|
||||
}
|
||||
if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_WAIT_RESPAWN)
|
||||
if (m_FlagState[TEAM_INDEX_HORDE] == BG_WS_FLAG_STATE_WAIT_RESPAWN)
|
||||
{
|
||||
m_FlagsTimer[BG_TEAM_HORDE] -= diff;
|
||||
m_FlagsTimer[TEAM_INDEX_HORDE] -= diff;
|
||||
|
||||
if (m_FlagsTimer[BG_TEAM_HORDE] < 0)
|
||||
if (m_FlagsTimer[TEAM_INDEX_HORDE] < 0)
|
||||
{
|
||||
m_FlagsTimer[BG_TEAM_HORDE] = 0;
|
||||
m_FlagsTimer[TEAM_INDEX_HORDE] = 0;
|
||||
RespawnFlag(HORDE, true);
|
||||
}
|
||||
}
|
||||
if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND)
|
||||
if (m_FlagState[TEAM_INDEX_HORDE] == BG_WS_FLAG_STATE_ON_GROUND)
|
||||
{
|
||||
m_FlagsDropTimer[BG_TEAM_HORDE] -= diff;
|
||||
m_FlagsDropTimer[TEAM_INDEX_HORDE] -= diff;
|
||||
|
||||
if (m_FlagsDropTimer[BG_TEAM_HORDE] < 0)
|
||||
if (m_FlagsDropTimer[TEAM_INDEX_HORDE] < 0)
|
||||
{
|
||||
m_FlagsDropTimer[BG_TEAM_HORDE] = 0;
|
||||
m_FlagsDropTimer[TEAM_INDEX_HORDE] = 0;
|
||||
RespawnDroppedFlag(HORDE);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_EndTimer <= diff)
|
||||
{
|
||||
if (m_TeamScores[BG_TEAM_ALLIANCE] > m_TeamScores[BG_TEAM_HORDE])
|
||||
if (m_TeamScores[TEAM_INDEX_ALLIANCE] > m_TeamScores[TEAM_INDEX_HORDE])
|
||||
EndBattleGround(ALLIANCE);
|
||||
else if (m_TeamScores[BG_TEAM_ALLIANCE] < m_TeamScores[BG_TEAM_HORDE])
|
||||
else if (m_TeamScores[TEAM_INDEX_ALLIANCE] < m_TeamScores[TEAM_INDEX_HORDE])
|
||||
EndBattleGround(HORDE);
|
||||
else
|
||||
{
|
||||
|
|
@ -141,13 +141,13 @@ void BattleGroundWS::RespawnFlag(Team team, bool captured)
|
|||
if (team == ALLIANCE)
|
||||
{
|
||||
DEBUG_LOG("Respawn Alliance flag");
|
||||
m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE;
|
||||
m_FlagState[TEAM_INDEX_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE;
|
||||
SpawnEvent(WS_EVENT_FLAG_A, 0, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("Respawn Horde flag");
|
||||
m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE;
|
||||
m_FlagState[TEAM_INDEX_HORDE] = BG_WS_FLAG_STATE_ON_BASE;
|
||||
SpawnEvent(WS_EVENT_FLAG_H, 0, true);
|
||||
}
|
||||
|
||||
|
|
@ -197,11 +197,11 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player* source)
|
|||
return;
|
||||
ClearHordeFlagCarrier(); // must be before aura remove to prevent 2 events (drop+capture) at the same time
|
||||
// horde flag in base (but not respawned yet)
|
||||
m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_WAIT_RESPAWN;
|
||||
m_FlagState[TEAM_INDEX_HORDE] = BG_WS_FLAG_STATE_WAIT_RESPAWN;
|
||||
// Drop Horde Flag from Player
|
||||
source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
|
||||
if (m_TeamScores[BG_TEAM_ALLIANCE] < BG_WS_MAX_TEAM_SCORE)
|
||||
m_TeamScores[BG_TEAM_ALLIANCE] += 1;
|
||||
if (m_TeamScores[TEAM_INDEX_ALLIANCE] < BG_WS_MAX_TEAM_SCORE)
|
||||
m_TeamScores[TEAM_INDEX_ALLIANCE] += 1;
|
||||
PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE);
|
||||
RewardReputationToTeam(890, m_ReputationCapture, ALLIANCE);
|
||||
}
|
||||
|
|
@ -211,11 +211,11 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player* source)
|
|||
return;
|
||||
ClearAllianceFlagCarrier(); // must be before aura remove to prevent 2 events (drop+capture) at the same time
|
||||
// alliance flag in base (but not respawned yet)
|
||||
m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_WAIT_RESPAWN;
|
||||
m_FlagState[TEAM_INDEX_ALLIANCE] = BG_WS_FLAG_STATE_WAIT_RESPAWN;
|
||||
// Drop Alliance Flag from Player
|
||||
source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG);
|
||||
if (m_TeamScores[BG_TEAM_HORDE] < BG_WS_MAX_TEAM_SCORE)
|
||||
m_TeamScores[BG_TEAM_HORDE] += 1;
|
||||
if (m_TeamScores[TEAM_INDEX_HORDE] < BG_WS_MAX_TEAM_SCORE)
|
||||
m_TeamScores[TEAM_INDEX_HORDE] += 1;
|
||||
PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE);
|
||||
RewardReputationToTeam(889, m_ReputationCapture, HORDE);
|
||||
}
|
||||
|
|
@ -237,9 +237,9 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player* source)
|
|||
UpdatePlayerScore(source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures
|
||||
|
||||
Team winner = TEAM_NONE;
|
||||
if (m_TeamScores[BG_TEAM_ALLIANCE] == BG_WS_MAX_TEAM_SCORE)
|
||||
if (m_TeamScores[TEAM_INDEX_ALLIANCE] == BG_WS_MAX_TEAM_SCORE)
|
||||
winner = ALLIANCE;
|
||||
else if (m_TeamScores[BG_TEAM_HORDE] == BG_WS_MAX_TEAM_SCORE)
|
||||
else if (m_TeamScores[TEAM_INDEX_HORDE] == BG_WS_MAX_TEAM_SCORE)
|
||||
winner = HORDE;
|
||||
|
||||
if (winner)
|
||||
|
|
@ -296,7 +296,7 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player* source)
|
|||
{
|
||||
ClearHordeFlagCarrier();
|
||||
source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
|
||||
m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_GROUND;
|
||||
m_FlagState[TEAM_INDEX_HORDE] = BG_WS_FLAG_STATE_ON_GROUND;
|
||||
source->CastSpell(source, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true);
|
||||
set = true;
|
||||
}
|
||||
|
|
@ -309,7 +309,7 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player* source)
|
|||
{
|
||||
ClearAllianceFlagCarrier();
|
||||
source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG);
|
||||
m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_GROUND;
|
||||
m_FlagState[TEAM_INDEX_ALLIANCE] = BG_WS_FLAG_STATE_ON_GROUND;
|
||||
source->CastSpell(source, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true);
|
||||
set = true;
|
||||
}
|
||||
|
|
@ -354,7 +354,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player* source, GameObject* target
|
|||
PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP);
|
||||
SpawnEvent(WS_EVENT_FLAG_A, 0, false);
|
||||
SetAllianceFlagCarrier(source->GetObjectGuid());
|
||||
m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER;
|
||||
m_FlagState[TEAM_INDEX_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER;
|
||||
// update world state to show correct flag carrier
|
||||
UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER);
|
||||
UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 1);
|
||||
|
|
@ -370,7 +370,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player* source, GameObject* target
|
|||
PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP);
|
||||
SpawnEvent(WS_EVENT_FLAG_H, 0, false);
|
||||
SetHordeFlagCarrier(source->GetObjectGuid());
|
||||
m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER;
|
||||
m_FlagState[TEAM_INDEX_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER;
|
||||
// update world state to show correct flag carrier
|
||||
UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER);
|
||||
UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 1);
|
||||
|
|
@ -397,7 +397,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player* source, GameObject* target
|
|||
SpawnEvent(WS_EVENT_FLAG_A, 0, false);
|
||||
SetAllianceFlagCarrier(source->GetObjectGuid());
|
||||
source->CastSpell(source, BG_WS_SPELL_SILVERWING_FLAG, true);
|
||||
m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER;
|
||||
m_FlagState[TEAM_INDEX_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER;
|
||||
UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER);
|
||||
UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 1);
|
||||
}
|
||||
|
|
@ -425,7 +425,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player* source, GameObject* target
|
|||
SpawnEvent(WS_EVENT_FLAG_H, 0, false);
|
||||
SetHordeFlagCarrier(source->GetObjectGuid());
|
||||
source->CastSpell(source, BG_WS_SPELL_WARSONG_FLAG, true);
|
||||
m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER;
|
||||
m_FlagState[TEAM_INDEX_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER;
|
||||
UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER);
|
||||
UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 1);
|
||||
}
|
||||
|
|
@ -478,9 +478,9 @@ void BattleGroundWS::UpdateFlagState(Team team, uint32 value)
|
|||
void BattleGroundWS::UpdateTeamScore(Team team)
|
||||
{
|
||||
if (team == ALLIANCE)
|
||||
UpdateWorldState(BG_WS_FLAG_CAPTURES_ALLIANCE, m_TeamScores[BG_TEAM_ALLIANCE]);
|
||||
UpdateWorldState(BG_WS_FLAG_CAPTURES_ALLIANCE, m_TeamScores[TEAM_INDEX_ALLIANCE]);
|
||||
else
|
||||
UpdateWorldState(BG_WS_FLAG_CAPTURES_HORDE, m_TeamScores[BG_TEAM_HORDE]);
|
||||
UpdateWorldState(BG_WS_FLAG_CAPTURES_HORDE, m_TeamScores[TEAM_INDEX_HORDE]);
|
||||
}
|
||||
|
||||
void BattleGroundWS::HandleAreaTrigger(Player* source, uint32 trigger)
|
||||
|
|
@ -501,12 +501,12 @@ void BattleGroundWS::HandleAreaTrigger(Player* source, uint32 trigger)
|
|||
case 3709: // Horde elixir of berserk spawn
|
||||
break;
|
||||
case 3646: // Alliance Flag spawn
|
||||
if (m_FlagState[BG_TEAM_HORDE] && !m_FlagState[BG_TEAM_ALLIANCE])
|
||||
if (m_FlagState[TEAM_INDEX_HORDE] && !m_FlagState[TEAM_INDEX_ALLIANCE])
|
||||
if (GetHordeFlagCarrierGuid() == source->GetObjectGuid())
|
||||
EventPlayerCapturedFlag(source);
|
||||
break;
|
||||
case 3647: // Horde Flag spawn
|
||||
if (m_FlagState[BG_TEAM_ALLIANCE] && !m_FlagState[BG_TEAM_HORDE])
|
||||
if (m_FlagState[TEAM_INDEX_ALLIANCE] && !m_FlagState[TEAM_INDEX_HORDE])
|
||||
if (GetAllianceFlagCarrierGuid() == source->GetObjectGuid())
|
||||
EventPlayerCapturedFlag(source);
|
||||
break;
|
||||
|
|
@ -532,7 +532,7 @@ void BattleGroundWS::Reset()
|
|||
m_ActiveEvents[WS_EVENT_FLAG_A] = BG_EVENT_NONE;
|
||||
m_ActiveEvents[WS_EVENT_FLAG_H] = BG_EVENT_NONE;
|
||||
|
||||
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
|
||||
for (uint8 i = 0; i < PVP_TEAM_COUNT; ++i)
|
||||
{
|
||||
m_DroppedFlagGuid[i].Clear();
|
||||
m_FlagState[i] = BG_WS_FLAG_STATE_ON_BASE;
|
||||
|
|
@ -620,31 +620,31 @@ WorldSafeLocsEntry const* BattleGroundWS::GetClosestGraveYard(Player* player)
|
|||
|
||||
void BattleGroundWS::FillInitialWorldStates(WorldPacket& data, uint32& count)
|
||||
{
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_CAPTURES_ALLIANCE, m_TeamScores[BG_TEAM_ALLIANCE]);
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_CAPTURES_HORDE, m_TeamScores[BG_TEAM_HORDE]);
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_CAPTURES_ALLIANCE, m_TeamScores[TEAM_INDEX_ALLIANCE]);
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_CAPTURES_HORDE, m_TeamScores[TEAM_INDEX_HORDE]);
|
||||
|
||||
if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND)
|
||||
if (m_FlagState[TEAM_INDEX_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND)
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_UNK_ALLIANCE, -1);
|
||||
else if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER)
|
||||
else if (m_FlagState[TEAM_INDEX_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER)
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_UNK_ALLIANCE, 1);
|
||||
else
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_UNK_ALLIANCE, 0);
|
||||
|
||||
if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND)
|
||||
if (m_FlagState[TEAM_INDEX_HORDE] == BG_WS_FLAG_STATE_ON_GROUND)
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_UNK_HORDE, -1);
|
||||
else if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER)
|
||||
else if (m_FlagState[TEAM_INDEX_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER)
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_UNK_HORDE, 1);
|
||||
else
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_UNK_HORDE, 0);
|
||||
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_CAPTURES_MAX, BG_WS_MAX_TEAM_SCORE);
|
||||
|
||||
if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER)
|
||||
if (m_FlagState[TEAM_INDEX_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER)
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_STATE_HORDE, 2);
|
||||
else
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_STATE_HORDE, 1);
|
||||
|
||||
if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER)
|
||||
if (m_FlagState[TEAM_INDEX_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER)
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_STATE_ALLIANCE, 2);
|
||||
else
|
||||
FillInitialWorldState(data, count, BG_WS_FLAG_STATE_ALLIANCE, 1);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,10 @@ class BattleGroundWGScore : public BattleGroundScore
|
|||
public:
|
||||
BattleGroundWGScore() : FlagCaptures(0), FlagReturns(0) {};
|
||||
virtual ~BattleGroundWGScore() {};
|
||||
|
||||
uint32 GetAttr1() const { return FlagCaptures; }
|
||||
uint32 GetAttr2() const { return FlagReturns; }
|
||||
|
||||
uint32 FlagCaptures;
|
||||
uint32 FlagReturns;
|
||||
};
|
||||
|
|
@ -154,10 +158,10 @@ class BattleGroundWS : public BattleGround
|
|||
ObjectGuid m_flagCarrierAlliance;
|
||||
ObjectGuid m_flagCarrierHorde;
|
||||
|
||||
ObjectGuid m_DroppedFlagGuid[BG_TEAMS_COUNT];
|
||||
uint8 m_FlagState[BG_TEAMS_COUNT];
|
||||
int32 m_FlagsTimer[BG_TEAMS_COUNT];
|
||||
int32 m_FlagsDropTimer[BG_TEAMS_COUNT];
|
||||
ObjectGuid m_DroppedFlagGuid[PVP_TEAM_COUNT];
|
||||
uint8 m_FlagState[PVP_TEAM_COUNT];
|
||||
int32 m_FlagsTimer[PVP_TEAM_COUNT];
|
||||
int32 m_FlagsDropTimer[PVP_TEAM_COUNT];
|
||||
|
||||
uint32 m_ReputationCapture;
|
||||
uint32 m_HonorWinKills;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
#include "Util.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "CellImpl.h"
|
||||
#include "WaypointMovementGenerator.h"
|
||||
#include <cctype>
|
||||
#include <iostream>
|
||||
|
|
|
|||
|
|
@ -6101,9 +6101,7 @@ bool ChatHandler::HandleGMFlyCommand(char* args)
|
|||
if (!target)
|
||||
target = m_session->GetPlayer();
|
||||
|
||||
WorldPacket data;
|
||||
target->BuildMoveSetCanFlyPacket(&data, value, 0);
|
||||
target->SendMessageToSet(&data, true);
|
||||
target->SetCanFly(value);
|
||||
PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, GetNameLink(target).c_str(), args);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -7310,6 +7308,64 @@ bool ChatHandler::HandleMmapTestArea(char* args)
|
|||
return true;
|
||||
}
|
||||
|
||||
// use ".mmap testheight 10" selecting any creature/player
|
||||
bool ChatHandler::HandleMmapTestHeight(char* args)
|
||||
{
|
||||
float radius = 0.0f;
|
||||
ExtractFloat(&args, radius);
|
||||
if (radius > 40.0f)
|
||||
radius = 40.0f;
|
||||
|
||||
Unit* unit = getSelectedUnit();
|
||||
|
||||
Player* player = m_session->GetPlayer();
|
||||
if (!unit)
|
||||
unit = player;
|
||||
|
||||
if (unit->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
if (radius < 0.1f)
|
||||
radius = static_cast<Creature*>(unit)->GetRespawnRadius();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unit->GetTypeId() != TYPEID_PLAYER)
|
||||
{
|
||||
PSendSysMessage(LANG_SELECT_CHAR_OR_CREATURE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (radius < 0.1f)
|
||||
{
|
||||
PSendSysMessage("Provided spawn radius for %s is too small. Using 5.0f instead.", unit->GetGuidStr().c_str());
|
||||
radius = 5.0f;
|
||||
}
|
||||
|
||||
float gx, gy, gz;
|
||||
unit->GetPosition(gx, gy, gz);
|
||||
|
||||
Creature* summoned = unit->SummonCreature(VISUAL_WAYPOINT, gx, gy, gz + 0.5f, 0, TEMPSUMMON_TIMED_DESPAWN, 20000);
|
||||
summoned->CastSpell(summoned, 8599, false);
|
||||
uint32 tries = 1;
|
||||
uint32 successes = 0;
|
||||
uint32 startTime = WorldTimer::getMSTime();
|
||||
for (; tries < 500; ++tries)
|
||||
{
|
||||
unit->GetPosition(gx, gy, gz);
|
||||
if (unit->GetMap()->GetReachableRandomPosition(unit, gx, gy, gz, radius))
|
||||
{
|
||||
unit->SummonCreature(VISUAL_WAYPOINT, gx, gy, gz, 0, TEMPSUMMON_TIMED_DESPAWN, 15000);
|
||||
++successes;
|
||||
if (successes >= 100)
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint32 genTime = WorldTimer::getMSTimeDiff(startTime, WorldTimer::getMSTime());
|
||||
PSendSysMessage("Generated %u valid points for %u try in %ums.", successes, tries, genTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleServerResetAllRaidCommand(char* args)
|
||||
{
|
||||
PSendSysMessage("Global raid instances reset, all players in raid instances will be teleported to homebind!");
|
||||
|
|
|
|||
|
|
@ -1117,9 +1117,9 @@ bool ChatHandler::HandleDebugSpellCoefsCommand(char* args)
|
|||
char const* dotDamageStr = GetMangosString(LANG_DOT_DAMAGE);
|
||||
|
||||
PSendSysMessage(LANG_SPELLCOEFS, spellid, isDirectHeal ? directHealStr : directDamageStr,
|
||||
direct_calc, direct_calc * 1.88f, bonus ? bonus->direct_damage : 0.0f, bonus ? bonus->ap_bonus : 0.0f);
|
||||
direct_calc, direct_calc * SCALE_SPELLPOWER_HEALING, bonus ? bonus->direct_damage : 0.0f, bonus ? bonus->ap_bonus : 0.0f);
|
||||
PSendSysMessage(LANG_SPELLCOEFS, spellid, isDotHeal ? dotHealStr : dotDamageStr,
|
||||
dot_calc, dot_calc * 1.88f, bonus ? bonus->dot_damage : 0.0f, bonus ? bonus->ap_dot_bonus : 0.0f);
|
||||
dot_calc, dot_calc * SCALE_SPELLPOWER_HEALING, bonus ? bonus->dot_damage : 0.0f, bonus ? bonus->ap_dot_bonus : 0.0f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ template<>
|
|||
void ConfusedMovementGenerator<Player>::Finalize(Player& unit)
|
||||
{
|
||||
unit.clearUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_CONFUSED_MOVE);
|
||||
unit.StopMoving();
|
||||
unit.StopMoving(true);
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
|
|||
|
|
@ -37,16 +37,17 @@
|
|||
template<class T>
|
||||
void FleeingMovementGenerator<T>::_setTargetLocation(T& owner)
|
||||
{
|
||||
if (!&owner)
|
||||
return;
|
||||
|
||||
// ignore in case other no reaction state
|
||||
if (owner.hasUnitState((UNIT_STAT_CAN_NOT_REACT | UNIT_STAT_NOT_MOVE) & ~UNIT_STAT_FLEEING))
|
||||
return;
|
||||
|
||||
float x, y, z;
|
||||
if (!_getPoint(owner, x, y, z))
|
||||
{
|
||||
// random point not found recheck later
|
||||
i_nextCheckTime.Reset(50);
|
||||
return;
|
||||
}
|
||||
|
||||
owner.addUnitState(UNIT_STAT_FLEEING_MOVE);
|
||||
|
||||
|
|
@ -55,7 +56,8 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T& owner)
|
|||
path.calculate(x, y, z);
|
||||
if (path.getPathType() & PATHFIND_NOPATH)
|
||||
{
|
||||
i_nextCheckTime.Reset(urand(1000, 1500));
|
||||
// path not found recheck later
|
||||
i_nextCheckTime.Reset(50);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -69,9 +71,6 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T& owner)
|
|||
template<class T>
|
||||
bool FleeingMovementGenerator<T>::_getPoint(T& owner, float& x, float& y, float& z)
|
||||
{
|
||||
if (!&owner)
|
||||
return false;
|
||||
|
||||
float dist_from_caster, angle_to_caster;
|
||||
if (Unit* fright = ObjectAccessor::GetUnit(owner, i_frightGuid))
|
||||
{
|
||||
|
|
@ -109,12 +108,23 @@ bool FleeingMovementGenerator<T>::_getPoint(T& owner, float& x, float& y, float&
|
|||
|
||||
x = curr_x + dist * cos(angle);
|
||||
y = curr_y + dist * sin(angle);
|
||||
z = curr_z;
|
||||
z = curr_z + 0.5f;
|
||||
|
||||
// try to fix z
|
||||
if (!owner.GetMap()->GetHeightInRange(owner.GetPhaseMask(), x, y, z))
|
||||
return false;
|
||||
|
||||
if (owner.GetTypeId() == TYPEID_PLAYER)
|
||||
owner.GetMap()->GetHitPosition(curr_x, curr_y, curr_z, x, y, z, owner.GetPhaseMask(), -0.1f);
|
||||
|
||||
owner.UpdateAllowedPositionZ(x, y, z);
|
||||
{
|
||||
// check any collision
|
||||
float testZ = z + 0.5f; // needed to avoid some false positive hit detection of terrain or passable little object
|
||||
if (owner.GetMap()->GetHitPosition(curr_x, curr_y, curr_z + 0.5f, x, y, testZ, owner.GetPhaseMask(), -0.1f))
|
||||
{
|
||||
z = testZ;
|
||||
if (!owner.GetMap()->GetHeightInRange(owner.GetPhaseMask(), x, y, z))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -509,6 +509,16 @@ void MotionMaster::MoveJump(float x, float y, float z, float horizontalSpeed, fl
|
|||
Mutate(new EffectMovementGenerator(id));
|
||||
}
|
||||
|
||||
void MotionMaster::MoveDestination(float x, float y, float z, float o, float horizontalSpeed, float max_height, Unit* target)
|
||||
{
|
||||
Movement::MoveSplineInit init(*m_owner);
|
||||
init.MoveTo(x, y, z);
|
||||
init.SetParabolic(max_height, 0);
|
||||
init.SetVelocity(horizontalSpeed);
|
||||
target ? init.SetFacing(target) : init.SetFacing(o);
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
void MotionMaster::MoveFall()
|
||||
{
|
||||
// use larger distance for vmap height search than in most other cases
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ class MotionMaster : private std::stack<MovementGenerator*>
|
|||
void MoveTaxiFlight(uint32 path, uint32 pathnode);
|
||||
void MoveDistract(uint32 timeLimit);
|
||||
void MoveJump(float x, float y, float z, float horizontalSpeed, float max_height, uint32 id = 0);
|
||||
void MoveDestination(float x, float y, float z, float o, float horizontalSpeed, float max_height, Unit* target = nullptr);
|
||||
void MoveFall();
|
||||
void MoveFlyOrLand(uint32 id, float x, float y, float z, bool liftOff);
|
||||
|
||||
|
|
|
|||
|
|
@ -333,6 +333,7 @@ void FlightPathMovementGenerator::Finalize(Player& player)
|
|||
|
||||
player.Unmount();
|
||||
player.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
|
||||
player.SetClientControl(&player, 1);
|
||||
|
||||
if (player.m_taxi.empty())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ AggressorAI::MoveInLineOfSight(Unit* u)
|
|||
return;
|
||||
|
||||
if (m_creature->CanInitiateAttack() && u->IsTargetableForAttack() &&
|
||||
m_creature->IsHostileTo(u) && u->isInAccessablePlaceFor(m_creature))
|
||||
m_creature->IsHostileTo(u) && u->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
float attackRadius = m_creature->GetAttackDistance(u);
|
||||
if (m_creature->IsWithinDistInMap(u, attackRadius) && m_creature->IsWithinLOSInMap(u))
|
||||
|
|
|
|||
|
|
@ -208,6 +208,10 @@ void Creature::AddToWorld()
|
|||
{ GetMap()->GetObjectsStore().insert<Creature>(GetObjectGuid(), (Creature*)this); }
|
||||
|
||||
Unit::AddToWorld();
|
||||
|
||||
// Make active if required
|
||||
if (sWorld.isForceLoadMap(GetMapId()) || (GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_ACTIVE))
|
||||
SetActiveObjectState(true);
|
||||
}
|
||||
|
||||
void Creature::RemoveFromWorld()
|
||||
|
|
@ -384,7 +388,14 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameE
|
|||
UpdateSpeed(MOVE_WALK, false);
|
||||
UpdateSpeed(MOVE_RUN, false);
|
||||
|
||||
SetLevitate(cinfo->InhabitType & INHABIT_AIR);
|
||||
SetLevitate((cinfo->InhabitType & INHABIT_AIR) != 0); // TODO: may not be correct to send opcode at this point (already handled by UPDATE_OBJECT createObject)
|
||||
|
||||
// check if we need to add swimming movement. TODO: i thing movement flags should be computed automatically at each movement of creature so we need a sort of UpdateMovementFlags() method
|
||||
if (cinfo->InhabitType & INHABIT_WATER && // check inhabit type water
|
||||
!(cinfo->ExtraFlags & CREATURE_EXTRA_FLAG_WALK_IN_WATER) && // check if creature is forced to walk (crabs, giant,...)
|
||||
data && // check if there is data to get creature spawn pos
|
||||
GetMap()->GetTerrain()->IsSwimmable(data->posX, data->posY, data->posZ, minfo->bounding_radius)) // check if creature is in water and have enough space to swim
|
||||
m_movementInfo.AddMovementFlag(MOVEFLAG_SWIMMING); // add swimming movement
|
||||
|
||||
// checked at loading
|
||||
m_defaultMovementType = MovementGeneratorType(cinfo->MovementType);
|
||||
|
|
@ -485,8 +496,10 @@ uint32 Creature::ChooseDisplayId(const CreatureInfo* cinfo, const CreatureData*
|
|||
// if mod2 use mod2 unless mod2 has modelid_alt_model (then both by 50%-chance)
|
||||
// if mod1 use mod1
|
||||
|
||||
// model selected here may be replaced with other_gender using own function
|
||||
// The follow decision tree needs to be updated if MAX_CREATURE_MODEL is changed.
|
||||
static_assert(MAX_CREATURE_MODEL == 4, "Need to update model selection code for new or removed model fields");
|
||||
|
||||
// model selected here may be replaced with other_gender using own function
|
||||
if (cinfo->ModelId[3] && cinfo->ModelId[2] && cinfo->ModelId[1] && cinfo->ModelId[0])
|
||||
{
|
||||
display_id = cinfo->ModelId[urand(0, 3)];
|
||||
|
|
@ -1159,6 +1172,9 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
|
|||
CreatureInfo const* cinfo = GetCreatureInfo();
|
||||
if (cinfo)
|
||||
{
|
||||
// The following if-else assumes that there are 4 model fields and needs updating if this is changed.
|
||||
static_assert(MAX_CREATURE_MODEL == 4, "Need to update custom model check for new/removed model fields.");
|
||||
|
||||
if (displayId != cinfo->ModelId[0] && displayId != cinfo->ModelId[1] &&
|
||||
displayId != cinfo->ModelId[2] && displayId != cinfo->ModelId[3])
|
||||
{
|
||||
|
|
@ -1765,6 +1781,35 @@ bool Creature::IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectInd
|
|||
return Unit::IsImmuneToSpellEffect(spellInfo, index, castOnSelf);
|
||||
}
|
||||
|
||||
// Set loot status. Also handle remove corpse timer
|
||||
void Creature::SetLootStatus(CreatureLootStatus status)
|
||||
{
|
||||
if (status <= m_lootStatus)
|
||||
return;
|
||||
|
||||
m_lootStatus = status;
|
||||
switch (status)
|
||||
{
|
||||
case CREATURE_LOOT_STATUS_LOOTED:
|
||||
if (m_creatureInfo->SkinningLootId)
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
|
||||
else
|
||||
RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
||||
break;
|
||||
case CREATURE_LOOT_STATUS_SKINNED:
|
||||
m_corpseDecayTimer = 0; // remove corpse at next update
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
|
||||
RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
||||
break;
|
||||
case CREATURE_LOOT_STATUS_SKIN_AVAILABLE:
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// return true if this creature is tapped by the player or by a member of his group.
|
||||
bool Creature::IsTappedBy(Player const* player) const
|
||||
{
|
||||
|
|
@ -2038,7 +2083,7 @@ bool Creature::IsOutOfThreatArea(Unit* pVictim) const
|
|||
if (!pVictim->IsTargetableForAttack())
|
||||
return true;
|
||||
|
||||
if (!pVictim->isInAccessablePlaceFor(this))
|
||||
if (!pVictim->IsInAccessablePlaceFor(this))
|
||||
return true;
|
||||
|
||||
if (!pVictim->IsVisibleForOrDetect(this, this, false))
|
||||
|
|
@ -2771,6 +2816,54 @@ void Creature::SetLevitate(bool enable)
|
|||
}
|
||||
}
|
||||
|
||||
void Creature::SetSwim(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
m_movementInfo.AddMovementFlag(MOVEFLAG_SWIMMING);
|
||||
else
|
||||
m_movementInfo.RemoveMovementFlag(MOVEFLAG_SWIMMING);
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_START_SWIM : SMSG_SPLINE_MOVE_STOP_SWIM);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void Creature::SetCanFly(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
m_movementInfo.AddMovementFlag(MOVEFLAG_CAN_FLY);
|
||||
else
|
||||
m_movementInfo.RemoveMovementFlag(MOVEFLAG_CAN_FLY);
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_FLYING : SMSG_SPLINE_MOVE_UNSET_FLYING, 9);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void Creature::SetFeatherFall(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
m_movementInfo.AddMovementFlag(MOVEFLAG_SAFE_FALL);
|
||||
else
|
||||
m_movementInfo.RemoveMovementFlag(MOVEFLAG_SAFE_FALL);
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_FEATHER_FALL : SMSG_SPLINE_MOVE_NORMAL_FALL);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void Creature::SetHover(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
m_movementInfo.AddMovementFlag(MOVEFLAG_HOVER);
|
||||
else
|
||||
m_movementInfo.RemoveMovementFlag(MOVEFLAG_HOVER);
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_HOVER : SMSG_SPLINE_MOVE_UNSET_HOVER, 9);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, false);
|
||||
}
|
||||
|
||||
void Creature::SetRoot(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
|
|
|
|||
|
|
@ -542,11 +542,11 @@ class Creature : public Unit
|
|||
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
|
||||
uint32 GetCorpseDelay() const { return m_corpseDelay; }
|
||||
bool IsRacialLeader() const { return GetCreatureInfo()->RacialLeader; }
|
||||
bool IsCivilian() const { return GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_CIVILIAN; }
|
||||
bool IsGuard() const { return GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_GUARD; }
|
||||
bool IsCivilian() const { return (GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_CIVILIAN) != 0; }
|
||||
bool IsGuard() const { return (GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_GUARD) != 0; }
|
||||
|
||||
bool CanWalk() const { return GetCreatureInfo()->InhabitType & INHABIT_GROUND; }
|
||||
bool CanSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; }
|
||||
bool CanWalk() const { return (GetCreatureInfo()->InhabitType & INHABIT_GROUND) != 0; }
|
||||
bool CanSwim() const { return (GetCreatureInfo()->InhabitType & INHABIT_WATER) != 0; }
|
||||
bool IsSwimming() const { return (m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_SWIMMING))); }
|
||||
bool CanFly() const { return (GetCreatureInfo()->InhabitType & INHABIT_AIR) || (GetByteValue(UNIT_FIELD_BYTES_1, 3) & UNIT_BYTE1_FLAG_FLY_ANIM) || m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_LEVITATING | MOVEFLAG_CAN_FLY)); }
|
||||
bool IsFlying() const { return (m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_FLYING | MOVEFLAG_LEVITATING))); }
|
||||
|
|
@ -560,6 +560,7 @@ class Creature : public Unit
|
|||
|
||||
bool IsImmuneToSpell(SpellEntry const* spellInfo, bool castOnSelf) override;
|
||||
bool IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index, bool castOnSelf) const override;
|
||||
void SetLootStatus(CreatureLootStatus status);
|
||||
bool IsTappedBy(Player const* player) const;
|
||||
|
||||
bool IsElite() const
|
||||
|
|
@ -591,6 +592,10 @@ class Creature : public Unit
|
|||
|
||||
void SetWalk(bool enable, bool asDefault = true);
|
||||
void SetLevitate(bool enable);
|
||||
void SetSwim(bool enable) override;
|
||||
void SetCanFly(bool enable) override;
|
||||
void SetFeatherFall(bool enable) override;
|
||||
void SetHover(bool enable) override;
|
||||
void SetRoot(bool enable) override;
|
||||
void SetWaterWalk(bool enable) override;
|
||||
|
||||
|
|
@ -818,6 +823,7 @@ class Creature : public Unit
|
|||
uint32 m_lootMoney;
|
||||
ObjectGuid m_lootRecipientGuid; // player who will have rights for looting if m_lootGroupRecipient==0 or group disbanded
|
||||
uint32 m_lootGroupRecipientId; // group who will have rights for looting if set and exist
|
||||
CreatureLootStatus m_lootStatus; // loot status (used to know when we could loot, pickpocket or skin)
|
||||
|
||||
/// Timers
|
||||
uint32 m_corpseDecayTimer; // (msecs)timer for death or corpse disappearance
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ inline bool IsTimerBasedEvent(EventAI_Type type)
|
|||
case EVENT_T_MISSING_AURA:
|
||||
case EVENT_T_TARGET_MISSING_AURA:
|
||||
case EVENT_T_RANGE:
|
||||
case EVENT_T_ENERGY:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
@ -276,6 +277,13 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
|
|||
pHolder.UpdateRepeatTimer(m_creature, event.spell_hit.repeatMin, event.spell_hit.repeatMax);
|
||||
break;
|
||||
case EVENT_T_RANGE:
|
||||
if (!m_creature->IsInCombat() || !m_creature->getVictim() || !m_creature->IsInMap(m_creature->getVictim()))
|
||||
return false;
|
||||
|
||||
// DISCUSS TODO - Likely replace IsInRange check with CombatReach checks (as used rather for such checks)
|
||||
if (!m_creature->IsInRange(m_creature->getVictim(), (float)event.range.minDist, (float)event.range.maxDist))
|
||||
return false;
|
||||
|
||||
// Repeat Timers
|
||||
pHolder.UpdateRepeatTimer(m_creature, event.range.repeatMin, event.range.repeatMax);
|
||||
break;
|
||||
|
|
@ -394,6 +402,9 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
|
|||
break;
|
||||
case EVENT_T_AURA:
|
||||
{
|
||||
if (!m_creature->IsInCombat())
|
||||
return false;
|
||||
|
||||
SpellAuraHolder* holder = m_creature->GetSpellAuraHolder(event.buffed.spellId);
|
||||
if (!holder || holder->GetStackAmount() < event.buffed.amount)
|
||||
return false;
|
||||
|
|
@ -419,6 +430,9 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
|
|||
}
|
||||
case EVENT_T_MISSING_AURA:
|
||||
{
|
||||
if (!m_creature->IsInCombat())
|
||||
return false;
|
||||
|
||||
SpellAuraHolder* holder = m_creature->GetSpellAuraHolder(event.buffed.spellId);
|
||||
if (holder && holder->GetStackAmount() >= event.buffed.amount)
|
||||
return false;
|
||||
|
|
@ -444,6 +458,21 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
|
|||
}
|
||||
case EVENT_T_RECEIVE_AI_EVENT:
|
||||
break;
|
||||
case EVENT_T_ENERGY:
|
||||
{
|
||||
if (!m_creature->IsInCombat() || !m_creature->GetMaxPower(POWER_ENERGY))
|
||||
return false;
|
||||
|
||||
uint32 perc = (m_creature->GetPower(POWER_ENERGY) * 100) / m_creature->GetMaxPower(POWER_ENERGY);
|
||||
|
||||
if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
|
||||
return false;
|
||||
|
||||
LOG_PROCESS_EVENT;
|
||||
// Repeat Timers
|
||||
pHolder.UpdateRepeatTimer(m_creature, event.percent_range.repeatMin, event.percent_range.repeatMax);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sLog.outErrorEventAI("Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
|
||||
break;
|
||||
|
|
@ -478,7 +507,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
|
|||
if (count)
|
||||
{
|
||||
// select action number from found amount
|
||||
uint32 idx = urand(0, count - 1);
|
||||
uint32 idx = rnd % count;
|
||||
|
||||
// find selected action, skipping not used
|
||||
uint32 j = 0;
|
||||
|
|
@ -520,17 +549,17 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
|
|||
if (action.type == ACTION_T_TEXT)
|
||||
{
|
||||
if (action.text.TextId[1] && action.text.TextId[2])
|
||||
textId = action.text.TextId[urand(0, 2)];
|
||||
else if (action.text.TextId[1] && urand(0, 1))
|
||||
textId = action.text.TextId[rnd % 3];
|
||||
else if (action.text.TextId[1] && (rnd % 2))
|
||||
textId = action.text.TextId[1];
|
||||
else
|
||||
textId = action.text.TextId[0];
|
||||
}
|
||||
// ACTION_T_CHANCED_TEXT, chance hits
|
||||
else if (urand(0, 99) < action.chanced_text.chance)
|
||||
else if ((rnd % 100) < action.chanced_text.chance)
|
||||
{
|
||||
if (action.chanced_text.TextId[0] && action.chanced_text.TextId[1])
|
||||
textId = action.chanced_text.TextId[urand(0, 1)];
|
||||
textId = action.chanced_text.TextId[rnd % 2];
|
||||
else
|
||||
textId = action.chanced_text.TextId[0];
|
||||
}
|
||||
|
|
@ -839,9 +868,9 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
|
|||
|
||||
Creature* pCreature = NULL;
|
||||
if ((*i).second.SpawnTimeSecs)
|
||||
pCreature = m_creature->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OOC_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs);
|
||||
pCreature = m_creature->SummonCreature(action.summon_id.creatureId, i->second.position_x, i->second.position_y, i->second.position_z, i->second.orientation, TEMPSUMMON_TIMED_OOC_OR_DEAD_DESPAWN, i->second.SpawnTimeSecs);
|
||||
else
|
||||
pCreature = m_creature->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OOC_DESPAWN, 0);
|
||||
pCreature = m_creature->SummonCreature(action.summon_id.creatureId, i->second.position_x, i->second.position_y, i->second.position_z, i->second.orientation, TEMPSUMMON_TIMED_OOC_DESPAWN, 0);
|
||||
|
||||
if (!pCreature)
|
||||
sLog.outErrorEventAI("failed to spawn creature %u. EventId %d.Creature %d", action.summon_id.creatureId, EventId, m_creature->GetEntry());
|
||||
|
|
@ -1035,29 +1064,26 @@ void CreatureEventAI::Reset()
|
|||
{
|
||||
m_EventUpdateTime = EVENT_UPDATE_TIME;
|
||||
m_EventDiff = 0;
|
||||
|
||||
m_throwAIEventStep = 0;
|
||||
|
||||
// Reset all events to enabled
|
||||
for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
|
||||
{
|
||||
CreatureEventAI_Event const& event = (*i).Event;
|
||||
CreatureEventAI_Event const& event = i->Event;
|
||||
switch (event.event_type)
|
||||
{
|
||||
// Reset all out of combat timers
|
||||
case EVENT_T_TIMER_OOC:
|
||||
{
|
||||
if ((*i).UpdateRepeatTimer(m_creature, event.timer.initialMin, event.timer.initialMax))
|
||||
(*i).Enabled = true;
|
||||
if (i->UpdateRepeatTimer(m_creature, event.timer.initialMin, event.timer.initialMax))
|
||||
i->Enabled = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
// default:
|
||||
// TODO: enable below code line / verify this is correct to enable events previously disabled (ex. aggro yell), instead of enable this in void Aggro()
|
||||
//(*i).Enabled = true;
|
||||
//(*i).Time = 0;
|
||||
// break;
|
||||
//i->Enabled = true;
|
||||
//i->Time = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1066,7 +1092,7 @@ void CreatureEventAI::JustReachedHome()
|
|||
{
|
||||
for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
|
||||
{
|
||||
if ((*i).Event.event_type == EVENT_T_REACHED_HOME)
|
||||
if (i->Event.event_type == EVENT_T_REACHED_HOME)
|
||||
ProcessEvent(*i);
|
||||
}
|
||||
|
||||
|
|
@ -1079,18 +1105,16 @@ void CreatureEventAI::EnterEvadeMode()
|
|||
m_creature->DeleteThreatList();
|
||||
m_creature->CombatStop(true);
|
||||
|
||||
if (m_creature->IsAlive())
|
||||
// only alive creatures that are not on transport can return to home position
|
||||
if (m_creature->IsAlive() && !m_creature->IsBoarded())
|
||||
m_creature->GetMotionMaster()->MoveTargetedHome();
|
||||
|
||||
m_creature->SetLootRecipient(NULL);
|
||||
|
||||
if (m_bEmptyList)
|
||||
return;
|
||||
m_creature->SetLootRecipient(nullptr);
|
||||
|
||||
// Handle Evade events
|
||||
for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
|
||||
{
|
||||
if ((*i).Event.event_type == EVENT_T_EVADE)
|
||||
if (i->Event.event_type == EVENT_T_EVADE)
|
||||
ProcessEvent(*i);
|
||||
}
|
||||
}
|
||||
|
|
@ -1112,7 +1136,7 @@ void CreatureEventAI::JustDied(Unit* killer)
|
|||
// Handle On Death events
|
||||
for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
|
||||
{
|
||||
if ((*i).Event.event_type == EVENT_T_DEATH)
|
||||
if (i->Event.event_type == EVENT_T_DEATH)
|
||||
ProcessEvent(*i, killer);
|
||||
}
|
||||
|
||||
|
|
@ -1127,7 +1151,7 @@ void CreatureEventAI::KilledUnit(Unit* victim)
|
|||
|
||||
for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
|
||||
{
|
||||
if ((*i).Event.event_type == EVENT_T_KILL)
|
||||
if (i->Event.event_type == EVENT_T_KILL)
|
||||
ProcessEvent(*i, victim);
|
||||
}
|
||||
}
|
||||
|
|
@ -1136,7 +1160,7 @@ void CreatureEventAI::JustSummoned(Creature* pUnit)
|
|||
{
|
||||
for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
|
||||
{
|
||||
if ((*i).Event.event_type == EVENT_T_SUMMONED_UNIT)
|
||||
if (i->Event.event_type == EVENT_T_SUMMONED_UNIT)
|
||||
ProcessEvent(*i, pUnit);
|
||||
}
|
||||
}
|
||||
|
|
@ -1145,7 +1169,7 @@ void CreatureEventAI::SummonedCreatureJustDied(Creature* pUnit)
|
|||
{
|
||||
for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
|
||||
{
|
||||
if ((*i).Event.event_type == EVENT_T_SUMMONED_JUST_DIED)
|
||||
if (i->Event.event_type == EVENT_T_SUMMONED_JUST_DIED)
|
||||
ProcessEvent(*i, pUnit);
|
||||
}
|
||||
}
|
||||
|
|
@ -1154,12 +1178,12 @@ void CreatureEventAI::SummonedCreatureDespawn(Creature* pUnit)
|
|||
{
|
||||
for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
|
||||
{
|
||||
if ((*i).Event.event_type == EVENT_T_SUMMONED_JUST_DESPAWN)
|
||||
if (i->Event.event_type == EVENT_T_SUMMONED_JUST_DESPAWN)
|
||||
ProcessEvent(*i, pUnit);
|
||||
}
|
||||
}
|
||||
|
||||
void CreatureEventAI::ReceiveAIEvent(AIEventType eventType, Creature* pSender, Unit* pInvoker, uint32 miscValue)
|
||||
void CreatureEventAI::ReceiveAIEvent(AIEventType eventType, Creature* pSender, Unit* pInvoker, uint32 /*miscValue*/)
|
||||
{
|
||||
MANGOS_ASSERT(pSender);
|
||||
|
||||
|
|
@ -1176,22 +1200,22 @@ void CreatureEventAI::EnterCombat(Unit* enemy)
|
|||
// Check for on combat start events
|
||||
for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
|
||||
{
|
||||
CreatureEventAI_Event const& event = (*i).Event;
|
||||
CreatureEventAI_Event const& event = i->Event;
|
||||
switch (event.event_type)
|
||||
{
|
||||
case EVENT_T_AGGRO:
|
||||
(*i).Enabled = true;
|
||||
i->Enabled = true;
|
||||
ProcessEvent(*i, enemy);
|
||||
break;
|
||||
// Reset all in combat timers
|
||||
case EVENT_T_TIMER_IN_COMBAT:
|
||||
if ((*i).UpdateRepeatTimer(m_creature, event.timer.initialMin, event.timer.initialMax))
|
||||
(*i).Enabled = true;
|
||||
if (i->UpdateRepeatTimer(m_creature, event.timer.initialMin, event.timer.initialMax))
|
||||
i->Enabled = true;
|
||||
break;
|
||||
// All normal events need to be re-enabled and their time set to 0
|
||||
default:
|
||||
(*i).Enabled = true;
|
||||
(*i).Time = 0;
|
||||
i->Enabled = true;
|
||||
i->Time = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1221,21 +1245,21 @@ void CreatureEventAI::MoveInLineOfSight(Unit* who)
|
|||
return;
|
||||
|
||||
// Check for OOC LOS Event
|
||||
if (!m_creature->getVictim())
|
||||
if (m_HasOOCLoSEvent && !m_creature->getVictim())
|
||||
{
|
||||
for (CreatureEventAIList::iterator itr = m_CreatureEventAIList.begin(); itr != m_CreatureEventAIList.end(); ++itr)
|
||||
{
|
||||
if ((*itr).Event.event_type == EVENT_T_OOC_LOS)
|
||||
if (itr->Event.event_type == EVENT_T_OOC_LOS)
|
||||
{
|
||||
// can trigger if closer than fMaxAllowedRange
|
||||
float fMaxAllowedRange = (float)(*itr).Event.ooc_los.maxRange;
|
||||
float fMaxAllowedRange = (float)itr->Event.ooc_los.maxRange;
|
||||
|
||||
// if friendly event && who is not hostile OR hostile event && who is hostile
|
||||
if ((itr->Event.ooc_los.noHostile && !m_creature->IsHostileTo(who)) ||
|
||||
((!itr->Event.ooc_los.noHostile) && m_creature->IsHostileTo(who)))
|
||||
{
|
||||
// if range is ok and we are actually in LOS
|
||||
if (m_creature->IsWithinDistInMap(who, fMaxAllowedRange) && m_creature->IsWithinLOSInMap(who))
|
||||
{
|
||||
// if friendly event&&who is not hostile OR hostile event&&who is hostile
|
||||
if (((*itr).Event.ooc_los.noHostile && !m_creature->IsHostileTo(who)) ||
|
||||
((!(*itr).Event.ooc_los.noHostile) && m_creature->IsHostileTo(who)))
|
||||
ProcessEvent(*itr, who);
|
||||
}
|
||||
}
|
||||
|
|
@ -1246,7 +1270,7 @@ void CreatureEventAI::MoveInLineOfSight(Unit* who)
|
|||
return;
|
||||
|
||||
if (m_creature->CanInitiateAttack() && who->IsTargetableForAttack() &&
|
||||
m_creature->IsHostileTo(who) && who->isInAccessablePlaceFor(m_creature))
|
||||
m_creature->IsHostileTo(who) && who->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
if (!m_creature->CanFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
|
||||
return;
|
||||
|
|
@ -1271,10 +1295,10 @@ void CreatureEventAI::MoveInLineOfSight(Unit* who)
|
|||
void CreatureEventAI::SpellHit(Unit* pUnit, const SpellEntry* pSpell)
|
||||
{
|
||||
for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
|
||||
if ((*i).Event.event_type == EVENT_T_SPELLHIT)
|
||||
if (i->Event.event_type == EVENT_T_SPELLHIT)
|
||||
// If spell id matches (or no spell id) & if spell school matches (or no spell school)
|
||||
if (!(*i).Event.spell_hit.spellId || pSpell->Id == (*i).Event.spell_hit.spellId)
|
||||
if (pSpell->SchoolMask & (*i).Event.spell_hit.schoolMask)
|
||||
if (!i->Event.spell_hit.spellId || pSpell->Id == i->Event.spell_hit.spellId)
|
||||
if (pSpell->SchoolMask & i->Event.spell_hit.schoolMask)
|
||||
ProcessEvent(*i, pUnit);
|
||||
}
|
||||
|
||||
|
|
@ -1292,66 +1316,53 @@ void CreatureEventAI::UpdateAI(const uint32 diff)
|
|||
for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
|
||||
{
|
||||
// Decrement Timers
|
||||
if ((*i).Time)
|
||||
if (i->Time)
|
||||
{
|
||||
if ((*i).Time > m_EventDiff)
|
||||
if (i->Time > m_EventDiff)
|
||||
{
|
||||
// Do not decrement timers if event cannot trigger in this phase
|
||||
if (!((*i).Event.event_inverse_phase_mask & (1 << m_Phase)))
|
||||
(*i).Time -= m_EventDiff;
|
||||
if (!(i->Event.event_inverse_phase_mask & (1 << m_Phase)))
|
||||
i->Time -= m_EventDiff;
|
||||
}
|
||||
else
|
||||
i->Time = 0;
|
||||
}
|
||||
|
||||
// Skip processing of events that have time remaining
|
||||
// Skip processing of events that have time remaining or are disabled
|
||||
if (!(i->Enabled) || i->Time)
|
||||
continue;
|
||||
}
|
||||
else (*i).Time = 0;
|
||||
}
|
||||
|
||||
// Events that are updated every EVENT_UPDATE_TIME
|
||||
switch ((*i).Event.event_type)
|
||||
{
|
||||
case EVENT_T_TIMER_OOC:
|
||||
case EVENT_T_TIMER_GENERIC:
|
||||
if (IsTimerBasedEvent(i->Event.event_type))
|
||||
ProcessEvent(*i);
|
||||
break;
|
||||
case EVENT_T_TIMER_IN_COMBAT:
|
||||
case EVENT_T_MANA:
|
||||
case EVENT_T_HP:
|
||||
case EVENT_T_TARGET_HP:
|
||||
case EVENT_T_TARGET_CASTING:
|
||||
case EVENT_T_FRIENDLY_HP:
|
||||
case EVENT_T_AURA:
|
||||
case EVENT_T_TARGET_AURA:
|
||||
case EVENT_T_MISSING_AURA:
|
||||
case EVENT_T_TARGET_MISSING_AURA:
|
||||
if (Combat)
|
||||
ProcessEvent(*i);
|
||||
break;
|
||||
case EVENT_T_RANGE:
|
||||
if (Combat)
|
||||
{
|
||||
if (m_creature->getVictim() && m_creature->IsInMap(m_creature->getVictim()))
|
||||
if (m_creature->IsInRange(m_creature->getVictim(), (float)(*i).Event.range.minDist, (float)(*i).Event.range.maxDist))
|
||||
ProcessEvent(*i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_EventDiff = 0;
|
||||
m_EventUpdateTime = EVENT_UPDATE_TIME;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_EventDiff += diff;
|
||||
m_EventUpdateTime -= diff;
|
||||
}
|
||||
|
||||
// Melee Auto-Attack (recheck m_creature->getVictim in case of combat state was changed while processing events)
|
||||
if (Combat && m_MeleeEnabled && m_creature->getVictim())
|
||||
// Melee Auto-Attack (getVictim might be nullptr as result of timer based events and actions)
|
||||
if (Combat && m_creature->getVictim())
|
||||
{
|
||||
// Update creature dynamic movement position before doing anything else
|
||||
if (m_DynamicMovement)
|
||||
{
|
||||
if (!m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT) && !m_creature->IsNonMeleeSpellCasted(false))
|
||||
{
|
||||
if (m_LastSpellMaxRange && m_creature->IsInRange(m_creature->getVictim(), 0, (m_LastSpellMaxRange / 1.5f)))
|
||||
SetCombatMovement(false, true);
|
||||
else
|
||||
SetCombatMovement(true, true);
|
||||
}
|
||||
}
|
||||
else if (m_MeleeEnabled)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
bool CreatureEventAI::IsVisible(Unit* pl) const
|
||||
{
|
||||
|
|
@ -1478,12 +1489,12 @@ void CreatureEventAI::ReceiveEmote(Player* pPlayer, uint32 text_emote)
|
|||
{
|
||||
for (CreatureEventAIList::iterator itr = m_CreatureEventAIList.begin(); itr != m_CreatureEventAIList.end(); ++itr)
|
||||
{
|
||||
if ((*itr).Event.event_type == EVENT_T_RECEIVE_EMOTE)
|
||||
if (itr->Event.event_type == EVENT_T_RECEIVE_EMOTE)
|
||||
{
|
||||
if ((*itr).Event.receive_emote.emoteId != text_emote)
|
||||
return;
|
||||
if (itr->Event.receive_emote.emoteId != text_emote)
|
||||
continue;
|
||||
|
||||
PlayerCondition pcon(0, (*itr).Event.receive_emote.condition, (*itr).Event.receive_emote.conditionValue1, (*itr).Event.receive_emote.conditionValue2);
|
||||
PlayerCondition pcon(0, itr->Event.receive_emote.condition, itr->Event.receive_emote.conditionValue1, itr->Event.receive_emote.conditionValue2);
|
||||
if (pcon.Meets(pPlayer, m_creature->GetMap(), m_creature, CONDITION_FROM_EVENTAI))
|
||||
{
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing");
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ enum EventAI_Type
|
|||
EVENT_T_TARGET_MISSING_AURA = 28, // Param1 = SpellID, Param2 = Number of time stacked expected, Param3/4 Repeat Min/Max
|
||||
EVENT_T_TIMER_GENERIC = 29, // InitialMin, InitialMax, RepeatMin, RepeatMax
|
||||
EVENT_T_RECEIVE_AI_EVENT = 30, // AIEventType, Sender-Entry, unused, unused
|
||||
EVENT_T_ENERGY = 31, // EnergyMax%, EnergyMin%, RepeatMin, RepeatMax
|
||||
|
||||
EVENT_T_END,
|
||||
};
|
||||
|
|
@ -467,6 +468,7 @@ struct CreatureEventAI_Event
|
|||
// EVENT_T_MANA = 3
|
||||
// EVENT_T_TARGET_HP = 12
|
||||
// EVENT_T_TARGET_MANA = 18
|
||||
// EVENT_T_ENERGY = 31
|
||||
struct
|
||||
{
|
||||
uint32 percentMax;
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ void CreatureEventAIMgr::CheckUnusedAITexts()
|
|||
sLog.outErrorEventAI("Entry %i in table `creature_ai_texts` but not used in EventAI scripts.", *itr);
|
||||
}
|
||||
|
||||
/// Helper function to check if a target-suite is suitable for the event-type
|
||||
/// Helper function to check if a target-type is suitable for the event-type
|
||||
bool IsValidTargetType(EventAI_Type eventType, EventAI_ActionType actionType, uint32 targetType, uint32 eventId, uint8 action)
|
||||
{
|
||||
switch (targetType)
|
||||
|
|
@ -327,6 +327,7 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
|
|||
case EVENT_T_MANA:
|
||||
case EVENT_T_TARGET_HP:
|
||||
case EVENT_T_TARGET_MANA:
|
||||
case EVENT_T_ENERGY:
|
||||
if (temp.percent_range.percentMax > 100)
|
||||
sLog.outErrorEventAI("Creature %u are using percentage event(%u) with param2 (MinPercent) > 100. Event will never trigger! ", temp.creature_id, i);
|
||||
|
||||
|
|
|
|||
|
|
@ -1269,8 +1269,11 @@ void GameObject::Use(Unit* user)
|
|||
player->RewardPlayerAndGroupAtCast(this);
|
||||
}
|
||||
|
||||
if (scriptReturnValue)
|
||||
{ return; }
|
||||
// activate script
|
||||
if (!scriptReturnValue)
|
||||
GetMap()->ScriptsStart(sGameObjectScripts, GetGUIDLow(), spellCaster, this);
|
||||
else
|
||||
return;
|
||||
|
||||
// cast this spell later if provided
|
||||
spellId = info->goober.spellId;
|
||||
|
|
@ -2382,6 +2385,23 @@ void GameObject::ForceGameObjectHealth(int32 diff, Unit* caster)
|
|||
SetGoAnimProgress(GetMaxHealth() ? m_useTimes * 255 / GetMaxHealth() : 255);
|
||||
}
|
||||
|
||||
float GameObject::GetInteractionDistance()
|
||||
{
|
||||
switch (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 chosen number
|
||||
case GAMEOBJECT_TYPE_GUILD_BANK:
|
||||
case GAMEOBJECT_TYPE_MAILBOX:
|
||||
return 10.0f;
|
||||
case GAMEOBJECT_TYPE_FISHINGHOLE:
|
||||
case GAMEOBJECT_TYPE_FISHINGNODE:
|
||||
return 20.0f + CONTACT_DISTANCE; // max spell range
|
||||
default:
|
||||
return INTERACTION_DISTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GameObject::GetScriptId()
|
||||
{
|
||||
return sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, -int32(GetGUIDLow())) ? sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, -int32(GetGUIDLow())) : sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, GetEntry());
|
||||
|
|
|
|||
|
|
@ -842,6 +842,11 @@ class GameObject : public WorldObject
|
|||
ObjectGuid m_lootRecipientGuid; // player who will have rights for looting if m_lootGroupRecipient==0 or group disbanded
|
||||
uint32 m_lootGroupRecipientId; // group who will have rights for looting if set and exist
|
||||
|
||||
// Used for chest type
|
||||
bool m_isInUse; // only one player at time are allowed to open chest
|
||||
time_t m_reStockTimer; // timer to refill the chest
|
||||
time_t m_despawnTimer; // timer to despawn the chest if something changed in it
|
||||
|
||||
private:
|
||||
void SwitchDoorOrButton(bool activate, bool alternative = false);
|
||||
void TickCapturePoint();
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ void GuardAI::MoveInLineOfSight(Unit* u)
|
|||
|
||||
if (!m_creature->getVictim() && u->IsTargetableForAttack() &&
|
||||
(u->IsHostileToPlayers() || m_creature->IsHostileTo(u) /*|| u->getVictim() && m_creature->IsFriendlyTo(u->getVictim())*/) &&
|
||||
u->isInAccessablePlaceFor(m_creature))
|
||||
u->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
float attackRadius = m_creature->GetAttackDistance(u);
|
||||
if (m_creature->IsWithinDistInMap(u, attackRadius))
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const
|
|||
return false;
|
||||
}
|
||||
|
||||
if (maxcount < mincountOrRef) // wrong max count
|
||||
if (maxcount < (uint32)mincountOrRef) // wrong max count
|
||||
{
|
||||
sLog.outErrorDb("Table '%s' entry %d item %d: max count (%u) less that min count (%i) - skipped", store.GetName(), entry, itemid, uint32(maxcount), mincountOrRef);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,9 @@ enum LootType
|
|||
|
||||
LOOT_FISHINGHOLE = 20, // unsupported by client, sending LOOT_FISHING instead
|
||||
LOOT_FISHING_FAIL = 21, // unsupported by client, sending LOOT_FISHING instead
|
||||
LOOT_INSIGNIA = 22 // unsupported by client, sending LOOT_CORPSE instead
|
||||
LOOT_INSIGNIA = 22, // unsupported by client, sending LOOT_CORPSE instead
|
||||
LOOT_MAIL = 23,
|
||||
LOOT_SPELL = 24,
|
||||
};
|
||||
|
||||
enum LootSlotType
|
||||
|
|
|
|||
|
|
@ -664,19 +664,37 @@ void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* u
|
|||
{
|
||||
*data << (m_uint32Values[index] & ~UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
// hide lootable animation for unallowed players
|
||||
/* Hide loot animation for players that aren't permitted to loot the corpse */
|
||||
else if (index == UNIT_DYNAMIC_FLAGS && GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
if (!target->isAllowedToLoot((Creature*)this))
|
||||
*data << (m_uint32Values[index] & ~(UNIT_DYNFLAG_LOOTABLE | UNIT_DYNFLAG_TAPPED_BY_PLAYER));
|
||||
else
|
||||
uint32 send_value = m_uint32Values[index];
|
||||
|
||||
/* Initiate pointer to creature so we can check loot */
|
||||
if (Creature* my_creature = (Creature*)this)
|
||||
/* If the creature is NOT fully looted */
|
||||
if (!my_creature->loot.isLooted())
|
||||
/* If the lootable flag is NOT set */
|
||||
if (!(send_value & UNIT_DYNFLAG_LOOTABLE))
|
||||
{
|
||||
// flag only for original loot recipent
|
||||
if (target->GetObjectGuid() == ((Creature*)this)->GetLootRecipientGuid())
|
||||
*data << m_uint32Values[index];
|
||||
else
|
||||
*data << (m_uint32Values[index] & ~(UNIT_DYNFLAG_TAPPED | UNIT_DYNFLAG_TAPPED_BY_PLAYER));
|
||||
/* Update it on the creature */
|
||||
my_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
||||
/* Update it in the packet */
|
||||
send_value = send_value | UNIT_DYNFLAG_LOOTABLE;
|
||||
}
|
||||
|
||||
/* If we're not allowed to loot the target, destroy the lootable flag */
|
||||
if (!target->isAllowedToLoot((Creature*)this))
|
||||
if (send_value & UNIT_DYNFLAG_LOOTABLE)
|
||||
{ send_value = send_value & ~UNIT_DYNFLAG_LOOTABLE; }
|
||||
|
||||
/* If we are allowed to loot it and mob is tapped by us, destroy the tapped flag */
|
||||
bool is_tapped = target->IsTappedByMeOrMyGroup((Creature*)this);
|
||||
|
||||
/* If the creature has tapped flag but is tapped by us, remove the flag */
|
||||
if (send_value & UNIT_DYNFLAG_TAPPED && is_tapped)
|
||||
{ send_value = send_value & ~UNIT_DYNFLAG_TAPPED; }
|
||||
|
||||
*data << send_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1479,8 +1497,11 @@ void WorldObject::UpdateGroundPositionZ(float x, float y, float& z) const
|
|||
{ z = new_z + 0.05f; } // just to be sure that we are not a few pixel under the surface
|
||||
}
|
||||
|
||||
void WorldObject::UpdateAllowedPositionZ(float x, float y, float& z) const
|
||||
void WorldObject::UpdateAllowedPositionZ(float x, float y, float& z, Map* atMap /*=nullptr*/) const
|
||||
{
|
||||
if (!atMap)
|
||||
atMap = GetMap();
|
||||
|
||||
switch (GetTypeId())
|
||||
{
|
||||
case TYPEID_UNIT:
|
||||
|
|
@ -1492,21 +1513,21 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float& z) const
|
|||
bool canSwim = ((Creature const*)this)->CanSwim();
|
||||
float ground_z = z;
|
||||
float max_z = canSwim
|
||||
? GetTerrain()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK))
|
||||
: ((ground_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z)));
|
||||
? atMap->GetTerrain()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK))
|
||||
: ((ground_z = atMap->GetHeight(GetPhaseMask(), x, y, z)));
|
||||
if (max_z > INVALID_HEIGHT)
|
||||
{
|
||||
if (z > max_z)
|
||||
{ z = max_z; }
|
||||
z = max_z;
|
||||
else if (z < ground_z)
|
||||
{ z = ground_z; }
|
||||
z = ground_z;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float ground_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z);
|
||||
float ground_z = atMap->GetHeight(GetPhaseMask(), x, y, z);
|
||||
if (z < ground_z)
|
||||
{ z = ground_z; }
|
||||
z = ground_z;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1516,18 +1537,18 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float& z) const
|
|||
if (!((Player const*)this)->CanFly())
|
||||
{
|
||||
float ground_z = z;
|
||||
float max_z = GetTerrain()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK));
|
||||
float max_z = atMap->GetTerrain()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK));
|
||||
if (max_z > INVALID_HEIGHT)
|
||||
{
|
||||
if (z > max_z)
|
||||
{ z = max_z; }
|
||||
z = max_z;
|
||||
else if (z < ground_z)
|
||||
{ z = ground_z; }
|
||||
z = ground_z;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float ground_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z);
|
||||
float ground_z = atMap->GetHeight(GetPhaseMask(), x, y, z);
|
||||
if (z < ground_z)
|
||||
z = ground_z;
|
||||
}
|
||||
|
|
@ -1535,9 +1556,9 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float& z) const
|
|||
}
|
||||
default:
|
||||
{
|
||||
float ground_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z);
|
||||
float ground_z = atMap->GetHeight(GetPhaseMask(), x, y, z);
|
||||
if (ground_z > INVALID_HEIGHT)
|
||||
{ z = ground_z; }
|
||||
z = ground_z;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1914,9 +1935,9 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
|
|||
if (!sWorld.getConfig(CONFIG_BOOL_DETECT_POS_COLLISION))
|
||||
{
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z, GetMap()); // update to LOS height if available
|
||||
else
|
||||
{ UpdateGroundPositionZ(x, y, z); }
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1942,12 +1963,12 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
|
|||
if (selector.CheckOriginalAngle())
|
||||
{
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z, GetMap()); // update to LOS height if available
|
||||
else
|
||||
{ UpdateGroundPositionZ(x, y, z); }
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
|
||||
if (fabs(init_z - z) < dist && IsWithinLOS(x, y, z))
|
||||
{ return; }
|
||||
return;
|
||||
|
||||
first_los_conflict = true; // first point have LOS problems
|
||||
}
|
||||
|
|
@ -1964,12 +1985,12 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
|
|||
z = GetPositionZ();
|
||||
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z, GetMap()); // update to LOS height if available
|
||||
else
|
||||
{ UpdateGroundPositionZ(x, y, z); }
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
|
||||
if (fabs(init_z - z) < dist && IsWithinLOS(x, y, z))
|
||||
{ return; }
|
||||
return;
|
||||
}
|
||||
|
||||
// BAD NEWS: not free pos (or used or have LOS problems)
|
||||
|
|
@ -1980,9 +2001,9 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
|
|||
y = first_y;
|
||||
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z, GetMap()); // update to LOS height if available
|
||||
else
|
||||
{ UpdateGroundPositionZ(x, y, z); }
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1996,12 +2017,12 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
|
|||
z = GetPositionZ();
|
||||
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z, GetMap()); // update to LOS height if available
|
||||
else
|
||||
{ UpdateGroundPositionZ(x, y, z); }
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
|
||||
if (fabs(init_z - z) < dist && IsWithinLOS(x, y, z))
|
||||
{ return; }
|
||||
return;
|
||||
}
|
||||
|
||||
// BAD BAD NEWS: all found pos (free and used) have LOS problem :(
|
||||
|
|
@ -2009,9 +2030,9 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
|
|||
y = first_y;
|
||||
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z, GetMap());// update to LOS height if available
|
||||
else
|
||||
{ UpdateGroundPositionZ(x, y, z); }
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
}
|
||||
|
||||
void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
|
||||
|
|
|
|||
|
|
@ -536,7 +536,7 @@ class WorldObject : public Object
|
|||
|
||||
bool IsPositionValid() const;
|
||||
void UpdateGroundPositionZ(float x, float y, float& z) const;
|
||||
void UpdateAllowedPositionZ(float x, float y, float& z) const;
|
||||
void UpdateAllowedPositionZ(float x, float y, float& z, Map* atMap = nullptr) const;
|
||||
|
||||
void GetRandomPoint(float x, float y, float z, float distance, float& rand_x, float& rand_y, float& rand_z) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -1438,7 +1438,7 @@ void ObjectMgr::LoadCreatures()
|
|||
|
||||
if (cInfo->RegenerateStats & REGEN_FLAG_HEALTH && data.curhealth < cInfo->MinLevelHealth)
|
||||
{
|
||||
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`RegenHealth`=1 and low current health (%u), `creature_template`.`MinLevelHealth`=%u.", guid, data.id, data.curhealth, cInfo->MinLevelHealth);
|
||||
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`RegenerateStats` & REGEN_FLAG_HEALTH and low current health (%u), `creature_template`.`MinLevelHealth`=%u.", guid, data.id, data.curhealth, cInfo->MinLevelHealth);
|
||||
data.curhealth = cInfo->MinLevelHealth;
|
||||
}
|
||||
|
||||
|
|
@ -1491,8 +1491,13 @@ void ObjectMgr::LoadCreatures()
|
|||
}
|
||||
|
||||
if (gameEvent == 0 && GuidPoolId == 0 && EntryPoolId == 0) // if not this is to be managed by GameEvent System or Pool system
|
||||
{
|
||||
AddCreatureToGrid(guid, &data);
|
||||
|
||||
if (cInfo->ExtraFlags & CREATURE_EXTRA_FLAG_ACTIVE)
|
||||
m_activeCreatures.insert(ActiveCreatureGuidsOnMap::value_type(data.mapid, guid));
|
||||
}
|
||||
|
||||
++count;
|
||||
}
|
||||
while (result->NextRow());
|
||||
|
|
@ -7580,9 +7585,9 @@ void ObjectMgr::LoadCreatureQuestRelations()
|
|||
{
|
||||
CreatureInfo const* cInfo = GetCreatureTemplate(itr->first);
|
||||
if (!cInfo)
|
||||
sLog.outErrorDb("Table `creature_questrelation` have data for nonexistent creature entry (%u) and existing quest %u", itr->first, itr->second);
|
||||
sLog.outErrorDb("Table `creature_involvedrelation` have data for nonexistent creature entry (%u) and existing quest %u", itr->first, itr->second);
|
||||
else if (!(cInfo->NpcFlags & UNIT_NPC_FLAG_QUESTGIVER))
|
||||
sLog.outErrorDb("Table `creature_questrelation` has creature entry (%u) for quest %u, but NpcFlags does not include UNIT_NPC_FLAG_QUESTGIVER", itr->first, itr->second);
|
||||
sLog.outErrorDb("Table `creature_involvedrelation` has creature entry (%u) for quest %u, but NpcFlags does not include UNIT_NPC_FLAG_QUESTGIVER", itr->first, itr->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9400,6 +9405,7 @@ void ObjectMgr::LoadTrainerTemplates()
|
|||
|
||||
// post loading check
|
||||
std::set<uint32> trainer_ids;
|
||||
bool hasErrored = false;
|
||||
|
||||
for (CacheTrainerSpellMap::const_iterator tItr = m_mCacheTrainerTemplateSpellMap.begin(); tItr != m_mCacheTrainerTemplateSpellMap.end(); ++tItr)
|
||||
trainer_ids.insert(tItr->first);
|
||||
|
|
@ -9407,19 +9413,22 @@ void ObjectMgr::LoadTrainerTemplates()
|
|||
for (uint32 i = 1; i < sCreatureStorage.GetMaxEntry(); ++i)
|
||||
{
|
||||
if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(i))
|
||||
{
|
||||
if (cInfo->TrainerTemplateId)
|
||||
{
|
||||
if (m_mCacheTrainerTemplateSpellMap.find(cInfo->TrainerTemplateId) != m_mCacheTrainerTemplateSpellMap.end())
|
||||
trainer_ids.erase(cInfo->TrainerTemplateId);
|
||||
else
|
||||
sLog.outErrorDb("Creature (Entry: %u) has trainer_id = %u for nonexistent trainer template", cInfo->Entry, cInfo->TrainerTemplateId);
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has TrainerTemplateId = %u for nonexistent trainer template", cInfo->Entry, cInfo->TrainerTemplateId);
|
||||
hasErrored = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::set<uint32>::const_iterator tItr = trainer_ids.begin(); tItr != trainer_ids.end(); ++tItr)
|
||||
sLog.outErrorDb("Table `npc_trainer_template` has trainer template %u not used by any trainers ", *tItr);
|
||||
|
||||
if (hasErrored || !trainer_ids.empty()) // Append extra line in case of reported errors
|
||||
sLog.outString();
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadVendors(char const* tableName, bool isTemplates)
|
||||
|
|
@ -9497,7 +9506,7 @@ void ObjectMgr::LoadVendorTemplates()
|
|||
if (m_mCacheVendorTemplateItemMap.find(cInfo->VendorTemplateId) != m_mCacheVendorTemplateItemMap.end())
|
||||
vendor_ids.erase(cInfo->VendorTemplateId);
|
||||
else
|
||||
sLog.outErrorDb("Creature (Entry: %u) has vendor_id = %u for nonexistent vendor template", cInfo->Entry, cInfo->VendorTemplateId);
|
||||
sLog.outErrorDb("Creature (Entry: %u) has VendorTemplateId = %u for nonexistent vendor template", cInfo->Entry, cInfo->VendorTemplateId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9506,6 +9515,56 @@ void ObjectMgr::LoadVendorTemplates()
|
|||
sLog.outErrorDb("Table `npc_vendor_template` has vendor template %u not used by any vendors ", *vItr);
|
||||
}
|
||||
|
||||
/* This function is supposed to take care of three things:
|
||||
* 1) Load Transports on Map or on Continents
|
||||
* 2) Load Active Npcs on Map or Continents
|
||||
* 3) Load Everything dependend on config setting LoadAllGridsOnMaps
|
||||
*
|
||||
* This function is currently WIP, hence parts exist only as draft.
|
||||
*/
|
||||
void ObjectMgr::LoadActiveEntities(Map* _map)
|
||||
{
|
||||
// Special case on startup - load continents
|
||||
if (!_map)
|
||||
{
|
||||
uint32 continents[] = {0, 1, 530, 571};
|
||||
for (int i = 0; i < countof(continents); ++i)
|
||||
{
|
||||
_map = sMapMgr.FindMap(continents[i]);
|
||||
if (!_map)
|
||||
_map = sMapMgr.CreateMap(continents[i], nullptr);
|
||||
|
||||
if (_map)
|
||||
LoadActiveEntities(_map);
|
||||
else
|
||||
sLog.outError("ObjectMgr::LoadActiveEntities - Unable to create Map %u", continents[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Load active objects for _map
|
||||
if (sWorld.isForceLoadMap(_map->GetId()))
|
||||
{
|
||||
for (CreatureDataMap::const_iterator itr = mCreatureDataMap.begin(); itr != mCreatureDataMap.end(); ++itr)
|
||||
{
|
||||
if (itr->second.mapid == _map->GetId())
|
||||
_map->ForceLoadGrid(itr->second.posX, itr->second.posY);
|
||||
}
|
||||
}
|
||||
else // Normal case - Load all npcs that are active
|
||||
{
|
||||
std::pair<ActiveCreatureGuidsOnMap::const_iterator, ActiveCreatureGuidsOnMap::const_iterator> bounds = m_activeCreatures.equal_range(_map->GetId());
|
||||
for (ActiveCreatureGuidsOnMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
|
||||
{
|
||||
CreatureData const& data = mCreatureDataMap[itr->second];
|
||||
_map->ForceLoadGrid(data.posX, data.posY);
|
||||
}
|
||||
}
|
||||
|
||||
// Load Transports on Map _map
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadNpcGossips()
|
||||
{
|
||||
m_mCacheNpcTextIdMap.clear();
|
||||
|
|
@ -9568,11 +9627,9 @@ void ObjectMgr::LoadGossipMenu(std::set<uint32>& gossipScriptSet)
|
|||
if (!result)
|
||||
{
|
||||
BarGoLink bar(1);
|
||||
|
||||
bar.step();
|
||||
|
||||
sLog.outString();
|
||||
sLog.outErrorDb(">> Loaded gossip_menu, table is empty!");
|
||||
sLog.outString();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -9631,20 +9688,25 @@ void ObjectMgr::LoadGossipMenu(std::set<uint32>& gossipScriptSet)
|
|||
|
||||
delete result;
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString(">> Loaded %u gossip_menu entries", count);
|
||||
|
||||
// post loading tests
|
||||
for (uint32 i = 1; i < sCreatureStorage.GetMaxEntry(); ++i)
|
||||
{
|
||||
if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(i))
|
||||
if (cInfo->GossipMenuId)
|
||||
if (m_mGossipMenusMap.find(cInfo->GossipMenuId) == m_mGossipMenusMap.end())
|
||||
sLog.outErrorDb("Creature (Entry: %u) has gossip_menu_id = %u for nonexistent menu", cInfo->Entry, cInfo->GossipMenuId);
|
||||
sLog.outErrorDb("Creature (Entry: %u) has GossipMenuId = %u for nonexistent menu", cInfo->Entry, cInfo->GossipMenuId);
|
||||
}
|
||||
|
||||
if (!sLog.HasLogFilter(LOG_FILTER_DB_STRICTED_CHECK))
|
||||
{
|
||||
for (SQLStorageBase::SQLSIterator<GameObjectInfo> itr = sGOStorage.getDataBegin<GameObjectInfo>(); itr < sGOStorage.getDataEnd<GameObjectInfo>(); ++itr)
|
||||
if (uint32 menuid = itr->GetGossipMenuId())
|
||||
if (m_mGossipMenusMap.find(menuid) == m_mGossipMenusMap.end())
|
||||
ERROR_DB_STRICT_LOG("Gameobject (Entry: %u) has gossip_menu_id = %u for nonexistent menu", itr->id, menuid);
|
||||
sLog.outErrorDb("Gameobject (Entry: %u) has gossip_menu_id = %u for nonexistent menu", itr->id, menuid);
|
||||
}
|
||||
|
||||
sLog.outString(">> Loaded %u gossip_menu entries", count);
|
||||
sLog.outString();
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
||||
|
|
@ -9660,11 +9722,9 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
if (!result)
|
||||
{
|
||||
BarGoLink bar(1);
|
||||
|
||||
bar.step();
|
||||
|
||||
sLog.outString();
|
||||
sLog.outErrorDb(">> Loaded gossip_menu_option, table is empty!");
|
||||
sLog.outString();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -9770,7 +9830,7 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
}
|
||||
|
||||
if (found_menu_uses && !found_flags_uses)
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has `npc_option_NpcFlags` = %u but creatures using this menu does not have corresponding`NpcFlags`. Option will not accessible in game.", gMenuItem.menu_id, gMenuItem.id, gMenuItem.npc_option_NpcFlags);
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has `npc_option_npcflag` = %u but creatures using this menu does not have corresponding `NpcFlags`. Option will not accessible in game.", gMenuItem.menu_id, gMenuItem.id, gMenuItem.npc_option_NpcFlags);
|
||||
}
|
||||
|
||||
if (gMenuItem.action_poi_id && !GetPointOfInterest(gMenuItem.action_poi_id))
|
||||
|
|
@ -9804,7 +9864,6 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
m_mGossipMenuItemsMap.insert(GossipMenuItemsMap::value_type(gMenuItem.menu_id, gMenuItem));
|
||||
|
||||
++count;
|
||||
|
||||
}
|
||||
while (result->NextRow());
|
||||
|
||||
|
|
@ -9816,8 +9875,8 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
sLog.outErrorDb("Table `gossip_menu` contain unused (in creature or GO or menu options) menu id %u.", *itr);
|
||||
}
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString(">> Loaded %u gossip_menu_option entries", count);
|
||||
sLog.outString();
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadGossipMenus()
|
||||
|
|
|
|||
|
|
@ -831,6 +831,9 @@ class ObjectMgr
|
|||
void LoadTrainerTemplates();
|
||||
void LoadTrainers() { LoadTrainers("npc_trainer", false); }
|
||||
|
||||
/// @param _map Map* of the map for which to load active entities. If nullptr active entities on continents are loaded
|
||||
void LoadActiveEntities(Map* _map);
|
||||
|
||||
void LoadVehicleAccessory();
|
||||
|
||||
std::string GeneratePetName(uint32 entry);
|
||||
|
|
@ -1340,10 +1343,13 @@ class ObjectMgr
|
|||
HalfNameMap PetHalfName0;
|
||||
HalfNameMap PetHalfName1;
|
||||
|
||||
typedef std::multimap<uint32 /*mapId*/, uint32 /*guid*/> ActiveCreatureGuidsOnMap;
|
||||
|
||||
// Array to store creature stats, Max creature level + 1 (for data alignement with in game level)
|
||||
CreatureClassLvlStats m_creatureClassLvlStats[DEFAULT_MAX_CREATURE_LEVEL + 1][MAX_CREATURE_CLASS][MAX_EXPANSION + 1];
|
||||
|
||||
MapObjectGuids mMapObjectGuids;
|
||||
ActiveCreatureGuidsOnMap m_activeCreatures;
|
||||
CreatureDataMap mCreatureDataMap;
|
||||
CreatureLocaleMap mCreatureLocaleMap;
|
||||
GameObjectDataMap mGameObjectDataMap;
|
||||
|
|
|
|||
|
|
@ -504,6 +504,7 @@ void Pet::SetDeathState(DeathState s) // overwrite virtual
|
|||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
|
||||
CastPetAuras(true);
|
||||
}
|
||||
CastOwnerTalentAuras();
|
||||
}
|
||||
|
||||
void Pet::Update(uint32 update_diff, uint32 diff)
|
||||
|
|
@ -2091,6 +2092,40 @@ void Pet::SynchronizeLevelWithOwner()
|
|||
}
|
||||
}
|
||||
|
||||
void Pet::SetModeFlags(PetModeFlags mode)
|
||||
{
|
||||
m_petModeFlags = mode;
|
||||
|
||||
Unit* owner = GetOwner();
|
||||
if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
WorldPacket data(SMSG_PET_MODE, 12);
|
||||
data << GetObjectGuid();
|
||||
data << uint32(m_petModeFlags);
|
||||
((Player*)owner)->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void Pet::SetStayPosition(bool stay)
|
||||
{
|
||||
if (stay)
|
||||
{
|
||||
m_stayPosX = GetPositionX();
|
||||
m_stayPosY = GetPositionY();
|
||||
m_stayPosZ = GetPositionZ();
|
||||
m_stayPosO = GetOrientation();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stayPosX = 0;
|
||||
m_stayPosY = 0;
|
||||
m_stayPosZ = 0;
|
||||
m_stayPosO = 0;
|
||||
}
|
||||
|
||||
m_stayPosSet = stay;
|
||||
}
|
||||
|
||||
void Pet::ApplyModeFlags(PetModeFlags mode, bool apply)
|
||||
{
|
||||
if (apply)
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ class Pet : public Creature
|
|||
bool CanTakeMoreActiveSpells(uint32 SpellIconID);
|
||||
void ToggleAutocast(uint32 spellid, bool apply);
|
||||
|
||||
void SetModeFlags(PetModeFlags mode);
|
||||
void ApplyModeFlags(PetModeFlags mode, bool apply);
|
||||
PetModeFlags GetModeFlags() const { return m_petModeFlags; }
|
||||
|
||||
|
|
@ -231,6 +232,25 @@ class Pet : public Creature
|
|||
bool removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab = true);
|
||||
void CleanupActionBar();
|
||||
|
||||
bool m_retreating;
|
||||
|
||||
void SetIsRetreating(bool retreating = false) { m_retreating = retreating; }
|
||||
bool GetIsRetreating() { return m_retreating; }
|
||||
|
||||
bool m_stayPosSet;
|
||||
float m_stayPosX;
|
||||
float m_stayPosY;
|
||||
float m_stayPosZ;
|
||||
float m_stayPosO;
|
||||
|
||||
void SetStayPosition(bool stay = false);
|
||||
bool IsStayPosSet() { return m_stayPosSet; }
|
||||
|
||||
float GetStayPosX() { return m_stayPosX; }
|
||||
float GetStayPosY() { return m_stayPosY; }
|
||||
float GetStayPosZ() { return m_stayPosZ; }
|
||||
float GetStayPosO() { return m_stayPosO; }
|
||||
|
||||
PetSpellMap m_spells;
|
||||
AutoSpellList m_autospells;
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ void PetAI::MoveInLineOfSight(Unit* u)
|
|||
return;
|
||||
|
||||
if (u->IsTargetableForAttack() && m_creature->IsHostileTo(u) &&
|
||||
u->isInAccessablePlaceFor(m_creature))
|
||||
u->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
float attackRadius = m_creature->GetAttackDistance(u);
|
||||
if (m_creature->IsWithinDistInMap(u, attackRadius) && m_creature->GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE)
|
||||
|
|
|
|||
|
|
@ -346,6 +346,12 @@ void TradeData::SetMoney(uint64 money)
|
|||
if (m_money == money)
|
||||
return;
|
||||
|
||||
if (money > m_player->GetMoney())
|
||||
{
|
||||
m_player->GetSession()->SendTradeStatus(TRADE_STATUS_CLOSE_WINDOW);
|
||||
return;
|
||||
}
|
||||
|
||||
m_money = money;
|
||||
|
||||
SetAccepted(false);
|
||||
|
|
@ -1264,19 +1270,17 @@ void Player::Update(uint32 update_diff, uint32 p_time)
|
|||
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}// Speed collect rest bonus (section/in hour)
|
||||
|
||||
if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING))
|
||||
{
|
||||
if (roll_chance_i(3) && GetTimeInnEnter() > 0) // Freeze update
|
||||
if (GetTimeInnEnter() > 0) // Freeze update
|
||||
{
|
||||
time_t time_inn = time(NULL) - GetTimeInnEnter();
|
||||
time_t time_inn = now - GetTimeInnEnter();
|
||||
if (time_inn >= 10) // Freeze update
|
||||
{
|
||||
float bubble = 0.125f * sWorld.getConfig(CONFIG_FLOAT_RATE_REST_INGAME);
|
||||
// Speed collect rest bonus (section/in hour)
|
||||
SetRestBonus(float(GetRestBonus() + time_inn * (GetUInt32Value(PLAYER_NEXT_LEVEL_XP) / 72000) * bubble));
|
||||
UpdateInnerTime(time(NULL));
|
||||
SetRestBonus(GetRestBonus() + ComputeRest(time_inn));
|
||||
UpdateInnerTime(now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2888,7 +2892,7 @@ void Player::InitStatsForLevel(bool reapplyMods)
|
|||
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK | PLAYER_FLAGS_DND | PLAYER_FLAGS_GM | PLAYER_FLAGS_GHOST);
|
||||
|
||||
RemoveStandFlags(UNIT_STAND_FLAGS_ALL); // one form stealth modified bytes
|
||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP | UNIT_BYTE2_FLAG_SANCTUARY);
|
||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP | UNIT_BYTE2_FLAG_SUPPORTABLE);
|
||||
|
||||
// restore if need some important flags
|
||||
SetUInt32Value(PLAYER_FIELD_BYTES2, 0); // flags empty by default
|
||||
|
|
@ -4147,14 +4151,14 @@ void Player::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
|
|||
{
|
||||
for (int i = 0; i < EQUIPMENT_SLOT_END; ++i)
|
||||
{
|
||||
if (m_items[i] == NULL)
|
||||
if (m_items[i] == nullptr)
|
||||
continue;
|
||||
|
||||
m_items[i]->BuildCreateUpdateBlockForPlayer(data, target);
|
||||
}
|
||||
for (int i = INVENTORY_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
{
|
||||
if (m_items[i] == NULL)
|
||||
if (m_items[i] == nullptr)
|
||||
continue;
|
||||
|
||||
m_items[i]->BuildCreateUpdateBlockForPlayer(data, target);
|
||||
|
|
@ -4555,6 +4559,38 @@ void Player::SetWaterWalk(bool enable)
|
|||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void Player::SetLevitate(bool enable)
|
||||
{
|
||||
WorldPacket data;
|
||||
BuildMoveLevitatePacket(&data, enable, 0);
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void Player::SetCanFly(bool enable)
|
||||
{
|
||||
WorldPacket data;
|
||||
BuildMoveSetCanFlyPacket(&data, enable, 0);
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void Player::SetFeatherFall(bool enable)
|
||||
{
|
||||
WorldPacket data;
|
||||
BuildMoveFeatherFallPacket(&data, enable, 0);
|
||||
SendMessageToSet(&data, true);
|
||||
|
||||
// start fall from current height
|
||||
if (!enable)
|
||||
SetFallInformation(0, GetPositionZ());
|
||||
}
|
||||
|
||||
void Player::SetHover(bool enable)
|
||||
{
|
||||
WorldPacket data;
|
||||
BuildMoveHoverPacket(&data, enable, 0);
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
/* Preconditions:
|
||||
- a resurrectable corpse must not be loaded for the player (only bones)
|
||||
- the player must be in world
|
||||
|
|
@ -6184,9 +6220,6 @@ bool Player::SetPosition(float x, float y, float z, float orientation, bool tele
|
|||
// group update
|
||||
if (GetGroup() && (old_x != x || old_y != y))
|
||||
SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION);
|
||||
|
||||
if (GetTrader() && !IsWithinDistInMap(GetTrader(), INTERACTION_DISTANCE))
|
||||
GetSession()->SendCancelTrade(); // will close both side trade windows
|
||||
}
|
||||
|
||||
if (m_positionStatusUpdateTimer) // Update position's state only on interval
|
||||
|
|
@ -6966,13 +6999,13 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
|
|||
|
||||
if (zone->flags & AREA_FLAG_SANCTUARY) // in sanctuary
|
||||
{
|
||||
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
|
||||
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE);
|
||||
if (sWorld.IsFFAPvPRealm())
|
||||
SetFFAPvP(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
|
||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE);
|
||||
}
|
||||
|
||||
if (zone->flags & AREA_FLAG_CAPITAL) // in capital city
|
||||
|
|
@ -7483,9 +7516,9 @@ void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change)
|
|||
else
|
||||
{
|
||||
// at un-apply remove all spells (not only at-apply, so any at-use active affects from item and etc)
|
||||
// except with at-use with negative charges, so allow consuming item spells (including with extra flag that prevent consume really)
|
||||
// except on form change and with at-use with negative charges, so allow consuming item spells (including with extra flag that prevent consume really)
|
||||
// applied to player after item remove from equip slot
|
||||
if (spellData.SpellTrigger == ITEM_SPELLTRIGGER_ON_USE && spellData.SpellCharges < 0)
|
||||
if (spellData.SpellTrigger == ITEM_SPELLTRIGGER_ON_USE && (form_change || spellData.SpellCharges < 0))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -14004,6 +14037,10 @@ bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) const
|
|||
return true;
|
||||
|
||||
// each-from-all exclusive group ( < 0)
|
||||
// given a group with 2+ quests, and one of those has a branch that is not restricted by the group, return true
|
||||
if (qInfo->GetPrevQuestId() != 0 && qPrevInfo->GetNextQuestId() != qInfo->GetPrevQuestId())
|
||||
return true;
|
||||
|
||||
// can be start if only all quests in prev quest exclusive group completed and rewarded
|
||||
ExclusiveQuestGroupsMapBounds bounds = sObjectMgr.GetExclusiveQuestGroupsMapBounds(qPrevInfo->GetExclusiveGroup());
|
||||
|
||||
|
|
@ -14037,6 +14074,11 @@ bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) const
|
|||
if (qPrevInfo->GetExclusiveGroup() >= 0)
|
||||
return true;
|
||||
|
||||
// each-from-all exclusive group ( < 0)
|
||||
// given a group with 2+ quests, and one of those has a branch that is not restricted by the group, return true
|
||||
if (qInfo->GetPrevQuestId() != 0 && qPrevInfo->GetNextQuestId() != abs(qInfo->GetPrevQuestId()))
|
||||
return true;
|
||||
|
||||
// each-from-all exclusive group ( < 0)
|
||||
// can be start if only all quests in prev quest exclusive group active
|
||||
ExclusiveQuestGroupsMapBounds bounds = sObjectMgr.GetExclusiveQuestGroupsMapBounds(qPrevInfo->GetExclusiveGroup());
|
||||
|
|
@ -15494,7 +15536,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder)
|
|||
m_bgData.bgTypeID = currentBg->GetTypeID(); // bg data not marked as modified
|
||||
|
||||
// join player to battleground group
|
||||
currentBg->EventPlayerLoggedIn(this, GetObjectGuid());
|
||||
currentBg->EventPlayerLoggedIn(this);
|
||||
currentBg->AddOrSetPlayerToCorrectBgGroup(this, GetObjectGuid(), m_bgData.bgTeam);
|
||||
|
||||
SetInviteForBattleGroundQueueType(bgQueueTypeId, currentBg->GetInstanceID());
|
||||
|
|
@ -15722,17 +15764,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder)
|
|||
m_rest_bonus = fields[21].GetFloat();
|
||||
|
||||
if (time_diff > 0)
|
||||
{
|
||||
// speed collect rest bonus in offline, in logout, far from tavern, city (section/in hour)
|
||||
float bubble0 = 0.031f;
|
||||
// speed collect rest bonus in offline, in logout, in tavern, city (section/in hour)
|
||||
float bubble1 = 0.125f;
|
||||
float bubble = fields[23].GetUInt32() > 0
|
||||
? bubble1 * sWorld.getConfig(CONFIG_FLOAT_RATE_REST_OFFLINE_IN_TAVERN_OR_CITY)
|
||||
: bubble0 * sWorld.getConfig(CONFIG_FLOAT_RATE_REST_OFFLINE_IN_WILDERNESS);
|
||||
|
||||
SetRestBonus(GetRestBonus() + time_diff * ((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP) / 72000)*bubble);
|
||||
}
|
||||
SetRestBonus(GetRestBonus() + ComputeRest(time_diff, true, (fields[23].GetInt32() > 0)));
|
||||
|
||||
// load skills after InitStatsForLevel because it triggering aura apply also
|
||||
_LoadSkills(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSKILLS));
|
||||
|
|
@ -15933,6 +15965,43 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Player::IsTappedByMeOrMyGroup(Creature* creature)
|
||||
{
|
||||
/* Nobody tapped the monster (solo kill by another NPC) */
|
||||
if (!creature->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TAPPED))
|
||||
{ return false; }
|
||||
|
||||
/* If there is a loot recipient, assign it to recipient */
|
||||
if (Player* recipient = creature->GetLootRecipient())
|
||||
{
|
||||
/* See if we're in a group */
|
||||
if (Group* plr_group = recipient->GetGroup())
|
||||
{
|
||||
/* Recipient is in a group... but is it ours? */
|
||||
if (Group* my_group = GetGroup())
|
||||
{
|
||||
/* Check groups are the same */
|
||||
if (plr_group != my_group)
|
||||
{ return false; } // Cheater, deny loot
|
||||
}
|
||||
else
|
||||
{ return false; } // We're not in a group, probably cheater
|
||||
|
||||
/* We're in the looters group, so mob is tapped by us */
|
||||
return true;
|
||||
}
|
||||
/* We're not in a group, check to make sure we're the recipient (prevent cheaters) */
|
||||
else if (recipient == this)
|
||||
{ return true; }
|
||||
}
|
||||
else
|
||||
/* Don't know what happened to the recipient, probably disconnected
|
||||
* Either way, it isn't us, so mark as tapped */
|
||||
{ return false; }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Player::isAllowedToLoot(Creature* creature)
|
||||
{
|
||||
// never tapped by any (mob solo kill)
|
||||
|
|
@ -21716,6 +21785,123 @@ void Player::SetTitle(CharTitlesEntry const* title, bool lost)
|
|||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void Player::UpdateRuneRegen(RuneType rune)
|
||||
{
|
||||
if (rune >= RUNE_DEATH)
|
||||
return;
|
||||
|
||||
RuneType actualRune = rune;
|
||||
float cooldown = RUNE_BASE_COOLDOWN;
|
||||
for (uint8 i = 0; i < MAX_RUNES; i += 2)
|
||||
{
|
||||
if (GetBaseRune(i) != rune)
|
||||
continue;
|
||||
|
||||
uint32 cd = GetRuneCooldown(i);
|
||||
uint32 secondRuneCd = GetRuneCooldown(i + 1);
|
||||
if (!cd && !secondRuneCd)
|
||||
actualRune = GetCurrentRune(i);
|
||||
else if (secondRuneCd && (cd > secondRuneCd || !cd))
|
||||
{
|
||||
cooldown = GetBaseRuneCooldown(i + 1);
|
||||
actualRune = GetCurrentRune(i + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cooldown = GetBaseRuneCooldown(i);
|
||||
actualRune = GetCurrentRune(i);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
float auraMod = 1.0f;
|
||||
Unit::AuraList const& regenAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
|
||||
for (Unit::AuraList::const_iterator i = regenAuras.begin(); i != regenAuras.end(); ++i)
|
||||
if ((*i)->GetMiscValue() == POWER_RUNE && (*i)->GetSpellEffect()->EffectMiscValueB == rune)
|
||||
auraMod *= (100.0f + (*i)->GetModifier()->m_amount) / 100.0f;
|
||||
|
||||
// Unholy Presence
|
||||
if (Aura* aura = GetAura(48265, EFFECT_INDEX_0))
|
||||
auraMod *= (100.0f + aura->GetModifier()->m_amount) / 100.0f;
|
||||
|
||||
// Runic Corruption
|
||||
if (Aura* aura = GetAura(51460, EFFECT_INDEX_0))
|
||||
auraMod *= (100.0f + aura->GetModifier()->m_amount) / 100.0f;
|
||||
|
||||
float hastePct = (100.0f - GetRatingBonusValue(CR_HASTE_MELEE)) / 100.0f;
|
||||
if (hastePct < 0)
|
||||
hastePct = 1.0f;
|
||||
|
||||
cooldown *= hastePct / auraMod;
|
||||
|
||||
float value = float(1 * IN_MILLISECONDS) / cooldown;
|
||||
SetFloatValue(PLAYER_RUNE_REGEN_1 + uint8(actualRune), value);
|
||||
}
|
||||
|
||||
void Player::UpdateRuneRegen()
|
||||
{
|
||||
for (uint8 i = 0; i < NUM_RUNE_TYPES; ++i)
|
||||
UpdateRuneRegen(RuneType(i));
|
||||
}
|
||||
|
||||
uint8 Player::GetRuneCooldownFraction(uint8 index) const
|
||||
{
|
||||
uint16 baseCd = GetBaseRuneCooldown(index);
|
||||
if (!baseCd || !GetRuneCooldown(index))
|
||||
return 255;
|
||||
else if (baseCd == GetRuneCooldown(index))
|
||||
return 0;
|
||||
|
||||
return uint8(float(baseCd - GetRuneCooldown(index)) / baseCd * 255);
|
||||
}
|
||||
|
||||
void Player::AddRuneByAuraEffect(uint8 index, RuneType newType, Aura const* aura)
|
||||
{
|
||||
// Item - Death Knight T11 DPS 4P Bonus
|
||||
if (newType == RUNE_DEATH && HasAura(90459))
|
||||
CastSpell(this, 90507, true); // Death Eater
|
||||
|
||||
SetRuneConvertAura(index, aura); ConvertRune(index, newType);
|
||||
}
|
||||
|
||||
void Player::RemoveRunesByAuraEffect(Aura const* aura)
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
if (m_runes->runes[i].ConvertAura == aura)
|
||||
{
|
||||
ConvertRune(i, GetBaseRune(i));
|
||||
SetRuneConvertAura(i, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::RestoreBaseRune(uint8 index)
|
||||
{
|
||||
Aura const* aura = m_runes->runes[index].ConvertAura;
|
||||
// If rune was converted by a non-pasive aura that still active we should keep it converted
|
||||
if (aura && !IsPassiveSpell(aura->GetSpellProto()))
|
||||
return;
|
||||
|
||||
// Blood of the North
|
||||
if (aura->GetId() == 54637 && HasAura(54637))
|
||||
return;
|
||||
|
||||
ConvertRune(index, GetBaseRune(index));
|
||||
SetRuneConvertAura(index, NULL);
|
||||
// Don't drop passive talents providing rune convertion
|
||||
if (!aura || aura->GetModifier()->m_auraname != SPELL_AURA_CONVERT_RUNE)
|
||||
return;
|
||||
|
||||
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
||||
if (aura == m_runes->runes[i].ConvertAura)
|
||||
return;
|
||||
|
||||
if (Unit* target = aura->GetTarget())
|
||||
target->RemoveSpellAuraHolder(const_cast<Aura*>(aura)->GetHolder());
|
||||
}
|
||||
|
||||
void Player::ConvertRune(uint8 index, RuneType newType)
|
||||
{
|
||||
SetCurrentRune(index, newType);
|
||||
|
|
@ -21749,7 +21935,7 @@ void Player::ResyncRunes()
|
|||
for (uint32 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
data << uint8(GetCurrentRune(i)); // rune type
|
||||
data << uint8(255 - (GetRuneCooldown(i) * 51)); // passed cooldown time (0-255)
|
||||
data << uint8(GetRuneCooldownFraction(i));
|
||||
}
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
|
@ -21761,16 +21947,6 @@ void Player::AddRunePower(uint8 index)
|
|||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
static RuneType runeSlotTypes[MAX_RUNES] =
|
||||
{
|
||||
/*0*/ RUNE_BLOOD,
|
||||
/*1*/ RUNE_BLOOD,
|
||||
/*2*/ RUNE_UNHOLY,
|
||||
/*3*/ RUNE_UNHOLY,
|
||||
/*4*/ RUNE_FROST,
|
||||
/*5*/ RUNE_FROST
|
||||
};
|
||||
|
||||
void Player::InitRunes()
|
||||
{
|
||||
if (getClass() != CLASS_DEATH_KNIGHT)
|
||||
|
|
@ -24066,6 +24242,77 @@ bool Player::FitArmorSpecializationRules(SpellEntry const * spellProto) const
|
|||
return true;
|
||||
}
|
||||
|
||||
float Player::ComputeRest(time_t timePassed, bool offline /*= false*/, bool inRestPlace /*= false*/)
|
||||
{
|
||||
// Every 8h in resting zone we gain a bubble
|
||||
// A bubble is 5% of the total xp so there is 20 bubbles
|
||||
// So we gain (total XP/20 every 8h) (8h = 288800 sec)
|
||||
// (TotalXP/20)/28800; simplified to (TotalXP/576000) per second
|
||||
// Client automatically double the value sent so we have to divide it by 2
|
||||
// So final formula (TotalXP/1152000)
|
||||
float bonus = timePassed * (GetUInt32Value(PLAYER_NEXT_LEVEL_XP) / 1152000.0f); // Get the gained rest xp for given second
|
||||
if (!offline)
|
||||
bonus *= sWorld.getConfig(CONFIG_FLOAT_RATE_REST_INGAME); // Apply the custom setting
|
||||
else
|
||||
{
|
||||
if (inRestPlace)
|
||||
bonus *= sWorld.getConfig(CONFIG_FLOAT_RATE_REST_OFFLINE_IN_TAVERN_OR_CITY);
|
||||
else
|
||||
bonus *= sWorld.getConfig(CONFIG_FLOAT_RATE_REST_OFFLINE_IN_WILDERNESS) / 4.0f; // bonus is reduced by 4 when not in rest place
|
||||
}
|
||||
return bonus;
|
||||
}
|
||||
|
||||
float Player::GetCollisionHeight(bool mounted) const
|
||||
{
|
||||
if (mounted)
|
||||
{
|
||||
// mounted case
|
||||
CreatureDisplayInfoEntry const* mountDisplayInfo = sCreatureDisplayInfoStore.LookupEntry(GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID));
|
||||
if (!mountDisplayInfo)
|
||||
return GetCollisionHeight(false);
|
||||
|
||||
CreatureModelDataEntry const* mountModelData = sCreatureModelDataStore.LookupEntry(mountDisplayInfo->ModelId);
|
||||
if (!mountModelData)
|
||||
return GetCollisionHeight(false);
|
||||
|
||||
CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(GetNativeDisplayId());
|
||||
if (!displayInfo)
|
||||
{
|
||||
sLog.outError("GetCollisionHeight::Unable to find CreatureDisplayInfoEntry for %u", GetNativeDisplayId());
|
||||
return 0;
|
||||
}
|
||||
CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(displayInfo->ModelId);
|
||||
if (!modelData)
|
||||
{
|
||||
sLog.outError("GetCollisionHeight::Unable to find CreatureModelDataEntry for %u", displayInfo->ModelId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float scaleMod = GetObjectScale(); // 99% sure about this
|
||||
|
||||
return scaleMod * mountModelData->MountHeight + modelData->CollisionHeight * 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// use native model collision height in dismounted case
|
||||
CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(GetNativeDisplayId());
|
||||
if (!displayInfo)
|
||||
{
|
||||
sLog.outError("GetCollisionHeight::Unable to find CreatureDisplayInfoEntry for %u", GetNativeDisplayId());
|
||||
return 0;
|
||||
}
|
||||
CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(displayInfo->ModelId);
|
||||
if (!modelData)
|
||||
{
|
||||
sLog.outError("GetCollisionHeight::Unable to find CreatureModelDataEntry for %u", displayInfo->ModelId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return modelData->CollisionHeight;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::SendPetitionSignResult(ObjectGuid petitionGuid, Player* player, uint32 result)
|
||||
{
|
||||
WorldPacket data(SMSG_PETITION_SIGN_RESULTS, 8 + 8 + 4);
|
||||
|
|
|
|||
|
|
@ -353,7 +353,12 @@ struct Areas
|
|||
};
|
||||
|
||||
#define MAX_RUNES 6
|
||||
#define RUNE_COOLDOWN (2*5*IN_MILLISECONDS) // msec
|
||||
|
||||
enum RuneCooldowns
|
||||
{
|
||||
RUNE_BASE_COOLDOWN = 10000,
|
||||
RUNE_MISS_COOLDOWN = 1500 // cooldown applied on runes when the spell misses
|
||||
};
|
||||
|
||||
enum RuneType
|
||||
{
|
||||
|
|
@ -364,17 +369,30 @@ enum RuneType
|
|||
NUM_RUNE_TYPES = 4
|
||||
};
|
||||
|
||||
static RuneType runeSlotTypes[MAX_RUNES] =
|
||||
{
|
||||
/*0*/ RUNE_BLOOD,
|
||||
/*1*/ RUNE_BLOOD,
|
||||
/*2*/ RUNE_UNHOLY,
|
||||
/*3*/ RUNE_UNHOLY,
|
||||
/*4*/ RUNE_FROST,
|
||||
/*5*/ RUNE_FROST
|
||||
};
|
||||
|
||||
struct RuneInfo
|
||||
{
|
||||
uint8 BaseRune;
|
||||
uint8 CurrentRune;
|
||||
uint16 BaseCooldown;
|
||||
uint16 Cooldown; // msec
|
||||
Aura const* ConvertAura;
|
||||
};
|
||||
|
||||
struct Runes
|
||||
{
|
||||
RuneInfo runes[MAX_RUNES];
|
||||
uint8 runeState; // mask of available runes
|
||||
uint32 lastUsedRuneMask;
|
||||
|
||||
void SetRuneState(uint8 index, bool set = true)
|
||||
{
|
||||
|
|
@ -1191,6 +1209,15 @@ class Player : public Unit
|
|||
}
|
||||
void SetRestBonus(float rest_bonus_new);
|
||||
|
||||
/**
|
||||
* \brief: compute rest bonus
|
||||
* \param: time_t timePassed > time from last check
|
||||
* \param: bool offline > is the player was offline?
|
||||
* \param: bool inRestPlace > if it was offline, is the player was in city/tavern/inn?
|
||||
* \returns: float
|
||||
**/
|
||||
float ComputeRest(time_t timePassed, bool offline = false, bool inRestPlace = false);
|
||||
|
||||
RestType GetRestType() const
|
||||
{
|
||||
return rest_type;
|
||||
|
|
@ -1539,6 +1566,9 @@ class Player : public Unit
|
|||
void AddTimedQuest(uint32 quest_id) { m_timedquests.insert(quest_id); }
|
||||
void RemoveTimedQuest(uint32 quest_id) { m_timedquests.erase(quest_id); }
|
||||
|
||||
//! Return collision height sent to client
|
||||
float GetCollisionHeight(bool mounted) const;
|
||||
|
||||
/*********************************************************/
|
||||
/*** LOAD SYSTEM ***/
|
||||
/*********************************************************/
|
||||
|
|
@ -2058,6 +2088,10 @@ class Player : public Unit
|
|||
StopMirrorTimer(FIRE_TIMER);
|
||||
}
|
||||
|
||||
void SetLevitate(bool enable) override;
|
||||
void SetCanFly(bool enable) override;
|
||||
void SetFeatherFall(bool enable) override;
|
||||
void SetHover(bool enable) override;
|
||||
void SetRoot(bool enable) override;
|
||||
void SetWaterWalk(bool enable) override;
|
||||
|
||||
|
|
@ -2371,6 +2405,7 @@ class Player : public Unit
|
|||
bool isMoving() const { return m_movementInfo.HasMovementFlag(movementFlagsMask); }
|
||||
bool isMovingOrTurning() const { return m_movementInfo.HasMovementFlag(movementOrTurningFlagsMask); }
|
||||
|
||||
bool CanSwim() const { return true; }
|
||||
bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_CAN_FLY); }
|
||||
bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_FLYING); }
|
||||
bool IsFreeFlying() const { return HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED) || HasAuraType(SPELL_AURA_FLY); }
|
||||
|
|
@ -2499,6 +2534,7 @@ class Player : public Unit
|
|||
GridReference<Player>& GetGridRef() { return m_gridRef; }
|
||||
MapReference& GetMapRef() { return m_mapRef; }
|
||||
|
||||
bool IsTappedByMeOrMyGroup(Creature* creature);
|
||||
bool isAllowedToLoot(Creature* creature);
|
||||
|
||||
DeclinedName const* GetDeclinedNames() const { return m_declinedname; }
|
||||
|
|
@ -2508,10 +2544,22 @@ class Player : public Unit
|
|||
RuneType GetBaseRune(uint8 index) const { return RuneType(m_runes->runes[index].BaseRune); }
|
||||
RuneType GetCurrentRune(uint8 index) const { return RuneType(m_runes->runes[index].CurrentRune); }
|
||||
uint16 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; }
|
||||
uint16 GetBaseRuneCooldown(uint8 index) const { return m_runes->runes[index].BaseCooldown; }
|
||||
uint8 GetRuneCooldownFraction(uint8 index) const;
|
||||
void UpdateRuneRegen(RuneType rune);
|
||||
void UpdateRuneRegen();
|
||||
bool IsBaseRuneSlotsOnCooldown(RuneType runeType) const;
|
||||
void ClearLastUsedRuneMask() { m_runes->lastUsedRuneMask = 0; }
|
||||
bool IsLastUsedRune(uint8 index) const { return (m_runes->lastUsedRuneMask & (1 << index)) != 0; }
|
||||
void SetLastUsedRune(RuneType type) { m_runes->lastUsedRuneMask |= 1 << uint32(type); }
|
||||
void SetBaseRune(uint8 index, RuneType baseRune) { m_runes->runes[index].BaseRune = baseRune; }
|
||||
void SetCurrentRune(uint8 index, RuneType currentRune) { m_runes->runes[index].CurrentRune = currentRune; }
|
||||
void SetRuneCooldown(uint8 index, uint16 cooldown) { m_runes->runes[index].Cooldown = cooldown; m_runes->SetRuneState(index, (cooldown == 0) ? true : false); }
|
||||
void SetBaseRuneCooldown(uint8 index, uint16 cooldown) { m_runes->runes[index].BaseCooldown = cooldown; }
|
||||
void SetRuneConvertAura(uint8 index, Aura const* aura) { m_runes->runes[index].ConvertAura = aura; }
|
||||
void AddRuneByAuraEffect(uint8 index, RuneType newType, Aura const* aura);
|
||||
void RemoveRunesByAuraEffect(Aura const* aura);
|
||||
void RestoreBaseRune(uint8 index);
|
||||
void ConvertRune(uint8 index, RuneType newType);
|
||||
bool ActivateRunes(RuneType type, uint32 count);
|
||||
void ResyncRunes();
|
||||
|
|
|
|||
|
|
@ -811,6 +811,7 @@ bool IsPositiveEffect(SpellEntry const* spellproto, SpellEffectIndex effIndex)
|
|||
case 13139: // net-o-matic special effect
|
||||
case 23445: // evil twin
|
||||
case 35679: // Protectorate Demolitionist
|
||||
case 37695: // Stanky
|
||||
case 38637: // Nether Exhaustion (red)
|
||||
case 38638: // Nether Exhaustion (green)
|
||||
case 38639: // Nether Exhaustion (blue)
|
||||
|
|
@ -843,6 +844,7 @@ bool IsPositiveEffect(SpellEntry const* spellproto, SpellEffectIndex effIndex)
|
|||
return false;
|
||||
break;
|
||||
case SPELL_AURA_MOD_DAMAGE_TAKEN: // dependent from bas point sign (positive -> negative)
|
||||
case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
|
||||
if (spellEffect->CalculateSimpleValue() < 0)
|
||||
return true;
|
||||
// let check by target modes (for Amplify Magic cases/etc)
|
||||
|
|
@ -1407,7 +1409,7 @@ struct DoSpellProcEvent
|
|||
++count;
|
||||
}
|
||||
|
||||
bool HasEntry(uint32 spellId) { return spe_map.count(spellId) > 0; }
|
||||
bool HasEntry(uint32 spellId) { return spe_map.find(spellId) != spe_map.end(); }
|
||||
bool SetStateToEntry(uint32 spellId) { return (state = spe_map.find(spellId)) != spe_map.end(); }
|
||||
SpellProcEventMap& spe_map;
|
||||
SpellProcEventMap::const_iterator state;
|
||||
|
|
@ -1694,7 +1696,7 @@ void SpellMgr::LoadSpellBonuses()
|
|||
break;
|
||||
}
|
||||
}
|
||||
direct_calc = CalculateDefaultCoefficient(spell, SPELL_DIRECT_DAMAGE) * (isHeal ? 1.88f : 1.0f);
|
||||
direct_calc = CalculateDefaultCoefficient(spell, SPELL_DIRECT_DAMAGE) * (isHeal ? SCALE_SPELLPOWER_HEALING : 1.0f);
|
||||
direct_diff = std::abs(sbe.direct_damage - direct_calc);
|
||||
}
|
||||
|
||||
|
|
@ -1716,7 +1718,7 @@ void SpellMgr::LoadSpellBonuses()
|
|||
break;
|
||||
}
|
||||
}
|
||||
dot_calc = CalculateDefaultCoefficient(spell, DOT) * (isHeal ? 1.88f : 1.0f);
|
||||
dot_calc = CalculateDefaultCoefficient(spell, DOT) * (isHeal ? SCALE_SPELLPOWER_HEALING : 1.0f);
|
||||
dot_diff = std::abs(sbe.dot_damage - dot_calc);
|
||||
}
|
||||
|
||||
|
|
@ -2874,7 +2876,7 @@ SpellEntry const* SpellMgr::SelectAuraRankForLevel(SpellEntry const* spellInfo,
|
|||
break;
|
||||
|
||||
// if found appropriate level
|
||||
if (level + 10 >= spellInfo->GetSpellLevel())
|
||||
if (level + 10 >= nextSpellInfo->GetSpellLevel())
|
||||
return nextSpellInfo;
|
||||
|
||||
// one rank less then
|
||||
|
|
@ -3562,7 +3564,7 @@ void SpellMgr::LoadSpellScriptTarget()
|
|||
{
|
||||
if (itr->spellId == 30427 && !cInfo->SkinningLootId)
|
||||
{
|
||||
sLog.outErrorDb("Table `spell_script_target` has creature %u as a target of spellid 30427, but this creature has no skinLootid. Gas extraction will not work!", cInfo->Entry);
|
||||
sLog.outErrorDb("Table `spell_script_target` has creature %u as a target of spellid 30427, but this creature has no SkinningLootId. Gas extraction will not work!", cInfo->Entry);
|
||||
sSpellScriptTargetStorage.EraseEntry(itr->spellId);
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -976,8 +976,8 @@ uint32 Unit::DealDamage(Unit* pVictim, uint32 damage, CleanDamage const* cleanDa
|
|||
{
|
||||
SpellEntry const* shareSpell = (*itr)->GetSpellProto();
|
||||
uint32 shareDamage = uint32(damage*(*itr)->GetModifier()->m_amount / 100.0f);
|
||||
DealDamageMods(shareTarget, shareDamage, NULL);
|
||||
DealDamage(shareTarget, shareDamage, 0, damagetype, GetSpellSchoolMask(shareSpell), shareSpell, false);
|
||||
DealDamageMods(shareTarget, shareDamage, nullptr);
|
||||
DealDamage(shareTarget, shareDamage, nullptr, damagetype, GetSpellSchoolMask(shareSpell), shareSpell, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1681,9 +1681,11 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage* damageInfo, int32 damage, S
|
|||
{ return; }
|
||||
|
||||
if (!this || !pVictim)
|
||||
{ return; }
|
||||
if (!this->IsAlive() || !pVictim->IsAlive())
|
||||
{ return; }
|
||||
return;
|
||||
|
||||
// units which are not alive cannot deal damage except for dying creatures
|
||||
if ((!this->IsAlive() || !pVictim->IsAlive()) && (this->GetTypeId() != TYPEID_UNIT || this->getDeathState() != DEAD))
|
||||
return;
|
||||
|
||||
// Check spell crit chance
|
||||
bool crit = IsSpellCrit(pVictim, spellInfo, damageSchoolMask, attackType);
|
||||
|
|
@ -3521,7 +3523,7 @@ SpellMissInfo Unit::SpellHitResult(Unit* pVictim, SpellEntry const* spell, bool
|
|||
return SPELL_MISS_EVADE;
|
||||
|
||||
// Check for immune
|
||||
if (pVictim->IsImmuneToSpell(spell, this == pVictim))
|
||||
if (pVictim->IsImmuneToSpell(spell, this == pVictim) && !spell->HasAttribute(SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY))
|
||||
return SPELL_MISS_IMMUNE;
|
||||
|
||||
// All positive spells can`t miss
|
||||
|
|
@ -3530,7 +3532,7 @@ SpellMissInfo Unit::SpellHitResult(Unit* pVictim, SpellEntry const* spell, bool
|
|||
return SPELL_MISS_NONE;
|
||||
|
||||
// Check for immune
|
||||
if (pVictim->IsImmunedToDamage(GetSpellSchoolMask(spell)))
|
||||
if (pVictim->IsImmunedToDamage(GetSpellSchoolMask(spell)) && !spell->HasAttribute(SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY))
|
||||
return SPELL_MISS_IMMUNE;
|
||||
|
||||
// Try victim reflect spell
|
||||
|
|
@ -4027,7 +4029,7 @@ void Unit::SetFacingToObject(WorldObject* pObject)
|
|||
SetFacingTo(GetAngle(pObject));
|
||||
}
|
||||
|
||||
bool Unit::isInAccessablePlaceFor(Creature const* c) const
|
||||
bool Unit::IsInAccessablePlaceFor(Creature const* c) const
|
||||
{
|
||||
if (IsInWater())
|
||||
return c->CanSwim();
|
||||
|
|
@ -5875,7 +5877,7 @@ bool Unit::IsHostileTo(Unit const* unit) const
|
|||
return false;
|
||||
|
||||
// Sanctuary
|
||||
if (pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY))
|
||||
if (pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE))
|
||||
return false;
|
||||
|
||||
// PvP FFA state
|
||||
|
|
@ -5987,7 +5989,7 @@ bool Unit::IsFriendlyTo(Unit const* unit) const
|
|||
return true;
|
||||
|
||||
// Sanctuary
|
||||
if (pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY))
|
||||
if (pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE))
|
||||
return true;
|
||||
|
||||
// PvP FFA state
|
||||
|
|
@ -6661,6 +6663,17 @@ void Unit::EnergizeBySpell(Unit* pVictim, uint32 SpellID, uint32 Damage, Powers
|
|||
pVictim->ModifyPower(powertype, Damage);
|
||||
}
|
||||
|
||||
/** Calculate spell coefficents and level penalties for spell/melee damage or heal
|
||||
*
|
||||
* this is the caster of the spell/ melee attacker
|
||||
* @param spellProto SpellEntry of the used spell
|
||||
* @param total current value onto which the Bonus and level penalty will be calculated
|
||||
* @param benefit additional benefit from ie spellpower-auras
|
||||
* @param ap_benefit additional melee attackpower benefit from auras
|
||||
* @param damagetype what kind of damage
|
||||
* @param donePart calculate for done or taken
|
||||
* @param defCoeffMod default coefficient for additional scaling (i.e. normal player healing SCALE_SPELLPOWER_HEALING)
|
||||
*/
|
||||
int32 Unit::SpellBonusWithCoeffs(SpellEntry const* spellProto, int32 total, int32 benefit, int32 ap_benefit, DamageEffectType damagetype, bool donePart, float defCoeffMod)
|
||||
{
|
||||
// Distribute Damage over multiple effects, reduce by AoE
|
||||
|
|
@ -7119,7 +7132,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* pCaster, SpellEntry const* spellProto,
|
|||
int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(GetSpellSchoolMask(spellProto));
|
||||
|
||||
// apply benefit affected by spell power implicit coeffs and spell level penalties
|
||||
TakenTotal = SpellBonusWithCoeffs(spellProto, TakenTotal, TakenAdvertisedBenefit, 0, damagetype, false);
|
||||
TakenTotal = pCaster->SpellBonusWithCoeffs(spellProto, TakenTotal, TakenAdvertisedBenefit, 0, damagetype, false);
|
||||
|
||||
float tmpDamage = (int32(pdamage) + TakenTotal * int32(stack)) * TakenTotalMod;
|
||||
|
||||
|
|
@ -7568,7 +7581,7 @@ uint32 Unit::SpellHealingBonusDone(Unit* pVictim, SpellEntry const* spellProto,
|
|||
int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(GetSpellSchoolMask(spellProto));
|
||||
|
||||
// apply ap bonus and benefit affected by spell power implicit coeffs and spell level penalties
|
||||
DoneTotal = SpellBonusWithCoeffs(spellProto, DoneTotal, DoneAdvertisedBenefit, 0, damagetype, true, 1.88f);
|
||||
DoneTotal = SpellBonusWithCoeffs(spellProto, DoneTotal, DoneAdvertisedBenefit, 0, damagetype, true, SCALE_SPELLPOWER_HEALING);
|
||||
|
||||
// use float as more appropriate for negative values and percent applying
|
||||
float heal = (healamount + DoneTotal * int32(stack)) * DoneTotalMod;
|
||||
|
|
@ -7612,7 +7625,7 @@ uint32 Unit::SpellHealingBonusTaken(Unit* pCaster, SpellEntry const* spellProto,
|
|||
int32 TakenAdvertisedBenefit = SpellBaseHealingBonusTaken(GetSpellSchoolMask(spellProto));
|
||||
|
||||
// apply benefit affected by spell power implicit coeffs and spell level penalties
|
||||
TakenTotal = SpellBonusWithCoeffs(spellProto, TakenTotal, TakenAdvertisedBenefit, 0, damagetype, false, 1.88f);
|
||||
TakenTotal = pCaster->SpellBonusWithCoeffs(spellProto, TakenTotal, TakenAdvertisedBenefit, 0, damagetype, false, SCALE_SPELLPOWER_HEALING);
|
||||
|
||||
AuraList const& mHealingGet = GetAurasByType(SPELL_AURA_MOD_HEALING_RECEIVED);
|
||||
for (AuraList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i)
|
||||
|
|
@ -8155,7 +8168,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* pCaster, uint32 pdamage, WeaponAttackTy
|
|||
if (!isWeaponDamageBasedSpell)
|
||||
{
|
||||
// apply benefit affected by spell power implicit coeffs and spell level penalties
|
||||
TakenFlat = SpellBonusWithCoeffs(spellProto, 0, TakenFlat, 0, damagetype, false);
|
||||
TakenFlat = pCaster->SpellBonusWithCoeffs(spellProto, 0, TakenFlat, 0, damagetype, false);
|
||||
}
|
||||
|
||||
float tmpDamage = float(int32(pdamage) + TakenFlat * int32(stack)) * TakenPercent;
|
||||
|
|
@ -8257,6 +8270,10 @@ void Unit::Mount(uint32 mount, uint32 spellId)
|
|||
pet->ApplyModeFlags(PET_MODE_DISABLE_ACTIONS, true);
|
||||
}
|
||||
}
|
||||
|
||||
float height = ((Player*)this)->GetCollisionHeight(true);
|
||||
if (height)
|
||||
SendCollisionHeightUpdate(height);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8284,9 +8301,17 @@ void Unit::Unmount(bool from_aura)
|
|||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if (Pet* pet = GetPet())
|
||||
pet->ApplyModeFlags(PET_MODE_DISABLE_ACTIONS, false);
|
||||
{
|
||||
// Get reaction state and display appropriately
|
||||
if (CharmInfo* charmInfo = pet->GetCharmInfo())
|
||||
pet->SetModeFlags(PetModeFlags(charmInfo->GetReactState() | charmInfo->GetCommandState() * 0x100));
|
||||
}
|
||||
else
|
||||
{ ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny(); }
|
||||
((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
|
||||
|
||||
float height = ((Player*)this)->GetCollisionHeight(false);
|
||||
if (height)
|
||||
SendCollisionHeightUpdate(height);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8687,8 +8712,23 @@ bool Unit::IsVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
|
|||
if (m_Visibility == VISIBILITY_OFF)
|
||||
return false;
|
||||
|
||||
// grouped players should always see stealthed party members
|
||||
if (GetTypeId() == TYPEID_PLAYER && u->GetTypeId() == TYPEID_PLAYER)
|
||||
if (((Player*)this)->IsGroupVisibleFor(((Player*)u)) && u->IsFriendlyTo(this))
|
||||
return true;
|
||||
|
||||
// raw invisibility
|
||||
bool invisible = (m_invisibilityMask != 0 || u->m_invisibilityMask != 0);
|
||||
if (u->GetTypeId() == TYPEID_PLAYER) // if object is player with mover, use its visibility masks, so that an invisible player MCing a creature can see stuff
|
||||
{
|
||||
if (Player* player = (Player*)u)
|
||||
{
|
||||
if (Unit* mover=player->GetMover())
|
||||
{
|
||||
invisible= (m_invisibilityMask != 0 || mover->m_invisibilityMask != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// detectable invisibility case
|
||||
if (invisible && (
|
||||
|
|
@ -8705,35 +8745,18 @@ bool Unit::IsVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
|
|||
// special cases for always overwrite invisibility/stealth
|
||||
if (invisible || m_Visibility == VISIBILITY_GROUP_STEALTH)
|
||||
{
|
||||
// non-hostile case
|
||||
if (!u->IsHostileTo(this))
|
||||
{
|
||||
// player see other player with stealth/invisibility only if he in same group or raid or same team (raid/team case dependent from conf setting)
|
||||
if (GetTypeId() == TYPEID_PLAYER && u->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if (((Player*)this)->IsGroupVisibleFor(((Player*)u)))
|
||||
return true;
|
||||
|
||||
// else apply same rules as for hostile case (detecting check for stealth)
|
||||
}
|
||||
}
|
||||
// hostile case
|
||||
else
|
||||
if (u->IsHostileTo(this))
|
||||
{
|
||||
// Hunter mark functionality
|
||||
AuraList const& auras = GetAurasByType(SPELL_AURA_MOD_STALKED);
|
||||
for (AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
|
||||
if ((*iter)->GetCasterGuid() == u->GetObjectGuid())
|
||||
return true;
|
||||
|
||||
// else apply detecting check for stealth
|
||||
}
|
||||
|
||||
// none other cases for detect invisibility, so invisible
|
||||
if (invisible)
|
||||
return false;
|
||||
|
||||
// else apply stealth detecting check
|
||||
}
|
||||
|
||||
// unit got in stealth in this moment and must ignore old detected state
|
||||
|
|
@ -9518,7 +9541,7 @@ bool Unit::SelectHostileTarget()
|
|||
for (AuraList::const_reverse_iterator aura = tauntAuras.rbegin(); aura != tauntAuras.rend(); ++aura)
|
||||
{
|
||||
if ((caster = (*aura)->GetCaster()) && caster->IsInMap(this) &&
|
||||
caster->IsTargetableForAttack() && caster->isInAccessablePlaceFor((Creature*)this) &&
|
||||
caster->IsTargetableForAttack() && caster->IsInAccessablePlaceFor((Creature*)this) &&
|
||||
!IsSecondChoiceTarget(caster, true))
|
||||
{
|
||||
target = caster;
|
||||
|
|
@ -9581,7 +9604,7 @@ bool Unit::SelectHostileTarget()
|
|||
{
|
||||
for (AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr)
|
||||
{
|
||||
if ((*itr)->IsInMap(this) && (*itr)->IsTargetableForAttack() && (*itr)->isInAccessablePlaceFor((Creature*)this))
|
||||
if ((*itr)->IsInMap(this) && (*itr)->IsTargetableForAttack() && (*itr)->IsInAccessablePlaceFor((Creature*)this))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -12156,3 +12179,59 @@ void Unit::BuildMoveFeatherFallPacket(WorldPacket* data, bool apply, uint32 valu
|
|||
}
|
||||
}
|
||||
|
||||
void Unit::BuildMoveHoverPacket(WorldPacket* data, bool apply, uint32 value)
|
||||
{
|
||||
ObjectGuid guid = GetObjectGuid();
|
||||
|
||||
if (apply)
|
||||
{
|
||||
data->Initialize(SMSG_MOVE_SET_HOVER, 8 + 4 + 1);
|
||||
data->WriteGuidMask<1, 4, 2, 3, 0, 5, 6, 7>(guid);
|
||||
data->WriteGuidBytes<5, 4, 1, 2, 3, 6, 0, 7>(guid);
|
||||
*data << uint32(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
data->Initialize(SMSG_MOVE_UNSET_HOVER, 8 + 4 + 1);
|
||||
data->WriteGuidMask<4, 6, 3, 1, 2, 7, 5, 0>(guid);
|
||||
data->WriteGuidBytes<4, 5, 3, 6, 7, 1, 2, 0>(guid);
|
||||
*data << uint32(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::BuildMoveLevitatePacket(WorldPacket* data, bool apply, uint32 value)
|
||||
{
|
||||
ObjectGuid guid = GetObjectGuid();
|
||||
|
||||
if (apply)
|
||||
{
|
||||
data->Initialize(SMSG_MOVE_GRAVITY_ENABLE);
|
||||
data->WriteGuidMask<1, 4, 7, 5, 2, 0, 3, 6>(GetObjectGuid());
|
||||
data->WriteGuidBytes<3>(GetObjectGuid());
|
||||
*data << uint32(value);
|
||||
data->WriteGuidBytes<7, 6, 4, 0, 1, 5, 2>(GetObjectGuid());
|
||||
}
|
||||
else
|
||||
{
|
||||
data->Initialize(SMSG_MOVE_GRAVITY_DISABLE);
|
||||
data->WriteGuidMask<0, 1, 5, 7, 6, 4, 3, 2>(GetObjectGuid());
|
||||
data->WriteGuidBytes<7, 2, 0>(GetObjectGuid());
|
||||
*data << uint32(value);
|
||||
data->WriteGuidBytes<5, 1, 3, 4, 6>(GetObjectGuid());
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::SendCollisionHeightUpdate(float height)
|
||||
{
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
WorldPacket data(SMSG_MOVE_SET_COLLISION_HGT, GetPackGUID().size() + 4 + 4);
|
||||
data.WriteGuidMask<6, 1, 4, 7, 5, 2, 0, 3>(GetObjectGuid());
|
||||
data.WriteGuidBytes<6, 0, 4, 3, 5>(GetObjectGuid());
|
||||
data << uint32(sWorld.GetGameTime()); // Packet counter
|
||||
data.WriteGuidBytes<1, 2, 7>(GetObjectGuid());
|
||||
data << ((Player*)this)->GetCollisionHeight(true);
|
||||
((Player*)this)->GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,8 @@ enum SpellFacingFlags
|
|||
#define BASE_ATTACK_TIME 2000
|
||||
#define BASE_BLOCK_DAMAGE_PERCENT 30
|
||||
|
||||
#define SCALE_SPELLPOWER_HEALING 1.88f
|
||||
|
||||
/**
|
||||
* byte value (UNIT_FIELD_BYTES_1,0).
|
||||
*
|
||||
|
|
@ -225,9 +227,9 @@ enum UnitPVPStateFlags
|
|||
UNIT_BYTE2_FLAG_PVP = 0x01,
|
||||
UNIT_BYTE2_FLAG_UNK1 = 0x02,
|
||||
UNIT_BYTE2_FLAG_FFA_PVP = 0x04,
|
||||
UNIT_BYTE2_FLAG_SANCTUARY = 0x08,
|
||||
UNIT_BYTE2_FLAG_UNK4 = 0x10,
|
||||
UNIT_BYTE2_FLAG_UNK5 = 0x20,
|
||||
UNIT_BYTE2_FLAG_SUPPORTABLE = 0x08, // allows for being targeted for healing/bandaging by friendlies
|
||||
UNIT_BYTE2_FLAG_AURAS = 0x10, // show possitive auras as positive, and allow its dispel
|
||||
UNIT_BYTE2_FLAG_UNK5 = 0x20, // show negative auras as positive, *not* allowing dispel (at least for pets)
|
||||
UNIT_BYTE2_FLAG_UNK6 = 0x40,
|
||||
UNIT_BYTE2_FLAG_UNK7 = 0x80
|
||||
};
|
||||
|
|
@ -596,7 +598,7 @@ enum UnitFlags
|
|||
UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3
|
||||
UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1
|
||||
UNIT_FLAG_UNK_14 = 0x00004000, // 2.0.8
|
||||
UNIT_FLAG_UNK_15 = 0x00008000,
|
||||
UNIT_FLAG_UNK_15 = 0x00008000, // related to jerky movement in water?
|
||||
UNIT_FLAG_UNK_16 = 0x00010000, // removes attackable icon
|
||||
UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok
|
||||
UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok
|
||||
|
|
@ -2399,7 +2401,7 @@ class Unit : public WorldObject
|
|||
|
||||
virtual bool IsInWater() const;
|
||||
virtual bool IsUnderWater() const;
|
||||
bool isInAccessablePlaceFor(Creature const* c) const;
|
||||
bool IsInAccessablePlaceFor(Creature const* c) const;
|
||||
|
||||
void SendHealSpellLog(Unit* pVictim, uint32 SpellID, uint32 Damage, uint32 OverHeal, bool critical = false, uint32 absorb = 0);
|
||||
void SendEnergizeSpellLog(Unit* pVictim, uint32 SpellID, uint32 Damage, Powers powertype);
|
||||
|
|
@ -2656,6 +2658,12 @@ class Unit : public WorldObject
|
|||
bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_LEVITATING); }
|
||||
bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE); }
|
||||
bool IsRooted() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_ROOT); }
|
||||
|
||||
virtual void SetLevitate(bool /*enabled*/) {}
|
||||
virtual void SetSwim(bool /*enabled*/) {}
|
||||
virtual void SetCanFly(bool /*enabled*/) {}
|
||||
virtual void SetFeatherFall(bool /*enabled*/) {}
|
||||
virtual void SetHover(bool /*enabled*/) {}
|
||||
virtual void SetRoot(bool /*enabled*/) {}
|
||||
/**
|
||||
* Changes this \ref Unit s ability to walk on water.
|
||||
|
|
@ -3327,6 +3335,7 @@ class Unit : public WorldObject
|
|||
|
||||
// at any changes to Scale and/or displayId
|
||||
void UpdateModelData();
|
||||
void SendCollisionHeightUpdate(float height);
|
||||
|
||||
DynamicObject* GetDynObject(uint32 spellId, SpellEffectIndex effIndex);
|
||||
DynamicObject* GetDynObject(uint32 spellId);
|
||||
|
|
@ -3485,6 +3494,9 @@ class Unit : public WorldObject
|
|||
|
||||
bool IsLinkingEventTrigger() const { return m_isCreatureLinkingTrigger; }
|
||||
|
||||
virtual bool CanSwim() const = 0;
|
||||
virtual bool CanFly() const = 0;
|
||||
|
||||
bool IsSplineEnabled() const;
|
||||
|
||||
bool IsInWorgenForm(bool inPermanent = false) const;
|
||||
|
|
@ -3496,6 +3508,8 @@ class Unit : public WorldObject
|
|||
void BuildSendPlayVisualPacket(WorldPacket* data, uint32 value, bool impact);
|
||||
void BuildMoveSetCanFlyPacket(WorldPacket* data, bool apply, uint32 value);
|
||||
void BuildMoveFeatherFallPacket(WorldPacket* data, bool apply, uint32 value);
|
||||
void BuildMoveHoverPacket(WorldPacket* data, bool apply, uint32 value);
|
||||
void BuildMoveLevitatePacket(WorldPacket* data, bool apply, uint32 value);
|
||||
|
||||
protected:
|
||||
explicit Unit();
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ void HostileReference::updateOnlineStatus()
|
|||
!getTarget()->IsTaxiFlying()))
|
||||
{
|
||||
Creature* creature = (Creature*) getSourceUnit();
|
||||
online = getTarget()->isInAccessablePlaceFor(creature);
|
||||
online = getTarget()->IsInAccessablePlaceFor(creature);
|
||||
if (!online)
|
||||
{
|
||||
if (creature->AI()->canReachByRangeAttack(getTarget()))
|
||||
|
|
|
|||
|
|
@ -86,7 +86,8 @@ DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore(CinematicSequences
|
|||
DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt);
|
||||
DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore(CreatureDisplayInfoExtrafmt);
|
||||
DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore(CreatureFamilyfmt);
|
||||
DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore(CreatureSpellDatafmt);
|
||||
DBCStorage <CreatureModelDataEntry> sCreatureModelDataStore(CreatureModelDatafmt);
|
||||
DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore(CreatureSpellDatafmt); // sCreatureModelDataStore
|
||||
DBCStorage <CreatureTypeEntry> sCreatureTypeStore(CreatureTypefmt);
|
||||
DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore(CurrencyTypesfmt);
|
||||
|
||||
|
|
@ -516,6 +517,7 @@ void LoadDBCStores(const std::string& dataPath)
|
|||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureDisplayInfoStore, dbcPath,"CreatureDisplayInfo.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureDisplayInfoExtraStore,dbcPath,"CreatureDisplayInfoExtra.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureFamilyStore, dbcPath,"CreatureFamily.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureModelDataStore, dbcPath,"CreatureModelData.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureSpellDataStore, dbcPath,"CreatureSpellData.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureTypeStore, dbcPath,"CreatureType.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCurrencyTypesStore, dbcPath,"CurrencyTypes.dbc");
|
||||
|
|
@ -1004,34 +1006,15 @@ uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId)
|
|||
return mapid;
|
||||
}
|
||||
|
||||
ContentLevels GetContentLevelsForMapAndZone(uint32 mapId, uint32 zoneId)
|
||||
ContentLevels GetContentLevelsForMap(uint32 mapid)
|
||||
{
|
||||
MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
|
||||
MapEntry const* mapEntry = sMapStore.LookupEntry(mapid);
|
||||
if (!mapEntry)
|
||||
return CONTENT_1_60;
|
||||
|
||||
if (mapEntry->rootPhaseMap != -1)
|
||||
mapId = mapEntry->rootPhaseMap;
|
||||
|
||||
switch (mapId)
|
||||
{
|
||||
case 648: // Lost Islands
|
||||
case 654: // Gilneas
|
||||
// exceptions for 648 - Goblin Starter area and 654 - Worgen Starter area
|
||||
if (mapid == 648 || mapid == 654)
|
||||
return CONTENT_1_60;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (zoneId)
|
||||
{
|
||||
case 616: // Mount Hyjal
|
||||
case 4922: // Twilight Highlands
|
||||
case 5034: // Uldum
|
||||
case 5042: // Deepholm
|
||||
return CONTENT_81_85;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mapEntry->Expansion())
|
||||
{
|
||||
|
|
@ -1051,50 +1034,9 @@ ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id)
|
|||
if (ch && ch->ChannelID == channel_id)
|
||||
return ch;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
static ChatChannelsEntry worldCh = { 26, 4, "world" };
|
||||
|
||||
ChatChannelsEntry const* GetChannelEntryFor(const std::string& name)
|
||||
{
|
||||
// not sorted, numbering index from 0
|
||||
for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i)
|
||||
{
|
||||
ChatChannelsEntry const* ch = sChatChannelsStore.LookupEntry(i);
|
||||
if (ch)
|
||||
{
|
||||
// need to remove %s from entryName if it exists before we match
|
||||
std::string entryName(ch->pattern[0]);
|
||||
std::size_t removeString = entryName.find("%s");
|
||||
|
||||
if (removeString != std::string::npos)
|
||||
entryName.replace(removeString, 2, "");
|
||||
|
||||
if (name.find(entryName) != std::string::npos)
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
|
||||
bool compare = true; // hack for world channel, TODO smth!
|
||||
std::string world = "world";
|
||||
for (uint8 i = 0; i < name.length(); ++i)
|
||||
{
|
||||
if (tolower(name[i]) != world[i])
|
||||
{
|
||||
compare = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (compare)
|
||||
return &worldCh;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId)
|
||||
{
|
||||
if (requiredTotemCategoryId==0)
|
||||
|
|
@ -1145,6 +1087,44 @@ bool Map2ZoneCoordinates(float& x, float& y, uint32 zone)
|
|||
return true;
|
||||
}
|
||||
|
||||
ContentLevels GetContentLevelsForMapAndZone(uint32 mapId, uint32 zoneId)
|
||||
{
|
||||
MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
|
||||
if (!mapEntry)
|
||||
return CONTENT_1_60;
|
||||
|
||||
if (mapEntry->rootPhaseMap != -1)
|
||||
mapId = mapEntry->rootPhaseMap;
|
||||
|
||||
switch (mapId)
|
||||
{
|
||||
case 648: // Lost Islands
|
||||
case 654: // Gilneas
|
||||
return CONTENT_1_60;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (zoneId)
|
||||
{
|
||||
case 616: // Mount Hyjal
|
||||
case 4922: // Twilight Highlands
|
||||
case 5034: // Uldum
|
||||
case 5042: // Deepholm
|
||||
return CONTENT_81_85;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mapEntry->Expansion())
|
||||
{
|
||||
default: return CONTENT_1_60;
|
||||
case 1: return CONTENT_61_70;
|
||||
case 2: return CONTENT_71_80;
|
||||
case 3: return CONTENT_81_85;
|
||||
}
|
||||
}
|
||||
|
||||
MapDifficultyEntry const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty)
|
||||
{
|
||||
MapDifficultyMap::const_iterator itr = sMapDifficultyMap.find(MAKE_PAIR32(mapId, difficulty));
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ extern DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore;
|
|||
extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore;
|
||||
extern DBCStorage <CreatureDisplayInfoExtraEntry>sCreatureDisplayInfoExtraStore;
|
||||
extern DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore;
|
||||
extern DBCStorage <CreatureModelDataEntry> sCreatureModelDataStore;
|
||||
extern DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore;
|
||||
extern DBCStorage <CreatureTypeEntry> sCreatureTypeStore;
|
||||
extern DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore;
|
||||
|
|
|
|||
|
|
@ -751,7 +751,7 @@ struct CinematicSequencesEntry
|
|||
struct CreatureDisplayInfoEntry
|
||||
{
|
||||
uint32 Displayid; // 0 m_ID
|
||||
// 1 m_modelID
|
||||
uint32 ModelId; // 1 m_modelID
|
||||
// 2 m_soundID
|
||||
uint32 ExtendedDisplayInfoID; // 3 m_extendedDisplayInfoID -> CreatureDisplayInfoExtraEntry::DisplayExtraId
|
||||
float Scale; // 4 m_creatureModelScale
|
||||
|
|
@ -797,6 +797,28 @@ struct CreatureFamilyEntry
|
|||
// 11 m_iconFile
|
||||
};
|
||||
|
||||
struct CreatureModelDataEntry
|
||||
{
|
||||
uint32 Id; // 0
|
||||
//uint32 Flags; // 1
|
||||
//char* ModelPath // 2
|
||||
//uint32 InhabitType; // 3 model inhabit type
|
||||
//float Scale; // 4 Used in calculation of unit collision data
|
||||
//int32 Unk2 // 5
|
||||
//int32 Unk3 // 6
|
||||
//uint32 Unk4 // 7
|
||||
//uint32 Unk5 // 8
|
||||
//float Unk6 // 9
|
||||
//uint32 Unk7 // 10
|
||||
//float Unk8 // 11
|
||||
//uint32 Unk9 // 12
|
||||
//uint32 Unk10 // 13
|
||||
//float CollisionWidth; // 14
|
||||
float CollisionHeight; // 15
|
||||
float MountHeight; // 16 Used in calculation of unit collision data when mounted
|
||||
//float Unks[14] // 17-30
|
||||
};
|
||||
|
||||
#define MAX_CREATURE_SPELL_DATA_SLOT 4
|
||||
|
||||
struct CreatureSpellDataEntry
|
||||
|
|
@ -861,7 +883,7 @@ struct DestructibleModelDataEntry
|
|||
// uint32 unk17; // 17
|
||||
// uint32 unk18; // 18
|
||||
// uint32 unk19; // 19
|
||||
//uint32 smokeDisplayId; // 20
|
||||
uint32 smokeDisplayId; // 20
|
||||
// uint32 unk21; // 21
|
||||
// uint32 unk22; // 22
|
||||
// uint32 unk23; // 23
|
||||
|
|
@ -1380,7 +1402,6 @@ struct MapEntry
|
|||
MapID == 509 || MapID == 534 || MapID == 560 || // AhnQiraj, HyjalPast, HillsbradPast
|
||||
MapID == 568 || MapID == 580 || MapID == 595 || // ZulAman, Sunwell Plateau, Culling of Stratholme
|
||||
MapID == 603 || MapID == 615 || MapID == 616 || // Ulduar, The Obsidian Sanctum, The Eye Of Eternity
|
||||
MapID == 603 || MapID == 615 || MapID == 616 || // Ulduar, The Obsidian Sanctum, The Eye Of Eternity
|
||||
MapID == 631 || MapID == 658 || MapID == 724 || // Icecrown Citadel, Pit of Saron, Ruby Sanctum
|
||||
MapID == 644 || MapID == 720 || MapID == 721 || // Halls of Origination, Firelands
|
||||
MapID == 734 || MapID == 755 || MapID == 859 || // Ahn'Qiraj Terrace, Lost City of Tol'Vir, Zul'Gurub
|
||||
|
|
@ -1724,36 +1745,45 @@ struct ClassFamilyMask
|
|||
struct SpellAuraOptionsEntry
|
||||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
uint32 StackAmount; // 51 m_cumulativeAura
|
||||
uint32 procChance; // 38 m_procChance
|
||||
uint32 procCharges; // 39 m_procCharges
|
||||
uint32 procFlags; // 37 m_procTypeMask
|
||||
uint32 StackAmount; // 1 m_cumulativeAura
|
||||
uint32 procChance; // 2 m_procChance
|
||||
uint32 procCharges; // 3 m_procCharges
|
||||
uint32 procFlags; // 4 m_procTypeMask
|
||||
};
|
||||
|
||||
// SpellAuraRestrictions.dbc
|
||||
struct SpellAuraRestrictionsEntry
|
||||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
uint32 CasterAuraState; // 21 m_casterAuraState
|
||||
uint32 TargetAuraState; // 22 m_targetAuraState
|
||||
uint32 CasterAuraStateNot; // 23 m_excludeCasterAuraState
|
||||
uint32 TargetAuraStateNot; // 24 m_excludeTargetAuraState
|
||||
uint32 casterAuraSpell; // 25 m_casterAuraSpell
|
||||
uint32 targetAuraSpell; // 26 m_targetAuraSpell
|
||||
uint32 excludeCasterAuraSpell; // 27 m_excludeCasterAuraSpell
|
||||
uint32 excludeTargetAuraSpell; // 28 m_excludeTargetAuraSpell
|
||||
uint32 CasterAuraState; // 1 m_casterAuraState
|
||||
uint32 TargetAuraState; // 2 m_targetAuraState
|
||||
uint32 CasterAuraStateNot; // 3 m_excludeCasterAuraState
|
||||
uint32 TargetAuraStateNot; // 4 m_excludeTargetAuraState
|
||||
uint32 casterAuraSpell; // 5 m_casterAuraSpell
|
||||
uint32 targetAuraSpell; // 6 m_targetAuraSpell
|
||||
uint32 excludeCasterAuraSpell; // 7 m_excludeCasterAuraSpell
|
||||
uint32 excludeTargetAuraSpell; // 8 m_excludeTargetAuraSpell
|
||||
};
|
||||
|
||||
// SpellCastingRequirements.dbc
|
||||
struct SpellCastingRequirementsEntry
|
||||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
uint32 FacingCasterFlags; // 20 m_facingCasterFlags
|
||||
//uint32 MinFactionId; // 159 m_minFactionID not used
|
||||
//uint32 MinReputation; // 160 m_minReputation not used
|
||||
int32 AreaGroupId; // 164 m_requiredAreaGroupId
|
||||
//uint32 RequiredAuraVision; // 161 m_requiredAuraVision not used
|
||||
uint32 RequiresSpellFocus; // 19 m_requiresSpellFocus
|
||||
uint32 FacingCasterFlags; // 1 m_facingCasterFlags
|
||||
//uint32 MinFactionId; // 2 m_minFactionID not used
|
||||
//uint32 MinReputation; // 3 m_minReputation not used
|
||||
int32 AreaGroupId; // 4 m_requiredAreaGroupId
|
||||
//uint32 RequiredAuraVision; // 5 m_requiredAuraVision not used
|
||||
uint32 RequiresSpellFocus; // 6 m_requiresSpellFocus
|
||||
};
|
||||
|
||||
// SpellCastTimes.dbc
|
||||
struct SpellCastTimesEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
int32 CastTime; // 1 m_base
|
||||
float CastTimePerLevel; // 2 m_perLevel
|
||||
int32 MinCastTime; // 3 m_minimum
|
||||
};
|
||||
|
||||
// SpellCategories.dbc
|
||||
|
|
@ -1761,22 +1791,21 @@ struct SpellCategoriesEntry
|
|||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
uint32 Category; // 1 m_category
|
||||
uint32 DmgClass; // 153 m_defenseType
|
||||
uint32 Dispel; // 2 m_dispelType
|
||||
uint32 Mechanic; // 3 m_mechanic
|
||||
uint32 PreventionType; // 154 m_preventionType
|
||||
uint32 StartRecoveryCategory; // 145 m_startRecoveryCategory
|
||||
uint32 DmgClass; // 2 m_defenseType
|
||||
uint32 Dispel; // 3 m_dispelType
|
||||
uint32 Mechanic; // 4 m_mechanic
|
||||
uint32 PreventionType; // 5 m_preventionType
|
||||
uint32 StartRecoveryCategory; // 6 m_startRecoveryCategory
|
||||
};
|
||||
|
||||
// SpellClassOptions.dbc
|
||||
struct SpellClassOptionsEntry
|
||||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
//uint32 modalNextSpell; // 50 m_modalNextSpell not used
|
||||
ClassFamilyMask SpellFamilyFlags; // 149-151 m_spellClassMask NOTE: size is 12 bytes!!!
|
||||
uint32 SpellFamilyName; // 148 m_spellClassSet
|
||||
//uint32 modalNextSpell; // 1 m_modalNextSpell not used
|
||||
ClassFamilyMask SpellFamilyFlags; // 2-4 m_spellClassMask NOTE: size is 12 bytes!!!
|
||||
uint32 SpellFamilyName; // 5 m_spellClassSet
|
||||
//char* Description; // 6 4.0.0
|
||||
|
||||
// helpers
|
||||
|
||||
bool IsFitToFamilyMask(uint64 familyFlags, uint32 familyFlags2 = 0) const
|
||||
|
|
@ -1809,9 +1838,9 @@ struct SpellClassOptionsEntry
|
|||
struct SpellCooldownsEntry
|
||||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
uint32 CategoryRecoveryTime; // 31 m_categoryRecoveryTime
|
||||
uint32 RecoveryTime; // 30 m_recoveryTime
|
||||
uint32 StartRecoveryTime; // 146 m_startRecoveryTime
|
||||
uint32 CategoryRecoveryTime; // 1 m_categoryRecoveryTime
|
||||
uint32 RecoveryTime; // 2 m_recoveryTime
|
||||
uint32 StartRecoveryTime; // 3 m_startRecoveryTime
|
||||
};
|
||||
|
||||
// SpellEffect.dbc
|
||||
|
|
@ -1842,6 +1871,7 @@ struct SpellEffectEntry
|
|||
uint32 EffectSpellId; // 24 m_spellId - spell.dbc
|
||||
uint32 EffectIndex; // 25 m_spellEffectIdx
|
||||
//uint32 unk; // 26 4.2.0 only 0 or 1
|
||||
|
||||
// helpers
|
||||
|
||||
int32 CalculateSimpleValue() const { return EffectBasePoints; }
|
||||
|
|
@ -1859,29 +1889,68 @@ struct SpellEffectEntry
|
|||
struct SpellEquippedItemsEntry
|
||||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
int32 EquippedItemClass; // 70 m_equippedItemClass (value)
|
||||
int32 EquippedItemInventoryTypeMask; // 72 m_equippedItemInvTypes (mask)
|
||||
int32 EquippedItemSubClassMask; // 71 m_equippedItemSubclass (mask)
|
||||
int32 EquippedItemClass; // 1 m_equippedItemClass (value)
|
||||
int32 EquippedItemInventoryTypeMask; // 2 m_equippedItemInvTypes (mask)
|
||||
int32 EquippedItemSubClassMask; // 3 m_equippedItemSubclass (mask)
|
||||
};
|
||||
|
||||
// SpellFocusObject.dbc
|
||||
struct SpellFocusObjectEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
//char* Name; // 1 m_name_lang
|
||||
};
|
||||
|
||||
// SpellInterrupts.dbc
|
||||
struct SpellInterruptsEntry
|
||||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
uint32 AuraInterruptFlags; // 33 m_auraInterruptFlags
|
||||
//uint32 // 34 4.0.0
|
||||
uint32 ChannelInterruptFlags; // 35 m_channelInterruptFlags
|
||||
//uint32 // 36 4.0.0
|
||||
uint32 InterruptFlags; // 32 m_interruptFlags
|
||||
uint32 AuraInterruptFlags; // 1 m_auraInterruptFlags
|
||||
//uint32 // 2 4.0.0
|
||||
uint32 ChannelInterruptFlags; // 3 m_channelInterruptFlags
|
||||
//uint32 // 4 4.0.0
|
||||
uint32 InterruptFlags; // 5 m_interruptFlags
|
||||
};
|
||||
|
||||
// SpellItemEnchantment.dbc
|
||||
struct SpellItemEnchantmentEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
//uint32 charges; // 1 m_charges
|
||||
uint32 type[3]; // 2-4 m_effect[3]
|
||||
uint32 amount[3]; // 5-7 m_effectPointsMin[3]
|
||||
//uint32 amount2[3] // 8-10 m_effectPointsMax[3]
|
||||
uint32 spellid[3]; // 11-13 m_effectArg[3]
|
||||
DBCString description; // 14 m_name_lang
|
||||
uint32 aura_id; // 15 m_itemVisual
|
||||
uint32 slot; // 16 m_flags
|
||||
uint32 GemID; // 17 m_src_itemID
|
||||
uint32 EnchantmentCondition; // 18 m_condition_id
|
||||
uint32 requiredSkill; // 19 m_requiredSkillID
|
||||
uint32 requiredSkillValue; // 20 m_requiredSkillRank
|
||||
uint32 requiredLevel; // 21 m_requiredLevel - 3.1
|
||||
// 22 new in 3.1
|
||||
};
|
||||
|
||||
// SpellItemEnchantmentCondition.dbc
|
||||
struct SpellItemEnchantmentConditionEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
uint8 Color[5]; // 1-5 m_lt_operandType[5]
|
||||
//uint32 LT_Operand[5]; // 6-10 m_lt_operand[5]
|
||||
uint8 Comparator[5]; // 11-15 m_operator[5]
|
||||
uint8 CompareColor[5]; // 15-20 m_rt_operandType[5]
|
||||
uint32 Value[5]; // 21-25 m_rt_operand[5]
|
||||
//uint8 Logic[5] // 25-30 m_logic[5]
|
||||
};
|
||||
|
||||
// SpellLevels.dbc
|
||||
struct SpellLevelsEntry
|
||||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
uint32 baseLevel; // 41 m_baseLevel
|
||||
uint32 maxLevel; // 40 m_maxLevel
|
||||
uint32 spellLevel; // 42 m_spellLevel
|
||||
uint32 baseLevel; // 1 m_baseLevel
|
||||
uint32 maxLevel; // 2 m_maxLevel
|
||||
uint32 spellLevel; // 3 m_spellLevel
|
||||
};
|
||||
|
||||
// SpellPower.dbc
|
||||
|
|
@ -1892,9 +1961,31 @@ struct SpellPowerEntry
|
|||
uint32 manaCostPerlevel; // 2 - m_manaCostPerLevel
|
||||
uint32 ManaCostPercentage; // 3 - m_manaCostPct
|
||||
uint32 manaPerSecond; // 4 - m_manaPerSecond
|
||||
//uint32 PowerDisplayId; // 5 - m_powerDisplayID - id from PowerDisplay.dbc, new in 3.1
|
||||
//uint32 unk1; // 6 - 4.0.0
|
||||
//unk // 7 - 4.3.0
|
||||
uint32 manaPerSecondPerLevel; // 5 m_manaPerSecondPerLevel
|
||||
//uint32 PowerDisplayId; // 6 - m_powerDisplayID - id from PowerDisplay.dbc, new in 3.1
|
||||
float ManaCostPercentageFloat; // 7 4.3.0
|
||||
};
|
||||
|
||||
// SpellRadius.dbc
|
||||
struct SpellRadiusEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
float Radius; // 1 m_radius
|
||||
float RadiusPerLevel; // 2 m_radiusPerLevel
|
||||
float RadiusMax; // 3 m_radiusMax
|
||||
};
|
||||
|
||||
// SpellRange.dbc
|
||||
struct SpellRangeEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
float minRange; // 1 m_rangeMin[2]
|
||||
float minRangeFriendly; // 2
|
||||
float maxRange; // 3 m_rangeMax[2]
|
||||
float maxRangeFriendly; // 4
|
||||
uint32 type; // 5 m_flags
|
||||
//char* Name; // 6-21 m_displayName_lang
|
||||
//char* ShortName; // 23-38 m_displayNameShort_lang
|
||||
};
|
||||
|
||||
// SpellReagents.dbc
|
||||
|
|
@ -1905,19 +1996,30 @@ struct SpellReagentsEntry
|
|||
uint32 ReagentCount[MAX_SPELL_REAGENTS]; // 62-69 m_reagentCount
|
||||
};
|
||||
|
||||
// SpellRuneCost.dbc
|
||||
struct SpellRuneCostEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
uint32 RuneCost[3]; // 1-3 m_blood m_unholy m_frost (0=blood, 1=frost, 2=unholy)
|
||||
uint32 runePowerGain; // 4 m_runicPower
|
||||
|
||||
bool NoRuneCost() const { return RuneCost[0] == 0 && RuneCost[1] == 0 && RuneCost[2] == 0; }
|
||||
bool NoRunicPowerGain() const { return runePowerGain == 0; }
|
||||
};
|
||||
|
||||
// SpellScaling.dbc
|
||||
struct SpellScalingEntry
|
||||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
int32 castTimeMin; // 1
|
||||
int32 castTimeMax; // 2
|
||||
int32 castScalingMaxLevel; // 3
|
||||
int32 playerClass; // 4 (index * 100) + charLevel => gtSpellScaling.dbc
|
||||
uint32 castTimeMin; // 1
|
||||
uint32 castTimeMax; // 2
|
||||
uint32 castScalingMaxLevel; // 3
|
||||
uint32 playerClass; // 4 (index * 100) + charLevel => gtSpellScaling.dbc
|
||||
float coeff1[3]; // 5-7
|
||||
float coeff2[3]; // 8-10
|
||||
float coeff3[3]; // 11-13
|
||||
float coefBase; // 14 some coefficient, mostly 1.0f
|
||||
int32 coefLevelBase; // 15 some level
|
||||
uint32 coefLevelBase; // 15 some level
|
||||
|
||||
bool IsScalableEffect(SpellEffectIndex i) const { return coeff1[i] != 0.0f; };
|
||||
};
|
||||
|
|
@ -1926,11 +2028,30 @@ struct SpellScalingEntry
|
|||
struct SpellShapeshiftEntry
|
||||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
uint32 StancesNot; // 13 m_shapeshiftMask
|
||||
// uint32 unk_320_2; // 14 3.2.0
|
||||
uint32 Stances; // 15 m_shapeshiftExclude
|
||||
// uint32 unk_320_3; // 16 3.2.0
|
||||
// uint32 StanceBarOrder; // 155 m_stanceBarOrder not used
|
||||
uint32 StancesNot; // 1 m_shapeshiftMask
|
||||
// uint32 unk_320_2; // 2 3.2.0
|
||||
uint32 Stances; // 3 m_shapeshiftExclude
|
||||
// uint32 unk_320_3; // 4 3.2.0
|
||||
// uint32 StanceBarOrder; // 5 m_stanceBarOrder not used
|
||||
};
|
||||
|
||||
// SpellShapeshiftForm.dbc
|
||||
struct SpellShapeshiftFormEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
//uint32 buttonPosition; // 1 m_bonusActionBar
|
||||
//char* Name; // 2 m_name_lang
|
||||
uint32 flags1; // 3 m_flags
|
||||
int32 creatureType; // 4 m_creatureType <=0 humanoid, other normal creature types
|
||||
//uint32 unk1; // 5 m_attackIconID
|
||||
uint32 attackSpeed; // 6 m_combatRoundTime
|
||||
uint32 modelID_A; // 7 m_creatureDisplayID[4]
|
||||
uint32 modelID_H; // 8
|
||||
//uint32 unk3; // 9 unused always 0
|
||||
//uint32 unk4; // 10 unused always 0
|
||||
uint32 spellId[8]; // 11-18 m_presetSpellID[8]
|
||||
//uint32 unk5; // 19 unused, !=0 for flight forms
|
||||
//uint32 unk6; // 20
|
||||
};
|
||||
|
||||
// SpellTargetRestrictions.dbc
|
||||
|
|
@ -1948,8 +2069,8 @@ struct SpellTargetRestrictionsEntry
|
|||
struct SpellTotemsEntry
|
||||
{
|
||||
//uint32 Id; // 0 m_ID
|
||||
uint32 TotemCategory[MAX_SPELL_TOTEM_CATEGORIES]; // 162-163 m_requiredTotemCategoryID
|
||||
uint32 Totem[MAX_SPELL_TOTEMS]; // 52-53 m_totem
|
||||
uint32 TotemCategory[MAX_SPELL_TOTEM_CATEGORIES]; // 1 2 m_requiredTotemCategoryID
|
||||
uint32 Totem[MAX_SPELL_TOTEMS]; // 3 4 m_totem
|
||||
};
|
||||
|
||||
// Spell.dbc
|
||||
|
|
@ -2116,68 +2237,6 @@ struct SpellEntry
|
|||
#define LOADED_SPELLDBC_FIELD_POS_EQUIPPED_ITEM_CLASS 65 // Must be converted to -1
|
||||
#define LOADED_SPELLDBC_FIELD_POS_SPELLNAME_0 132 // Links to "MaNGOS server-side spell"
|
||||
|
||||
struct SpellCastTimesEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
int32 CastTime; // 1 m_base
|
||||
float CastTimePerLevel; // 2 m_perLevel
|
||||
int32 MinCastTime; // 3 m_minimum
|
||||
};
|
||||
|
||||
struct SpellFocusObjectEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
//char* Name; // 1 m_name_lang
|
||||
};
|
||||
|
||||
struct SpellRadiusEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
float Radius; // 1 m_radius
|
||||
// 2 m_radiusPerLevel
|
||||
//float RadiusMax; // 3 m_radiusMax
|
||||
};
|
||||
|
||||
struct SpellRangeEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
float minRange; // 1 m_rangeMin[2]
|
||||
float minRangeFriendly; // 2
|
||||
float maxRange; // 3 m_rangeMax[2]
|
||||
float maxRangeFriendly; // 4
|
||||
//uint32 Flags; // 5 m_flags
|
||||
//char* Name; // 6-21 m_displayName_lang
|
||||
//char* ShortName; // 23-38 m_displayNameShort_lang
|
||||
};
|
||||
|
||||
struct SpellRuneCostEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
uint32 RuneCost[3]; // 1-3 m_blood m_unholy m_frost (0=blood, 1=frost, 2=unholy)
|
||||
uint32 runePowerGain; // 4 m_runicPower
|
||||
|
||||
bool NoRuneCost() const { return RuneCost[0] == 0 && RuneCost[1] == 0 && RuneCost[2] == 0; }
|
||||
bool NoRunicPowerGain() const { return runePowerGain == 0; }
|
||||
};
|
||||
|
||||
struct SpellShapeshiftFormEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
//uint32 buttonPosition; // 1 m_bonusActionBar
|
||||
//char* Name; // 2 m_name_lang
|
||||
uint32 flags1; // 3 m_flags
|
||||
int32 creatureType; // 4 m_creatureType <=0 humanoid, other normal creature types
|
||||
//uint32 unk1; // 5 m_attackIconID
|
||||
uint32 attackSpeed; // 6 m_combatRoundTime
|
||||
uint32 modelID_A; // 7 m_creatureDisplayID[4]
|
||||
uint32 modelID_H; // 8
|
||||
//uint32 unk3; // 9 unused always 0
|
||||
//uint32 unk4; // 10 unused always 0
|
||||
uint32 spellId[8]; // 11-18 m_presetSpellID[8]
|
||||
//uint32 unk5; // 19 unused, !=0 for flight forms
|
||||
//uint32 unk6; // 20
|
||||
};
|
||||
|
||||
struct SpellDifficultyEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
|
|
@ -2190,36 +2249,6 @@ struct SpellDurationEntry
|
|||
int32 Duration[3]; // m_duration, m_durationPerLevel, m_maxDuration
|
||||
};
|
||||
|
||||
struct SpellItemEnchantmentEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
//uint32 charges; // 1 m_charges
|
||||
uint32 type[3]; // 2-4 m_effect[3]
|
||||
uint32 amount[3]; // 5-7 m_effectPointsMin[3]
|
||||
//uint32 amount2[3] // 8-10 m_effectPointsMax[3]
|
||||
uint32 spellid[3]; // 11-13 m_effectArg[3]
|
||||
DBCString description; // 14 m_name_lang
|
||||
uint32 aura_id; // 15 m_itemVisual
|
||||
uint32 slot; // 16 m_flags
|
||||
uint32 GemID; // 17 m_src_itemID
|
||||
uint32 EnchantmentCondition; // 18 m_condition_id
|
||||
//uint32 requiredSkill; // 19 m_requiredSkillID
|
||||
//uint32 requiredSkillValue; // 20 m_requiredSkillRank
|
||||
// 21 new in 3.1
|
||||
// 22 new in 3.1
|
||||
};
|
||||
|
||||
struct SpellItemEnchantmentConditionEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
uint8 Color[5]; // 1-5 m_lt_operandType[5]
|
||||
//uint32 LT_Operand[5]; // 6-10 m_lt_operand[5]
|
||||
uint8 Comparator[5]; // 11-15 m_operator[5]
|
||||
uint8 CompareColor[5]; // 15-20 m_rt_operandType[5]
|
||||
uint32 Value[5]; // 21-25 m_rt_operand[5]
|
||||
//uint8 Logic[5] // 25-30 m_logic[5]
|
||||
};
|
||||
|
||||
struct SummonPropertiesEntry
|
||||
{
|
||||
uint32 Id; // 0 m_id
|
||||
|
|
|
|||
|
|
@ -44,11 +44,12 @@ const char ChrClassesEntryfmt[]="nixsxxxixiiiii";
|
|||
const char ChrRacesEntryfmt[]="nxixiixixxxxixsxxxxxixxx";
|
||||
const char ChrClassesXPowerTypesfmt[]="nii";
|
||||
const char CinematicSequencesEntryfmt[] = "nxxxxxxxxx";
|
||||
const char CreatureDisplayInfofmt[]="nxxifxxxxxxxxxxxx";
|
||||
const char CreatureDisplayInfofmt[]="nixifxxxxxxxxxxxx";
|
||||
const char CreatureDisplayInfoExtrafmt[] = "nixxxxxxxxxxxxxxxxxxx";
|
||||
const char CreatureFamilyfmt[]="nfifiiiiixsx";
|
||||
const char CreatureModelDatafmt[] = "nxxxxxxxxxxxxxxffxxxxxxxxxxxxxx";
|
||||
const char CreatureSpellDatafmt[] = "niiiixxxx";
|
||||
const char DestructibleModelDataFmt[] = "nixxxixxxxixxxxixxxxxxxx";
|
||||
const char DestructibleModelDataFmt[] = "nixxxixxxxixxxxixxxxixxx";
|
||||
const char DungeonEncounterfmt[]="niiiisxx";
|
||||
const char CreatureTypefmt[]="nxx";
|
||||
const char CurrencyTypesfmt[]="nisxxxxiiix";
|
||||
|
|
|
|||
|
|
@ -856,14 +856,14 @@ void InitializeOpcodes()
|
|||
//OPCODE(SMSG_SPLINE_SET_SWIM_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//OPCODE(SMSG_SPLINE_SET_TURN_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_UNROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//OPCODE(SMSG_SPLINE_MOVE_FEATHER_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//OPCODE(SMSG_SPLINE_MOVE_NORMAL_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_FEATHER_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_NORMAL_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_SET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_UNSET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_WATER_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_LAND_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_START_SWIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//OPCODE(SMSG_SPLINE_MOVE_STOP_SWIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_STOP_SWIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_SET_RUN_MODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_SET_WALK_MODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//OPCODE(CMSG_GM_NUKE_ACCOUNT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
|
|
@ -1319,9 +1319,9 @@ void InitializeOpcodes()
|
|||
//OPCODE(CMSG_START_BATTLEFIELD_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
//OPCODE(CMSG_END_BATTLEFIELD_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
//OPCODE(SMSG_COMPOUND_MOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_MOVE_GRAVITY_DISABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_MOVE_GRAVITY_DISABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(CMSG_MOVE_GRAVITY_DISABLE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
OPCODE(SMSG_MOVE_GRAVITY_ENABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_MOVE_GRAVITY_ENABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(CMSG_MOVE_GRAVITY_ENABLE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
//OPCODE(MSG_MOVE_GRAVITY_CHNG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_SPLINE_MOVE_GRAVITY_DISABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
|
|
@ -1392,7 +1392,7 @@ void InitializeOpcodes()
|
|||
//OPCODE(SMSG_SEND_ALL_COMBAT_LOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_OPEN_LFG_DUNGEON_FINDER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
OPCODE(SMSG_MOVE_SET_COLLISION_HGT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//OPCODE(CMSG_MOVE_SET_COLLISION_HGT_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
OPCODE(CMSG_MOVE_SET_COLLISION_HGT_ACK, STATUS_UNHANDLED,PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
//OPCODE(MSG_MOVE_SET_COLLISION_HGT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//OPCODE(CMSG_CLEAR_RANDOM_BG_WIN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
//OPCODE(CMSG_CLEAR_HOLIDAY_BG_WIN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
|
|
|
|||
|
|
@ -840,8 +840,8 @@ enum Opcodes
|
|||
SMSG_SPLINE_SET_SWIM_BACK_SPEED = 0x1303,
|
||||
SMSG_SPLINE_SET_TURN_RATE = 0x1304,
|
||||
SMSG_SPLINE_MOVE_UNROOT = 0x75B6, // 4.3.4 15595
|
||||
SMSG_SPLINE_MOVE_FEATHER_FALL = 0x1306,
|
||||
SMSG_SPLINE_MOVE_NORMAL_FALL = 0x1307,
|
||||
SMSG_SPLINE_MOVE_FEATHER_FALL = 0x3DA5, // 4.3.4 15595
|
||||
SMSG_SPLINE_MOVE_NORMAL_FALL = 0x38B2, // 4.3.4 15595
|
||||
SMSG_SPLINE_MOVE_SET_HOVER = 0x14B6, // 4.3.4 15595
|
||||
SMSG_SPLINE_MOVE_UNSET_HOVER = 0x7DA5, // 4.3.4 15595
|
||||
SMSG_SPLINE_MOVE_WATER_WALK = 0x50A2, // 4.3.4 15595
|
||||
|
|
@ -1238,7 +1238,7 @@ enum Opcodes
|
|||
CMSG_REMOVE_GLYPH = 0x148B,
|
||||
CMSG_DUMP_OBJECTS = 0x148C,
|
||||
SMSG_DUMP_OBJECTS_DATA = 0x148D,
|
||||
CMSG_DISMISS_CRITTER = 0x4227,
|
||||
CMSG_DISMISS_CRITTER = 0x4227, // 4.3.4 15595
|
||||
SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x148F,
|
||||
CMSG_AUCTION_LIST_PENDING_SALES = 0x2C17, // 4.3.4 15595
|
||||
SMSG_AUCTION_LIST_PENDING_SALES = 0x6A27, // 4.3.4 15595
|
||||
|
|
@ -1264,9 +1264,9 @@ enum Opcodes
|
|||
CMSG_SET_BREATH = 0x14A5,
|
||||
CMSG_QUERY_VEHICLE_STATUS = 0x14A6,
|
||||
SMSG_BATTLEGROUND_INFO_THROTTLED = 0x14A7,
|
||||
SMSG_SET_VEHICLE_REC_ID = 0x14A8,
|
||||
CMSG_RIDE_VEHICLE_INTERACT = 0x14A9,
|
||||
CMSG_CONTROLLER_EJECT_PASSENGER = 0x14AA,
|
||||
SMSG_SET_VEHICLE_REC_ID = 0x4115, // 4.3.4 15595
|
||||
CMSG_RIDE_VEHICLE_INTERACT = 0x2705, // 4.3.4 15595
|
||||
CMSG_CONTROLLER_EJECT_PASSENGER = 0x6927, // 4.3.4 15595
|
||||
SMSG_PET_GUIDS = 0x2D26, // 4.3.4 15595
|
||||
SMSG_CLIENTCACHE_VERSION = 0x2734, // 4.3.4 15595
|
||||
CMSG_CHANGE_GDF_ARENA_RATING = 0x14AD,
|
||||
|
|
@ -1376,7 +1376,7 @@ enum Opcodes
|
|||
SMSG_SEND_ALL_COMBAT_LOG = 0x1515,
|
||||
SMSG_OPEN_LFG_DUNGEON_FINDER = 0x0412, // 4.3.4 15595
|
||||
SMSG_MOVE_SET_COLLISION_HGT = 0x11B0, // 4.3.4 15595
|
||||
CMSG_MOVE_SET_COLLISION_HGT_ACK = 0x1518,
|
||||
CMSG_MOVE_SET_COLLISION_HGT_ACK = 0x7114, // 4.3.4 15595
|
||||
MSG_MOVE_SET_COLLISION_HGT = 0x1519,
|
||||
CMSG_CLEAR_RANDOM_BG_WIN_TIME = 0x151A,
|
||||
CMSG_CLEAR_HOLIDAY_BG_WIN_TIME = 0x151B,
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ enum SpellAttributesEx4
|
|||
|
||||
enum SpellAttributesEx5
|
||||
{
|
||||
SPELL_ATTR_EX5_UNK0 = 0x00000001,// 0
|
||||
SPELL_ATTR_EX5_CAN_CHANNEL_WHEN_MOVING = 0x00000001,// 0 don't interrupt channeling spells when moving
|
||||
SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP = 0x00000002,// 1 not need reagents if UNIT_FLAG_PREPARATION
|
||||
SPELL_ATTR_EX5_UNK2 = 0x00000004,// 2 removed at enter arena (e.g. 31850 since 3.3.3)
|
||||
SPELL_ATTR_EX5_USABLE_WHILE_STUNNED = 0x00000008,// 3 usable while stunned
|
||||
|
|
@ -3792,4 +3792,14 @@ enum TeleportLocation
|
|||
TELEPORT_LOCATION_BG_ENTRY_POINT = 1,
|
||||
};
|
||||
|
||||
// For Loot system
|
||||
enum CreatureLootStatus
|
||||
{
|
||||
CREATURE_LOOT_STATUS_NONE = 0,
|
||||
CREATURE_LOOT_STATUS_PICKPOCKETED = 1,
|
||||
CREATURE_LOOT_STATUS_LOOTED = 2,
|
||||
CREATURE_LOOT_STATUS_SKIN_AVAILABLE = 3,
|
||||
CREATURE_LOOT_STATUS_SKINNED = 4
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -677,6 +677,7 @@ class WorldSession
|
|||
void HandleGossipHelloOpcode(WorldPacket& recvPacket);
|
||||
void HandleGossipSelectOptionOpcode(WorldPacket& recvPacket);
|
||||
void HandleSpiritHealerActivateOpcode(WorldPacket& recvPacket);
|
||||
void HandleReturnToGraveyardOpcode(WorldPacket& recvPacket);
|
||||
void HandleNpcTextQueryOpcode(WorldPacket& recvPacket);
|
||||
void HandleBinderActivateOpcode(WorldPacket& recvPacket);
|
||||
void HandleListStabledPetsOpcode(WorldPacket& recvPacket);
|
||||
|
|
|
|||
|
|
@ -232,6 +232,7 @@ bool AccountMgr::CheckPassword(uint32 accid, std::string passwd)
|
|||
return false;
|
||||
|
||||
normalizeString(passwd);
|
||||
normalizeString(username);
|
||||
|
||||
QueryResult* result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%u' AND sha_pass_hash='%s'", accid, CalculateShaPassHash(username, passwd).c_str());
|
||||
if (result)
|
||||
|
|
|
|||
|
|
@ -40,15 +40,22 @@ void WorldSession::HandleInspectArenaTeamsOpcode(WorldPacket& recv_data)
|
|||
recv_data >> guid;
|
||||
DEBUG_LOG("Inspect Arena stats %s", guid.GetString().c_str());
|
||||
|
||||
if (Player* plr = sObjectMgr.GetPlayer(guid))
|
||||
{
|
||||
Player* player = sObjectMgr.GetPlayer(guid);
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
if (!_player->IsWithinDistInMap(player, INSPECT_DISTANCE, false))
|
||||
return;
|
||||
|
||||
if (_player->IsHostileTo(player))
|
||||
return;
|
||||
|
||||
for (uint8 i = 0; i < MAX_ARENA_SLOT; ++i)
|
||||
{
|
||||
if (uint32 a_id = plr->GetArenaTeamId(i))
|
||||
if (uint32 a_id = player->GetArenaTeamId(i))
|
||||
{
|
||||
if (ArenaTeam* at = sObjectMgr.GetArenaTeamById(a_id))
|
||||
at->InspectStats(this, plr->GetObjectGuid());
|
||||
}
|
||||
if (ArenaTeam* arenaTeam = sObjectMgr.GetArenaTeamById(a_id))
|
||||
arenaTeam->InspectStats(this, player->GetObjectGuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ ChatCommand* ChatHandler::getCommandTable()
|
|||
{ "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectPhaseCommand, "", NULL },
|
||||
{ "target", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectTargetCommand, "", NULL },
|
||||
{ "turn", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectTurnCommand, "", NULL },
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
{ nullptr, 0, false, NULL, "", NULL }
|
||||
};
|
||||
|
||||
static ChatCommand guildCommandTable[] =
|
||||
|
|
@ -413,6 +413,7 @@ ChatCommand* ChatHandler::getCommandTable()
|
|||
{ "loadedtiles", SEC_GAMEMASTER, false, &ChatHandler::HandleMmapLoadedTilesCommand, "", NULL },
|
||||
{ "stats", SEC_GAMEMASTER, false, &ChatHandler::HandleMmapStatsCommand, "", NULL },
|
||||
{ "testarea", SEC_GAMEMASTER, false, &ChatHandler::HandleMmapTestArea, "", NULL },
|
||||
{ "testheight", SEC_GAMEMASTER, false, &ChatHandler::HandleMmapTestHeight, "", NULL },
|
||||
{ "", SEC_ADMINISTRATOR, false, &ChatHandler::HandleMmap, "", NULL },
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -639,6 +639,7 @@ class ChatHandler
|
|||
bool HandleMmapStatsCommand(char* args);
|
||||
bool HandleMmap(char* args);
|
||||
bool HandleMmapTestArea(char* args);
|
||||
bool HandleMmapTestHeight(char* args);
|
||||
|
||||
//! Development Commands
|
||||
bool HandleSaveAllCommand(char* args);
|
||||
|
|
|
|||
|
|
@ -173,7 +173,14 @@ void CreatureLinkingMgr::LoadFromDB()
|
|||
delete result;
|
||||
}
|
||||
|
||||
// This function is used to check if a DB-Entry is valid
|
||||
/** This function is used to check if a DB-Entry is valid
|
||||
*
|
||||
* @param byEntry: is the first parameter of the function a npc entry or a npc guid?
|
||||
* @param slaveEntry: dependend on byEntry param this is either the slave's npc-entry or the npc-guid
|
||||
* @param pTmp: Information about the CreatureLinking of the npc. Note that this information may be changed in some cases
|
||||
*
|
||||
* In case of checking by entry and in case of linked spawning and searchRange == 0, pTmp will be changed to keep information about the (unique!) master's db-guid
|
||||
*/
|
||||
bool CreatureLinkingMgr::IsLinkingEntryValid(uint32 slaveEntry, CreatureLinkingInfo* pTmp, bool byEntry)
|
||||
{
|
||||
// Basic checks first
|
||||
|
|
@ -238,14 +245,22 @@ bool CreatureLinkingMgr::IsLinkingEntryValid(uint32 slaveEntry, CreatureLinkingI
|
|||
// Check for uniqueness of mob whom is followed, on whom spawning is dependend
|
||||
if (pTmp->searchRange == 0 && pTmp->linkingFlag & (FLAG_FOLLOW | FLAG_CANT_SPAWN_IF_BOSS_DEAD | FLAG_CANT_SPAWN_IF_BOSS_ALIVE))
|
||||
{
|
||||
// Painfully slow, needs better idea
|
||||
QueryResult* result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id=%u AND map=%u", pTmp->masterId, pTmp->mapId);
|
||||
if (result)
|
||||
QueryResult* result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id=%u AND map=%u LIMIT 2", pTmp->masterId, pTmp->mapId);
|
||||
if (!result)
|
||||
{
|
||||
sLog.outErrorDb("`creature_linking_template` has FLAG_FOLLOW, but no master, (entry: %u, map: %u, master: %u)", slaveEntry, pTmp->mapId, pTmp->masterId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result->GetRowCount() > 1)
|
||||
{
|
||||
if ((*result)[0].GetUInt32() > 1)
|
||||
sLog.outErrorDb("`creature_linking_template` has FLAG_FOLLOW, but non unique master, (entry: %u, map: %u, master: %u)", slaveEntry, pTmp->mapId, pTmp->masterId);
|
||||
delete result;
|
||||
return false;
|
||||
}
|
||||
Field* fields = result->Fetch();
|
||||
pTmp->masterDBGuid = fields[0].GetUInt32();
|
||||
delete result;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -265,7 +280,7 @@ enum EventMask
|
|||
};
|
||||
|
||||
// This functions checks if the NPC has linked NPCs for dynamic action
|
||||
bool CreatureLinkingMgr::IsLinkedEventTrigger(Creature* pCreature)
|
||||
bool CreatureLinkingMgr::IsLinkedEventTrigger(Creature* pCreature) const
|
||||
{
|
||||
// Entry case
|
||||
if (m_eventTriggers.find(pCreature->GetEntry()) != m_eventTriggers.end())
|
||||
|
|
@ -284,37 +299,43 @@ bool CreatureLinkingMgr::IsLinkedEventTrigger(Creature* pCreature)
|
|||
|
||||
// This function check if the NPC is a master to other NPCs
|
||||
// return true only for masters stored by entry - this prevents adding them to master-holder maps
|
||||
bool CreatureLinkingMgr::IsLinkedMaster(Creature* pCreature)
|
||||
bool CreatureLinkingMgr::IsLinkedMaster(Creature* pCreature) const
|
||||
{
|
||||
return m_eventTriggers.find(pCreature->GetEntry()) != m_eventTriggers.end();
|
||||
}
|
||||
|
||||
// This function checks if the spawning of this NPC is dependend on other NPCs
|
||||
bool CreatureLinkingMgr::IsSpawnedByLinkedMob(Creature* pCreature)
|
||||
bool CreatureLinkingMgr::IsSpawnedByLinkedMob(Creature* pCreature) const
|
||||
{
|
||||
return IsSpawnedByLinkedMob(GetLinkedTriggerInformation(pCreature));
|
||||
}
|
||||
bool CreatureLinkingMgr::IsSpawnedByLinkedMob(CreatureLinkingInfo const* pInfo) const
|
||||
{
|
||||
CreatureLinkingInfo const* pInfo = CreatureLinkingMgr::GetLinkedTriggerInformation(pCreature);
|
||||
|
||||
return pInfo && pInfo->linkingFlag & (FLAG_CANT_SPAWN_IF_BOSS_DEAD | FLAG_CANT_SPAWN_IF_BOSS_ALIVE) && (pInfo->masterDBGuid || pInfo->searchRange);
|
||||
}
|
||||
|
||||
// This gives the information of a linked NPC (describes action when its ActionTrigger triggers)
|
||||
// Depends of the map
|
||||
CreatureLinkingInfo const* CreatureLinkingMgr::GetLinkedTriggerInformation(Creature* pCreature)
|
||||
CreatureLinkingInfo const* CreatureLinkingMgr::GetLinkedTriggerInformation(Creature* pCreature) const
|
||||
{
|
||||
return GetLinkedTriggerInformation(pCreature->GetEntry(), pCreature->GetGUIDLow(), pCreature->GetMapId());
|
||||
}
|
||||
CreatureLinkingInfo const* CreatureLinkingMgr::GetLinkedTriggerInformation(uint32 entry, uint32 lowGuid, uint32 mapId) const
|
||||
{
|
||||
// guid case
|
||||
CreatureLinkingMapBounds bounds = m_creatureLinkingGuidMap.equal_range(pCreature->GetGUIDLow());
|
||||
for (CreatureLinkingMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter)
|
||||
CreatureLinkingMapBounds bounds = m_creatureLinkingGuidMap.equal_range(lowGuid);
|
||||
for (CreatureLinkingMap::const_iterator iter = bounds.first; iter != bounds.second;)
|
||||
return &(iter->second);
|
||||
|
||||
// entry case
|
||||
bounds = m_creatureLinkingMap.equal_range(pCreature->GetEntry());
|
||||
bounds = m_creatureLinkingMap.equal_range(entry);
|
||||
for (CreatureLinkingMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter)
|
||||
{
|
||||
if (iter->second.mapId == pCreature->GetMapId())
|
||||
if (iter->second.mapId == mapId)
|
||||
return &(iter->second);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Function to add slave-NPCs to the holder
|
||||
|
|
@ -384,7 +405,7 @@ void CreatureLinkingHolder::AddMasterToHolder(Creature* pCreature)
|
|||
|
||||
// Check, if already stored
|
||||
BossGuidMapBounds bounds = m_masterGuid.equal_range(pCreature->GetEntry());
|
||||
for (BossGuidMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
|
||||
for (BossGuidMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
|
||||
if (itr->second == pCreature->GetObjectGuid())
|
||||
return; // Already added
|
||||
|
||||
|
|
@ -432,11 +453,11 @@ void CreatureLinkingHolder::DoCreatureLinkingEvent(CreatureLinkingEvent eventTyp
|
|||
{
|
||||
if (pInfo->linkingFlag & reverseEventFlagFilter)
|
||||
{
|
||||
Creature* pMaster = NULL;
|
||||
Creature* pMaster = nullptr;
|
||||
if (pInfo->mapId != INVALID_MAP_ID) // entry case
|
||||
{
|
||||
BossGuidMapBounds finds = m_masterGuid.equal_range(pInfo->masterId);
|
||||
for (BossGuidMap::iterator itr = finds.first; itr != finds.second; ++itr)
|
||||
for (BossGuidMap::const_iterator itr = finds.first; itr != finds.second; ++itr)
|
||||
{
|
||||
pMaster = pSource->GetMap()->GetCreature(itr->second);
|
||||
if (pMaster && IsSlaveInRangeOfBoss(pSource, pMaster, pInfo->searchRange))
|
||||
|
|
@ -589,49 +610,93 @@ void CreatureLinkingHolder::SetFollowing(Creature* pWho, Creature* pWhom)
|
|||
}
|
||||
|
||||
// Function to check if a slave belongs to a boss by range-issue
|
||||
bool CreatureLinkingHolder::IsSlaveInRangeOfBoss(Creature* pSlave, Creature* pBoss, uint16 searchRange)
|
||||
bool CreatureLinkingHolder::IsSlaveInRangeOfBoss(Creature const* pSlave, Creature const* pBoss, uint16 searchRange) const
|
||||
{
|
||||
float sX, sY, sZ;
|
||||
pSlave->GetRespawnCoord(sX, sY, sZ);
|
||||
return IsSlaveInRangeOfBoss(pBoss, sX, sY, searchRange);
|
||||
}
|
||||
bool CreatureLinkingHolder::IsSlaveInRangeOfBoss(Creature const* pBoss, float sX, float sY, uint16 searchRange) const
|
||||
{
|
||||
if (!searchRange)
|
||||
return true;
|
||||
|
||||
// Do some calculations
|
||||
float sX, sY, sZ, mX, mY, mZ;
|
||||
pSlave->GetRespawnCoord(sX, sY, sZ);
|
||||
float mX, mY, mZ, dx, dy;
|
||||
pBoss->GetRespawnCoord(mX, mY, mZ);
|
||||
|
||||
float dx, dy;
|
||||
dx = sX - mX;
|
||||
dy = sY - mY;
|
||||
|
||||
return dx * dx + dy * dy < searchRange * searchRange;
|
||||
}
|
||||
|
||||
// helper function to check if a lowguid can respawn
|
||||
bool CreatureLinkingHolder::IsRespawnReady(uint32 dbLowGuid, Map* _map) const
|
||||
{
|
||||
time_t respawnTime = _map->GetPersistentState()->GetCreatureRespawnTime(dbLowGuid);
|
||||
return (!respawnTime || respawnTime <= time(nullptr)) && CanSpawn(dbLowGuid, _map, nullptr, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
// Function to check if a passive spawning condition is met
|
||||
bool CreatureLinkingHolder::CanSpawn(Creature* pCreature)
|
||||
bool CreatureLinkingHolder::CanSpawn(Creature* pCreature) const
|
||||
{
|
||||
CreatureLinkingInfo const* pInfo = sCreatureLinkingMgr.GetLinkedTriggerInformation(pCreature);
|
||||
if (!pInfo)
|
||||
return true;
|
||||
|
||||
float sx, sy, sz;
|
||||
pCreature->GetRespawnCoord(sx, sy, sz);
|
||||
return CanSpawn(0, pCreature->GetMap(), pInfo, sx, sy);
|
||||
}
|
||||
|
||||
/** Worker function to check if a spawning condition is met
|
||||
*
|
||||
* This function is used directly from above function, and for recursive use
|
||||
* in case of recursive use it is used only on _map with information of lowGuid.
|
||||
*
|
||||
* @param lowGuid (only relevant in case of recursive uses) -- db-guid of the npc that is checked
|
||||
* @param _map Map on which things are checked
|
||||
* @param pInfo (only shipped in case of initial use) -- used as marker of first use, also in first use filled directly
|
||||
* @param sx, sy (spawn position of the checked npc with initial use)
|
||||
*/
|
||||
bool CreatureLinkingHolder::CanSpawn(uint32 lowGuid, Map* _map, CreatureLinkingInfo const* pInfo, float sx, float sy) const
|
||||
{
|
||||
if (!pInfo) // Prepare data for recursive use
|
||||
{
|
||||
CreatureData const* data = sObjectMgr.GetCreatureData(lowGuid);
|
||||
if (!data)
|
||||
return true;
|
||||
pInfo = sCreatureLinkingMgr.GetLinkedTriggerInformation(data->id, lowGuid, data->mapid);
|
||||
if (!pInfo)
|
||||
return true;
|
||||
// Has lowGuid npc actually spawning linked?
|
||||
if (!sCreatureLinkingMgr.IsSpawnedByLinkedMob(pInfo))
|
||||
return true;
|
||||
|
||||
sx = data->posX; // Fill position data
|
||||
sy = data->posY;
|
||||
}
|
||||
|
||||
if (pInfo->searchRange == 0) // Map wide case
|
||||
{
|
||||
if (!pInfo->masterDBGuid)
|
||||
return false; // This should never happen
|
||||
|
||||
if (pInfo->linkingFlag & FLAG_CANT_SPAWN_IF_BOSS_DEAD)
|
||||
return pCreature->GetMap()->GetPersistentState()->GetCreatureRespawnTime(pInfo->masterDBGuid) == 0;
|
||||
return IsRespawnReady(pInfo->masterDBGuid, _map);
|
||||
else if (pInfo->linkingFlag & FLAG_CANT_SPAWN_IF_BOSS_ALIVE)
|
||||
return pCreature->GetMap()->GetPersistentState()->GetCreatureRespawnTime(pInfo->masterDBGuid) > 0;
|
||||
return !IsRespawnReady(pInfo->masterDBGuid, _map);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
// Search for nearby master
|
||||
BossGuidMapBounds finds = m_masterGuid.equal_range(pInfo->masterId);
|
||||
for (BossGuidMap::iterator itr = finds.first; itr != finds.second; ++itr)
|
||||
for (BossGuidMap::const_iterator itr = finds.first; itr != finds.second; ++itr)
|
||||
{
|
||||
Creature* pMaster = pCreature->GetMap()->GetCreature(itr->second);
|
||||
if (pMaster && IsSlaveInRangeOfBoss(pCreature, pMaster, pInfo->searchRange))
|
||||
Creature* pMaster = _map->GetCreature(itr->second);
|
||||
if (pMaster && IsSlaveInRangeOfBoss(pMaster, sx, sy, pInfo->searchRange))
|
||||
{
|
||||
if (pInfo->linkingFlag & FLAG_CANT_SPAWN_IF_BOSS_DEAD)
|
||||
return pMaster->IsAlive();
|
||||
|
|
@ -652,11 +717,11 @@ bool CreatureLinkingHolder::TryFollowMaster(Creature* pCreature)
|
|||
if (!pInfo || !(pInfo->linkingFlag & FLAG_FOLLOW))
|
||||
return false;
|
||||
|
||||
Creature* pMaster = NULL;
|
||||
Creature* pMaster = nullptr;
|
||||
if (pInfo->mapId != INVALID_MAP_ID) // entry case
|
||||
{
|
||||
BossGuidMapBounds finds = m_masterGuid.equal_range(pInfo->masterId);
|
||||
for (BossGuidMap::iterator itr = finds.first; itr != finds.second; ++itr)
|
||||
for (BossGuidMap::const_iterator itr = finds.first; itr != finds.second; ++itr)
|
||||
{
|
||||
pMaster = pCreature->GetMap()->GetCreature(itr->second);
|
||||
if (pMaster && IsSlaveInRangeOfBoss(pCreature, pMaster, pInfo->searchRange))
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
class Unit;
|
||||
class Creature;
|
||||
class Map;
|
||||
|
||||
// enum on which Events an action for linked NPCs can trigger
|
||||
enum CreatureLinkingEvent
|
||||
|
|
@ -111,17 +112,19 @@ class CreatureLinkingMgr
|
|||
|
||||
public: // Accessors
|
||||
// This functions checks if the NPC triggers actions for other NPCs
|
||||
bool IsLinkedEventTrigger(Creature* pCreature);
|
||||
bool IsLinkedEventTrigger(Creature* pCreature) const;
|
||||
|
||||
// This function checks if the NPC is a master NPC.
|
||||
bool IsLinkedMaster(Creature* pCreature);
|
||||
bool IsLinkedMaster(Creature* pCreature) const;
|
||||
|
||||
// This function checks if the spawning of this NPC is dependend on other NPCs
|
||||
bool IsSpawnedByLinkedMob(Creature* pCreature);
|
||||
bool IsSpawnedByLinkedMob(Creature* pCreature) const;
|
||||
bool IsSpawnedByLinkedMob(CreatureLinkingInfo const* pInfo) const;
|
||||
|
||||
// This gives the information of a linked NPC (describes action when its ActionTrigger triggers)
|
||||
// Depends of the map
|
||||
CreatureLinkingInfo const* GetLinkedTriggerInformation(Creature* pCreature);
|
||||
CreatureLinkingInfo const* GetLinkedTriggerInformation(Creature* pCreature) const;
|
||||
CreatureLinkingInfo const* GetLinkedTriggerInformation(uint32 entry, uint32 lowGuid, uint32 mapId) const;
|
||||
|
||||
private:
|
||||
typedef std::multimap < uint32 /*slaveEntry*/, CreatureLinkingInfo > CreatureLinkingMap;
|
||||
|
|
@ -162,7 +165,7 @@ class CreatureLinkingHolder
|
|||
void DoCreatureLinkingEvent(CreatureLinkingEvent eventType, Creature* pSource, Unit* pEnemy = NULL);
|
||||
|
||||
// Function to check if a passive spawning condition is met
|
||||
bool CanSpawn(Creature* pCreature);
|
||||
bool CanSpawn(Creature* pCreature) const;
|
||||
|
||||
// This function lets a slave refollow his master
|
||||
bool TryFollowMaster(Creature* pCreature);
|
||||
|
|
@ -185,7 +188,7 @@ class CreatureLinkingHolder
|
|||
typedef std::multimap < uint32 /*masterEntryOrGuid*/, InfoAndGuids > HolderMap;
|
||||
typedef std::pair<HolderMap::iterator, HolderMap::iterator> HolderMapBounds;
|
||||
typedef std::multimap < uint32 /*Entry*/, ObjectGuid > BossGuidMap;
|
||||
typedef std::pair<BossGuidMap::iterator, BossGuidMap::iterator> BossGuidMapBounds;
|
||||
typedef std::pair<BossGuidMap::const_iterator, BossGuidMap::const_iterator> BossGuidMapBounds;
|
||||
|
||||
// Helper function, to process a slave list
|
||||
void ProcessSlaveGuidList(CreatureLinkingEvent eventType, Creature* pSource, uint32 flag, uint16 searchRange, GuidList& slaveGuidList, Unit* pEnemy);
|
||||
|
|
@ -194,7 +197,12 @@ class CreatureLinkingHolder
|
|||
// Helper function to set following
|
||||
void SetFollowing(Creature* pWho, Creature* pWhom);
|
||||
// Helper function to return if a slave is in range of a boss
|
||||
bool IsSlaveInRangeOfBoss(Creature* pSlave, Creature* pBoss, uint16 searchRange);
|
||||
bool IsSlaveInRangeOfBoss(Creature const* pSlave, Creature const* pBoss, uint16 searchRange) const;
|
||||
bool IsSlaveInRangeOfBoss(Creature const* pBoss, float slaveX, float slaveY, uint16 searchRange) const;
|
||||
// Another helper function
|
||||
bool IsRespawnReady(uint32 dbLowGuid, Map* _map) const;
|
||||
// Helper function for recursive spawning-checks of an additional linked
|
||||
bool CanSpawn(uint32 lowGuid, Map* _map, CreatureLinkingInfo const* pInfo, float sx, float sy) const;
|
||||
|
||||
// Storage of Data (boss, flag, searchRange, GuidList) for action triggering
|
||||
HolderMap m_holderMap;
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ namespace MaNGOS
|
|||
|
||||
inline bool IsValidMapCoord(float c)
|
||||
{
|
||||
return finite(c) && (std::fabs(c) <= MAP_HALFSIZE - 0.5);
|
||||
return std::isfinite(c) && (std::fabs(c) <= MAP_HALFSIZE - 0.5);
|
||||
}
|
||||
|
||||
inline bool IsValidMapCoord(float x, float y)
|
||||
|
|
@ -184,12 +184,12 @@ namespace MaNGOS
|
|||
|
||||
inline bool IsValidMapCoord(float x, float y, float z)
|
||||
{
|
||||
return IsValidMapCoord(x, y) && finite(z);
|
||||
return IsValidMapCoord(x, y) && std::isfinite(z);
|
||||
}
|
||||
|
||||
inline bool IsValidMapCoord(float x, float y, float z, float o)
|
||||
{
|
||||
return IsValidMapCoord(x, y, z) && finite(o);
|
||||
return IsValidMapCoord(x, y, z) && std::isfinite(o);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ char const* MAP_AREA_MAGIC = "AREA";
|
|||
char const* MAP_HEIGHT_MAGIC = "MHGT";
|
||||
char const* MAP_LIQUID_MAGIC = "MLIQ";
|
||||
|
||||
static uint16 holetab_h[4] = { 0x1111, 0x2222, 0x4444, 0x8888 };
|
||||
static uint16 holetab_v[4] = { 0x000F, 0x00F0, 0x0F00, 0xF000 };
|
||||
|
||||
GridMap::GridMap()
|
||||
{
|
||||
m_flags = 0;
|
||||
|
|
@ -1061,6 +1064,23 @@ bool TerrainInfo::IsInWater(float x, float y, float pZ, GridMapLiquidData* data)
|
|||
return false;
|
||||
}
|
||||
|
||||
// check if creature is in water and have enough space to swim
|
||||
bool TerrainInfo::IsSwimmable(float x, float y, float pZ, float radius /*= 1.5f*/, GridMapLiquidData* data /*= 0*/) const
|
||||
{
|
||||
// Check surface in x, y point for liquid
|
||||
if (const_cast<TerrainInfo*>(this)->GetGrid(x, y))
|
||||
{
|
||||
GridMapLiquidData liquid_status;
|
||||
GridMapLiquidData* liquid_ptr = data ? data : &liquid_status;
|
||||
if (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr))
|
||||
{
|
||||
if (liquid_ptr->level - liquid_ptr->depth_level > radius) // is unit have enough space to swim
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TerrainInfo::IsUnderWater(float x, float y, float z) const
|
||||
{
|
||||
if (const_cast<TerrainInfo*>(this)->GetGrid(x, y))
|
||||
|
|
|
|||
|
|
@ -231,6 +231,7 @@ class TerrainInfo : public Referencable<AtomicLong>
|
|||
float GetWaterLevel(float x, float y, float z, float* pGround = NULL) const;
|
||||
float GetWaterOrGroundLevel(float x, float y, float z, float* pGround = NULL, bool swim = false) const;
|
||||
bool IsInWater(float x, float y, float z, GridMapLiquidData* data = 0) const;
|
||||
bool IsSwimmable(float x, float y, float pZ, float radius = 1.5f, GridMapLiquidData* data = nullptr) const;
|
||||
bool IsUnderWater(float x, float y, float z) const;
|
||||
|
||||
GridMapLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, GridMapLiquidData* data = 0) const;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,9 @@ enum LootMethod
|
|||
ROUND_ROBIN = 1,
|
||||
MASTER_LOOT = 2,
|
||||
GROUP_LOOT = 3,
|
||||
NEED_BEFORE_GREED = 4
|
||||
NEED_BEFORE_GREED = 4,
|
||||
|
||||
NOT_GROUP_TYPE_LOOT = 5 // internal use only
|
||||
};
|
||||
|
||||
enum RollVote
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ bool WorldSession::CheckMailBox(ObjectGuid guid)
|
|||
Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE);
|
||||
if (!creature)
|
||||
{
|
||||
DEBUG_LOG("%s not found or %s can't interact with him.", creature->GetGuidStr().c_str(), GetPlayer()->GetGuidStr().c_str());
|
||||
DEBUG_LOG("%s not found or %s can't interact with him.", guid.GetString().c_str(), GetPlayer()->GetGuidStr().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -298,13 +298,16 @@ bool Map::EnsureGridLoaded(const Cell& cell)
|
|||
return false;
|
||||
}
|
||||
|
||||
void Map::LoadGrid(const Cell& cell, bool no_unload)
|
||||
void Map::ForceLoadGrid(float x, float y)
|
||||
{
|
||||
EnsureGridLoaded(cell);
|
||||
|
||||
if (no_unload)
|
||||
if (!IsLoaded(x, y))
|
||||
{
|
||||
CellPair p = MaNGOS::ComputeCellPair(x, y);
|
||||
Cell cell(p);
|
||||
EnsureGridLoadedAtEnter(cell);
|
||||
getNGrid(cell.GridX(), cell.GridY())->setUnloadExplicitLock(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool Map::Add(Player* player)
|
||||
{
|
||||
|
|
@ -2116,6 +2119,61 @@ bool Map::GetHitPosition(float srcX, float srcY, float srcZ, float& destX, float
|
|||
return result0 || result1;
|
||||
}
|
||||
|
||||
// Find an height within a reasonable range of provided Z. This method may fail so we have to handle that case.
|
||||
bool Map::GetHeightInRange(uint32 phasemask, float x, float y, float& z, float maxSearchDist /*= 4.0f*/) const
|
||||
{
|
||||
float height, vmapHeight, mapHeight;
|
||||
vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
|
||||
|
||||
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
|
||||
if (!vmgr->isLineOfSightCalcEnabled())
|
||||
vmgr = nullptr;
|
||||
|
||||
if (vmgr)
|
||||
{
|
||||
// pure vmap search
|
||||
vmapHeight = vmgr->getHeight(i_id, x, y, z + 2.0f, maxSearchDist + 2.0f);
|
||||
}
|
||||
|
||||
// find raw height from .map file on X,Y coordinates
|
||||
if (GridMap* gmap = const_cast<TerrainInfo*>(m_TerrainData)->GetGrid(x, y)) // TODO:: find a way to remove that const_cast
|
||||
mapHeight = gmap->getHeight(x, y);
|
||||
|
||||
float diffMaps = fabs(fabs(z) - fabs(mapHeight));
|
||||
float diffVmaps = fabs(fabs(z) - fabs(vmapHeight));
|
||||
if (diffVmaps < maxSearchDist)
|
||||
{
|
||||
if (diffMaps < maxSearchDist)
|
||||
{
|
||||
// well we simply have to take the highest as normally there we cannot be on top of cavern is maxSearchDist is not too big
|
||||
if (vmapHeight > mapHeight)
|
||||
height = vmapHeight;
|
||||
else
|
||||
height = mapHeight;
|
||||
|
||||
//sLog.outString("vmap %5.4f, map %5.4f, height %5.4f", vmapHeight, mapHeight, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
//sLog.outString("vmap %5.4f", vmapHeight);
|
||||
height = vmapHeight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (diffMaps < maxSearchDist)
|
||||
{
|
||||
//sLog.outString("map %5.4f", mapHeight);
|
||||
height = mapHeight;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
z = std::max<float>(height, m_dyn_tree.getHeight(x, y, height + 1.0f, maxSearchDist, phasemask));
|
||||
return true;
|
||||
}
|
||||
|
||||
float Map::GetHeight(uint32 phasemask, float x, float y, float z) const
|
||||
{
|
||||
float staticHeight = m_TerrainData->GetHeightStatic(x, y, z);
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ class Map : public GridRefManager<NGridType>
|
|||
|
||||
bool GetUnloadLock(const GridPair& p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); }
|
||||
void SetUnloadLock(const GridPair& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); }
|
||||
void LoadGrid(const Cell& cell, bool no_unload = false);
|
||||
void ForceLoadGrid(float x, float y);
|
||||
bool UnloadGrid(const uint32& x, const uint32& y, bool pForce);
|
||||
virtual void UnloadAll(bool pForce);
|
||||
|
||||
|
|
@ -194,7 +194,6 @@ class Map : public GridRefManager<NGridType>
|
|||
MapDifficultyEntry const* GetMapDifficulty() const; // dependent from map difficulty
|
||||
|
||||
bool Instanceable() const { return i_mapEntry && i_mapEntry->Instanceable(); }
|
||||
// NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable
|
||||
bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); }
|
||||
bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); }
|
||||
bool IsHeroic() const { return IsRaid() ? i_spawnMode >= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; }
|
||||
|
|
@ -203,6 +202,7 @@ class Map : public GridRefManager<NGridType>
|
|||
bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); }
|
||||
bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
|
||||
bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); }
|
||||
bool IsContinent() const { return i_mapEntry && i_mapEntry->IsContinent(); }
|
||||
|
||||
// can't be NULL for loaded map
|
||||
MapPersistentState* GetPersistentState() const { return m_persistentState; }
|
||||
|
|
|
|||
|
|
@ -92,30 +92,30 @@ void MapManager::InitializeVisibilityDistanceInfo()
|
|||
(*iter).second->InitVisibilityDistance();
|
||||
}
|
||||
|
||||
/// @param id - MapId of the to be created map. @param obj WorldObject for which the map is to be created. Must be player for Instancable maps.
|
||||
Map* MapManager::CreateMap(uint32 id, const WorldObject* obj)
|
||||
{
|
||||
MANGOS_ASSERT(obj);
|
||||
// if(!obj->IsInWorld()) sLog.outError("GetMap: called for map %d with object (typeid %d, guid %d, mapid %d, instanceid %d) who is not in world!", id, obj->GetTypeId(), obj->GetGUIDLow(), obj->GetMapId(), obj->GetInstanceId());
|
||||
Guard _guard(*this);
|
||||
|
||||
Map* m = NULL;
|
||||
Map* m = nullptr;
|
||||
|
||||
const MapEntry* entry = sMapStore.LookupEntry(id);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
if (entry->Instanceable())
|
||||
{
|
||||
MANGOS_ASSERT(obj->GetTypeId() == TYPEID_PLAYER);
|
||||
MANGOS_ASSERT(obj && obj->GetTypeId() == TYPEID_PLAYER);
|
||||
// create DungeonMap object
|
||||
if (obj->GetTypeId() == TYPEID_PLAYER)
|
||||
m = CreateInstance(id, (Player*)obj);
|
||||
// Load active objects for this map
|
||||
sObjectMgr.LoadActiveEntities(m);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create regular non-instanceable map
|
||||
m = FindMap(id);
|
||||
if (m == NULL)
|
||||
if (m == nullptr)
|
||||
{
|
||||
m = new WorldMap(id, i_gridCleanUpDelay);
|
||||
// add map into container
|
||||
|
|
|
|||
|
|
@ -94,7 +94,6 @@ class MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::ClassLevelLockab
|
|||
i_timer.Reset();
|
||||
}
|
||||
|
||||
// void LoadGrid(int mapid, int instId, float x, float y, const WorldObject* obj, bool no_unload = false);
|
||||
void UnloadAll();
|
||||
|
||||
static bool ExistMapAndVMap(uint32 mapid, float x, float y);
|
||||
|
|
|
|||
|
|
@ -280,7 +280,6 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recv_data*/)
|
|||
|
||||
// Can not logout if...
|
||||
if (GetPlayer()->IsInCombat() || //...is in combat
|
||||
GetPlayer()->duel || //...is in Duel
|
||||
//...is jumping ...is falling
|
||||
GetPlayer()->m_movementInfo.HasMovementFlag(MovementFlags(MOVEFLAG_FALLING | MOVEFLAG_FALLINGFAR)))
|
||||
{
|
||||
|
|
@ -1082,12 +1081,16 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recv_data)
|
|||
recv_data >> guid;
|
||||
DEBUG_LOG("Inspected guid is %s", guid.GetString().c_str());
|
||||
|
||||
_player->SetSelectionGuid(guid);
|
||||
|
||||
Player* plr = sObjectMgr.GetPlayer(guid);
|
||||
if (!plr) // wrong player
|
||||
return;
|
||||
|
||||
if (!_player->IsWithinDistInMap(plr, INSPECT_DISTANCE, false))
|
||||
return;
|
||||
|
||||
if (_player->IsHostileTo(plr))
|
||||
return;
|
||||
|
||||
WorldPacket data(SMSG_INSPECT_RESULTS, 50);
|
||||
data << plr->GetObjectGuid();
|
||||
|
||||
|
|
@ -1119,13 +1122,18 @@ void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data)
|
|||
recv_data.ReadGuidBytes<4, 7, 0, 5, 1, 6, 2, 3>(guid);
|
||||
|
||||
Player* player = sObjectMgr.GetPlayer(guid);
|
||||
|
||||
if (!player)
|
||||
{
|
||||
sLog.outError("InspectHonorStats: WTF, player not found...");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_player->IsWithinDistInMap(player, INSPECT_DISTANCE, false))
|
||||
return;
|
||||
|
||||
if (_player->IsHostileTo(player))
|
||||
return;
|
||||
|
||||
WorldPacket data(SMSG_INSPECT_HONOR_STATS, 18);
|
||||
data.WriteGuidMask<4, 3, 6, 2, 5, 0, 7, 1>(player->GetObjectGuid());
|
||||
data << uint8(0); // rank
|
||||
|
|
@ -1520,7 +1528,16 @@ void WorldSession::HandleQueryInspectAchievementsOpcode(WorldPacket& recv_data)
|
|||
|
||||
recv_data >> guid.ReadAsPacked();
|
||||
|
||||
if (Player* player = sObjectMgr.GetPlayer(guid))
|
||||
Player* player = sObjectMgr.GetPlayer(guid);
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
if (!_player->IsWithinDistInMap(player, INSPECT_DISTANCE, false))
|
||||
return;
|
||||
|
||||
if (_player->IsHostileTo(player))
|
||||
return;
|
||||
|
||||
player->GetAchievementMgr().SendRespondInspectAchievements(_player);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -477,6 +477,20 @@ void WorldSession::SendSpiritResurrect()
|
|||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleReturnToGraveyardOpcode(WorldPacket& recv_data)
|
||||
{
|
||||
Corpse* corpse = _player->GetCorpse();
|
||||
if (!corpse)
|
||||
return;
|
||||
|
||||
WorldSafeLocsEntry const* corpseGrave = sObjectMgr.GetClosestGraveYard(corpse->GetPositionX(), corpse->GetPositionY(),
|
||||
corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam());
|
||||
if (!corpseGrave)
|
||||
return;
|
||||
|
||||
_player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation());
|
||||
}
|
||||
|
||||
void WorldSession::HandleBinderActivateOpcode(WorldPacket& recv_data)
|
||||
{
|
||||
ObjectGuid npcGuid;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ void WorldSession::HandleLearnTalentOpcode(WorldPacket& recv_data)
|
|||
_player->SendTalentsInfoData(false);
|
||||
else
|
||||
sLog.outError("WorldSession::HandleLearnTalentOpcode: learn talent %u rank %u failed for %s (account %u)", talent_id, requested_rank, GetPlayerName(), GetAccountId());
|
||||
|
||||
// if player has a pet, update owner talent auras
|
||||
if (_player->GetPet())
|
||||
_player->GetPet()->CastOwnerTalentAuras();
|
||||
}
|
||||
|
||||
void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket)
|
||||
|
|
@ -84,6 +88,10 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket)
|
|||
}
|
||||
|
||||
_player->SendTalentsInfoData(false);
|
||||
|
||||
// if player has a pet, update owner talent auras
|
||||
if (_player->GetPet())
|
||||
_player->GetPet()->CastOwnerTalentAuras();
|
||||
}
|
||||
|
||||
void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recv_data)
|
||||
|
|
@ -99,9 +107,8 @@ void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recv_data)
|
|||
return;
|
||||
}
|
||||
|
||||
// remove fake death
|
||||
if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
|
||||
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
|
||||
if (!unit->CanTrainAndResetTalentsOf(_player))
|
||||
return;
|
||||
|
||||
if (!(_player->resetTalents()))
|
||||
{
|
||||
|
|
@ -114,6 +121,8 @@ void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recv_data)
|
|||
|
||||
_player->SendTalentsInfoData(false);
|
||||
unit->CastSpell(_player, 14867, true); // spell: "Untalent Visual Effect"
|
||||
if (_player->GetPet())
|
||||
_player->GetPet()->CastOwnerTalentAuras();
|
||||
}
|
||||
|
||||
void WorldSession::HandleUnlearnSkillOpcode(WorldPacket& recv_data)
|
||||
|
|
|
|||
|
|
@ -520,8 +520,8 @@ void Spell::FillTargetMap()
|
|||
// for TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT (A) all is checked in Spell::CheckCast and in Spell::CheckItem
|
||||
// filled in Spell::CheckCast call
|
||||
if (spellEffect->EffectImplicitTargetA == TARGET_SCRIPT_COORDINATES ||
|
||||
spellEffect->EffectImplicitTargetA == TARGET_SCRIPT ||
|
||||
spellEffect->EffectImplicitTargetA == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT ||
|
||||
(spellEffect->EffectImplicitTargetA == TARGET_SCRIPT && spellEffect->EffectImplicitTargetB != TARGET_SELF) ||
|
||||
(spellEffect->EffectImplicitTargetB == TARGET_SCRIPT && spellEffect->EffectImplicitTargetA != TARGET_SELF))
|
||||
continue;
|
||||
|
||||
|
|
@ -571,8 +571,9 @@ void Spell::FillTargetMap()
|
|||
case TARGET_SELF:
|
||||
switch(spellEffect->EffectImplicitTargetB)
|
||||
{
|
||||
case TARGET_NONE:
|
||||
case TARGET_NONE: // Fill Target based on A only
|
||||
case TARGET_EFFECT_SELECT:
|
||||
case TARGET_SCRIPT: // B-target only used with CheckCast here
|
||||
SetTargetMap(SpellEffectIndex(i), spellEffect->EffectImplicitTargetA, tmpUnitLists[i /*==effToIndex[i]*/]);
|
||||
break;
|
||||
case TARGET_AREAEFFECT_INSTANT: // use B case that not dependent from from A in fact
|
||||
|
|
@ -716,6 +717,17 @@ void Spell::FillTargetMap()
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case TARGET_SCRIPT:
|
||||
switch (spellEffect->EffectImplicitTargetB)
|
||||
{
|
||||
case TARGET_SELF:
|
||||
// Fill target based on B only, A is only used with CheckCast here.
|
||||
SetTargetMap(SpellEffectIndex(i), spellEffect->EffectImplicitTargetB, tmpUnitLists[i /*==effToIndex[i]*/]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch(spellEffect->EffectImplicitTargetB)
|
||||
{
|
||||
|
|
@ -3273,6 +3285,9 @@ void Spell::cast(bool skipCheck)
|
|||
// Chaos Bane strength buff
|
||||
else if (m_spellInfo->Id == 71904)
|
||||
AddTriggeredSpell(73422);
|
||||
// Weak Alcohol
|
||||
else if (m_spellInfo->SpellIconID == 1306 && m_spellInfo->SpellVisual[0] == 11359)
|
||||
AddTriggeredSpell(51655); // BOTM - Create Empty Brew Bottle
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_MAGE:
|
||||
|
|
@ -3710,14 +3725,20 @@ void Spell::update(uint32 difftime)
|
|||
SpellEffectEntry const* spellEffect = m_spellInfo->GetSpellEffect(EFFECT_INDEX_0);
|
||||
SpellInterruptsEntry const* spellInterrupts = m_spellInfo->GetSpellInterrupts();
|
||||
|
||||
// check if the player caster has moved before the spell finished
|
||||
if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
|
||||
if (m_CastItemGuid && !m_CastItem)
|
||||
{
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
// check if the player or unit caster has moved before the spell finished (exclude casting on vehicles)
|
||||
if (((m_caster->GetTypeId() == TYPEID_PLAYER || m_caster->GetTypeId() == TYPEID_UNIT) && m_timer != 0) &&
|
||||
(m_castPositionX != m_caster->GetPositionX() || m_castPositionY != m_caster->GetPositionY() || m_castPositionZ != m_caster->GetPositionZ()) &&
|
||||
((spellEffect && spellEffect->Effect != SPELL_EFFECT_STUCK) || !((Player*)m_caster)->m_movementInfo.HasMovementFlag(MOVEFLAG_FALLINGFAR)) &&
|
||||
!m_caster->HasAffectedAura(SPELL_AURA_ALLOW_CAST_WHILE_MOVING, m_spellInfo))
|
||||
{
|
||||
// always cancel for channeled spells
|
||||
if (m_spellState == SPELL_STATE_CASTING)
|
||||
if (m_spellState == SPELL_STATE_CASTING && !m_spellInfo->HasAttribute(SPELL_ATTR_EX5_CAN_CHANNEL_WHEN_MOVING))
|
||||
cancel();
|
||||
// don't cancel for melee, autorepeat, triggered and instant spells
|
||||
else if(!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !m_IsTriggeredSpell && (spellInterrupts && spellInterrupts->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT))
|
||||
|
|
@ -3743,16 +3764,20 @@ void Spell::update(uint32 difftime)
|
|||
{
|
||||
if (m_timer > 0)
|
||||
{
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER || m_caster->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
// check if player has jumped before the channeling finished
|
||||
if (((Player*)m_caster)->m_movementInfo.HasMovementFlag(MOVEFLAG_FALLING) &&
|
||||
if (m_caster->m_movementInfo.HasMovementFlag(MOVEFLAG_FALLING) &&
|
||||
!m_caster->HasAffectedAura(SPELL_AURA_ALLOW_CAST_WHILE_MOVING, m_spellInfo))
|
||||
cancel();
|
||||
|
||||
// check for incapacitating player states
|
||||
if (m_caster->hasUnitState(UNIT_STAT_CAN_NOT_REACT))
|
||||
{
|
||||
// certain channel spells are not interrupted
|
||||
if (!m_spellInfo->HasAttribute(SPELL_ATTR_EX_CHANNELED_1) && !m_spellInfo->HasAttribute(SPELL_ATTR_EX3_UNK28))
|
||||
cancel();
|
||||
}
|
||||
|
||||
// check if player has turned if flag is set
|
||||
if( spellInterrupts && (spellInterrupts->ChannelInterruptFlags & CHANNEL_FLAG_TURNING) && m_castOrientation != m_caster->GetOrientation() )
|
||||
|
|
@ -3790,7 +3815,7 @@ void Spell::update(uint32 difftime)
|
|||
continue;
|
||||
|
||||
Unit* unit = m_caster->GetObjectGuid() == target.targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, target.targetGUID);
|
||||
if (unit == NULL)
|
||||
if (unit == nullptr)
|
||||
continue;
|
||||
|
||||
p->RewardPlayerAndGroupAtCast(unit, m_spellInfo->Id);
|
||||
|
|
@ -4082,7 +4107,7 @@ void Spell::SendSpellStart()
|
|||
data << uint8(m_runesState);
|
||||
data << uint8(caster->GetRunesState());
|
||||
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
||||
data << uint8(255 - ((caster->GetRuneCooldown(i) / REGEN_TIME_FULL) * 51));
|
||||
data << uint8(caster->GetRuneCooldownFraction(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -4702,6 +4727,7 @@ void Spell::TakePower()
|
|||
if (m_spellInfo->powerType == POWER_HEALTH)
|
||||
{
|
||||
m_caster->ModifyHealth(-(int32)m_powerCost);
|
||||
m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, m_powerCost, GetSpellSchoolMask(m_spellInfo), 0, 0, false, 0, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -4740,14 +4766,14 @@ void Spell::TakePower()
|
|||
|
||||
if (powerType == POWER_RUNE)
|
||||
{
|
||||
CheckOrTakeRunePower(hit);
|
||||
TakeRunePower(hit);
|
||||
return;
|
||||
}
|
||||
|
||||
m_caster->ModifyPower(powerType, -(int32)m_powerCost);
|
||||
}
|
||||
|
||||
SpellCastResult Spell::CheckOrTakeRunePower(bool take)
|
||||
SpellCastResult Spell::CheckRunePower()
|
||||
{
|
||||
if (m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||
return SPELL_CAST_OK;
|
||||
|
|
@ -4758,83 +4784,127 @@ SpellCastResult Spell::CheckOrTakeRunePower(bool take)
|
|||
return SPELL_CAST_OK;
|
||||
|
||||
SpellRuneCostEntry const* src = sSpellRuneCostStore.LookupEntry(m_spellInfo->runeCostID);
|
||||
if (!src || (src->NoRuneCost() && (!take || src->NoRunicPowerGain())))
|
||||
|
||||
if (!src)
|
||||
return SPELL_CAST_OK;
|
||||
|
||||
m_runesState = plr->GetRunesState(); // store previous state
|
||||
if (src->NoRuneCost())
|
||||
return SPELL_CAST_OK;
|
||||
|
||||
// at this moment for rune cost exist only no cost mods, and no percent mods
|
||||
int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death
|
||||
|
||||
// init cost data and apply mods
|
||||
for (uint8 i = 0; i < RUNE_DEATH; ++i)
|
||||
for (uint32 i = 0; i < RUNE_DEATH; ++i)
|
||||
{
|
||||
runeCost[i] = src->RuneCost[i];
|
||||
if (Player* modOwner = plr->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, runeCost[i], this);
|
||||
if (Player* modOwner = m_caster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, runeCost[i]);
|
||||
}
|
||||
|
||||
|
||||
runeCost[RUNE_DEATH] = MAX_RUNES; // calculated later
|
||||
|
||||
// scan non-death runes (death rune not used explicitly in rune costs)
|
||||
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
// already used
|
||||
if (plr->GetRuneCooldown(i) != 0)
|
||||
continue;
|
||||
|
||||
RuneType rune = plr->GetCurrentRune(i);
|
||||
if (plr->GetRuneCooldown(i) == 0 && runeCost[rune] > 0)
|
||||
for (uint32 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
RuneType rune = plr->GetCurrentRune(i);
|
||||
if (runeCost[rune] <= 0)
|
||||
continue;
|
||||
if (!plr->GetRuneCooldown(i) && runeCost[rune] > 0)
|
||||
--runeCost[rune];
|
||||
}
|
||||
|
||||
// already used
|
||||
if (plr->GetRuneCooldown(i) != 0)
|
||||
continue;
|
||||
for (uint32 i = 0; i < RUNE_DEATH; ++i)
|
||||
if (runeCost[i] > 0)
|
||||
runeCost[RUNE_DEATH] += runeCost[i];
|
||||
|
||||
if (take)
|
||||
plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec
|
||||
if (runeCost[RUNE_DEATH] > MAX_RUNES)
|
||||
return SPELL_FAILED_NO_POWER; // not sure if result code is correct
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
void Spell::TakeRunePower(bool hit)
|
||||
{
|
||||
if (m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
Player* plr = (Player*)m_caster;
|
||||
|
||||
if (plr->getClass() != CLASS_DEATH_KNIGHT)
|
||||
return;
|
||||
|
||||
SpellRuneCostEntry const* src = sSpellRuneCostStore.LookupEntry(m_spellInfo->runeCostID);
|
||||
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
if (src->NoRuneCost() && src->NoRunicPowerGain())
|
||||
return;
|
||||
|
||||
m_runesState = plr->GetRunesState(); // store previous state
|
||||
|
||||
// at this moment for rune cost exist only no cost mods, and no percent mods
|
||||
int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death
|
||||
for (uint32 i = 0; i < RUNE_DEATH; ++i)
|
||||
{
|
||||
runeCost[i] = src->RuneCost[i];
|
||||
if (Player* modOwner = m_caster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, runeCost[i]);
|
||||
}
|
||||
|
||||
runeCost[RUNE_DEATH] = 0; // calculated later
|
||||
|
||||
plr->ClearLastUsedRuneMask();
|
||||
|
||||
for (uint32 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
RuneType rune = plr->GetCurrentRune(i);
|
||||
if (!plr->GetRuneCooldown(i) && runeCost[rune] > 0)
|
||||
{
|
||||
uint16 baseCd = hit ? uint16(RUNE_BASE_COOLDOWN) : uint16(RUNE_MISS_COOLDOWN);
|
||||
plr->SetBaseRuneCooldown(i, baseCd);
|
||||
plr->SetRuneCooldown(i, baseCd);
|
||||
plr->SetLastUsedRune(rune);
|
||||
--runeCost[rune];
|
||||
}
|
||||
}
|
||||
|
||||
// collect all not counted rune costs to death runes cost
|
||||
for (uint8 i = 0; i < RUNE_DEATH; ++i)
|
||||
if (runeCost[i] > 0)
|
||||
runeCost[RUNE_DEATH] += runeCost[i];
|
||||
runeCost[RUNE_DEATH] = runeCost[RUNE_BLOOD] + runeCost[RUNE_UNHOLY] + runeCost[RUNE_FROST];
|
||||
|
||||
// scan death runes
|
||||
if (runeCost[RUNE_DEATH] > 0)
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
||||
for (uint32 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
RuneType rune = plr->GetCurrentRune(i);
|
||||
if (!plr->GetRuneCooldown(i) && rune == RUNE_DEATH)
|
||||
{
|
||||
plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec
|
||||
runeCost[rune]--;
|
||||
uint16 baseCd = hit ? uint16(RUNE_BASE_COOLDOWN) : uint16(RUNE_MISS_COOLDOWN);
|
||||
plr->SetBaseRuneCooldown(i, baseCd);
|
||||
plr->SetRuneCooldown(i, baseCd);
|
||||
plr->SetLastUsedRune(rune);
|
||||
--runeCost[rune];
|
||||
|
||||
if (take)
|
||||
plr->ConvertRune(i, plr->GetBaseRune(i));
|
||||
// keep Death Rune type if missed
|
||||
if (hit)
|
||||
plr->RestoreBaseRune(i);
|
||||
|
||||
if (runeCost[RUNE_DEATH] == 0)
|
||||
return SPELL_FAILED_NO_POWER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (take)
|
||||
if (hit)
|
||||
{
|
||||
// you can gain some runic power when use runes
|
||||
float rp = float(src->runePowerGain);
|
||||
rp *= sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_RUNICPOWER_INCOME);
|
||||
int32 rp = int32(src->runePowerGain);
|
||||
if (rp)
|
||||
{
|
||||
if (Player* modOwner = m_caster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, rp);
|
||||
|
||||
rp = int32(sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_RUNICPOWER_INCOME) * rp);
|
||||
rp += m_caster->GetTotalAuraModifier(SPELL_AURA_MOD_RUNIC_POWER_REGEN) * rp / 100;
|
||||
if (rp > 0)
|
||||
plr->ModifyPower(POWER_RUNIC_POWER, (int32)rp);
|
||||
}
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::TakeReagents()
|
||||
|
|
@ -5437,12 +5507,12 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||
continue;
|
||||
|
||||
if (spellEffect->EffectImplicitTargetA == TARGET_SCRIPT ||
|
||||
(spellEffect->EffectImplicitTargetB == TARGET_SCRIPT && spellEffect->EffectImplicitTargetA != TARGET_SELF) ||
|
||||
spellEffect->EffectImplicitTargetB == TARGET_SCRIPT ||
|
||||
spellEffect->EffectImplicitTargetA == TARGET_SCRIPT_COORDINATES ||
|
||||
spellEffect->EffectImplicitTargetB == TARGET_SCRIPT_COORDINATES ||
|
||||
spellEffect->EffectImplicitTargetA == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT)
|
||||
spellEffect->EffectImplicitTargetA == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT ||
|
||||
spellEffect->EffectImplicitTargetB == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT)
|
||||
{
|
||||
|
||||
SQLMultiStorage::SQLMSIteratorBounds<SpellTargetEntry> bounds = sSpellScriptTargetStorage.getBounds<SpellTargetEntry>(m_spellInfo->Id);
|
||||
|
||||
if (bounds.first == bounds.second)
|
||||
|
|
@ -5453,13 +5523,17 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||
if (spellEffect->EffectImplicitTargetA == TARGET_SCRIPT_COORDINATES || spellEffect->EffectImplicitTargetB == TARGET_SCRIPT_COORDINATES)
|
||||
sLog.outErrorDb("Spell entry %u, effect %i has EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT_COORDINATES, but gameobject or creature are not defined in `spell_script_target`", m_spellInfo->Id, j);
|
||||
|
||||
if (spellEffect->EffectImplicitTargetA == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT)
|
||||
if (spellEffect->EffectImplicitTargetA == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT || spellEffect->EffectImplicitTargetB == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT)
|
||||
sLog.outErrorDb("Spell entry %u, effect %i has EffectImplicitTargetA/EffectImplicitTargetB = TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT, but gameobject are not defined in `spell_script_target`", m_spellInfo->Id, j);
|
||||
}
|
||||
|
||||
SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
|
||||
float range = GetSpellMaxRange(srange);
|
||||
|
||||
// override range with default when it's not provided
|
||||
if (!range)
|
||||
range = m_caster->GetMap()->IsDungeon() ? DEFAULT_VISIBILITY_INSTANCE : DEFAULT_VISIBILITY_DISTANCE;
|
||||
|
||||
Creature* targetExplicit = NULL; // used for cases where a target is provided (by script for example)
|
||||
Creature* creatureScriptTarget = NULL;
|
||||
GameObject* goScriptTarget = NULL;
|
||||
|
|
@ -5905,12 +5979,6 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||
if (ReqValue > skillValue)
|
||||
return SPELL_FAILED_LOW_CASTLEVEL;
|
||||
|
||||
// chance for fail at orange skinning attempt
|
||||
if ((m_selfContainer && (*m_selfContainer) == this) &&
|
||||
skillValue < sWorld.GetConfigMaxSkillValue() &&
|
||||
(ReqValue < 0 ? 0 : ReqValue) > irand(skillValue - 25, skillValue + 37))
|
||||
return SPELL_FAILED_TRY_AGAIN;
|
||||
|
||||
break;
|
||||
}
|
||||
case SPELL_EFFECT_OPEN_LOCK:
|
||||
|
|
@ -5962,9 +6030,10 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||
if (res != SPELL_CAST_OK)
|
||||
return res;
|
||||
|
||||
// chance for fail at orange mining/herb/LockPicking gathering attempt
|
||||
// Failing gathering attempt for mining and herbalism was removed in patch 3.1.0: http://wowwiki.wikia.com/wiki/Patch_3.1.0
|
||||
// chance for fail at orange LockPicking gathering attempt
|
||||
// second check prevent fail at rechecks
|
||||
if (skillId != SKILL_NONE && (!m_selfContainer || ((*m_selfContainer) != this)))
|
||||
if (m_spellState != SPELL_STATE_CREATED && skillId != SKILL_NONE && skillId != SKILL_HERBALISM && skillId != SKILL_MINING )
|
||||
{
|
||||
bool canFailAtMax = skillId != SKILL_HERBALISM && skillId != SKILL_MINING;
|
||||
|
||||
|
|
@ -5972,7 +6041,6 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||
if ((canFailAtMax || skillValue < sWorld.GetConfigMaxSkillValue()) && reqSkillValue > irand(skillValue - 25, skillValue + 37))
|
||||
return SPELL_FAILED_TRY_AGAIN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPELL_EFFECT_SUMMON_DEAD_PET:
|
||||
{
|
||||
|
|
@ -6823,7 +6891,7 @@ SpellCastResult Spell::CheckPower()
|
|||
// check rune cost only if a spell has PowerType == POWER_RUNE
|
||||
if (m_spellInfo->powerType == POWER_RUNE)
|
||||
{
|
||||
SpellCastResult failReason = CheckOrTakeRunePower(false);
|
||||
SpellCastResult failReason = CheckRunePower();
|
||||
if (failReason != SPELL_CAST_OK)
|
||||
return failReason;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,10 +235,12 @@ inline ByteBuffer& operator>> (ByteBuffer& buf, SpellCastTargetsReader const& ta
|
|||
|
||||
enum SpellState
|
||||
{
|
||||
SPELL_STATE_PREPARING = 0, // cast time delay period, non channeled spell
|
||||
SPELL_STATE_CASTING = 1, // channeled time period spell casting state
|
||||
SPELL_STATE_FINISHED = 2, // cast finished to success or fail
|
||||
SPELL_STATE_DELAYED = 3 // spell casted but need time to hit target(s)
|
||||
SPELL_STATE_CREATED = 0, // just created
|
||||
SPELL_STATE_STARTING = 1, // doing initial check
|
||||
SPELL_STATE_PREPARING = 2, // cast time delay period, non channeled spell
|
||||
SPELL_STATE_CASTING = 3, // channeled time period spell casting state
|
||||
SPELL_STATE_FINISHED = 4, // cast finished to success or fail
|
||||
SPELL_STATE_DELAYED = 5 // spell casted but need time to hit target(s)
|
||||
};
|
||||
|
||||
enum SpellTargets
|
||||
|
|
@ -396,6 +398,7 @@ class Spell
|
|||
void cast(bool skipCheck = false);
|
||||
void finish(bool ok = true);
|
||||
void TakePower();
|
||||
void TakeRunePower(bool hit);
|
||||
void TakeAmmo();
|
||||
void TakeReagents();
|
||||
void TakeCastItem();
|
||||
|
|
@ -413,7 +416,7 @@ class Spell
|
|||
SpellCastResult CheckItems();
|
||||
SpellCastResult CheckRange(bool strict);
|
||||
SpellCastResult CheckPower();
|
||||
SpellCastResult CheckOrTakeRunePower(bool take);
|
||||
SpellCastResult CheckRunePower();
|
||||
SpellCastResult CheckCasterAuras() const;
|
||||
|
||||
int32 CalculateDamage(SpellEffectIndex i, Unit* target) { return m_caster->CalculateSpellDamage(target, m_spellInfo, i, &m_currentBasePoints[i]); }
|
||||
|
|
@ -455,6 +458,8 @@ class Spell
|
|||
SpellEntry const* m_triggeredBySpellInfo;
|
||||
SpellInterruptsEntry const* m_spellInterrupts;
|
||||
int32 m_currentBasePoints[MAX_EFFECT_INDEX]; // cache SpellEntry::CalculateSimpleValue and use for set custom base points
|
||||
|
||||
ObjectGuid m_CastItemGuid;
|
||||
Item* m_CastItem;
|
||||
uint8 m_cast_count;
|
||||
uint32 m_glyphIndex;
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS] =
|
|||
&Aura::HandleNULL, //297 14 spells in 4.3.4
|
||||
&Aura::HandleUnused, //298 6 spells in 4.3.4
|
||||
&Aura::HandleUnused, //299 unused (3.2.2a-4.3.4)
|
||||
&Aura::HandleNULL, //300 21 spells (share damage?)
|
||||
&Aura::HandleNoImmediateEffect, //300 SPELL_AURA_SHARE_DAMAGE_PCT 21 spells
|
||||
&Aura::HandleNULL, //301 SPELL_AURA_HEAL_ABSORB 31 spells
|
||||
&Aura::HandleUnused, //302 unused (3.2.2a-4.3.4)
|
||||
&Aura::HandleNULL, //303 35 spells increases damage done vs. creature type
|
||||
|
|
@ -510,7 +510,8 @@ Aura::~Aura()
|
|||
}
|
||||
|
||||
AreaAura::AreaAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32* currentBasePoints, SpellAuraHolder* holder, Unit* target,
|
||||
Unit* caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, holder, target, caster, castItem)
|
||||
Unit* caster, Item* castItem, uint32 originalRankSpellId)
|
||||
: Aura(spellproto, eff, currentBasePoints, holder, target, caster, castItem), m_originalRankSpellId(originalRankSpellId)
|
||||
{
|
||||
m_isAreaAura = true;
|
||||
|
||||
|
|
@ -751,18 +752,26 @@ void AreaAura::Update(uint32 diff)
|
|||
// flag for selection is need apply aura to current iteration target
|
||||
bool apply = true;
|
||||
|
||||
SpellEntry const* actualSpellInfo;
|
||||
if (GetCasterGuid() == (*tIter)->GetObjectGuid()) // if caster is same as target then no need to change rank of the spell
|
||||
actualSpellInfo = GetSpellProto();
|
||||
else
|
||||
actualSpellInfo = sSpellMgr.SelectAuraRankForLevel(GetSpellProto(), (*tIter)->getLevel()); // use spell id according level of the target
|
||||
if (!actualSpellInfo)
|
||||
continue;
|
||||
|
||||
Unit::SpellAuraHolderBounds spair = (*tIter)->GetSpellAuraHolderBounds(actualSpellInfo->Id);
|
||||
// we need ignore present caster self applied are auras sometime
|
||||
// in cases if this only auras applied for spell effect
|
||||
Unit::SpellAuraHolderBounds spair = (*tIter)->GetSpellAuraHolderBounds(GetId());
|
||||
for (Unit::SpellAuraHolderMap::const_iterator i = spair.first; i != spair.second; ++i)
|
||||
{
|
||||
if (i->second->IsDeleted())
|
||||
{ continue; }
|
||||
continue;
|
||||
|
||||
Aura* aur = i->second->GetAuraByEffectIndex(m_effIndex);
|
||||
|
||||
if (!aur)
|
||||
{ continue; }
|
||||
continue;
|
||||
|
||||
switch (m_areaAuraType)
|
||||
{
|
||||
|
|
@ -787,18 +796,16 @@ void AreaAura::Update(uint32 diff)
|
|||
}
|
||||
|
||||
if (!apply)
|
||||
{ continue; }
|
||||
continue;
|
||||
|
||||
// Skip some targets (TODO: Might require better checks, also unclear how the actual caster must/can be handled)
|
||||
if (GetSpellProto()->HasAttribute(SPELL_ATTR_EX3_TARGET_ONLY_PLAYER) && (*tIter)->GetTypeId() != TYPEID_PLAYER)
|
||||
{ continue; }
|
||||
if (actualSpellInfo->HasAttribute(SPELL_ATTR_EX3_TARGET_ONLY_PLAYER) && (*tIter)->GetTypeId() != TYPEID_PLAYER)
|
||||
continue;
|
||||
|
||||
if (SpellEntry const* actualSpellInfo = sSpellMgr.SelectAuraRankForLevel(GetSpellProto(), (*tIter)->getLevel()))
|
||||
{
|
||||
int32 actualBasePoints = m_currentBasePoints;
|
||||
// recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
|
||||
if (actualSpellInfo != GetSpellProto())
|
||||
{ actualBasePoints = actualSpellInfo->CalculateSimpleValue(m_effIndex); }
|
||||
actualBasePoints = actualSpellInfo->CalculateSimpleValue(m_effIndex);
|
||||
|
||||
SpellAuraHolder* holder = (*tIter)->GetSpellAuraHolder(actualSpellInfo->Id, GetCasterGuid());
|
||||
|
||||
|
|
@ -811,7 +818,7 @@ void AreaAura::Update(uint32 diff)
|
|||
|
||||
holder->SetAuraDuration(GetAuraDuration());
|
||||
|
||||
AreaAura* aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, holder, (*tIter), caster, NULL);
|
||||
AreaAura* aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, holder, (*tIter), caster, nullptr, GetSpellProto()->Id);
|
||||
holder->AddAura(aur, m_effIndex);
|
||||
|
||||
if (addedToExisting)
|
||||
|
|
@ -823,7 +830,7 @@ void AreaAura::Update(uint32 diff)
|
|||
}
|
||||
else
|
||||
(*tIter)->AddSpellAuraHolder(holder);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Aura::Update(diff);
|
||||
|
|
@ -832,6 +839,7 @@ void AreaAura::Update(uint32 diff)
|
|||
{
|
||||
Unit* caster = GetCaster();
|
||||
Unit* target = GetTarget();
|
||||
uint32 originalRankSpellId = m_originalRankSpellId ? m_originalRankSpellId : GetId(); // caster may have different spell id if target has lower level
|
||||
|
||||
Aura::Update(diff);
|
||||
|
||||
|
|
@ -839,9 +847,10 @@ void AreaAura::Update(uint32 diff)
|
|||
// or caster is isolated or caster no longer has the aura
|
||||
// or caster is (no longer) friendly
|
||||
bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
|
||||
if (!caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
|
||||
if (!caster ||
|
||||
caster->hasUnitState(UNIT_STAT_ISOLATED) ||
|
||||
!caster->HasAura(originalRankSpellId, GetEffIndex()) ||
|
||||
!caster->IsWithinDistInMap(target, m_radius) ||
|
||||
!caster->HasAura(GetId(), GetEffIndex()) ||
|
||||
caster->IsFriendlyTo(target) != needFriendly
|
||||
)
|
||||
{
|
||||
|
|
@ -854,29 +863,29 @@ void AreaAura::Update(uint32 diff)
|
|||
{
|
||||
Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
|
||||
Group* pGroup = check ? check->GetGroup() : NULL;
|
||||
Group* pGroup = check ? check->GetGroup() : nullptr;
|
||||
if (pGroup)
|
||||
{
|
||||
Player* checkTarget = target->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
if (!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
|
||||
{ target->RemoveSingleAuraFromSpellAuraHolder(GetId(), GetEffIndex(), GetCasterGuid()); }
|
||||
target->RemoveSingleAuraFromSpellAuraHolder(GetId(), GetEffIndex(), GetCasterGuid());
|
||||
}
|
||||
else
|
||||
{ target->RemoveSingleAuraFromSpellAuraHolder(GetId(), GetEffIndex(), GetCasterGuid()); }
|
||||
target->RemoveSingleAuraFromSpellAuraHolder(GetId(), GetEffIndex(), GetCasterGuid());
|
||||
}
|
||||
}
|
||||
else if (m_areaAuraType == AREA_AURA_RAID) // TODO: fix me!
|
||||
else if (m_areaAuraType == AREA_AURA_RAID) // Check if on same raid group
|
||||
{
|
||||
// not check group if target == owner or target == pet
|
||||
if (caster->GetCharmerOrOwnerGuid() != target->GetObjectGuid() && caster->GetObjectGuid() != target->GetCharmerOrOwnerGuid())
|
||||
{
|
||||
Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
|
||||
Group* pGroup = check ? check->GetGroup() : NULL;
|
||||
Group* pGroup = check ? check->GetGroup() : nullptr;
|
||||
if (pGroup)
|
||||
{
|
||||
Player* checkTarget = target->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
if (!checkTarget)
|
||||
if (!checkTarget || !checkTarget->GetGroup() || checkTarget->GetGroup()->GetId() != pGroup->GetId())
|
||||
target->RemoveSingleAuraFromSpellAuraHolder(GetId(), GetEffIndex(), GetCasterGuid());
|
||||
}
|
||||
else
|
||||
|
|
@ -886,7 +895,7 @@ void AreaAura::Update(uint32 diff)
|
|||
else if (m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER)
|
||||
{
|
||||
if (target->GetObjectGuid() != caster->GetCharmerOrOwnerGuid())
|
||||
{ target->RemoveSingleAuraFromSpellAuraHolder(GetId(), GetEffIndex(), GetCasterGuid()); }
|
||||
target->RemoveSingleAuraFromSpellAuraHolder(GetId(), GetEffIndex(), GetCasterGuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1191,7 +1200,7 @@ void Aura::TriggerSpell()
|
|||
{
|
||||
int32 damageForTick[8] = { 500, 500, 1000, 1000, 2000, 2000, 3000, 5000 };
|
||||
triggerTarget->CastCustomSpell(triggerTarget, 19698, &damageForTick[GetAuraTicks() - 1], nullptr, nullptr, true, nullptr);
|
||||
return;
|
||||
return;;
|
||||
}
|
||||
|
||||
// // Frostwolf Muzzle DND
|
||||
|
|
@ -3526,62 +3535,18 @@ void Aura::HandleAuraFeatherFall(bool apply, bool Real)
|
|||
{
|
||||
// only at real add/remove aura
|
||||
if (!Real)
|
||||
{ return; }
|
||||
Unit* target = GetTarget();
|
||||
WorldPacket data;
|
||||
target->BuildMoveFeatherFallPacket(&data, apply, 0);
|
||||
target->SendMessageToSet(&data, true);
|
||||
return;
|
||||
|
||||
// start fall from current height
|
||||
if (!apply && target->GetTypeId() == TYPEID_PLAYER)
|
||||
((Player*)target)->SetFallInformation(0, target->GetPositionZ());
|
||||
GetTarget()->SetFeatherFall(apply);
|
||||
}
|
||||
|
||||
void Aura::HandleAuraHover(bool apply, bool Real)
|
||||
{
|
||||
// only at real add/remove aura
|
||||
if (!Real)
|
||||
{ return; }
|
||||
return;
|
||||
|
||||
WorldPacket data;
|
||||
if (apply)
|
||||
{
|
||||
GetTarget()->m_movementInfo.AddMovementFlag(MOVEFLAG_HOVER);
|
||||
if (GetTarget()->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
data.Initialize(SMSG_MOVE_SET_HOVER, 8 + 4 + 1);
|
||||
data.WriteGuidMask<1, 4, 2, 3, 0, 5, 6, 7>(GetTarget()->GetObjectGuid());
|
||||
data.WriteGuidBytes<5, 4, 1, 2, 3, 6, 0, 7>(GetTarget()->GetObjectGuid());
|
||||
data << uint32(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Initialize(SMSG_SPLINE_MOVE_SET_HOVER, 8 + 4 + 1);
|
||||
data.WriteGuidMask<3, 7, 0, 1, 4, 6, 2, 5>(GetTarget()->GetObjectGuid());
|
||||
data.WriteGuidBytes<2, 4, 3, 1, 7, 0, 5, 6>(GetTarget()->GetObjectGuid());
|
||||
GetTarget()->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_FLY_ANIM);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GetTarget()->m_movementInfo.RemoveMovementFlag(MOVEFLAG_HOVER);
|
||||
data.Initialize(GetTarget()->GetTypeId() == TYPEID_PLAYER ? SMSG_MOVE_UNSET_HOVER : SMSG_SPLINE_MOVE_UNSET_HOVER, 8+4);
|
||||
if (GetTarget()->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
data.Initialize(SMSG_MOVE_UNSET_HOVER, 8 + 4 + 1);
|
||||
data.WriteGuidMask<4, 6, 3, 1, 2, 7, 5, 0>(GetTarget()->GetObjectGuid());
|
||||
data.WriteGuidBytes<4, 5, 3, 6, 7, 1, 2, 0>(GetTarget()->GetObjectGuid());
|
||||
data << uint32(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Initialize(SMSG_SPLINE_MOVE_UNSET_HOVER, 8 + 4 + 1);
|
||||
data.WriteGuidMask<6, 7, 4, 0, 3, 1, 5, 2>(GetTarget()->GetObjectGuid());
|
||||
data.WriteGuidBytes<4, 5, 3, 0, 2, 7, 6, 1>(GetTarget()->GetObjectGuid());
|
||||
GetTarget()->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_FLY_ANIM);
|
||||
}
|
||||
}
|
||||
GetTarget()->SendMessageToSet(&data, true);
|
||||
GetTarget()->SetHover(apply);
|
||||
}
|
||||
|
||||
void Aura::HandleWaterBreathing(bool /*apply*/, bool /*Real*/)
|
||||
|
|
@ -4069,8 +4034,7 @@ void Aura::HandleAuraTransform(bool apply, bool Real)
|
|||
if (Unit* caster = GetCaster())
|
||||
if (caster->HasAura(52648)) // Glyph of the Penguin
|
||||
model_id = 26452;
|
||||
else
|
||||
if (caster->HasAura(57927)) // Glyph of the Monkey
|
||||
else if (caster->HasAura(57927)) // Glyph of the Monkey
|
||||
model_id = 21362;
|
||||
|
||||
target->SetDisplayId(model_id);
|
||||
|
|
@ -5209,9 +5173,7 @@ void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real)
|
|||
// Enable Fly mode for flying mounts
|
||||
if (m_modifier.m_auraname == SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED)
|
||||
{
|
||||
WorldPacket data;
|
||||
target->BuildMoveSetCanFlyPacket(&data, apply, 0);
|
||||
target->SendMessageToSet(&data, true);
|
||||
target->SetCanFly(apply);
|
||||
|
||||
// Players on flying mounts must be immune to polymorph
|
||||
if (target->GetTypeId() == TYPEID_PLAYER)
|
||||
|
|
@ -7109,10 +7071,7 @@ void Aura::HandleAuraAllowFlight(bool apply, bool Real)
|
|||
if (!Real)
|
||||
return;
|
||||
|
||||
// allow fly
|
||||
WorldPacket data;
|
||||
GetTarget()->BuildMoveSetCanFlyPacket(&data, apply, 0);
|
||||
GetTarget()->SendMessageToSet(&data, true);
|
||||
GetTarget()->SetCanFly(apply);
|
||||
}
|
||||
|
||||
void Aura::HandleModRating(bool apply, bool Real)
|
||||
|
|
|
|||
|
|
@ -545,13 +545,14 @@ class Aura
|
|||
class AreaAura : public Aura
|
||||
{
|
||||
public:
|
||||
AreaAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32* currentBasePoints, SpellAuraHolder* holder, Unit* target, Unit* caster = NULL, Item* castItem = NULL);
|
||||
AreaAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32* currentBasePoints, SpellAuraHolder* holder, Unit* target, Unit* caster = nullptr, Item* castItem = nullptr, uint32 originalRankSpellId = 0);
|
||||
~AreaAura();
|
||||
protected:
|
||||
void Update(uint32 diff) override;
|
||||
private:
|
||||
float m_radius;
|
||||
AreaAuraType m_areaAuraType;
|
||||
uint32 m_originalRankSpellId;
|
||||
};
|
||||
|
||||
class PersistentAreaAura : public Aura
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS] =
|
|||
&Spell::EffectQuestOffer, //150 SPELL_EFFECT_QUEST_OFFER
|
||||
&Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
|
||||
&Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
|
||||
&Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
|
||||
&Spell::EffectCreateTamedPet, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
|
||||
&Spell::EffectTeachTaxiNode, //154 SPELL_EFFECT_TEACH_TAXI_NODE single spell: Teach River's Heart Taxi Path
|
||||
&Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
|
||||
&Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
|
||||
|
|
@ -4191,17 +4191,12 @@ void Spell::EffectTriggerSpell(SpellEffectEntry const* effect)
|
|||
pet->CastSpell(pet, 28305, true);
|
||||
return;
|
||||
}
|
||||
case 53258: // Empower Rune Weapon
|
||||
case 58832: // Mirror Image
|
||||
{
|
||||
// remove cooldown of frost/death, undead/blood activated in main spell
|
||||
if (unitTarget->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
bool res1 = ((Player*)unitTarget)->ActivateRunes(RUNE_FROST, 2);
|
||||
bool res2 = ((Player*)unitTarget)->ActivateRunes(RUNE_DEATH, 2);
|
||||
if (res1 || res2)
|
||||
((Player*)unitTarget)->ResyncRunes();
|
||||
}
|
||||
return;
|
||||
// Glyph of Mirror Image
|
||||
if (m_caster->HasAura(63093))
|
||||
m_caster->CastSpell(m_caster, 65047, true, m_CastItem, nullptr, m_originalCasterGUID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4339,7 +4334,11 @@ void Spell::EffectJump(SpellEffectEntry const* effect)
|
|||
return;
|
||||
}
|
||||
|
||||
m_caster->NearTeleportTo(x, y, z, o, true); // TODO Implement this as jump movement?
|
||||
// Try to normalize Z coord because GetContactPoint do nothing with Z axis
|
||||
m_caster->UpdateAllowedPositionZ(x, y, z);
|
||||
|
||||
float speed = m_spellInfo->speed ? m_spellInfo->speed : 27.0f;
|
||||
m_caster->GetMotionMaster()->MoveDestination(x, y, z, o, speed, 2.5f);
|
||||
}
|
||||
|
||||
void Spell::EffectTeleportUnits(SpellEffectEntry const* effect) // TODO - Use target settings for this effect!
|
||||
|
|
@ -6629,56 +6628,45 @@ void Spell::EffectSummonPet(SpellEffectEntry const* effect)
|
|||
{
|
||||
uint32 petentry = effect->EffectMiscValue;
|
||||
|
||||
Pet* OldSummon = m_caster->GetPet();
|
||||
|
||||
// if pet requested type already exist
|
||||
if (OldSummon)
|
||||
{
|
||||
if ((petentry == 0 || OldSummon->GetEntry() == petentry) && OldSummon->getPetType() != SUMMON_PET)
|
||||
{
|
||||
// pet in corpse state can't be summoned
|
||||
if (OldSummon->IsDead())
|
||||
return;
|
||||
|
||||
OldSummon->GetMap()->Remove((Creature*)OldSummon, false);
|
||||
|
||||
float px, py, pz;
|
||||
m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectBoundingRadius());
|
||||
|
||||
OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
|
||||
m_caster->GetMap()->Add((Creature*)OldSummon);
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled())
|
||||
{
|
||||
((Player*)m_caster)->PetSpellInitialize();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
OldSummon->Unsummon(OldSummon->getPetType() == HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT, m_caster);
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(petentry);
|
||||
|
||||
// == 0 in case call current pet, check only real summon case
|
||||
if (petentry && !cInfo)
|
||||
{
|
||||
sLog.outErrorDb("EffectSummonPet: creature entry %u not found for spell %u.", petentry, m_spellInfo->Id);
|
||||
return;
|
||||
}
|
||||
|
||||
Pet* NewSummon = new Pet;
|
||||
|
||||
// petentry==0 for hunter "call pet" (current pet summoned if any)
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster, petentry))
|
||||
return;
|
||||
|
||||
// not error in case fail hunter call pet
|
||||
if (!petentry)
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
switch(m_caster->getClass())
|
||||
{
|
||||
case CLASS_HUNTER:
|
||||
{
|
||||
// Everything already taken care of, we are only here because we loaded pet from db successfully
|
||||
delete NewSummon;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (Pet* OldSummon = m_caster->GetPet())
|
||||
OldSummon->Unsummon(PET_SAVE_NOT_IN_SLOT, m_caster);
|
||||
|
||||
// Load pet from db; if any to load
|
||||
if (NewSummon->LoadPetFromDB((Player*)m_caster, petentry))
|
||||
{
|
||||
NewSummon->SetHealth(NewSummon->GetMaxHealth());
|
||||
NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
|
||||
|
||||
NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
NewSummon->setPetType(SUMMON_PET);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
NewSummon->setPetType(GUARDIAN_PET);
|
||||
|
||||
CreatureInfo const* cInfo = petentry ? ObjectMgr::GetCreatureTemplate(petentry) : nullptr;
|
||||
if (!cInfo)
|
||||
{
|
||||
sLog.outErrorDb("EffectSummonPet: creature entry %u not found for spell %u.", petentry, m_spellInfo->Id);
|
||||
delete NewSummon;
|
||||
return;
|
||||
}
|
||||
|
|
@ -6695,29 +6683,38 @@ void Spell::EffectSummonPet(SpellEffectEntry const* effect)
|
|||
|
||||
NewSummon->SetRespawnCoord(pos);
|
||||
|
||||
uint32 petlevel = m_caster->getLevel();
|
||||
NewSummon->setPetType(SUMMON_PET);
|
||||
// Level of pet summoned
|
||||
uint32 level = std::max(m_caster->getLevel() + effect->EffectMultipleValue, 1.0f);
|
||||
|
||||
uint32 faction = m_caster->getFaction();
|
||||
if (m_caster->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
if (((Creature*)m_caster)->IsTotem())
|
||||
NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
|
||||
else
|
||||
NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
|
||||
}
|
||||
|
||||
NewSummon->SetOwnerGuid(m_caster->GetObjectGuid());
|
||||
NewSummon->SetCreatorGuid(m_caster->GetObjectGuid());
|
||||
NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
||||
NewSummon->setFaction(faction);
|
||||
NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL)));
|
||||
NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
|
||||
NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
|
||||
NewSummon->setFaction(m_caster->getFaction());
|
||||
NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(nullptr)));
|
||||
NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
||||
|
||||
NewSummon->InitStatsForLevel(level);
|
||||
NewSummon->InitPetCreateSpells();
|
||||
NewSummon->InitLevelupSpellsForLevel();
|
||||
NewSummon->InitTalentForLevel();
|
||||
|
||||
map->Add((Creature*)NewSummon);
|
||||
NewSummon->AIM_Initialize();
|
||||
|
||||
m_caster->SetPet(NewSummon);
|
||||
DEBUG_LOG("New Pet has guid %u", NewSummon->GetGUIDLow());
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
||||
|
||||
NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE | UNIT_BYTE2_FLAG_AURAS);
|
||||
NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||
|
||||
NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
|
||||
// this enables pet details window (Shift+P)
|
||||
|
||||
// generate new name for summon pet
|
||||
NewSummon->SetName(sObjectMgr.GeneratePetName(petentry));
|
||||
|
||||
if (m_caster->IsPvP())
|
||||
NewSummon->SetPvP(true);
|
||||
|
|
@ -6725,39 +6722,26 @@ void Spell::EffectSummonPet(SpellEffectEntry const* effect)
|
|||
if (m_caster->IsFFAPvP())
|
||||
NewSummon->SetFFAPvP(true);
|
||||
|
||||
NewSummon->InitStatsForLevel(petlevel, m_caster);
|
||||
NewSummon->InitPetCreateSpells();
|
||||
NewSummon->InitLevelupSpellsForLevel();
|
||||
NewSummon->InitTalentForLevel();
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->getPetType() == SUMMON_PET)
|
||||
{
|
||||
// generate new name for summon pet
|
||||
std::string new_name = sObjectMgr.GeneratePetName(petentry);
|
||||
if (!new_name.empty())
|
||||
NewSummon->SetName(new_name);
|
||||
}
|
||||
|
||||
if (NewSummon->getPetType() == HUNTER_PET)
|
||||
{
|
||||
NewSummon->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
|
||||
NewSummon->SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_ABANDONED);
|
||||
}
|
||||
|
||||
NewSummon->AIM_Initialize();
|
||||
NewSummon->SetHealth(NewSummon->GetMaxHealth());
|
||||
NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
|
||||
|
||||
map->Add((Creature*)NewSummon);
|
||||
|
||||
m_caster->SetPet(NewSummon);
|
||||
DEBUG_LOG("New Pet has guid %u", NewSummon->GetGUIDLow());
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
|
||||
((Player*)m_caster)->PetSpellInitialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Notify Summoner
|
||||
if (m_originalCaster && (m_originalCaster != m_caster)
|
||||
&& (m_originalCaster->GetTypeId() == TYPEID_UNIT) && ((Creature*)m_originalCaster)->AI())
|
||||
{
|
||||
((Creature*)m_originalCaster)->AI()->JustSummoned(NewSummon);
|
||||
if (m_originalCaster->IsInCombat() && !(NewSummon->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)))
|
||||
((Creature*)NewSummon)->AI()->AttackStart(m_originalCaster->getAttackerForHelper());
|
||||
}
|
||||
else if ((m_caster->GetTypeId() == TYPEID_UNIT) && ((Creature*)m_caster)->AI())
|
||||
{
|
||||
((Creature*)m_caster)->AI()->JustSummoned(NewSummon);
|
||||
if (m_caster->IsInCombat() && !(NewSummon->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)))
|
||||
((Creature*)NewSummon)->AI()->AttackStart(m_caster->getAttackerForHelper());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::EffectLearnPetSpell(SpellEffectEntry const* effect)
|
||||
|
|
@ -11490,7 +11474,7 @@ void Spell::EffectActivateRune(SpellEffectEntry const* effect)
|
|||
return;
|
||||
|
||||
int32 count = damage; // max amount of reset runes
|
||||
if (plr->ActivateRunes(RuneType(effect->EffectMiscValue), count))
|
||||
|
||||
plr->ResyncRunes();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -186,6 +186,14 @@ void WorldSession::HandleActivateTaxiExpressOpcode(WorldPacket& recv_data)
|
|||
{
|
||||
uint32 node;
|
||||
recv_data >> node;
|
||||
|
||||
if (!_player->m_taxi.IsTaximaskNodeKnown(node) && !_player->IsTaxiCheater())
|
||||
{
|
||||
SendActivateTaxiReply(ERR_TAXINOTVISITED);
|
||||
recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
|
||||
return;
|
||||
}
|
||||
|
||||
nodes.push_back(node);
|
||||
}
|
||||
|
||||
|
|
@ -282,5 +290,14 @@ void WorldSession::HandleActivateTaxiOpcode(WorldPacket& recv_data)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!_player->IsTaxiCheater())
|
||||
{
|
||||
if (!_player->m_taxi.IsTaximaskNodeKnown(nodes[0]) || !_player->m_taxi.IsTaximaskNodeKnown(nodes[1]))
|
||||
{
|
||||
SendActivateTaxiReply(ERR_TAXINOTVISITED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GetPlayer()->ActivateTaxiPathTo(nodes, npc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,12 +101,16 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket& recvPacket)
|
|||
DEBUG_LOG("WORLD: Received opcode CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE");
|
||||
recvPacket.hexlike();
|
||||
|
||||
ObjectGuid srcVehicleGuid;
|
||||
MovementInfo movementInfo;
|
||||
ObjectGuid destVehicleGuid;
|
||||
uint8 seat;
|
||||
|
||||
recvPacket >> movementInfo; // Not used at the moment
|
||||
ObjectGuid srcVehicleGuid = movementInfo.GetGuid();
|
||||
ObjectGuid destVehicleGuid = movementInfo.GetGuid2();
|
||||
uint8 seat = movementInfo.GetByteParam();
|
||||
recvPacket >> movementInfo;
|
||||
|
||||
srcVehicleGuid = movementInfo.GetGuid();
|
||||
destVehicleGuid = movementInfo.GetGuid2();
|
||||
seat = movementInfo.GetByteParam();
|
||||
|
||||
TransportInfo* transportInfo = _player->GetTransportInfo();
|
||||
if (!transportInfo || !transportInfo->IsOnVehicle())
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "Log.h"
|
||||
// #include "ObjectMgr.h" // chucky delete ?
|
||||
#include "Util.h"
|
||||
#include "ProgressBar.h"
|
||||
#ifdef ENABLE_ELUNA
|
||||
#include "LuaEngine.h"
|
||||
#endif /* ENABLE_ELUNA */
|
||||
|
|
@ -155,7 +156,7 @@ bool Weather::ReGenerate()
|
|||
uint32 chance2 = chance1 + m_weatherChances->data[season].snowChance;
|
||||
uint32 chance3 = chance2 + m_weatherChances->data[season].stormChance;
|
||||
|
||||
uint32 rnd = urand(0, 99);
|
||||
uint32 rnd = urand(1, 100);
|
||||
if (rnd <= chance1)
|
||||
{
|
||||
m_type = WEATHER_TYPE_RAIN;
|
||||
|
|
|
|||
|
|
@ -144,19 +144,17 @@ World::~World()
|
|||
// it is assumed that no other thread is accessing this data when the destructor is called. therefore, no locks are necessary
|
||||
|
||||
///- Empty the kicked session set
|
||||
std::for_each(m_sessions.begin(), m_sessions.end(), [](const SessionMap::value_type &p) { delete p.second; });
|
||||
m_sessions.clear();
|
||||
for (auto const session : m_sessions)
|
||||
delete session.second;
|
||||
|
||||
std::for_each(m_cliCommandQueue.begin(), m_cliCommandQueue.end(), [](const CliCommandHolder *p) { delete p; });
|
||||
m_cliCommandQueue.clear();
|
||||
for (auto const cliCommand : m_cliCommandQueue)
|
||||
delete cliCommand;
|
||||
|
||||
std::for_each(m_sessionAddQueue.begin(), m_sessionAddQueue.end(), [](const WorldSession *s) { delete s; });
|
||||
m_sessionAddQueue.clear();
|
||||
for (auto const session : m_sessionAddQueue)
|
||||
delete session;
|
||||
|
||||
VMAP::VMapFactory::clear();
|
||||
MMAP::MMapFactory::clear();
|
||||
|
||||
delete m_configForceLoadMapIds;
|
||||
}
|
||||
|
||||
/// Cleanups before world stop
|
||||
|
|
@ -577,6 +575,17 @@ void World::LoadConfigSettings(bool reload)
|
|||
setConfig(CONFIG_BOOL_ADDON_CHANNEL, "AddonChannel", true);
|
||||
setConfig(CONFIG_BOOL_CLEAN_CHARACTER_DB, "CleanCharacterDB", true);
|
||||
setConfig(CONFIG_BOOL_GRID_UNLOAD, "GridUnload", true);
|
||||
|
||||
std::string forceLoadGridOnMaps = sConfig.GetStringDefault("LoadAllGridsOnMaps", "");
|
||||
if (!forceLoadGridOnMaps.empty())
|
||||
{
|
||||
unsigned int pos = 0;
|
||||
unsigned int id;
|
||||
VMAP::VMapFactory::chompAndTrim(forceLoadGridOnMaps);
|
||||
while (VMAP::VMapFactory::getNextId(forceLoadGridOnMaps, pos, id))
|
||||
m_configForceLoadMapIds.insert(id);
|
||||
}
|
||||
|
||||
setConfig(CONFIG_UINT32_INTERVAL_SAVE, "PlayerSave.Interval", 15 * MINUTE * IN_MILLISECONDS);
|
||||
setConfigMinMax(CONFIG_UINT32_MIN_LEVEL_STAT_SAVE, "PlayerSave.Stats.MinLevel", 0, 0, MAX_LEVEL);
|
||||
setConfig(CONFIG_BOOL_STATS_SAVE_ONLY_ON_LOGOUT, "PlayerSave.Stats.SaveOnlyOnLogout", true);
|
||||
|
|
@ -635,7 +644,7 @@ void World::LoadConfigSettings(bool reload)
|
|||
if (configNoReload(reload, CONFIG_UINT32_MAX_PLAYER_LEVEL, "MaxPlayerLevel", DEFAULT_MAX_LEVEL))
|
||||
{ setConfigMinMax(CONFIG_UINT32_MAX_PLAYER_LEVEL, "MaxPlayerLevel", DEFAULT_MAX_LEVEL, 1, DEFAULT_MAX_LEVEL); }
|
||||
|
||||
setConfigMinMax(CONFIG_UINT32_START_PLAYER_LEVEL, "StartPlayerLevel", 1, 1, getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL));
|
||||
setConfigMinMax(CONFIG_UINT32_START_PLAYER_LEVEL, "StartPlayerLevel", 1, 1, (uint32)getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL));
|
||||
setConfigMinMax(CONFIG_UINT32_START_HEROIC_PLAYER_LEVEL, "StartHeroicPlayerLevel", 55, 1, getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL));
|
||||
|
||||
setConfigMinMax(CONFIG_UINT64_START_PLAYER_MONEY, "StartPlayerMoney", 0, 0, MAX_MONEY_AMOUNT);
|
||||
|
|
@ -787,6 +796,7 @@ void World::LoadConfigSettings(bool reload)
|
|||
setConfig(CONFIG_BOOL_BATTLEGROUND_CAST_DESERTER, "Battleground.CastDeserter", true);
|
||||
setConfigMinMax(CONFIG_UINT32_BATTLEGROUND_QUEUE_ANNOUNCER_JOIN, "Battleground.QueueAnnouncer.Join", 0, 0, 2);
|
||||
setConfig(CONFIG_BOOL_BATTLEGROUND_QUEUE_ANNOUNCER_START, "Battleground.QueueAnnouncer.Start", false);
|
||||
setConfig(CONFIG_BOOL_BATTLEGROUND_SCORE_STATISTICS, "Battleground.ScoreStatistics", false);
|
||||
setConfig(CONFIG_UINT32_BATTLEGROUND_INVITATION_TYPE, "Battleground.InvitationType", 0);
|
||||
setConfig(CONFIG_UINT32_BATTLEGROUND_PREMATURE_FINISH_TIMER, "BattleGround.PrematureFinishTimer", 5 * MINUTE * IN_MILLISECONDS);
|
||||
setConfig(CONFIG_UINT32_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH, "BattleGround.PremadeGroupWaitForMatch", 30 * MINUTE * IN_MILLISECONDS);
|
||||
|
|
|
|||
|
|
@ -612,6 +612,9 @@ class World
|
|||
/// Get a server configuration element (see #eConfigBoolValues)
|
||||
bool getConfig(eConfigBoolValues index) const { return m_configBoolValues[index]; }
|
||||
|
||||
/// Get configuration about force-loaded maps
|
||||
bool isForceLoadMap(uint32 id) const { return m_configForceLoadMapIds.find(id) != m_configForceLoadMapIds.end(); }
|
||||
|
||||
/// Are we on a "Player versus Player" server?
|
||||
bool IsPvPRealm() { return (getConfig(CONFIG_UINT32_GAME_TYPE) == REALM_TYPE_PVP || getConfig(CONFIG_UINT32_GAME_TYPE) == REALM_TYPE_RPPVP || getConfig(CONFIG_UINT32_GAME_TYPE) == REALM_TYPE_FFA_PVP); }
|
||||
bool IsFFAPvPRealm() { return getConfig(CONFIG_UINT32_GAME_TYPE) == REALM_TYPE_FFA_PVP; }
|
||||
|
|
@ -766,9 +769,10 @@ class World
|
|||
|
||||
// used versions
|
||||
std::string m_DBVersion;
|
||||
std::string m_CreatureEventAIVersion;
|
||||
|
||||
// List of Maps that should be force-loaded on startup
|
||||
std::set<uint32>* m_configForceLoadMapIds;
|
||||
std::set<uint32> m_configForceLoadMapIds;
|
||||
};
|
||||
|
||||
extern uint32 realmID;
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ namespace Movement
|
|||
{
|
||||
// mix existing state into new
|
||||
args.flags.walkmode = unit.m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE);
|
||||
args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_FLYING | MOVEFLAG_LEVITATING));
|
||||
args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_CAN_FLY | MOVEFLAG_FLYING | MOVEFLAG_LEVITATING));
|
||||
}
|
||||
|
||||
void MoveSplineInit::SetFacing(const Unit* target)
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace Movement
|
|||
* @brief Initializes and launches spline movement
|
||||
*
|
||||
*/
|
||||
class MoveSplineInit
|
||||
class MANGOS_DLL_SPEC MoveSplineInit
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ using namespace G3D;
|
|||
|
||||
namespace VMAP
|
||||
{
|
||||
void chompAndTrim(std::string& str)
|
||||
void VMapFactory::chompAndTrim(std::string& str)
|
||||
{
|
||||
while (str.length() > 0)
|
||||
{
|
||||
|
|
@ -64,7 +64,7 @@ namespace VMAP
|
|||
//===============================================
|
||||
// result false, if no more id are found
|
||||
|
||||
bool getNextId(const std::string& pString, unsigned int& pStartPos, unsigned int& pId)
|
||||
bool VMapFactory::getNextId(const std::string& pString, unsigned int& pStartPos, unsigned int& pId)
|
||||
{
|
||||
bool result = false;
|
||||
unsigned int i;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ namespace VMAP
|
|||
|
||||
static void preventSpellsFromBeingTestedForLoS(const char* pSpellIdString);
|
||||
static bool checkSpellForLoS(unsigned int pSpellId);
|
||||
|
||||
static void chompAndTrim(std::string& str);
|
||||
static bool getNextId(const std::string& pString, unsigned int& pStartPos, unsigned int& pId);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -113,6 +113,12 @@ BindIP = "0.0.0.0"
|
|||
# Default: 1 (unload grids)
|
||||
# 0 (do not unload grids)
|
||||
#
|
||||
# LoadAllGridsOnMaps
|
||||
# Load grids of maps at server startup (if you have lot memory you can try it to have a living world always loaded)
|
||||
# This also allow ALL creatures on the given maps to update their grid without any player around.
|
||||
# Default: "" (don't load all grids at startup)
|
||||
# "mapId1[,mapId2[..]]" (DO load all grids on the given maps- Experimental and very resource consumming)
|
||||
#
|
||||
# GridCleanUpDelay
|
||||
# Grid clean up delay (in milliseconds)
|
||||
# Default: 300000 (5 min)
|
||||
|
|
@ -207,6 +213,7 @@ PlayerLimit = 100
|
|||
SaveRespawnTimeImmediately = 1
|
||||
MaxOverspeedPings = 2
|
||||
GridUnload = 1
|
||||
LoadAllGridsOnMaps = ""
|
||||
GridCleanUpDelay = 300000
|
||||
MapUpdateInterval = 100
|
||||
ChangeWeatherInterval = 600000
|
||||
|
|
@ -1487,6 +1494,11 @@ Death.Ghost.RunSpeed.Battleground = 1.0
|
|||
# 1 (send to joined player only)
|
||||
# 2 (send to all players)
|
||||
#
|
||||
# Battleground.ScoreStatistics
|
||||
# Enable Battleground scores storage in database
|
||||
# Default: 0 (disable)
|
||||
# 1 (enable)
|
||||
#
|
||||
# Battleground.QueueAnnouncer.Start
|
||||
# Enable queue announcer posting to chat at BG start
|
||||
# Default: 0 (disable)
|
||||
|
|
@ -1512,6 +1524,7 @@ Death.Ghost.RunSpeed.Battleground = 1.0
|
|||
Battleground.CastDeserter = 1
|
||||
Battleground.QueueAnnouncer.Join = 0
|
||||
Battleground.QueueAnnouncer.Start = 0
|
||||
Battleground.ScoreStatistics = 0
|
||||
Battleground.InvitationType = 0
|
||||
BattleGround.PrematureFinishTimer = 300000
|
||||
BattleGround.PremadeGroupWaitForMatch = 1800000
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ namespace LuaUnit
|
|||
Creature* creature = Eluna::CHECKOBJ<Creature>(L, 2);
|
||||
|
||||
#ifndef TRINITY
|
||||
Eluna::Push(L, unit->isInAccessablePlaceFor(creature));
|
||||
Eluna::Push(L, unit->IsInAccessablePlaceFor(creature));
|
||||
#else
|
||||
Eluna::Push(L, unit->isInAccessiblePlaceFor(creature));
|
||||
#endif
|
||||
|
|
@ -1707,12 +1707,12 @@ namespace LuaUnit
|
|||
|
||||
if (apply)
|
||||
{
|
||||
unit->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
|
||||
unit->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE);
|
||||
unit->CombatStop();
|
||||
unit->CombatStopWithPets();
|
||||
}
|
||||
else
|
||||
unit->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
|
||||
unit->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ bool npc_escortAI::AssistPlayerInCombat(Unit* pWho)
|
|||
|
||||
void npc_escortAI::MoveInLineOfSight(Unit* pWho)
|
||||
{
|
||||
if (pWho->IsTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature))
|
||||
if (pWho->IsTargetableForAttack() && pWho->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
// AssistPlayerInCombat can start attack, so return if true
|
||||
if (HasEscortState(STATE_ESCORT_ESCORTING) && AssistPlayerInCombat(pWho))
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ bool FollowerAI::AssistPlayerInCombat(Unit* pWho)
|
|||
|
||||
void FollowerAI::MoveInLineOfSight(Unit* pWho)
|
||||
{
|
||||
if (pWho->IsTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature))
|
||||
if (pWho->IsTargetableForAttack() && pWho->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
// AssistPlayerInCombat can start attack, so return if true
|
||||
if (HasFollowState(STATE_FOLLOW_INPROGRESS) && AssistPlayerInCombat(pWho))
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ void ScriptedPetAI::MoveInLineOfSight(Unit* pWho)
|
|||
}
|
||||
|
||||
if (m_creature->CanInitiateAttack() && pWho->IsTargetableForAttack() &&
|
||||
m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature))
|
||||
m_creature->IsHostileTo(pWho) && pWho->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ bool ScriptedAI::IsVisible(Unit* pWho) const
|
|||
void ScriptedAI::MoveInLineOfSight(Unit* pWho)
|
||||
{
|
||||
if (m_creature->CanInitiateAttack() && pWho->IsTargetableForAttack() &&
|
||||
m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature))
|
||||
m_creature->IsHostileTo(pWho) && pWho->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -59,14 +59,14 @@ struct npc_ragged_john : public CreatureScript
|
|||
{
|
||||
if (who->HasAura(16468, EFFECT_INDEX_0))
|
||||
{
|
||||
if (who->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(who, 15) && who->isInAccessablePlaceFor(m_creature))
|
||||
if (who->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(who, 15) && who->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
DoCastSpellIfCan(who, 16472);
|
||||
((Player*)who)->AreaExploredOrEventHappens(4866);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_creature->getVictim() && who->IsTargetableForAttack() && (m_creature->IsHostileTo(who)) && who->isInAccessablePlaceFor(m_creature))
|
||||
if (!m_creature->getVictim() && who->IsTargetableForAttack() && (m_creature->IsHostileTo(who)) && who->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
if (!m_creature->CanFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1247,7 +1247,7 @@ struct horde_defender : public CreatureScript
|
|||
void MoveInLineOfSight(Unit* u) override
|
||||
{
|
||||
if (m_creature->CanInitiateAttack() && u->IsTargetableForAttack() &&
|
||||
m_creature->IsHostileTo(u) && u->isInAccessablePlaceFor(m_creature))
|
||||
m_creature->IsHostileTo(u) && u->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
float attackRadius = 38.0f;
|
||||
if (m_creature->IsWithinDistInMap(u, attackRadius) && m_creature->IsWithinLOSInMap(u))
|
||||
|
|
@ -1330,7 +1330,7 @@ struct kolkar_invader : public CreatureScript
|
|||
void MoveInLineOfSight(Unit* u) override
|
||||
{
|
||||
if (m_creature->CanInitiateAttack() && u->IsTargetableForAttack() &&
|
||||
m_creature->IsHostileTo(u) && u->isInAccessablePlaceFor(m_creature))
|
||||
m_creature->IsHostileTo(u) && u->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
float attackRadius = 38.0f;
|
||||
if (m_creature->IsWithinDistInMap(u, attackRadius) && m_creature->IsWithinLOSInMap(u))
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ struct boss_talon_king_ikiss : public CreatureScript
|
|||
|
||||
void MoveInLineOfSight(Unit* pWho) override
|
||||
{
|
||||
if (!m_creature->getVictim() && pWho->IsTargetableForAttack() && (m_creature->IsHostileTo(pWho)) && pWho->isInAccessablePlaceFor(m_creature))
|
||||
if (!m_creature->getVictim() && pWho->IsTargetableForAttack() && (m_creature->IsHostileTo(pWho)) && pWho->IsInAccessablePlaceFor(m_creature))
|
||||
{
|
||||
if (!m_bIntro && m_creature->IsWithinDistInMap(pWho, 100.0f))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -179,9 +179,12 @@ struct npc_ancestral_wolf : public CreatureScript
|
|||
|
||||
void Reset() override
|
||||
{
|
||||
m_creature->CastSpell(m_creature, SPELL_ANCESTRAL_WOLF_BUFF, true);
|
||||
DoCastSpellIfCan(m_creature, SPELL_ANCESTRAL_WOLF_BUFF);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* /*pWho*/) override { }
|
||||
void MoveInLineOfSight(Unit* /*pWho*/) override { }
|
||||
|
||||
void WaypointReached(uint32 uiPointId) override
|
||||
{
|
||||
switch (uiPointId)
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
|
|
@ -172,7 +172,7 @@ typedef off_t ACE_OFF_T;
|
|||
* @param f
|
||||
* @return float
|
||||
*/
|
||||
inline float finiteAlways(float f) { return finite(f) ? f : 0.0f; }
|
||||
inline float finiteAlways(float f) { return std::isfinite(f) ? f : 0.0f; }
|
||||
|
||||
#define atol(a) strtoul( a, NULL, 10)
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ uint32 WorldTimer::getMSTime_internal(bool savetime /*= false*/)
|
|||
// calculate time diff between two world ticks
|
||||
// special case: curr_time < old_time - we suppose that our time has not ticked at all
|
||||
// this should be constant value otherwise it is possible that our time can start ticking backwards until next world tick!!!
|
||||
uint64 diff = 0;
|
||||
ACE_UINT64 diff = 0;
|
||||
(currTime - g_SystemTickTime).msec(diff);
|
||||
|
||||
// lets calculate current world time
|
||||
|
|
|
|||
|
|
@ -33,11 +33,11 @@
|
|||
|
||||
#define CHAR_DB_VERSION_NR 21
|
||||
#define CHAR_DB_STRUCTURE_NR 2
|
||||
#define CHAR_DB_CONTENT_NR 1
|
||||
#define CHAR_DB_CONTENT_NR 2
|
||||
#define CHAR_DB_UPDATE_DESCRIPTION "match_client_limits"
|
||||
|
||||
#define WORLD_DB_VERSION_NR 21
|
||||
#define WORLD_DB_STRUCTURE_NR 1
|
||||
#define WORLD_DB_CONTENT_NR 0
|
||||
#define WORLD_DB_STRUCTURE_NR 2
|
||||
#define WORLD_DB_CONTENT_NR 3
|
||||
#define WORLD_DB_UPDATE_DESCRIPTION "script_binding populated"
|
||||
#endif // __REVISION_H__
|
||||
|
|
|
|||
|
|
@ -67,19 +67,11 @@ else()
|
|||
target_link_libraries(${EXECUTABLE_NAME} ACE)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${EXECUTABLE_NAME} g3dlite vmap detour recast zlib shared)
|
||||
|
||||
if(UNIX)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
set(EXECUTABLE_LINK_FLAGS "-Wl,--no-as-needed -lrt -pthread ${EXECUTABLE_LINK_FLAGS}")
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(EXECUTABLE_LINK_FLAGS "-Wl,--no-as-needed -ldl -pthread -lrt ${EXECUTABLE_LINK_FLAGS}")
|
||||
endif()
|
||||
target_link_libraries(${EXECUTABLE_NAME} rt)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(EXECUTABLE_LINK_FLAGS "-framework CoreServices ${EXECUTABLE_LINK_FLAGS}")
|
||||
endif()
|
||||
target_link_libraries(${EXECUTABLE_NAME} g3dlite vmap detour recast zlib shared)
|
||||
|
||||
#Output the compiled exes to build/bin/$(Configuration)/tools directory on windows by default
|
||||
if(WIN32)
|
||||
|
|
|
|||
|
|
@ -47,22 +47,20 @@ else()
|
|||
target_link_libraries(${EXECUTABLE_NAME} ACE)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
target_link_libraries(${EXECUTABLE_NAME} rt dl)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${EXECUTABLE_NAME} vmap g3dlite zlib)
|
||||
|
||||
set(EXECUTABLE_LINK_FLAGS "")
|
||||
|
||||
if(UNIX)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
set(EXECUTABLE_LINK_FLAGS "-Wl,--no-as-needed -lrt -pthread ${EXECUTABLE_LINK_FLAGS}")
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(EXECUTABLE_LINK_FLAGS "-Wl,--no-as-needed -ldl -pthread -lrt ${EXECUTABLE_LINK_FLAGS}")
|
||||
if(CMAKE_C_COMPILER MATCHES "clang" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
set(EXECUTABLE_LINK_FLAGS "-pthread${EXECUTABLE_LINK_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(EXECUTABLE_LINK_FLAGS "-framework CoreServices ${EXECUTABLE_LINK_FLAGS}")
|
||||
endif()
|
||||
|
||||
set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS "${EXECUTABLE_LINK_FLAGS}")
|
||||
|
||||
#Output the compiled exes to build/bin/$(Configuration)/tools directory on windows by default
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ add_executable(${EXECUTABLE_NAME} ${EXECUTABLE_SRCS}
|
|||
${CMAKE_SOURCE_DIR}/src/tools/Extractor_projects/shared/ExtractorCommon.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${EXECUTABLE_NAME} StormLib loadlib bzip2 zlib)
|
||||
target_link_libraries(${EXECUTABLE_NAME} loadlib bzip2 zlib StormLib)
|
||||
|
||||
#Output the compiled exes to build/bin/$(Configuration)/tools directory on windows by default
|
||||
if(WIN32)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue