Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2025-02-19 22:29:36 +08:00
parent d1032678ff
commit 7d431dc796
277 changed files with 7092 additions and 5050 deletions
+1 -1
View File
@@ -359,7 +359,7 @@ public:
virtual void JustExitedCombat() { }
/// @brief Called at any Damage to any victim (before damage apply)
virtual void DamageDealt(Unit* /*victim*/, uint32& /*damage*/, DamageEffectType /*damageType*/) { }
virtual void DamageDealt(Unit* /*victim*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) {}
/** @brief Called at any Damage from any attacker (before damage apply)
*
+1 -1
View File
@@ -893,7 +893,7 @@ void SmartAI::IsSummonedBy(WorldObject* summoner)
GetScript()->ProcessEventsFor(SMART_EVENT_JUST_SUMMONED, summoner->ToUnit(), 0, 0, false, nullptr, summoner->ToGameObject());
}
void SmartAI::DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType /*damagetype*/)
void SmartAI::DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/)
{
GetScript()->ProcessEventsFor(SMART_EVENT_DAMAGED_TARGET, doneTo, damage);
}
+1 -1
View File
@@ -131,7 +131,7 @@ public:
void IsSummonedBy(WorldObject* summoner) override;
// Called at any Damage to any victim (before damage apply)
void DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType damagetyp) override;
void DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType damagetyp, SpellSchoolMask damageSchoolMask) override;
// Called when a summoned creature dissapears (UnSommoned)
void SummonedCreatureDespawn(Creature* unit) override;
+10 -14
View File
@@ -44,6 +44,7 @@
#include "SpellMgr.h"
#include "World.h"
#include "WorldPacket.h"
#include "WorldSessionMgr.h"
bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
{
@@ -580,7 +581,7 @@ void AchievementMgr::SaveToDB(CharacterDatabaseTransaction trans)
iter->second.changed = false;
sScriptMgr->OnAchievementSave(trans, GetPlayer(), iter->first, iter->second);
sScriptMgr->OnPlayerAchievementSave(trans, GetPlayer(), iter->first, iter->second);
}
}
@@ -609,7 +610,7 @@ void AchievementMgr::SaveToDB(CharacterDatabaseTransaction trans)
iter->second.changed = false;
sScriptMgr->OnCriteriaSave(trans, GetPlayer(), iter->first, iter->second);
sScriptMgr->OnPlayerCriteriaSave(trans, GetPlayer(), iter->first, iter->second);
}
}
}
@@ -728,7 +729,7 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
data << GetPlayer()->GetGUID();
data << uint32(achievement->ID);
data << uint32(0); // display name as plain string in chat (always 0 for guild)
sWorld->SendGlobalMessage(&data);
sWorldSessionMgr->SendGlobalMessage(&data);
}
else
{
@@ -741,20 +742,15 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
data << uint32(achievement->ID);
std::size_t linkTypePos = data.wpos();
data << uint32(1); // display name as clickable link in chat
sWorld->SendGlobalMessage(&data, nullptr, teamId);
sWorldSessionMgr->SendGlobalMessage(&data, nullptr, teamId);
data.put<uint32>(linkTypePos, 0); // display name as plain string in chat
sWorld->SendGlobalMessage(&data, nullptr, teamId == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE);
sWorldSessionMgr->SendGlobalMessage(&data, nullptr, teamId == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE);
}
}
// if player is in world he can tell his friends about new achievement
else if (GetPlayer()->IsInWorld())
{
CellCoord p = Acore::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY());
Cell cell(p);
cell.SetNoCreate();
Acore::BroadcastTextBuilder _builder(GetPlayer(), CHAT_MSG_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, GetPlayer()->getGender(), GetPlayer(), achievement->ID);
Acore::LocalizedPacketDo<Acore::BroadcastTextBuilder> _localizer(_builder);
Acore::PlayerDistWorker<Acore::LocalizedPacketDo<Acore::BroadcastTextBuilder>> _worker(GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _localizer);
@@ -2103,7 +2099,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
if (entry->timeLimit && timedIter == _timedAchievements.end())
return;
if (!sScriptMgr->OnBeforeCriteriaProgress(GetPlayer(), entry))
if (!sScriptMgr->OnPlayerBeforeCriteriaProgress(GetPlayer(), entry))
{
return;
}
@@ -2169,7 +2165,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
SendCriteriaUpdate(entry, progress, timeElapsed, true);
sScriptMgr->OnCriteriaProgress(GetPlayer(), entry);
sScriptMgr->OnPlayerCriteriaProgress(GetPlayer(), entry);
}
void AchievementMgr::RemoveCriteriaProgress(const AchievementCriteriaEntry* entry)
@@ -2277,7 +2273,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
return;
}
if (!sScriptMgr->OnBeforeAchievementComplete(GetPlayer(), achievement))
if (!sScriptMgr->OnPlayerBeforeAchievementComplete(GetPlayer(), achievement))
{
return;
}
@@ -2292,7 +2288,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
ca.date = GameTime::GetGameTime().count();
ca.changed = true;
sScriptMgr->OnAchievementComplete(GetPlayer(), achievement);
sScriptMgr->OnPlayerAchievementComplete(GetPlayer(), achievement);
// pussywizard: set all progress counters to 0, so progress will be deleted from db during save
{
+2 -1
View File
@@ -31,6 +31,7 @@
#include "ObjectMgr.h"
#include "Transport.h"
#include "WorldPacket.h"
#include "WorldSessionMgr.h"
/// @todo: this import is not necessary for compilation and marked as unused by the IDE
// however, for some reasons removing it would cause a damn linking issue
@@ -143,7 +144,7 @@ bool Battlefield::Update(uint32 diff)
{
if (m_Timer <= diff)
{
if (!IsEnabled() || (!IsWarTime() && sWorld->GetActiveSessionCount() > 3500)) // if WG is disabled or there is more than 3500 connections, switch automaticly
if (!IsEnabled() || (!IsWarTime() && sWorldSessionMgr->GetActiveSessionCount() > 3500)) // if WG is disabled or there is more than 3500 connections, switch automaticly
{
m_isActive = true;
EndBattle(false);
+2 -2
View File
@@ -81,7 +81,7 @@ public:
virtual ~BfCapturePoint() { }
virtual void FillInitialWorldStates(WorldPacket& /*data*/) {}
virtual void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& /*packet*/) { }
// Send world state update to all players present
void SendUpdateWorldState(uint32 field, uint32 value);
@@ -334,7 +334,7 @@ public:
/// Send all worldstate data to all player in zone.
virtual void SendInitWorldStatesToAll() = 0;
virtual void FillInitialWorldStates(WorldPacket& /*data*/) = 0;
virtual void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& /*packet*/) = 0;
/// Return if we can use mount in battlefield
bool CanFlyIn() { return !m_isActive; }
@@ -29,6 +29,7 @@
#include "TemporarySummon.h"
#include "Vehicle.h"
#include "WorldSession.h"
#include "WorldStatePackets.h"
BattlefieldWG::~BattlefieldWG()
{
@@ -74,7 +75,7 @@ bool BattlefieldWG::SetupBattlefield()
m_saveTimer = 60000;
// Init GraveYards
// Init Graveyards
SetGraveyardNumber(BATTLEFIELD_WG_GRAVEYARD_MAX);
// Load from db
@@ -102,12 +103,12 @@ bool BattlefieldWG::SetupBattlefield()
BfGraveyardWG* graveyard = new BfGraveyardWG(this);
// When between games, the graveyard is controlled by the defending team
if (WGGraveYard[i].startcontrol == TEAM_NEUTRAL)
graveyard->Initialize(WGGraveYard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SE || WGGraveYard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SW ? GetAttackerTeam() : m_DefenderTeam, WGGraveYard[i].gyid);
if (WGGraveyard[i].startcontrol == TEAM_NEUTRAL)
graveyard->Initialize(WGGraveyard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SE || WGGraveyard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SW ? GetAttackerTeam() : m_DefenderTeam, WGGraveyard[i].gyid);
else
graveyard->Initialize(WGGraveYard[i].startcontrol, WGGraveYard[i].gyid);
graveyard->Initialize(WGGraveyard[i].startcontrol, WGGraveyard[i].gyid);
graveyard->SetTextId(WGGraveYard[i].textid);
graveyard->SetTextId(WGGraveyard[i].textid);
m_GraveyardList[i] = graveyard;
}
@@ -933,46 +934,46 @@ uint32 BattlefieldWG::GetData(uint32 data) const
return Battlefield::GetData(data);
}
void BattlefieldWG::FillInitialWorldStates(WorldPacket& data)
void BattlefieldWG::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(BATTLEFIELD_WG_WORLD_STATE_ATTACKER) << uint32(GetAttackerTeam());
data << uint32(BATTLEFIELD_WG_WORLD_STATE_DEFENDER) << uint32(GetDefenderTeam());
data << uint32(BATTLEFIELD_WG_WORLD_STATE_ACTIVE) << uint32(IsWarTime() ? 0 : 1); // Note: cleanup these two, their names look awkward
data << uint32(BATTLEFIELD_WG_WORLD_STATE_SHOW_WORLDSTATE) << uint32(IsWarTime() ? 1 : 0);
packet.Worldstates.reserve(4+2+WG_MAX_OBJ+WG_MAX_WORKSHOP);
packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_ATTACKER, GetAttackerTeam());
packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_DEFENDER, GetDefenderTeam());
// Note: cleanup these two, their names look awkward
packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_ACTIVE, IsWarTime() ? 0 : 1);
packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_SHOW_WORLDSTATE, IsWarTime() ? 1 : 0);
for (uint32 i = 0; i < 2; ++i)
data << ClockWorldState[i] << uint32(GameTime::GetGameTime().count() + (m_Timer / 1000));
packet.Worldstates.emplace_back(ClockWorldState[i], GameTime::GetGameTime().count() + (m_Timer / 1000));
data << uint32(BATTLEFIELD_WG_WORLD_STATE_VEHICLE_H) << uint32(GetData(BATTLEFIELD_WG_DATA_VEHICLE_H));
data << uint32(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_H) << GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H);
data << uint32(BATTLEFIELD_WG_WORLD_STATE_VEHICLE_A) << uint32(GetData(BATTLEFIELD_WG_DATA_VEHICLE_A));
data << uint32(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_A) << GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A);
packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_VEHICLE_H));
packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H));
packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_VEHICLE_A));
packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A));
data << uint32(WORLDSTATE_HORDE_KEEP_CAPTURED) << uint32(sWorld->getWorldState(WORLDSTATE_HORDE_KEEP_CAPTURED));
data << uint32(WORLDSTATE_HORDE_KEEP_DEFENDED) << uint32(sWorld->getWorldState(WORLDSTATE_HORDE_KEEP_DEFENDED));
data << uint32(WORLDSTATE_ALLIANCE_KEEP_CAPTURED) << uint32(sWorld->getWorldState(WORLDSTATE_ALLIANCE_KEEP_CAPTURED));
data << uint32(WORLDSTATE_ALLIANCE_KEEP_DEFENDED) << uint32(sWorld->getWorldState(WORLDSTATE_ALLIANCE_KEEP_DEFENDED));
packet.Worldstates.emplace_back(WORLDSTATE_ALLIANCE_KEEP_DEFENDED, uint32(sWorld->getWorldState(WORLDSTATE_ALLIANCE_KEEP_DEFENDED)));
packet.Worldstates.emplace_back(WORLDSTATE_HORDE_KEEP_CAPTURED, uint32(sWorld->getWorldState(WORLDSTATE_HORDE_KEEP_CAPTURED)));
packet.Worldstates.emplace_back(WORLDSTATE_HORDE_KEEP_DEFENDED, uint32(sWorld->getWorldState(WORLDSTATE_HORDE_KEEP_DEFENDED)));
packet.Worldstates.emplace_back(WORLDSTATE_ALLIANCE_KEEP_CAPTURED, uint32(sWorld->getWorldState(WORLDSTATE_ALLIANCE_KEEP_CAPTURED)));
for (GameObjectBuilding::const_iterator itr = BuildingsInZone.begin(); itr != BuildingsInZone.end(); ++itr)
data << (*itr)->m_WorldState << (*itr)->m_State;
packet.Worldstates.emplace_back((*itr)->m_WorldState, (*itr)->m_State);
for (Workshop::const_iterator itr = WorkshopsList.begin(); itr != WorkshopsList.end(); ++itr)
if (*itr)
data << WorkshopsData[(*itr)->workshopId].worldstate << (*itr)->state;
packet.Worldstates.emplace_back(WorkshopsData[(*itr)->workshopId].worldstate, (*itr)->state);
}
void BattlefieldWG::SendInitWorldStatesTo(Player* player)
{
WorldPacket data(SMSG_INIT_WORLD_STATES, (4 + 4 + 4 + 2 + (BuildingsInZone.size() * 8) + (WorkshopsList.size() * 8)));
WorldPackets::WorldState::InitWorldStates packet;
packet.MapID = m_MapId;
packet.ZoneID = m_ZoneId;
packet.AreaID = player->GetAreaId();
FillInitialWorldStates(packet);
data << uint32(m_MapId);
data << uint32(m_ZoneId);
data << uint32(0);
data << uint16(14 + BuildingsInZone.size() + WorkshopsList.size()); // Number of fields
FillInitialWorldStates(data);
player->GetSession()->SendPacket(&data);
player->SendDirectMessage(packet.Write());
}
void BattlefieldWG::SendInitWorldStatesToAll()
@@ -21,6 +21,7 @@
#include "Battlefield.h"
#include "Log.h"
#include "World.h"
#include "WorldStatePackets.h"
class Group;
class BattlefieldWG;
@@ -238,7 +239,7 @@ const uint32 WGQuest[2][6] =
{ 13185, 13183, 13223, 13539, 13178, 13180 },
};
// 7 in sql, 7 in header
const BfWGCoordGY WGGraveYard[BATTLEFIELD_WG_GRAVEYARD_MAX] =
const BfWGCoordGY WGGraveyard[BATTLEFIELD_WG_GRAVEYARD_MAX] =
{
{ 5104.750f, 2300.940f, 368.579f, 0.733038f, 1329, BATTLEFIELD_WG_GY_WORKSHOP_NE, BATTLEFIELD_WG_GOSSIPTEXT_GY_NE, TEAM_NEUTRAL },
{ 5099.120f, 3466.036f, 368.484f, 5.317802f, 1330, BATTLEFIELD_WG_GY_WORKSHOP_NW, BATTLEFIELD_WG_GOSSIPTEXT_GY_NW, TEAM_NEUTRAL },
@@ -403,7 +404,7 @@ public:
void SendInitWorldStatesTo(Player* player);
void SendInitWorldStatesToAll() override;
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void HandleKill(Player* killer, Unit* victim) override;
void OnUnitDeath(Unit* unit) override;
+7 -5
View File
@@ -25,7 +25,8 @@
#include "ScriptMgr.h"
#include "World.h"
#include "WorldSession.h"
//#include "WorldStatePackets.h"
#include "WorldSessionMgr.h"
#include "WorldStatePackets.h"
void ArenaScore::AppendToPacket(WorldPacket& data)
{
@@ -146,10 +147,11 @@ void Arena::RemovePlayer(Player* /*player*/)
CheckWinConditions();
}
void Arena::FillInitialWorldStates(WorldPacket& data)
void Arena::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(ARENA_WORLD_STATE_ALIVE_PLAYERS_GREEN) << uint32(GetAlivePlayersCountByTeam(TEAM_HORDE));
data << uint32(ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD) << uint32(GetAlivePlayersCountByTeam(TEAM_ALLIANCE));
packet.Worldstates.reserve(2);
packet.Worldstates.emplace_back(ARENA_WORLD_STATE_ALIVE_PLAYERS_GREEN, GetAlivePlayersCountByTeam(TEAM_HORDE));
packet.Worldstates.emplace_back(ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD, GetAlivePlayersCountByTeam(TEAM_ALLIANCE));
}
void Arena::UpdateArenaWorldState()
@@ -224,7 +226,7 @@ void Arena::EndBattleground(TeamId winnerTeamId)
{
// pussywizard: arena logs in database
uint32 fightId = sArenaTeamMgr->GetNextArenaLogId();
uint32 currOnline = sWorld->GetActiveSessionCount();
uint32 currOnline = sWorldSessionMgr->GetActiveSessionCount();
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
CharacterDatabasePreparedStatement* stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_LOG_FIGHT);
+1 -1
View File
@@ -52,7 +52,7 @@ protected:
void AddPlayer(Player* player) override;
void RemovePlayer(Player* /*player*/) override;
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void UpdateArenaWorldState();
void HandleKillPlayer(Player* player, Player* killer) override;
@@ -0,0 +1,224 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ArenaSeasonMgr.h"
#include "ArenaTeamMgr.h"
#include "ArenaSeasonRewardsDistributor.h"
#include "BattlegroundMgr.h"
#include "GameEventMgr.h"
#include "MapMgr.h"
#include "Player.h"
ArenaSeasonMgr* ArenaSeasonMgr::instance()
{
static ArenaSeasonMgr instance;
return &instance;
}
void ArenaSeasonMgr::LoadRewards()
{
uint32 oldMSTime = getMSTime();
std::unordered_map<std::string, ArenaSeasonRewardGroupCriteriaType> stringToArenaSeasonRewardGroupCriteriaType = {
{"pct", ArenaSeasonRewardGroupCriteriaType::ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE},
{"abs", ArenaSeasonRewardGroupCriteriaType::ARENA_SEASON_REWARD_CRITERIA_TYPE_ABSOLUTE_VALUE}
};
QueryResult result = WorldDatabase.Query("SELECT id, arena_season, criteria_type, min_criteria, max_criteria, reward_mail_template_id, reward_mail_subject, reward_mail_body, gold_reward FROM arena_season_reward_group");
if (!result)
{
LOG_WARN("server.loading", ">> Loaded 0 arena season rewards. DB table `arena_season_reward_group` is empty.");
LOG_INFO("server.loading", " ");
return;
}
std::unordered_map<uint32, ArenaSeasonRewardGroup> groupsMap;
do
{
Field* fields = result->Fetch();
uint32 id = fields[0].Get<uint32>();
ArenaSeasonRewardGroup group;
group.season = fields[1].Get<uint8>();
group.criteriaType = stringToArenaSeasonRewardGroupCriteriaType[fields[2].Get<std::string>()];
group.minCriteria = fields[3].Get<float>();
group.maxCriteria = fields[4].Get<float>();
group.rewardMailTemplateID = fields[5].Get<uint32>();
group.rewardMailSubject = fields[6].Get<std::string>();
group.rewardMailBody = fields[7].Get<std::string>();
group.goldReward = fields[8].Get<uint32>();
groupsMap[id] = group;
} while (result->NextRow());
std::unordered_map<std::string, ArenaSeasonRewardType> stringToArenaSeasonRewardType = {
{"achievement", ArenaSeasonRewardType::ARENA_SEASON_REWARD_TYPE_ACHIEVEMENT},
{"item", ArenaSeasonRewardType::ARENA_SEASON_REWARD_TYPE_ITEM}
};
result = WorldDatabase.Query("SELECT group_id, type, entry FROM arena_season_reward");
if (!result)
{
LOG_WARN("server.loading", ">> Loaded 0 arena season rewards. DB table `arena_season_reward` is empty.");
LOG_INFO("server.loading", " ");
return;
}
do
{
Field* fields = result->Fetch();
uint32 groupId = fields[0].Get<uint32>();
ArenaSeasonReward reward;
reward.type = stringToArenaSeasonRewardType[fields[1].Get<std::string>()];
reward.entry = fields[2].Get<uint32>();
auto itr = groupsMap.find(groupId);
ASSERT(itr != groupsMap.end(), "Unknown arena_season_reward_group ({}) in arena_season_reward", groupId);
(reward.type == ARENA_SEASON_REWARD_TYPE_ITEM) ?
groupsMap[groupId].itemRewards.push_back(reward) :
groupsMap[groupId].achievementRewards.push_back(reward);
} while (result->NextRow());
for (auto const& itr : groupsMap)
_arenaSeasonRewardGroupsStore[itr.second.season].push_back(itr.second);
LOG_INFO("server.loading", ">> Loaded {} arena season rewards in {} ms", (uint32)groupsMap.size(), GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
}
void ArenaSeasonMgr::LoadActiveSeason()
{
QueryResult result = CharacterDatabase.Query("SELECT season_id, season_state FROM active_arena_season");
ASSERT(result, "active_arena_season can't be empty");
Field* fields = result->Fetch();
_currentSeason = fields[0].Get<uint8>();
_currentSeasonState = static_cast<ArenaSeasonState>(fields[1].Get<uint8>());
uint16 eventID = GameEventForArenaSeason(_currentSeason);
sGameEventMgr->StartEvent(eventID, true);
LOG_INFO("server.loading", "Arena Season {} loaded...", _currentSeason);
LOG_INFO("server.loading", " ");
}
void ArenaSeasonMgr::RewardTeamsForTheSeason(std::shared_ptr<ArenaTeamFilter> teamsFilter)
{
ArenaSeasonTeamRewarderImpl rewarder = ArenaSeasonTeamRewarderImpl();
ArenaSeasonRewardDistributor distributor = ArenaSeasonRewardDistributor(&rewarder);
std::vector<ArenaSeasonRewardGroup> rewards = _arenaSeasonRewardGroupsStore[GetCurrentSeason()];
ArenaTeamMgr::ArenaTeamContainer filteredTeams = teamsFilter->Filter(sArenaTeamMgr->GetArenaTeams());
distributor.DistributeRewards(filteredTeams, rewards);
}
bool ArenaSeasonMgr::CanDeleteArenaTeams()
{
std::vector<ArenaSeasonRewardGroup> rewards = _arenaSeasonRewardGroupsStore[GetCurrentSeason()];
if (rewards.empty())
return false;
for (auto const& bg : sBattlegroundMgr->GetActiveBattlegrounds())
if (bg->isRated())
return false;
return true;
}
void ArenaSeasonMgr::DeleteArenaTeams()
{
if (!CanDeleteArenaTeams())
return;
// Cleanup queue first.
std::vector<BattlegroundQueueTypeId> arenasQueueTypes = {BATTLEGROUND_QUEUE_2v2, BATTLEGROUND_QUEUE_3v3, BATTLEGROUND_QUEUE_5v5};
for (BattlegroundQueueTypeId queueType : arenasQueueTypes)
{
auto queue = sBattlegroundMgr->GetBattlegroundQueue(queueType);
for (auto const& [playerGUID, other] : queue.m_QueuedPlayers)
queue.RemovePlayer(playerGUID, true);
}
sArenaTeamMgr->DeleteAllArenaTeams();
}
void ArenaSeasonMgr::ChangeCurrentSeason(uint8 season)
{
if (_currentSeason == season)
return;
uint16 currentEventID = GameEventForArenaSeason(_currentSeason);
sGameEventMgr->StopEvent(currentEventID, true);
uint16 newEventID = GameEventForArenaSeason(season);
sGameEventMgr->StartEvent(newEventID, true);
_currentSeason = season;
_currentSeasonState = ARENA_SEASON_STATE_IN_PROGRESS;
CharacterDatabase.Execute("UPDATE active_arena_season SET season_id = {}, season_state = {}", _currentSeason, _currentSeasonState);
BroadcastUpdatedWorldState();
}
void ArenaSeasonMgr::SetSeasonState(ArenaSeasonState state)
{
if (_currentSeasonState == state)
return;
_currentSeasonState = state;
CharacterDatabase.Execute("UPDATE active_arena_season SET season_state = {}", _currentSeasonState);
BroadcastUpdatedWorldState();
}
uint16 ArenaSeasonMgr::GameEventForArenaSeason(uint8 season)
{
QueryResult result = WorldDatabase.Query("SELECT eventEntry FROM game_event_arena_seasons WHERE season = '{}'", season);
if (!result)
{
LOG_ERROR("arenaseasonmgr", "ArenaSeason ({}) must be an existant Arena Season", season);
return 0;
}
Field* fields = result->Fetch();
return fields[0].Get<uint16>();
}
void ArenaSeasonMgr::BroadcastUpdatedWorldState()
{
sMapMgr->DoForAllMaps([](Map* map)
{
// Ignore instanceable maps, players will get a fresh state once they change the map.
if (map->Instanceable())
return;
map->DoForAllPlayers([&](Player* player)
{
uint32 currZone, currArea;
player->GetZoneAndAreaId(currZone, currArea);
player->SendInitWorldStates(currZone, currArea);
});
});
}
@@ -0,0 +1,126 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARENASEASONMGR_H
#define _ARENASEASONMGR_H
#include "Common.h"
#include "ArenaTeamFilter.h"
#include <vector>
#include <unordered_map>
enum ArenaSeasonState
{
ARENA_SEASON_STATE_DISABLED = 0,
ARENA_SEASON_STATE_IN_PROGRESS = 1
};
enum ArenaSeasonRewardType
{
ARENA_SEASON_REWARD_TYPE_ITEM,
ARENA_SEASON_REWARD_TYPE_ACHIEVEMENT
};
enum ArenaSeasonRewardGroupCriteriaType
{
ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE,
ARENA_SEASON_REWARD_CRITERIA_TYPE_ABSOLUTE_VALUE
};
// ArenaSeasonReward represents one reward, it can be an item or achievement.
struct ArenaSeasonReward
{
ArenaSeasonReward() = default;
// Item or acheivement entry.
uint32 entry{};
ArenaSeasonRewardType type{ARENA_SEASON_REWARD_TYPE_ITEM};
// Used in unit tests.
bool operator==(const ArenaSeasonReward& other) const
{
return entry == other.entry && type == other.type;
}
};
struct ArenaSeasonRewardGroup
{
ArenaSeasonRewardGroup() = default;
uint8 season{};
ArenaSeasonRewardGroupCriteriaType criteriaType;
float minCriteria{};
float maxCriteria{};
uint32 rewardMailTemplateID{};
std::string rewardMailSubject{};
std::string rewardMailBody{};
uint32 goldReward{};
std::vector<ArenaSeasonReward> itemRewards;
std::vector<ArenaSeasonReward> achievementRewards;
// Used in unit tests.
bool operator==(const ArenaSeasonRewardGroup& other) const
{
return minCriteria == other.minCriteria &&
maxCriteria == other.maxCriteria &&
criteriaType == other.criteriaType &&
itemRewards == other.itemRewards &&
achievementRewards == other.achievementRewards;
}
};
class ArenaSeasonMgr
{
public:
static ArenaSeasonMgr* instance();
using ArenaSeasonRewardGroupsBySeasonContainer = std::unordered_map<uint8, std::vector<ArenaSeasonRewardGroup>>;
// Loading functions
void LoadRewards();
void LoadActiveSeason();
// Season management functions
void ChangeCurrentSeason(uint8 season);
uint8 GetCurrentSeason() { return _currentSeason; }
void SetSeasonState(ArenaSeasonState state);
ArenaSeasonState GetSeasonState() { return _currentSeasonState; }
// Season completion functions
void RewardTeamsForTheSeason(std::shared_ptr<ArenaTeamFilter> teamsFilter);
bool CanDeleteArenaTeams();
void DeleteArenaTeams();
private:
uint16 GameEventForArenaSeason(uint8 season);
void BroadcastUpdatedWorldState();
ArenaSeasonRewardGroupsBySeasonContainer _arenaSeasonRewardGroupsStore;
uint8 _currentSeason{};
ArenaSeasonState _currentSeasonState{};
};
#define sArenaSeasonMgr ArenaSeasonMgr::instance()
#endif // _ARENASEASONMGR_H
@@ -0,0 +1,166 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ArenaSeasonRewardsDistributor.h"
#include "AchievementMgr.h"
#include "CharacterDatabase.h"
#include "Mail.h"
#include "Player.h"
#include <algorithm>
constexpr float minPctTeamGamesForMemberToGetReward = 30;
void ArenaSeasonTeamRewarderImpl::RewardTeamWithRewardGroup(ArenaTeam *arenaTeam, const ArenaSeasonRewardGroup &rewardGroup)
{
RewardWithMail(arenaTeam, rewardGroup);
RewardWithAchievements(arenaTeam, rewardGroup);
}
void ArenaSeasonTeamRewarderImpl::RewardWithMail(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup)
{
if (rewardGroup.itemRewards.empty() && rewardGroup.goldReward == 0)
return;
const uint32 npcKingDondSender = 18897;
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
for (auto const& member : arenaTeam->GetMembers())
{
uint32 teamSeasonGames = arenaTeam->GetStats().SeasonGames;
// Avoid division by zero.
if (teamSeasonGames == 0)
continue;
float memberParticipationPercentage = (static_cast<float>(member.SeasonGames) / teamSeasonGames) * 100;
if (memberParticipationPercentage < minPctTeamGamesForMemberToGetReward)
continue;
Player* player = ObjectAccessor::FindPlayer(member.Guid);
auto draft = rewardGroup.rewardMailTemplateID > 0 ?
MailDraft(rewardGroup.rewardMailTemplateID, false) :
MailDraft(rewardGroup.rewardMailSubject, rewardGroup.rewardMailBody);
if (rewardGroup.goldReward > 0)
draft.AddMoney(rewardGroup.goldReward);
for (auto const& reward : rewardGroup.itemRewards)
if (Item* item = Item::CreateItem(reward.entry, 1))
{
item->SaveToDB(trans);
draft.AddItem(item);
}
draft.SendMailTo(trans, MailReceiver(player, member.Guid.GetCounter()), MailSender(npcKingDondSender));
}
CharacterDatabase.CommitTransaction(trans);
}
void ArenaSeasonTeamRewarderImpl::RewardWithAchievements(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup)
{
if (rewardGroup.achievementRewards.empty())
return;
for (auto const& member : arenaTeam->GetMembers())
{
uint32 teamSeasonGames = arenaTeam->GetStats().SeasonGames;
// Avoid division by zero.
if (teamSeasonGames == 0)
continue;
float memberParticipationPercentage = (static_cast<float>(member.SeasonGames) / teamSeasonGames) * 100;
if (memberParticipationPercentage < minPctTeamGamesForMemberToGetReward)
continue;
Player* player = ObjectAccessor::FindPlayer(member.Guid);
for (auto const& reward : rewardGroup.achievementRewards)
{
AchievementEntry const* achievement = sAchievementStore.LookupEntry(reward.entry);
if (!achievement)
continue;
if (player)
player->CompletedAchievement(achievement);
else
sAchievementMgr->CompletedAchievementForOfflinePlayer(member.Guid.GetCounter(), achievement);
}
}
}
ArenaSeasonRewardDistributor::ArenaSeasonRewardDistributor(ArenaSeasonTeamRewarder* rewarder)
: _rewarder(rewarder)
{
}
void ArenaSeasonRewardDistributor::DistributeRewards(ArenaTeamMgr::ArenaTeamContainer &arenaTeams, std::vector<ArenaSeasonRewardGroup> &rewardGroups)
{
std::vector<ArenaTeam*> sortedTeams;
sortedTeams.reserve(arenaTeams.size());
static constexpr uint16 minRequiredGames = 30;
for (auto const& [id, team] : arenaTeams)
if (team->GetStats().SeasonGames >= minRequiredGames)
sortedTeams.push_back(team);
std::sort(sortedTeams.begin(), sortedTeams.end(), [](ArenaTeam* a, ArenaTeam* b) {
return a->GetRating() > b->GetRating();
});
std::vector<ArenaSeasonRewardGroup> pctRewardGroup;
std::vector<ArenaSeasonRewardGroup> absRewardGroup;
for (auto const& reward : rewardGroups)
{
if (reward.criteriaType == ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE)
pctRewardGroup.push_back(reward);
else
absRewardGroup.push_back(reward);
}
size_t totalTeams = sortedTeams.size();
for (auto const& rewardGroup : pctRewardGroup)
{
size_t minIndex = static_cast<size_t>(rewardGroup.minCriteria * totalTeams / 100);
size_t maxIndex = static_cast<size_t>(rewardGroup.maxCriteria * totalTeams / 100);
minIndex = std::min(minIndex, totalTeams);
maxIndex = std::min(maxIndex, totalTeams);
for (size_t i = minIndex; i < maxIndex; ++i)
{
ArenaTeam* team = sortedTeams[i];
_rewarder->RewardTeamWithRewardGroup(team, rewardGroup);
}
}
for (auto const& rewardGroup : absRewardGroup)
{
size_t minIndex = rewardGroup.minCriteria-1; // Top 1 team is the team with index 0, so we need make -1.
size_t maxIndex = rewardGroup.maxCriteria;
minIndex = std::max(minIndex, size_t(0));
minIndex = std::min(minIndex, totalTeams);
maxIndex = std::min(maxIndex, totalTeams);
for (size_t i = minIndex; i < maxIndex; ++i)
{
ArenaTeam* team = sortedTeams[i];
_rewarder->RewardTeamWithRewardGroup(team, rewardGroup);
}
}
}
@@ -0,0 +1,54 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARENASEASONREWARDDISTRIBUTOR_H
#define _ARENASEASONREWARDDISTRIBUTOR_H
#include "ArenaSeasonMgr.h"
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h"
class ArenaSeasonTeamRewarder
{
public:
virtual ~ArenaSeasonTeamRewarder() = default;
virtual void RewardTeamWithRewardGroup(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup) = 0;
};
class ArenaSeasonTeamRewarderImpl: public ArenaSeasonTeamRewarder
{
public:
void RewardTeamWithRewardGroup(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup) override;
private:
void RewardWithMail(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup);
void RewardWithAchievements(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup);
};
class ArenaSeasonRewardDistributor
{
public:
ArenaSeasonRewardDistributor(ArenaSeasonTeamRewarder* rewarder);
void DistributeRewards(ArenaTeamMgr::ArenaTeamContainer& arenaTeams, std::vector<ArenaSeasonRewardGroup>& rewardGroups);
private:
ArenaSeasonTeamRewarder* _rewarder;
};
#endif // _ARENASEASONREWARDDISTRIBUTOR_H
@@ -0,0 +1,113 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARENATEAMFILTER_H
#define _ARENATEAMFILTER_H
#include "Common.h"
#include "ArenaTeamMgr.h"
#include "ArenaTeam.h"
#include "Tokenize.h"
#include "StringConvert.h"
#include <sstream>
#include <string>
#include <memory>
#include <unordered_map>
#include <algorithm>
#include <cctype>
class ArenaTeamFilter
{
public:
virtual ~ArenaTeamFilter() = default;
virtual ArenaTeamMgr::ArenaTeamContainer Filter(ArenaTeamMgr::ArenaTeamContainer teams) = 0;
};
class ArenaTeamFilterByTypes : public ArenaTeamFilter
{
public:
ArenaTeamFilterByTypes(std::vector<uint8> validTypes) : _validTypes(validTypes) {}
ArenaTeamMgr::ArenaTeamContainer Filter(ArenaTeamMgr::ArenaTeamContainer teams) override
{
ArenaTeamMgr::ArenaTeamContainer result;
for (auto const& pair : teams)
{
ArenaTeam* team = pair.second;
for (uint8 arenaType : _validTypes)
{
if (team->GetType() == arenaType)
{
result[pair.first] = team;
break;
}
}
}
return result;
}
private:
std::vector<uint8> _validTypes;
};
class ArenaTeamFilterAllTeams : public ArenaTeamFilter
{
public:
ArenaTeamMgr::ArenaTeamContainer Filter(ArenaTeamMgr::ArenaTeamContainer teams) override
{
return teams;
}
};
class ArenaTeamFilterFactoryByUserInput
{
public:
std::unique_ptr<ArenaTeamFilter> CreateFilterByUserInput(std::string userInput)
{
std::transform(userInput.begin(), userInput.end(), userInput.begin(),
[](unsigned char c) { return std::tolower(c); });
if (userInput == "all")
return std::make_unique<ArenaTeamFilterAllTeams>();
// Parse the input string (e.g., "2,3") into valid types
std::vector<uint8> validTypes = ParseTypes(userInput);
if (!validTypes.empty())
return std::make_unique<ArenaTeamFilterByTypes>(validTypes);
return nullptr;
}
private:
std::vector<uint8> ParseTypes(std::string_view userInput)
{
std::vector<uint8> validTypes;
auto tokens = Acore::Tokenize(userInput, ',', false);
for (auto const& token : tokens)
if (auto typeOpt = Acore::StringTo<uint8>(token))
validTypes.push_back(*typeOpt);
return validTypes;
}
};
#endif // _ARENATEAMFILTER_H
+2 -1
View File
@@ -17,6 +17,7 @@
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h"
#include "ArenaSeasonMgr.h"
#include "BattlegroundMgr.h"
#include "CharacterCache.h"
#include "Group.h"
@@ -658,7 +659,7 @@ uint32 ArenaTeam::GetPoints(uint32 memberRating)
if (rating <= 1500)
{
if (sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) < 6 && !sWorld->getIntConfig(CONFIG_LEGACY_ARENA_POINTS_CALC))
if (sArenaSeasonMgr->GetCurrentSeason() < 6 && !sWorld->getIntConfig(CONFIG_LEGACY_ARENA_POINTS_CALC))
points = (float)rating * 0.22f + 14.0f;
else
points = 344;
@@ -125,6 +125,27 @@ void ArenaTeamMgr::RemoveArenaTeam(uint32 arenaTeamId)
ArenaTeamStore.erase(arenaTeamId);
}
void ArenaTeamMgr::DeleteAllArenaTeams()
{
for (auto const& [id, team] : ArenaTeamStore)
{
while (team->GetMembersSize() > 0)
team->DelMember(team->GetMembers().front().Guid, false);
delete team;
}
ArenaTeamStore.clear();
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
trans->Append("DELETE FROM arena_team_member");
trans->Append("DELETE FROM arena_team");
trans->Append("DELETE FROM character_arena_stats");
CharacterDatabase.CommitTransaction(trans);
NextArenaTeamId = 1;
}
uint32 ArenaTeamMgr::GenerateArenaTeamId()
{
if (NextArenaTeamId >= MAX_ARENA_TEAM_ID)
@@ -43,6 +43,8 @@ public:
void AddArenaTeam(ArenaTeam* arenaTeam);
void RemoveArenaTeam(uint32 Id);
void DeleteAllArenaTeams();
ArenaTeamContainer::iterator GetArenaTeamMapBegin() { return ArenaTeamStore.begin(); }
ArenaTeamContainer::iterator GetArenaTeamMapEnd() { return ArenaTeamStore.end(); }
ArenaTeamContainer& GetArenaTeams() { return ArenaTeamStore; }
+2 -1
View File
@@ -24,6 +24,7 @@
#include "GameObject.h"
#include "SharedDefines.h"
#include "World.h"
#include "WorldStatePackets.h"
class Creature;
class GameObject;
@@ -458,7 +459,7 @@ public:
// Packet Transfer
// method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!)
virtual void FillInitialWorldStates(WorldPacket& /*data*/) { }
virtual void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& /*packet*/) { }
void SendPacketToTeam(TeamId teamId, WorldPacket const* packet, Player* sender = nullptr, bool self = true);
void SendPacketToAll(WorldPacket const* packet);
void YellToAll(Creature* creature, const char* text, uint32 language);
@@ -334,6 +334,18 @@ Battleground* BattlegroundMgr::GetBattlegroundTemplate(BattlegroundTypeId bgType
return bgs.empty() ? nullptr : bgs.begin()->second;
}
std::vector<Battleground const*> BattlegroundMgr::GetActiveBattlegrounds()
{
std::vector<Battleground const*> result;
for (auto const& [bgType, bgData] : bgDataStore)
for (auto const& [id, bg] : bgData._Battlegrounds)
if (bg->GetStatus() == STATUS_WAIT_JOIN || bg->GetStatus() == STATUS_IN_PROGRESS)
result.push_back(static_cast<const Battleground*>(bg));
return result;
}
uint32 BattlegroundMgr::CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
{
if (IsArenaType(bgTypeId))
@@ -82,6 +82,7 @@ public:
Battleground* GetBattleground(uint32 instanceID, BattlegroundTypeId bgTypeId);
Battleground* GetBattlegroundTemplate(BattlegroundTypeId bgTypeId);
Battleground* CreateNewBattleground(BattlegroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated);
std::vector<Battleground const*> GetActiveBattlegrounds();
void AddBattleground(Battleground* bg);
void RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId);
@@ -1355,11 +1355,11 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
CharacterDatabase.Execute(stmt);
}
sScriptMgr->OnBattlegroundDesertion(player, BG_DESERTION_TYPE_NO_ENTER_BUTTON);
sScriptMgr->OnPlayerBattlegroundDesertion(player, BG_DESERTION_TYPE_NO_ENTER_BUTTON);
}
if (bg && bg->isArena() && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN))
sScriptMgr->OnBattlegroundDesertion(player, ARENA_DESERTION_TYPE_NO_ENTER_BUTTON);
sScriptMgr->OnPlayerBattlegroundDesertion(player, ARENA_DESERTION_TYPE_NO_ENTER_BUTTON);
LOG_DEBUG("bg.battleground", "Battleground: removing player {} from bg queue for instance {} because of not pressing enter battle in time.", player->GetGUID().ToString(), m_BgInstanceGUID);
@@ -23,6 +23,7 @@
#include "Util.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldStatePackets.h"
void BattlegroundABScore::BuildObjectivesBlock(WorldPacket& data)
{
@@ -234,24 +235,26 @@ void BattlegroundAB::DeleteBanner(uint8 node)
SpawnBGObject(node * BG_AB_OBJECTS_PER_NODE + BG_AB_OBJECT_AURA_ALLY + _capturePointInfo[node]._ownerTeamId, RESPAWN_ONE_DAY);
}
void BattlegroundAB::FillInitialWorldStates(WorldPacket& data)
void BattlegroundAB::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
packet.Worldstates.reserve(BG_AB_DYNAMIC_NODES_COUNT+7);
for (auto& node : _capturePointInfo)
{
if (node._state == BG_AB_NODE_STATE_NEUTRAL)
data << uint32(node._iconNone) << uint32(1);
packet.Worldstates.emplace_back(node._iconNone, 1);
for (uint8 i = BG_AB_NODE_STATE_ALLY_OCCUPIED; i <= BG_AB_NODE_STATE_HORDE_CONTESTED; ++i)
data << uint32(node._iconCapture + i - 1) << uint32(node._state == i);
packet.Worldstates.emplace_back(node._iconCapture + i - 1, node._state == i ? 1 : 0);
}
data << uint32(BG_AB_OP_OCCUPIED_BASES_ALLY) << uint32(_controlledPoints[TEAM_ALLIANCE]);
data << uint32(BG_AB_OP_OCCUPIED_BASES_HORDE) << uint32(_controlledPoints[TEAM_HORDE]);
data << uint32(BG_AB_OP_RESOURCES_MAX) << uint32(BG_AB_MAX_TEAM_SCORE);
data << uint32(BG_AB_OP_RESOURCES_WARNING) << uint32(BG_AB_WARNING_NEAR_VICTORY_SCORE);
data << uint32(BG_AB_OP_RESOURCES_ALLY) << uint32(m_TeamScores[TEAM_ALLIANCE]);
data << uint32(BG_AB_OP_RESOURCES_HORDE) << uint32(m_TeamScores[TEAM_HORDE]);
data << uint32(0x745) << uint32(0x2); // 37 1861 unk
packet.Worldstates.emplace_back(BG_AB_OP_OCCUPIED_BASES_ALLY, _controlledPoints[TEAM_ALLIANCE]);
packet.Worldstates.emplace_back(BG_AB_OP_OCCUPIED_BASES_HORDE, _controlledPoints[TEAM_HORDE]);
packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_MAX, BG_AB_MAX_TEAM_SCORE);
packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_WARNING, BG_AB_WARNING_NEAR_VICTORY_SCORE);
packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[TEAM_ALLIANCE]);
packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_HORDE, m_TeamScores[TEAM_HORDE]);
packet.Worldstates.emplace_back(0x745, 2);
}
void BattlegroundAB::SendNodeUpdate(uint8 node)
@@ -316,7 +316,7 @@ public:
GraveyardStruct const* GetClosestGraveyard(Player* player) override;
bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void EventPlayerClickedOnFlag(Player* source, GameObject* gameObject) override;
bool AllNodesConrolledByTeam(TeamId teamId) const override;
@@ -25,6 +25,7 @@
#include "Player.h"
#include "SpellAuras.h"
#include "WorldPacket.h"
#include "WorldStatePackets.h"
void BattlegroundAVScore::BuildObjectivesBlock(WorldPacket& data)
{
@@ -1084,9 +1085,10 @@ void BattlegroundAV::EventPlayerAssaultsPoint(Player* player, uint32 object)
player->KilledMonsterCredit((IsTower(node)) ? BG_AV_QUEST_CREDIT_TOWER : BG_AV_QUEST_CREDIT_GRAVEYARD);
}
void BattlegroundAV::FillInitialWorldStates(WorldPacket& data)
void BattlegroundAV::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
bool stateok;
packet.Worldstates.reserve(7*2*2 + 8*2*2 + 5);
//graveyards
for (uint8 i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; i++)
{
@@ -1094,8 +1096,8 @@ void BattlegroundAV::FillInitialWorldStates(WorldPacket& data)
{
//j=1=assaulted j=3=controled
stateok = (m_Nodes[i].State == j);
data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)]) << uint32((m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0);
data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)]) << uint32((m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0);
packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)], (m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0);
packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)], (m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0);
}
}
@@ -1105,23 +1107,19 @@ void BattlegroundAV::FillInitialWorldStates(WorldPacket& data)
{
//j=1=assaulted j=3=controled //i dont have j=2=destroyed cause destroyed is the same like enemy-team controll
stateok = (m_Nodes[i].State == j || (m_Nodes[i].State == POINT_DESTROYED && j == 3));
data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)]) << uint32((m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0);
data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)]) << uint32((m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0);
packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)], (m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0);
packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)], (m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0);
}
if (m_Nodes[BG_AV_NODES_SNOWFALL_GRAVE].OwnerId == TEAM_NEUTRAL) //cause neutral teams aren't handled generic
data << uint32(AV_SNOWFALL_N) << uint32(1);
data << uint32(AV_Alliance_Score) << uint32(m_Team_Scores[0]);
data << uint32(AV_Horde_Score) << uint32(m_Team_Scores[1]);
if (GetStatus() == STATUS_IN_PROGRESS) //only if game started the teamscores are displayed
{
data << uint32(AV_SHOW_A_SCORE) << uint32(1);
data << uint32(AV_SHOW_H_SCORE) << uint32(1);
}
else
{
data << uint32(AV_SHOW_A_SCORE) << uint32(0);
data << uint32(AV_SHOW_H_SCORE) << uint32(0);
packet.Worldstates.emplace_back(AV_SNOWFALL_N, 1);
}
packet.Worldstates.emplace_back(AV_Alliance_Score, m_Team_Scores[0]);
packet.Worldstates.emplace_back(AV_Horde_Score, m_Team_Scores[1]);
packet.Worldstates.emplace_back(AV_SHOW_A_SCORE, GetStatus() == STATUS_IN_PROGRESS ? 1 : 0);
packet.Worldstates.emplace_back(AV_SHOW_H_SCORE, GetStatus() == STATUS_IN_PROGRESS ? 1 : 0);
SendMineWorldStates(AV_NORTH_MINE);
SendMineWorldStates(AV_SOUTH_MINE);
}
@@ -1940,7 +1940,7 @@ private:
void ChangeMineOwner(uint8 mine, TeamId teamId, bool initial = false);
/*worldstates*/
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
uint8 GetWorldStateType(uint8 state, TeamId teamId);
void SendMineWorldStates(uint32 mine);
void UpdateNodeWorldState(BG_AV_Nodes node);
@@ -19,6 +19,7 @@
#include "Log.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldStatePackets.h"
BattlegroundBE::BattlegroundBE()
{
@@ -87,10 +88,10 @@ void BattlegroundBE::HandleAreaTrigger(Player* player, uint32 trigger)
}
}
void BattlegroundBE::FillInitialWorldStates(WorldPacket& data)
void BattlegroundBE::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(0x9f3) << uint32(1); // 9
Arena::FillInitialWorldStates(data);
packet.Worldstates.emplace_back(0x9f3, 1); // BATTLEGROUND_BLADES_EDGE_ARENA_SHOW
Arena::FillInitialWorldStates(packet);
}
bool BattlegroundBE::SetupBattleground()
@@ -54,7 +54,7 @@ public:
void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override;
void FillInitialWorldStates(WorldPacket& d) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
bool HandlePlayerUnderMap(Player* player) override;
};
@@ -22,6 +22,7 @@
#include "ObjectAccessor.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldStatePackets.h"
BattlegroundDS::BattlegroundDS()
{
@@ -173,10 +174,10 @@ bool BattlegroundDS::HandlePlayerUnderMap(Player* player)
return true;
}
void BattlegroundDS::FillInitialWorldStates(WorldPacket& data)
void BattlegroundDS::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(3610) << uint32(1); // 9 show
Arena::FillInitialWorldStates(data);
packet.Worldstates.emplace_back(0xe1a, 1); // ARENA_WORLD_STATE_ALIVE_PLAYERS_SHOW
Arena::FillInitialWorldStates(packet);
}
bool BattlegroundDS::SetupBattleground()
@@ -101,7 +101,7 @@ public:
void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override;
void FillInitialWorldStates(WorldPacket& d) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
bool HandlePlayerUnderMap(Player* player) override;
private:
@@ -26,6 +26,7 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldStatePackets.h"
void BattlegroundEYScore::BuildObjectivesBlock(WorldPacket& data)
{
@@ -506,7 +507,7 @@ void BattlegroundEY::EventTeamCapturedPoint(Player* player, TeamId teamId, uint3
_capturePointInfo[point]._ownerTeamId = teamId;
GraveyardStruct const* sg = sGraveyard->GetGraveyard(m_CapturingPointTypes[point].GraveYardId);
GraveyardStruct const* sg = sGraveyard->GetGraveyard(m_CapturingPointTypes[point].GraveyardId);
AddSpiritGuide(point, sg->x, sg->y, sg->z, 3.124139f, teamId);
UpdatePointsIcons(point);
@@ -568,30 +569,31 @@ bool BattlegroundEY::UpdatePlayerScore(Player* player, uint32 type, uint32 value
return true;
}
void BattlegroundEY::FillInitialWorldStates(WorldPacket& data)
void BattlegroundEY::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(EY_HORDE_BASE) << uint32(_ownedPointsCount[TEAM_HORDE]);
data << uint32(EY_ALLIANCE_BASE) << uint32(_ownedPointsCount[TEAM_ALLIANCE]);
data << uint32(DRAENEI_RUINS_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_HORDE));
data << uint32(DRAENEI_RUINS_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_ALLIANCE));
data << uint32(DRAENEI_RUINS_UNCONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUncontrolled());
data << uint32(MAGE_TOWER_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_HORDE));
data << uint32(MAGE_TOWER_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_ALLIANCE));
data << uint32(MAGE_TOWER_UNCONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUncontrolled());
data << uint32(FEL_REAVER_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_HORDE));
data << uint32(FEL_REAVER_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_ALLIANCE));
data << uint32(FEL_REAVER_UNCONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUncontrolled());
data << uint32(BLOOD_ELF_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_HORDE));
data << uint32(BLOOD_ELF_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_ALLIANCE));
data << uint32(BLOOD_ELF_UNCONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUncontrolled());
data << uint32(NETHERSTORM_FLAG) << uint32(_flagState == BG_EY_FLAG_STATE_ON_BASE);
data << uint32(NETHERSTORM_FLAG_STATE_HORDE) << uint32(1);
data << uint32(NETHERSTORM_FLAG_STATE_ALLIANCE) << uint32(1);
data << uint32(EY_HORDE_RESOURCES) << uint32(GetTeamScore(TEAM_HORDE));
data << uint32(EY_ALLIANCE_RESOURCES) << uint32(GetTeamScore(TEAM_ALLIANCE));
data << uint32(PROGRESS_BAR_SHOW) << uint32(0);
data << uint32(PROGRESS_BAR_PERCENT_GREY) << uint32(0);
data << uint32(PROGRESS_BAR_STATUS) << uint32(0);
packet.Worldstates.reserve(22);
packet.Worldstates.emplace_back(EY_HORDE_BASE, _ownedPointsCount[TEAM_HORDE]);
packet.Worldstates.emplace_back(EY_ALLIANCE_BASE, _ownedPointsCount[TEAM_ALLIANCE]);
packet.Worldstates.emplace_back(DRAENEI_RUINS_HORDE_CONTROL, _capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_HORDE));
packet.Worldstates.emplace_back(DRAENEI_RUINS_ALLIANCE_CONTROL, _capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(DRAENEI_RUINS_UNCONTROL, _capturePointInfo[POINT_DRAENEI_RUINS].IsUncontrolled());
packet.Worldstates.emplace_back(MAGE_TOWER_ALLIANCE_CONTROL, _capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_HORDE));
packet.Worldstates.emplace_back(MAGE_TOWER_HORDE_CONTROL, _capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(MAGE_TOWER_UNCONTROL, _capturePointInfo[POINT_MAGE_TOWER].IsUncontrolled());
packet.Worldstates.emplace_back(FEL_REAVER_HORDE_CONTROL, _capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_HORDE));
packet.Worldstates.emplace_back(FEL_REAVER_ALLIANCE_CONTROL, _capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(FEL_REAVER_UNCONTROL, _capturePointInfo[POINT_FEL_REAVER].IsUncontrolled());
packet.Worldstates.emplace_back(BLOOD_ELF_HORDE_CONTROL, _capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_HORDE));
packet.Worldstates.emplace_back(BLOOD_ELF_ALLIANCE_CONTROL, _capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(BLOOD_ELF_UNCONTROL, _capturePointInfo[POINT_BLOOD_ELF].IsUncontrolled());
packet.Worldstates.emplace_back(NETHERSTORM_FLAG, _flagState == BG_EY_FLAG_STATE_ON_BASE);
packet.Worldstates.emplace_back(NETHERSTORM_FLAG_STATE_HORDE, 1);
packet.Worldstates.emplace_back(NETHERSTORM_FLAG_STATE_ALLIANCE, 1);
packet.Worldstates.emplace_back(EY_HORDE_RESOURCES, GetTeamScore(TEAM_HORDE));
packet.Worldstates.emplace_back(EY_ALLIANCE_RESOURCES, GetTeamScore(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(PROGRESS_BAR_SHOW, 0);
packet.Worldstates.emplace_back(PROGRESS_BAR_PERCENT_GREY, 0);
packet.Worldstates.emplace_back(PROGRESS_BAR_STATUS, 0);
}
GraveyardStruct const* BattlegroundEY::GetClosestGraveyard(Player* player)
@@ -608,7 +610,7 @@ GraveyardStruct const* BattlegroundEY::GetClosestGraveyard(Player* player)
for (uint8 i = 0; i < EY_POINTS_MAX; ++i)
if (_capturePointInfo[i].IsUnderControl(player->GetTeamId()))
{
entry = sGraveyard->GetGraveyard(m_CapturingPointTypes[i].GraveYardId);
entry = sGraveyard->GetGraveyard(m_CapturingPointTypes[i].GraveyardId);
dist = (entry->x - pX) * (entry->x - pX) + (entry->y - pY) * (entry->y - pY) + (entry->z - pZ) * (entry->z - pZ);
if (dist < minDist)
{
@@ -305,11 +305,11 @@ struct BattlegroundEYLosingPointStruct
struct BattlegroundEYCapturingPointStruct
{
BattlegroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveYardId)
BattlegroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveyardId)
: DespawnNeutralObjectType(_DespawnNeutralObjectType),
SpawnObjectTypeAlliance(_SpawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance),
SpawnObjectTypeHorde(_SpawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde),
GraveYardId(_GraveYardId)
GraveyardId(_GraveyardId)
{}
uint32 DespawnNeutralObjectType;
@@ -317,7 +317,7 @@ struct BattlegroundEYCapturingPointStruct
uint32 MessageIdAlliance;
uint32 SpawnObjectTypeHorde;
uint32 MessageIdHorde;
uint32 GraveYardId;
uint32 GraveyardId;
};
const uint32 BG_EY_TickPoints[EY_POINTS_MAX] = {1, 2, 5, 10};
@@ -421,7 +421,7 @@ public:
void Init() override;
void EndBattleground(TeamId winnerTeamId) override;
bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void SetDroppedFlagGUID(ObjectGuid guid, TeamId /*teamId*/ = TEAM_NEUTRAL) override { _droppedFlagGUID = guid; }
ObjectGuid GetDroppedFlagGUID() const { return _droppedFlagGUID; }
@@ -26,6 +26,7 @@
#include "Transport.h"
#include "Vehicle.h"
#include "WorldPacket.h"
#include "WorldStatePackets.h"
void BattlegroundICScore::BuildObjectivesBlock(WorldPacket& data)
{
@@ -381,21 +382,24 @@ bool BattlegroundIC::UpdatePlayerScore(Player* player, uint32 type, uint32 value
return true;
}
void BattlegroundIC::FillInitialWorldStates(WorldPacket& data)
void BattlegroundIC::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(BG_IC_ALLIANCE_RENFORT_SET) << uint32(1);
data << uint32(BG_IC_HORDE_RENFORT_SET) << uint32(1);
data << uint32(BG_IC_ALLIANCE_RENFORT) << uint32(factionReinforcements[TEAM_ALLIANCE]);
data << uint32(BG_IC_HORDE_RENFORT) << uint32(factionReinforcements[TEAM_HORDE]);
packet.Worldstates.reserve(4+MAX_FORTRESS_GATES_SPAWNS+MAX_NODE_TYPES+1);
packet.Worldstates.emplace_back(BG_IC_ALLIANCE_RENFORT_SET, 1);
packet.Worldstates.emplace_back(BG_IC_HORDE_RENFORT_SET, 1);
packet.Worldstates.emplace_back(BG_IC_ALLIANCE_RENFORT, factionReinforcements[TEAM_ALLIANCE]);
packet.Worldstates.emplace_back(BG_IC_HORDE_RENFORT, factionReinforcements[TEAM_HORDE]);
for (uint8 i = 0; i < MAX_FORTRESS_GATES_SPAWNS; ++i)
{
uint32 uws = GetWorldStateFromGateEntry(BG_IC_ObjSpawnlocs[i].entry, (GateStatus[GetGateIDFromEntry(BG_IC_ObjSpawnlocs[i].entry)] == BG_IC_GATE_DESTROYED));
data << uint32(uws) << uint32(1);
packet.Worldstates.emplace_back(uws, 1);
}
for (uint8 i = 0; i < MAX_NODE_TYPES; ++i)
data << uint32(nodePoint[i].worldStates[nodePoint[i].nodeState]) << uint32(1);
packet.Worldstates.emplace_back(nodePoint[i].worldStates[nodePoint[i].nodeState], 1);
packet.Worldstates.emplace_back(BG_IC_HORDE_RENFORT_SET, 1);
}
bool BattlegroundIC::SetupBattleground()
@@ -974,7 +974,7 @@ public:
/* Scorekeeping */
bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void HandlePlayerResurrect(Player* player) override;
@@ -64,10 +64,10 @@ void BattlegroundNA::HandleAreaTrigger(Player* player, uint32 trigger)
}
}
void BattlegroundNA::FillInitialWorldStates(WorldPacket& data)
void BattlegroundNA::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(0xa11) << uint32(1); // 9
Arena::FillInitialWorldStates(data);
packet.Worldstates.emplace_back(0xa11, 1); // BATTLEGROUND_NAGRAND_ARENA_SHOW
Arena::FillInitialWorldStates(packet);
}
bool BattlegroundNA::SetupBattleground()
@@ -54,7 +54,8 @@ public:
void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override;
void FillInitialWorldStates(WorldPacket& d) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
bool HandlePlayerUnderMap(Player* player) override;
};
@@ -91,10 +91,10 @@ void BattlegroundRL::HandleAreaTrigger(Player* player, uint32 trigger)
}
}
void BattlegroundRL::FillInitialWorldStates(WorldPacket& data)
void BattlegroundRL::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(0xbba) << uint32(1); // 9
Arena::FillInitialWorldStates(data);
packet.Worldstates.emplace_back(0xbba, 1); // BATTELGROUND_RUINS_OF_LORDAERNON_SHOW
Arena::FillInitialWorldStates(packet);
}
bool BattlegroundRL::SetupBattleground()
@@ -45,7 +45,7 @@ public:
BattlegroundRL();
/* inherited from BattlegroundClass */
void FillInitialWorldStates(WorldPacket& d) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void StartingEventCloseDoors() override;
void StartingEventOpenDoors() override;
@@ -204,10 +204,10 @@ void BattlegroundRV::HandleAreaTrigger(Player* player, uint32 trigger)
}
}
void BattlegroundRV::FillInitialWorldStates(WorldPacket& data)
void BattlegroundRV::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(BG_RV_WORLD_STATE) << uint32(1);
Arena::FillInitialWorldStates(data);
packet.Worldstates.emplace_back(BG_RV_WORLD_STATE, 1);
Arena::FillInitialWorldStates(packet);
}
void BattlegroundRV::Init()
@@ -90,7 +90,7 @@ public:
/* inherited from BattlegroundClass */
void StartingEventOpenDoors() override;
void Init() override;
void FillInitialWorldStates(WorldPacket& d) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override;
bool HandlePlayerUnderMap(Player* player) override;
@@ -467,44 +467,46 @@ void BattlegroundSA::StartingEventOpenDoors()
{
}
void BattlegroundSA::FillInitialWorldStates(WorldPacket& data)
void BattlegroundSA::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
uint32 ally_attacks = uint32(Attackers == TEAM_ALLIANCE ? 1 : 0);
uint32 horde_attacks = uint32(Attackers == TEAM_HORDE ? 1 : 0);
bool const ally_attacks = Attackers == TEAM_ALLIANCE;
bool const horde_attacks = Attackers == TEAM_HORDE;
data << uint32(BG_SA_ANCIENT_GATEWS) << uint32(GateStatus[BG_SA_ANCIENT_GATE]);
data << uint32(BG_SA_YELLOW_GATEWS) << uint32(GateStatus[BG_SA_YELLOW_GATE]);
data << uint32(BG_SA_GREEN_GATEWS) << uint32(GateStatus[BG_SA_GREEN_GATE]);
data << uint32(BG_SA_BLUE_GATEWS) << uint32(GateStatus[BG_SA_BLUE_GATE]);
data << uint32(BG_SA_RED_GATEWS) << uint32(GateStatus[BG_SA_RED_GATE]);
data << uint32(BG_SA_PURPLE_GATEWS) << uint32(GateStatus[BG_SA_PURPLE_GATE]);
packet.Worldstates.reserve(25);
packet.Worldstates.emplace_back(BG_SA_ANCIENT_GATEWS, GateStatus[BG_SA_ANCIENT_GATE]);
packet.Worldstates.emplace_back(BG_SA_YELLOW_GATEWS, GateStatus[BG_SA_YELLOW_GATE]);
packet.Worldstates.emplace_back(BG_SA_GREEN_GATEWS, GateStatus[BG_SA_GREEN_GATE]);
packet.Worldstates.emplace_back(BG_SA_BLUE_GATEWS, GateStatus[BG_SA_BLUE_GATE]);
packet.Worldstates.emplace_back(BG_SA_RED_GATEWS, GateStatus[BG_SA_RED_GATE]);
packet.Worldstates.emplace_back(BG_SA_PURPLE_GATEWS, GateStatus[BG_SA_PURPLE_GATE]);
data << uint32(BG_SA_BONUS_TIMER) << uint32(0);
packet.Worldstates.emplace_back(BG_SA_BONUS_TIMER, 0);
data << uint32(BG_SA_HORDE_ATTACKS) << horde_attacks;
data << uint32(BG_SA_ALLY_ATTACKS) << ally_attacks;
packet.Worldstates.emplace_back(BG_SA_HORDE_ATTACKS, horde_attacks);
packet.Worldstates.emplace_back(BG_SA_ALLY_ATTACKS, ally_attacks);
//Time will be sent on first update...
data << uint32(BG_SA_ENABLE_TIMER) << ((TimerEnabled) ? uint32(1) : uint32(0));
data << uint32(BG_SA_TIMER_MINS) << uint32(0);
data << uint32(BG_SA_TIMER_SEC_TENS) << uint32(0);
data << uint32(BG_SA_TIMER_SEC_DECS) << uint32(0);
packet.Worldstates.emplace_back(BG_SA_ENABLE_TIMER, TimerEnabled ? 1 : 0);
data << uint32(BG_SA_RIGHT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
data << uint32(BG_SA_LEFT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
data << uint32(BG_SA_CENTER_GY_HORDE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_TIMER_MINS, 0);
packet.Worldstates.emplace_back(BG_SA_TIMER_SEC_TENS, 0);
packet.Worldstates.emplace_back(BG_SA_TIMER_SEC_DECS, 0);
data << uint32(BG_SA_RIGHT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
data << uint32(BG_SA_LEFT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
data << uint32(BG_SA_CENTER_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_RIGHT_GY_HORDE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_LEFT_GY_HORDE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_CENTER_GY_HORDE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
data << uint32(BG_SA_HORDE_DEFENCE_TOKEN) << ally_attacks;
data << uint32(BG_SA_ALLIANCE_DEFENCE_TOKEN) << horde_attacks;
packet.Worldstates.emplace_back(BG_SA_RIGHT_GY_ALLIANCE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_LEFT_GY_ALLIANCE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_CENTER_GY_ALLIANCE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
data << uint32(BG_SA_LEFT_ATT_TOKEN_HRD) << horde_attacks;
data << uint32(BG_SA_RIGHT_ATT_TOKEN_HRD) << horde_attacks;
data << uint32(BG_SA_RIGHT_ATT_TOKEN_ALL) << ally_attacks;
data << uint32(BG_SA_LEFT_ATT_TOKEN_ALL) << ally_attacks;
packet.Worldstates.emplace_back(BG_SA_HORDE_DEFENCE_TOKEN, ally_attacks);
packet.Worldstates.emplace_back(BG_SA_ALLIANCE_DEFENCE_TOKEN, horde_attacks);
packet.Worldstates.emplace_back(BG_SA_LEFT_ATT_TOKEN_HRD, horde_attacks);
packet.Worldstates.emplace_back(BG_SA_RIGHT_ATT_TOKEN_HRD, horde_attacks);
packet.Worldstates.emplace_back(BG_SA_RIGHT_ATT_TOKEN_ALL, ally_attacks);
packet.Worldstates.emplace_back(BG_SA_LEFT_ATT_TOKEN_ALL, ally_attacks);
}
void BattlegroundSA::AddPlayer(Player* player)
@@ -475,7 +475,7 @@ public:
bool SetupBattleground() override;
void Init() override;
/// Called for generate packet contain worldstate data
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
/// Called when a player deal damage to building (door)
void EventPlayerDamagedGO(Player* player, GameObject* go, uint32 eventType) override;
/// Called when a player kill a unit in bg
@@ -546,17 +546,18 @@ GraveyardStruct const* BattlegroundWS::GetClosestGraveyard(Player* player)
return sGraveyard->GetGraveyard(player->GetTeamId() == TEAM_ALLIANCE ? WS_GRAVEYARD_FLAGROOM_ALLIANCE : WS_GRAVEYARD_FLAGROOM_HORDE);
}
void BattlegroundWS::FillInitialWorldStates(WorldPacket& data)
void BattlegroundWS::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(TEAM_ALLIANCE));
data << uint32(BG_WS_FLAG_CAPTURES_HORDE) << uint32(GetTeamScore(TEAM_HORDE));
data << uint32(BG_WS_FLAG_CAPTURES_MAX) << uint32(BG_WS_MAX_TEAM_SCORE);
packet.Worldstates.reserve(7);
packet.Worldstates.emplace_back(BG_WS_FLAG_CAPTURES_ALLIANCE, GetTeamScore(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(BG_WS_FLAG_CAPTURES_HORDE, GetTeamScore(TEAM_HORDE));
packet.Worldstates.emplace_back(BG_WS_FLAG_CAPTURES_MAX, BG_WS_MAX_TEAM_SCORE);
data << uint32(BG_WS_STATE_TIMER_ACTIVE) << uint32(GetStatus() == STATUS_IN_PROGRESS);
data << uint32(BG_WS_STATE_TIMER) << uint32(GetMatchTime());
packet.Worldstates.emplace_back(BG_WS_STATE_TIMER_ACTIVE, GetStatus() == STATUS_IN_PROGRESS ? 1 : 0);
packet.Worldstates.emplace_back(BG_WS_STATE_TIMER, GetMatchTime());
data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(GetFlagState(TEAM_HORDE));
data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(GetFlagState(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(BG_WS_FLAG_STATE_HORDE, GetFlagState(TEAM_HORDE));
packet.Worldstates.emplace_back(BG_WS_FLAG_STATE_ALLIANCE, GetFlagState(TEAM_ALLIANCE));
}
TeamId BattlegroundWS::GetPrematureWinner()
@@ -252,7 +252,7 @@ public:
bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void SetDroppedFlagGUID(ObjectGuid guid, TeamId teamId) override { _droppedFlagGUID[teamId] = guid; }
ObjectGuid GetDroppedFlagGUID(TeamId teamId) const { return _droppedFlagGUID[teamId];}
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
/* Scorekeeping */
void AddPoints(TeamId teamId, uint32 points) { m_TeamScores[teamId] += points; }
+2 -1
View File
@@ -19,6 +19,7 @@
#include "GuildMgr.h"
#include "ObjectAccessor.h"
#include "World.h"
#include "WorldSessionMgr.h"
WhoListCacheMgr* WhoListCacheMgr::instance()
{
@@ -30,7 +31,7 @@ void WhoListCacheMgr::Update()
{
// clear current list
_whoListStorage.clear();
_whoListStorage.reserve(sWorld->GetPlayerCount() + 1);
_whoListStorage.reserve(sWorldSessionMgr->GetPlayerCount() + 1);
for (auto const& [guid, player] : ObjectAccessor::GetPlayers())
{
+6 -5
View File
@@ -30,6 +30,7 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldSessionMgr.h"
#include <boost/algorithm/string/replace.hpp>
Player* ChatHandler::GetPlayer() const
@@ -81,7 +82,7 @@ bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_ac
return false;
// ignore only for non-players for non strong checks (when allow apply command at least to same sec level)
if (!AccountMgr::IsPlayerAccount(m_session->GetSecurity()) && !strong && !sWorld->getBoolConfig(CONFIG_GM_LOWER_SECURITY))
if (!AccountMgr::IsPlayerAccount(m_session->GetSecurity()) && !strong && sWorld->getBoolConfig(CONFIG_GM_LOWER_SECURITY))
return false;
if (target)
@@ -188,7 +189,7 @@ void ChatHandler::SendGlobalSysMessage(const char* str)
for (std::string_view line : Acore::Tokenize(str, '\n', true))
{
BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
sWorld->SendGlobalMessage(&data);
sWorldSessionMgr->SendGlobalMessage(&data);
}
}
@@ -198,7 +199,7 @@ void ChatHandler::SendGlobalGMSysMessage(const char* str)
for (std::string_view line : Acore::Tokenize(str, '\n', true))
{
BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
sWorld->SendGlobalGMMessage(&data);
sWorldSessionMgr->SendGlobalGMMessage(&data);
}
}
@@ -514,8 +515,8 @@ bool ChatHandler::HasSession() const
void ChatHandler::DoForAllValidSessions(std::function<void(Player*)> exec)
{
SessionMap::const_iterator itr;
for (itr = sWorld->GetAllSessions().begin(); itr != sWorld->GetAllSessions().end(); ++itr)
WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions();
for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr)
if (Player* player = itr->second->GetPlayer())
if (player->IsInWorld())
exec(player);
+2 -2
View File
@@ -328,7 +328,7 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
Unit* cvUnit = currentVictim->getTarget();
if (!attacker->CanCreatureAttack(cvUnit)) // pussywizard: if currentVictim is not valid => don't compare the threat with it, just take the highest threat valid target
currentVictim = nullptr;
else if (cvUnit->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || cvUnit->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE)) // pussywizard: no 10%/30% if currentVictim is immune to damage or has auras breakable by damage
else if (cvUnit->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || cvUnit->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || cvUnit->HasUnitState(UNIT_STATE_CONFUSED)) // pussywizard: no 10%/30% if currentVictim is immune to damage or has auras breakable by damage
currentVictim = nullptr;
}
@@ -345,7 +345,7 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
// pussywizard: don't go to threat comparison if this ref is immune to damage or has aura breakable on damage (second choice target)
// pussywizard: if this is the last entry on the threat list, then all targets are second choice, set bool to true and loop threat list again, ignoring this section
if (!noPriorityTargetFound && (target->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || target->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, attacker->GetGUID())))
if (!noPriorityTargetFound && (target->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || target->HasUnitState(UNIT_STATE_CONFUSED) || target->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, attacker->GetGUID())))
{
if (iter != lastRef)
{
+4 -6
View File
@@ -28,7 +28,7 @@
#include "VMapMgr2.h"
#include "World.h"
std::map<DisableType, std::map<uint32, DisableData>> DisableMgr::m_DisableMap;
DisableMgr::DisableMap DisableMgr::m_DisableMap;
DisableMgr::DisableMgr() {}
DisableMgr::~DisableMgr() {}
@@ -44,10 +44,8 @@ void DisableMgr::LoadDisables()
uint32 oldMSTime = getMSTime();
// reload case
for (DisableMap::iterator itr = m_DisableMap.begin(); itr != m_DisableMap.end(); ++itr)
itr->second.clear();
m_DisableMap.clear();
for (DisableTypeMap& disableTypeMap : m_DisableMap)
disableTypeMap.clear();
QueryResult result = WorldDatabase.Query("SELECT sourceType, entry, flags, params_0, params_1 FROM disables");
@@ -99,7 +97,7 @@ void DisableMgr::LoadDisables()
* @param param0 MapId if DISABLE_TYPE_SPELL used, 0 for all maps.
* @param param1 AreaId if DISABLE_TYPE_SPELL used, 0 for all areas.
*/
void DisableMgr::AddDisable(DisableType type, uint32 entry, uint8 flags, std::string param0, std::string param1)
void DisableMgr::AddDisable(DisableType type, uint32 entry, uint8 flags, std::string const& param0, std::string const& param1)
{
if (type >= MAX_DISABLE_TYPES)
{
+5 -4
View File
@@ -20,6 +20,7 @@
#include "Define.h"
#include "Map.h"
class Unit;
enum DisableType
@@ -68,19 +69,19 @@ public:
static DisableMgr* instance();
void LoadDisables();
void AddDisable(DisableType type, uint32 entry, uint8 flags, std::string param0, std::string param1);
void AddDisable(DisableType type, uint32 entry, uint8 flags, std::string const& param0, std::string const& param1);
bool HandleDisableType(DisableType type, uint32 entry, uint8 flags, std::string const& params_0, std::string const& params_1, DisableData& data);
static bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags = 0);
void CheckQuestDisables();
static bool IsVMAPDisabledFor(uint32 entry, uint8 flags);
static bool IsPathfindingEnabled(Map const* map);
private:
// single disables here with optional data
typedef std::map<uint32, DisableData> DisableTypeMap;
typedef std::unordered_map<uint32, DisableData> DisableTypeMap;
// global disable map by source
typedef std::map<DisableType, DisableTypeMap> DisableMap;
typedef std::array<DisableTypeMap, MAX_DISABLE_TYPES> DisableMap;
private:
static DisableMap m_DisableMap;
};
+1 -1
View File
@@ -523,7 +523,7 @@ namespace lfg
if (grp && (grp->isBGGroup() || grp->isBFGroup()))
return;
if (!sScriptMgr->CanJoinLfg(player, roles, dungeons, comment))
if (!sScriptMgr->OnPlayerCanJoinLfg(player, roles, dungeons, comment))
return;
// pussywizard: can't join LFG/LFR while using LFR
@@ -41,7 +41,7 @@ namespace lfg
{
}
void LFGPlayerScript::OnLevelChanged(Player* player, uint8 /*oldLevel*/)
void LFGPlayerScript::OnPlayerLevelChanged(Player* player, uint8 /*oldLevel*/)
{
if (!sLFGMgr->isOptionEnabled(LFG_OPTION_ENABLE_DUNGEON_FINDER | LFG_OPTION_ENABLE_RAID_BROWSER | LFG_OPTION_ENABLE_SEASONAL_BOSSES))
return;
@@ -49,7 +49,7 @@ namespace lfg
sLFGMgr->InitializeLockedDungeons(player, player->GetGroup());
}
void LFGPlayerScript::OnLogout(Player* player)
void LFGPlayerScript::OnPlayerLogout(Player* player)
{
if (!sLFGMgr->isOptionEnabled(LFG_OPTION_ENABLE_DUNGEON_FINDER | LFG_OPTION_ENABLE_RAID_BROWSER | LFG_OPTION_ENABLE_SEASONAL_BOSSES))
return;
@@ -69,7 +69,7 @@ namespace lfg
sLFGMgr->LfrSearchRemove(player);
}
void LFGPlayerScript::OnLogin(Player* player)
void LFGPlayerScript::OnPlayerLogin(Player* player)
{
if (!sLFGMgr->isOptionEnabled(LFG_OPTION_ENABLE_DUNGEON_FINDER | LFG_OPTION_ENABLE_RAID_BROWSER | LFG_OPTION_ENABLE_SEASONAL_BOSSES))
return;
@@ -93,14 +93,14 @@ namespace lfg
/// @todo - Restore LfgPlayerData and send proper status to player if it was in a group
}
void LFGPlayerScript::OnBindToInstance(Player* player, Difficulty difficulty, uint32 mapId, bool /*permanent*/)
void LFGPlayerScript::OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapId, bool /*permanent*/)
{
MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
if (mapEntry->IsDungeon() && difficulty > DUNGEON_DIFFICULTY_NORMAL)
sLFGMgr->InitializeLockedDungeons(player, player->GetGroup());
}
void LFGPlayerScript::OnMapChanged(Player* player)
void LFGPlayerScript::OnPlayerMapChanged(Player* player)
{
Map const* map = player->GetMap();
+5 -5
View File
@@ -34,11 +34,11 @@ namespace lfg
LFGPlayerScript();
// Player Hooks
void OnLevelChanged(Player* player, uint8 oldLevel) override;
void OnLogout(Player* player) override;
void OnLogin(Player* player) override;
void OnBindToInstance(Player* player, Difficulty difficulty, uint32 mapId, bool permanent) override;
void OnMapChanged(Player* player) override;
void OnPlayerLevelChanged(Player* player, uint8 oldLevel) override;
void OnPlayerLogout(Player* player) override;
void OnPlayerLogin(Player* player) override;
void OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapId, bool permanent) override;
void OnPlayerMapChanged(Player* player) override;
};
class LFGGroupScript : public GroupScript
@@ -47,6 +47,7 @@
#include "WaypointMovementGenerator.h"
#include "World.h"
#include "WorldPacket.h"
#include "WorldSessionMgr.h"
/// @todo: this import is not necessary for compilation and marked as unused by the IDE
// however, for some reasons removing it would cause a damn linking issue
@@ -1975,7 +1976,8 @@ void Creature::setDeathState(DeathState state, bool despawn)
if (state == DeathState::JustDied)
{
m_corpseRemoveTime = GameTime::GetGameTime().count() + m_corpseDelay;
m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelay + m_corpseDelay;
uint32 dynamicRespawnDelay = GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelay);
m_respawnTime = GameTime::GetGameTime().count() + dynamicRespawnDelay + m_corpseDelay;
// always save boss respawn time at death to prevent crash cheating
if (GetMap()->IsDungeon() || isWorldBoss() || GetCreatureTemplate()->rank >= CREATURE_ELITE_ELITE)
@@ -2818,7 +2820,7 @@ void Creature::SendZoneUnderAttackMessage(Player* attacker)
{
WorldPacket data(SMSG_ZONE_UNDER_ATTACK, 4);
data << (uint32)GetAreaId();
sWorld->SendGlobalMessage(&data, nullptr, (attacker->GetTeamId() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE));
sWorldSessionMgr->SendGlobalMessage(&data, nullptr, (attacker->GetTeamId() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE));
}
/**
@@ -3180,7 +3182,8 @@ bool Creature::IsDungeonBoss() const
if (GetOwnerGUID().IsPlayer())
return false;
return HasFlagsExtra(CREATURE_FLAG_EXTRA_DUNGEON_BOSS);
CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(GetEntry());
return cinfo && cinfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_DUNGEON_BOSS);
}
bool Creature::IsImmuneToKnockback() const
@@ -3188,7 +3191,8 @@ bool Creature::IsImmuneToKnockback() const
if (GetOwnerGUID().IsPlayer())
return false;
return HasFlagsExtra(CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK);
CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(GetEntry());
return cinfo && cinfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK);
}
bool Creature::HasWeapon(WeaponAttackType type) const
@@ -22,6 +22,7 @@
#include "MoveSplineInit.h"
#include "ObjectMgr.h"
#include "QueryResult.h"
#include "Timer.h"
#include "WaypointMgr.h"
FormationMgr::~FormationMgr()
@@ -455,14 +455,14 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU
uint32 moneyRew = 0;
Player* player = _session->GetPlayer();
if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)))
if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(player)))
{
moneyRew = quest->GetRewMoneyMaxLevel();
}
moneyRew += quest->GetRewOrReqMoney(player ? player->GetLevel() : 0); // reward money (below max lvl)
data << moneyRew;
uint32 questXp;
if (player && !sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player))
if (player && !sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(player))
{
questXp = player->CalculateQuestRewardXP(quest);
}
@@ -470,7 +470,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU
{
questXp = 0;
}
sScriptMgr->OnQuestComputeXP(player, quest, questXp);
sScriptMgr->OnPlayerQuestComputeXP(player, quest, questXp);
data << questXp;
}
@@ -555,7 +555,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
{
uint32 moneyRew = 0;
Player* player = _session->GetPlayer();
if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)))
if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(player)))
{
moneyRew = quest->GetRewMoneyMaxLevel();
}
@@ -707,14 +707,14 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI
uint32 moneyRew = 0;
Player* player = _session->GetPlayer();
if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)))
if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(player)))
{
moneyRew = quest->GetRewMoneyMaxLevel();
}
moneyRew += quest->GetRewOrReqMoney(player ? player->GetLevel() : 0); // reward money (below max lvl)
data << moneyRew;
uint32 questXp;
if (player && !sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player))
if (player && !sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(player))
{
questXp = player->CalculateQuestRewardXP(quest);
}
@@ -722,7 +722,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI
{
questXp = 0;
}
sScriptMgr->OnQuestComputeXP(player, quest, questXp);
sScriptMgr->OnPlayerQuestComputeXP(player, quest, questXp);
data << questXp;
// rewarded honor points. Multiply with 10 to satisfy client
@@ -204,7 +204,7 @@ void TempSummon::InitStats(uint32 duration)
Unit* owner = GetSummonerUnit();
if (owner)
if (Player* player = owner->ToPlayer())
sScriptMgr->OnBeforeTempSummonInitStats(player, this, duration);
sScriptMgr->OnPlayerBeforeTempSummonInitStats(player, this, duration);
m_timer = duration;
m_lifetime = duration;
@@ -897,7 +897,8 @@ void GameObject::Update(uint32 diff)
return;
}
m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelayTime;
uint32 dynamicRespawnDelay = GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelayTime);
m_respawnTime = GameTime::GetGameTime().count() + dynamicRespawnDelay;
// if option not set then object will be saved at grid unload
if (GetMap()->IsDungeon())
@@ -1758,7 +1759,7 @@ void GameObject::Use(Unit* user)
LOG_DEBUG("entities.gameobject", "Fishing check (skill: {} zone min skill: {} chance {} roll: {}", skill, zone_skill, chance, roll);
if (sScriptMgr->OnUpdateFishingSkill(player, skill, zone_skill, chance, roll))
if (sScriptMgr->OnPlayerUpdateFishingSkill(player, skill, zone_skill, chance, roll))
{
player->UpdateFishingSkill();
}
@@ -21,6 +21,7 @@
#include "Log.h"
#include "ObjectMgr.h"
#include "QueryResult.h"
#include "Timer.h"
#include "Util.h"
#include <cmath>
#include <functional>
+1 -10
View File
@@ -3098,18 +3098,9 @@ void WorldObject::BuildUpdate(UpdateDataMapType& data_map, UpdatePlayerSet& play
void WorldObject::GetCreaturesWithEntryInRange(std::list<Creature*>& creatureList, float radius, uint32 entry)
{
CellCoord pair(Acore::ComputeCellCoord(this->GetPositionX(), this->GetPositionY()));
Cell cell(pair);
cell.SetNoCreate();
Acore::AllCreaturesOfEntryInRange check(this, entry, radius);
Acore::CreatureListSearcher<Acore::AllCreaturesOfEntryInRange> searcher(this, creatureList, check);
TypeContainerVisitor<Acore::CreatureListSearcher<Acore::AllCreaturesOfEntryInRange>, WorldTypeMapContainer> world_visitor(searcher);
cell.Visit(pair, world_visitor, *(this->GetMap()), *this, radius);
TypeContainerVisitor<Acore::CreatureListSearcher<Acore::AllCreaturesOfEntryInRange>, GridTypeMapContainer> grid_visitor(searcher);
cell.Visit(pair, grid_visitor, *(this->GetMap()), *this, radius);
Cell::VisitAllObjects(this, searcher, radius);
}
void WorldObject::AddToObjectUpdate()
@@ -64,6 +64,11 @@ struct Position
return !(operator==(a));
}
inline bool operator!=(Position const& a) const
{
return !(operator==(a));
}
operator G3D::Vector3() const
{
return { m_positionX, m_positionY, m_positionZ };
+12 -10
View File
@@ -47,7 +47,7 @@ Pet::Pet(Player* owner, PetType type) : Guardian(nullptr, owner ? owner->GetGUID
m_auraRaidUpdateMask(0),
m_loading(false),
m_petRegenTimer(PET_FOCUS_REGEN_INTERVAL),
m_tempspellTarget(nullptr),
m_tempspellTarget(),
m_tempoldTarget(),
m_tempspellIsPositive(false),
m_tempspell(0)
@@ -237,7 +237,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
return false;
bool forceLoadFromDB = false;
sScriptMgr->OnBeforeLoadPetFromDB(owner, petEntry, petnumber, current, forceLoadFromDB);
sScriptMgr->OnPlayerBeforeLoadPetFromDB(owner, petEntry, petnumber, current, forceLoadFromDB);
if (!forceLoadFromDB && (owner->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET) && !owner->CanSeeDKPet())) // DK Pet exception
return false;
@@ -716,9 +716,11 @@ void Pet::Update(uint32 diff)
if (m_tempspell)
{
Unit* tempspellTarget = m_tempspellTarget;
Unit* tempoldTarget = nullptr;
Unit* tempspellTarget = nullptr;
if (!m_tempspellTarget.IsEmpty())
tempspellTarget = ObjectAccessor::GetUnit(*this, m_tempspellTarget);
Unit* tempoldTarget = nullptr;
if (!m_tempoldTarget.IsEmpty())
tempoldTarget = ObjectAccessor::GetUnit(*this, m_tempoldTarget);
@@ -758,7 +760,7 @@ void Pet::Update(uint32 diff)
CastSpell(tempspellTarget, tempspell, false);
m_tempspell = 0;
m_tempspellTarget = nullptr;
m_tempspellTarget = ObjectGuid::Empty;
if (tempspellIsPositive)
{
@@ -798,7 +800,7 @@ void Pet::Update(uint32 diff)
else
{
m_tempspell = 0;
m_tempspellTarget = nullptr;
m_tempspellTarget = ObjectGuid::Empty;
m_tempoldTarget = ObjectGuid::Empty;
m_tempspellIsPositive = false;
@@ -1031,7 +1033,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
PetType petType = MAX_PET_TYPE;
if (owner->IsPlayer())
{
sScriptMgr->OnBeforeGuardianInitStatsForLevel(owner->ToPlayer(), this, cinfo, petType);
sScriptMgr->OnPlayerBeforeGuardianInitStatsForLevel(owner->ToPlayer(), this, cinfo, petType);
if (IsPet())
{
@@ -1425,7 +1427,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
if (owner->IsPlayer())
sScriptMgr->OnAfterGuardianInitStatsForLevel(owner->ToPlayer(), this);
sScriptMgr->OnPlayerAfterGuardianInitStatsForLevel(owner->ToPlayer(), this);
return true;
}
@@ -2433,7 +2435,7 @@ void Pet::CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, ObjectGuid ol
if (!spellTarget)
return;
m_tempspellTarget = spellTarget;
m_tempspellTarget = spellTarget->GetGUID();
m_tempspell = spellid;
m_tempspellIsPositive = spellIsPositive;
@@ -2445,7 +2447,7 @@ void Pet::ClearCastWhenWillAvailable()
{
m_tempspellIsPositive = false;
m_tempspell = 0;
m_tempspellTarget = nullptr;
m_tempspellTarget = ObjectGuid::Empty;
m_tempoldTarget = ObjectGuid::Empty;
}
+1 -1
View File
@@ -158,7 +158,7 @@ protected:
std::unique_ptr<DeclinedName> m_declinedname;
Unit* m_tempspellTarget;
ObjectGuid m_tempspellTarget;
ObjectGuid m_tempoldTarget;
bool m_tempspellIsPositive;
uint32 m_tempspell;
@@ -167,7 +167,7 @@ void KillRewarder::_RewardXP(Player* player, float rate)
AddPct(xp, (*i)->GetAmount());
// 4.2.3. Give XP to player.
sScriptMgr->OnGivePlayerXP(player, xp, _victim, PlayerXPSource::XPSOURCE_KILL);
sScriptMgr->OnPlayerGiveXP(player, xp, _victim, PlayerXPSource::XPSOURCE_KILL);
player->GiveXP(xp, _victim, _groupRate);
if (Pet* pet = player->GetPet())
// 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
@@ -210,7 +210,7 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
if (!_isPvP || _isBattleGround)
{
float xpRate = _group ? _groupRate * float(player->GetLevel()) / _aliveSumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on the sum of levels.
sScriptMgr->OnRewardKillRewarder(player, this, isDungeon, xpRate); // Personal rate is 100%.
sScriptMgr->OnPlayerRewardKillRewarder(player, this, isDungeon, xpRate); // Personal rate is 100%.
if (_xp)
{
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -65,7 +65,7 @@ class SpellCastTargets;
class UpdateMask;
typedef std::deque<Mail*> PlayerMails;
typedef void(*bgZoneRef)(Battleground*, WorldPacket&);
typedef void(*bgZoneRef)(Battleground*, WorldPackets::WorldState::InitWorldStates&);
#define PLAYER_MAX_SKILLS 127
#define PLAYER_MAX_DAILY_QUESTS 25
@@ -2227,7 +2227,7 @@ public:
void SetEquipmentSet(uint32 index, EquipmentSet eqset);
void DeleteEquipmentSet(uint64 setGuid);
void SendInitWorldStates(uint32 zone, uint32 area);
void SendInitWorldStates(uint32 zoneId, uint32 areaId);
void SendUpdateWorldState(uint32 variable, uint32 value) const;
void SendDirectMessage(WorldPacket const* data) const;
void SendBGWeekendWorldStates();
@@ -399,7 +399,7 @@ void Player::UpdateFFAPvPFlag(time_t currTime)
if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
sScriptMgr->OnFfaPvpStateUpdate(this, false);
sScriptMgr->OnPlayerFfaPvpStateUpdate(this, false);
}
for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
(*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
@@ -602,7 +602,7 @@ void Player::CompleteQuest(uint32 quest_id)
return;
}
if (!sScriptMgr->OnBeforePlayerQuestComplete(this, quest_id))
if (!sScriptMgr->OnPlayerBeforeQuestComplete(this, quest_id))
{
return;
}
@@ -699,7 +699,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
Item* item = StoreNewItem(dest, itemId, true);
SendNewItem(item, quest->RewardChoiceItemCount[reward], true, false, false, false);
sScriptMgr->OnQuestRewardItem(this, item, quest->RewardChoiceItemCount[reward]);
sScriptMgr->OnPlayerQuestRewardItem(this, item, quest->RewardChoiceItemCount[reward]);
}
else
{
@@ -720,7 +720,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
Item* item = StoreNewItem(dest, itemId, true);
SendNewItem(item, quest->RewardItemIdCount[i], true, false, false, false);
sScriptMgr->OnQuestRewardItem(this, item, quest->RewardItemIdCount[i]);
sScriptMgr->OnPlayerQuestRewardItem(this, item, quest->RewardItemIdCount[i]);
}
else
problematicItems.emplace_back(itemId, quest->RewardItemIdCount[i]);
@@ -745,15 +745,15 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
// Not give XP in case already completed once repeatable quest
uint32 XP = rewarded ? 0 : CalculateQuestRewardXP(quest);
sScriptMgr->OnQuestComputeXP(this, quest, XP);
sScriptMgr->OnPlayerQuestComputeXP(this, quest, XP);
int32 moneyRew = 0;
if (GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(this))
if (GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(this))
{
moneyRew = quest->GetRewMoneyMaxLevel();
}
else
{
sScriptMgr->OnGivePlayerXP(this, XP, nullptr, isLFGReward ? PlayerXPSource::XPSOURCE_QUEST_DF : PlayerXPSource::XPSOURCE_QUEST);
sScriptMgr->OnPlayerGiveXP(this, XP, nullptr, isLFGReward ? PlayerXPSource::XPSOURCE_QUEST_DF : PlayerXPSource::XPSOURCE_QUEST);
GiveXP(XP, nullptr, 1.0f, isLFGReward);
}
@@ -1953,7 +1953,7 @@ void Player::KilledMonsterCredit(uint32 entry, ObjectGuid guid)
if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid(GetMap()->GetDifficulty()) ||
(qInfo->IsPVPQuest() && (GetGroup()->isBFGroup() || GetGroup()->isBGGroup()))))
{
if (!sScriptMgr->PassedQuestKilledMonsterCredit(this, qInfo, entry, real_entry, guid))
if (!sScriptMgr->OnPlayerPassedQuestKilledMonsterCredit(this, qInfo, entry, real_entry, guid))
continue;
if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL) /*&& !qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_CAST)*/)
@@ -1811,7 +1811,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool
ItemTemplate const* pProto = pItem->GetTemplate();
if (pProto)
{
if (!sScriptMgr->CanEquipItem(const_cast<Player*>(this), slot, dest, pItem, swap, not_loading))
if (!sScriptMgr->OnPlayerCanEquipItem(const_cast<Player*>(this), slot, dest, pItem, swap, not_loading))
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
// item used
@@ -1983,7 +1983,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool
InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const
{
if (!sScriptMgr->CanUnequipItem(const_cast<Player*>(this), pos, swap))
if (!sScriptMgr->OnPlayerCanUnequipItem(const_cast<Player*>(this), pos, swap))
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
// Applied only to equipped items and bank bags
@@ -2326,7 +2326,7 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const
InventoryResult result = EQUIP_ERR_OK;
if (!sScriptMgr->CanUseItem(const_cast<Player*>(this), proto, result))
if (!sScriptMgr->OnPlayerCanUseItem(const_cast<Player*>(this), proto, result))
{
return result;
}
@@ -2566,7 +2566,7 @@ Item* Player::StoreNewItem(ItemPosCountVec const& dest, uint32 item, bool update
CharacterDatabase.Execute(stmt);
}
sScriptMgr->OnStoreNewItem(this, pItem, count);
sScriptMgr->OnPlayerStoreNewItem(this, pItem, count);
}
return pItem;
}
@@ -2710,7 +2710,7 @@ Item* Player::EquipNewItem(uint16 pos, uint32 item, bool update)
if (!_item)
return nullptr;
if (!IsEquipmentPos(pos) || sScriptMgr->CanSaveEquipNewItem(this, _item, pos, update))
if (!IsEquipmentPos(pos) || sScriptMgr->OnPlayerCanSaveEquipNewItem(this, _item, pos, update))
{
// pussywizard: obtaining blue or better items saves to db
if (ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item))
@@ -2819,7 +2819,7 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update)
pItem2->SetState(ITEM_CHANGED, this);
ApplyEquipCooldown(pItem2);
sScriptMgr->OnEquip(this, pItem2, bag, slot, update);
sScriptMgr->OnPlayerEquip(this, pItem2, bag, slot, update);
return pItem2;
}
@@ -2827,7 +2827,7 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update)
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry());
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot);
sScriptMgr->OnEquip(this, pItem, bag, slot, update);
sScriptMgr->OnPlayerEquip(this, pItem, bag, slot, update);
UpdateForQuestWorldObjects();
return pItem;
}
@@ -2851,7 +2851,7 @@ void Player::QuickEquipItem(uint16 pos, Item* pItem)
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry());
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot);
sScriptMgr->OnEquip(this, pItem, (pos >> 8), slot, true);
sScriptMgr->OnPlayerEquip(this, pItem, (pos >> 8), slot, true);
}
}
@@ -2869,7 +2869,7 @@ void Player::SetVisibleItemSlot(uint8 slot, Item* pItem)
SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 0);
}
sScriptMgr->OnAfterPlayerSetVisibleItemSlot(this, slot, pItem);
sScriptMgr->OnPlayerAfterSetVisibleItemSlot(this, slot, pItem);
}
void Player::VisualizeItem(uint8 slot, Item* pItem)
@@ -2990,7 +2990,7 @@ void Player::MoveItemFromInventory(uint8 bag, uint8 slot, bool update)
it->DestroyForPlayer(this);
}
sScriptMgr->OnAfterPlayerMoveItemFromInventory(this, it, bag, slot, update);
sScriptMgr->OnPlayerAfterMoveItemFromInventory(this, it, bag, slot, update);
}
}
@@ -4326,7 +4326,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
if (pEnchant->requiredSkill > 0 && pEnchant->requiredSkillValue > GetSkillValue(pEnchant->requiredSkill))
return;
if (!sScriptMgr->CanApplyEnchantment(this, item, slot, apply, apply_dur, ignore_condition))
if (!sScriptMgr->OnPlayerCanApplyEnchantment(this, item, slot, apply, apply_dur, ignore_condition))
return;
// If we're dealing with a gem inside a prismatic socket we need to check the prismatic socket requirements
@@ -4433,7 +4433,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
}
}
sScriptMgr->OnApplyEnchantmentItemModsBefore(this, item, slot, apply, enchant_spell_id, enchant_amount);
sScriptMgr->OnPlayerApplyEnchantmentItemModsBefore(this, item, slot, apply, enchant_spell_id, enchant_amount);
LOG_DEBUG("entities.player.items", "Adding {} to stat nb {}", enchant_amount, enchant_spell_id);
switch (enchant_spell_id)
@@ -5876,7 +5876,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
else if (IsEquipmentPos(INVENTORY_SLOT_BAG_0, slot))
{
uint16 dest;
if (sScriptMgr->CheckItemInSlotAtLoadInventory(this, item, slot, err, dest))
if (sScriptMgr->OnPlayerCheckItemInSlotAtLoadInventory(this, item, slot, err, dest))
err = CanEquipItem(slot, dest, item, false, false);
if (err == EQUIP_ERR_OK)
QuickEquipItem(dest, item);
@@ -6826,7 +6826,7 @@ bool Player::Satisfy(DungeonProgressionRequirements const* ar, uint32 target_map
|| missingPlayerItems.size() || missingPlayerQuests.size() || missingPlayerAchievements.size()
|| missingLeaderItems.size() || missingLeaderQuests.size() || missingLeaderAchievements.size())
{
if (!sScriptMgr->NotAvoidSatisfy(partyLeader, ar, target_map, report))
if (!sScriptMgr->OnPlayerNotAvoidSatisfy(partyLeader, ar, target_map, report))
return true;
if (report)
@@ -55,7 +55,7 @@ void Player::Update(uint32 p_time)
if (!IsInWorld())
return;
sScriptMgr->OnBeforePlayerUpdate(this, p_time);
sScriptMgr->OnPlayerBeforeUpdate(this, p_time);
// undelivered mail
if (m_nextMailDelivereTime && m_nextMailDelivereTime <= GameTime::GetGameTime().count())
@@ -424,7 +424,7 @@ void Player::Update(uint32 p_time)
m_delayed_unit_relocation_timer = 0;
RemoveFromNotify(NOTIFY_VISIBILITY_CHANGED);
}
sScriptMgr->OnAfterPlayerUpdate(this, p_time);
sScriptMgr->OnPlayerAfterUpdate(this, p_time);
}
void Player::UpdateMirrorTimers()
@@ -551,17 +551,16 @@ void Player::UpdateLocalChannels(uint32 newZone)
// names are not changing
char new_channel_name_buf[100];
char const* currentNameExt;
std::string currentNameExt;
if (channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY)
currentNameExt = sObjectMgr->GetAcoreStringForDBCLocale(
LANG_CHANNEL_CITY).c_str();
currentNameExt = sObjectMgr->GetAcoreStringForDBCLocale(LANG_CHANNEL_CITY);
else
currentNameExt = current_zone_name.c_str();
currentNameExt = current_zone_name;
snprintf(new_channel_name_buf, 100,
channel->pattern[m_session->GetSessionDbcLocale()],
currentNameExt);
currentNameExt.c_str());
joinChannel = cMgr->GetJoinChannel(new_channel_name_buf,
channel->ChannelID);
@@ -710,7 +709,7 @@ void Player::UpdateAllRatings()
// skill+step, checking for max value
bool Player::UpdateSkill(uint32 skill_id, uint32 step)
{
if (!skill_id)
if (!skill_id || !sScriptMgr->OnPlayerCanUpdateSkill(this, skill_id))
return false;
SkillStatusMap::iterator itr = mSkillStatus.find(skill_id);
@@ -722,6 +721,8 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
uint32 value = SKILL_VALUE(data);
uint32 max = SKILL_MAX(data);
sScriptMgr->OnPlayerBeforeUpdateSkill(this, skill_id, value, max, step);
if ((!max) || (!value) || (value >= max))
return false;
@@ -738,6 +739,8 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
UpdateSkillEnchantments(skill_id, value, new_value);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,
skill_id);
sScriptMgr->OnPlayerUpdateSkill(this, skill_id, value, max, step, new_value);
return true;
}
@@ -766,7 +769,7 @@ bool Player::UpdateGatherSkill(uint32 SkillId, uint32 SkillValue,
uint32 gathering_skill_gain =
sWorld->getIntConfig(CONFIG_SKILL_GAIN_GATHERING);
sScriptMgr->OnUpdateGatheringSkill(this, SkillId, SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25, gathering_skill_gain);
sScriptMgr->OnPlayerUpdateGatheringSkill(this, SkillId, SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25, gathering_skill_gain);
// For skinning and Mining chance decrease with level. 1-74 - no decrease,
// 75-149 - 2 times, 225-299 - 8 times
@@ -844,7 +847,7 @@ bool Player::UpdateCraftSkill(uint32 spellid)
uint32 craft_skill_gain =
sWorld->getIntConfig(CONFIG_SKILL_GAIN_CRAFTING);
sScriptMgr->OnUpdateCraftingSkill(this, _spell_idx->second, SkillValue, craft_skill_gain);
sScriptMgr->OnPlayerUpdateCraftingSkill(this, _spell_idx->second, SkillValue, craft_skill_gain);
return UpdateSkillPro(
_spell_idx->second->SkillLine,
@@ -913,7 +916,7 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
LOG_DEBUG("entities.player.skills",
"UpdateSkillPro(SkillId {}, Chance {:3.1f}%)", SkillId,
Chance / 10.0f);
if (!SkillId)
if (!SkillId || !sScriptMgr->OnPlayerCanUpdateSkill(this, SkillId))
return false;
if (Chance <= 0) // speedup in 0 chance case
@@ -931,8 +934,10 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
uint32 data = GetUInt32Value(valueIndex);
uint16 SkillValue = SKILL_VALUE(data);
uint16 MaxValue = SKILL_MAX(data);
uint32 SkillValue = SKILL_VALUE(data);
uint32 MaxValue = SKILL_MAX(data);
sScriptMgr->OnPlayerBeforeUpdateSkill(this, SkillId, SkillValue, MaxValue, step);
if (!MaxValue || !SkillValue || SkillValue >= MaxValue)
return false;
@@ -964,6 +969,8 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
LOG_DEBUG("entities.player.skills",
"Player::UpdateSkillPro Chance={:3.1f}% taken",
Chance / 10.0f);
sScriptMgr->OnPlayerUpdateSkill(this, SkillId, SkillValue, MaxValue, step, new_value);
return true;
}
@@ -1246,9 +1253,7 @@ void Player::UpdateArea(uint32 newArea)
void Player::UpdateZone(uint32 newZone, uint32 newArea)
{
if (!newZone)
{
return;
}
if (m_zoneUpdateId != newZone)
{
@@ -1265,6 +1270,8 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
guild->UpdateMemberData(this, GUILD_MEMBER_DATA_ZONEID, newZone);
}
GetMap()->UpdatePlayerZoneStats(m_zoneUpdateId, newZone);
// group update
if (GetGroup())
SetGroupUpdateFlag(GROUP_UPDATE_FULL);
@@ -1377,7 +1384,7 @@ void Player::UpdateEquipSpellsAtFormChange()
ApplyEquipSpell(spellInfo, nullptr, false,
true); // remove spells that not fit to form
if (!sScriptMgr->CanApplyEquipSpellsItemSet(this, eff))
if (!sScriptMgr->OnPlayerCanApplyEquipSpellsItemSet(this, eff))
break;
ApplyEquipSpell(spellInfo, nullptr, true,
true); // add spells that fit form but not active
@@ -1455,7 +1462,7 @@ void Player::UpdateFFAPvPState(bool reset /*= true*/)
{
if (!IsFFAPvP())
{
sScriptMgr->OnFfaPvpStateUpdate(this, true);
sScriptMgr->OnPlayerFfaPvpStateUpdate(this, true);
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
for (ControlSet::iterator itr = m_Controlled.begin();
itr != m_Controlled.end(); ++itr)
@@ -1477,7 +1484,7 @@ void Player::UpdateFFAPvPState(bool reset /*= true*/)
if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
sScriptMgr->OnFfaPvpStateUpdate(this, false);
sScriptMgr->OnPlayerFfaPvpStateUpdate(this, false);
}
for (ControlSet::iterator itr = m_Controlled.begin();
itr != m_Controlled.end(); ++itr)
@@ -2379,7 +2386,15 @@ void Player::ProcessSpellQueue()
if (CanExecutePendingSpellCastRequest(spellInfo))
{
ExecuteOrCancelSpellCastRequest(&request);
SpellQueue.pop_front(); // Remove from the queue
// ExecuteOrCancelSpellCastRequest() can lead to clearing the SpellQueue.
// Example scenario:
// Handling a spell → Dealing damage to yourself (e.g., spell_pri_vampiric_touch) →
// Killing yourself → Player::setDeathState() → SpellQueue.clear().
// Calling std::deque::pop_front() on an empty deque results in undefined behavior,
// so an additional check is added.
if (!SpellQueue.empty())
SpellQueue.pop_front();
}
else // If the first spell can't execute, stop processing
break;
@@ -19,6 +19,7 @@
#define TRANSPORTS_H
#include "GameObject.h"
#include "Timer.h"
#include "TransportMgr.h"
#include "VehicleDefines.h"
#include "ZoneScript.h"
+4 -4
View File
@@ -302,7 +302,7 @@ void Player::UpdateMaxHealth()
value += GetModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina();
value *= GetModifierValue(unitMod, TOTAL_PCT);
sScriptMgr->OnAfterUpdateMaxHealth(this, value);
sScriptMgr->OnPlayerAfterUpdateMaxHealth(this, value);
SetMaxHealth((uint32)value);
}
@@ -317,7 +317,7 @@ void Player::UpdateMaxPower(Powers power)
value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower;
value *= GetModifierValue(unitMod, TOTAL_PCT);
sScriptMgr->OnAfterUpdateMaxPower(this, power, value);
sScriptMgr->OnPlayerAfterUpdateMaxPower(this, power, value);
SetMaxPower(power, uint32(value));
}
@@ -332,7 +332,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
float val2 = 0.0f;
float level = float(GetLevel());
sScriptMgr->OnBeforeUpdateAttackPowerAndDamage(this, level, val2, ranged);
sScriptMgr->OnPlayerBeforeUpdateAttackPowerAndDamage(this, level, val2, ranged);
UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER;
@@ -499,7 +499,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
sScriptMgr->OnAfterUpdateAttackPowerAndDamage(this, level, base_attPower, attPowerMod, attPowerMultiplier, ranged);
sScriptMgr->OnPlayerAfterUpdateAttackPowerAndDamage(this, level, base_attPower, attPowerMod, attPowerMultiplier, ranged);
SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field
SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
+6 -4
View File
@@ -819,7 +819,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
victim->GetAI()->DamageTaken(attacker, damage, damagetype, damageSchoolMask);
if (attacker && attacker->IsAIEnabled)
attacker->GetAI()->DamageDealt(victim, damage, damagetype);
attacker->GetAI()->DamageDealt(victim, damage, damagetype, damageSchoolMask);
}
// Hook for OnDamage Event
@@ -17897,7 +17897,7 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp
if (Unit* owner = killer->GetOwner())
{
Unit::ProcDamageAndSpell(owner, victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell);
sScriptMgr->OnCreatureKilledByPet( killer->GetCharmerOrOwnerPlayerOrPlayerItself(), victim->ToCreature());
sScriptMgr->OnPlayerCreatureKilledByPet( killer->GetCharmerOrOwnerPlayerOrPlayerItself(), victim->ToCreature());
}
if (killer != victim)
@@ -18099,9 +18099,9 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp
if (Player* killerPlr = killer->ToPlayer())
{
if (Player* killedPlr = victim->ToPlayer())
sScriptMgr->OnPVPKill(killerPlr, killedPlr);
sScriptMgr->OnPlayerPVPKill(killerPlr, killedPlr);
else if (Creature* killedCre = victim->ToCreature())
sScriptMgr->OnCreatureKill(killerPlr, killedCre);
sScriptMgr->OnPlayerCreatureKill(killerPlr, killedCre);
}
else if (Creature* killerCre = killer->ToCreature())
{
@@ -20566,6 +20566,8 @@ void Unit::ExecuteDelayedUnitRelocationEvent()
}
}
GetMap()->LoadGridsInRange(*player, MAX_VISIBILITY_DISTANCE);
Acore::PlayerRelocationNotifier relocateNoLarge(*player, false); // visit only objects which are not large; default distance
Cell::VisitAllObjects(viewPoint, relocateNoLarge, player->GetSightRange() + VISIBILITY_INC_FOR_GOBJECTS);
relocateNoLarge.SendToSelf();
+2 -29
View File
@@ -31,6 +31,7 @@
#include "Transport.h"
#include "UnitAI.h"
#include "World.h"
#include "WorldSessionMgr.h"
#include "WorldStatePackets.h"
#include <time.h>
@@ -1163,34 +1164,6 @@ uint32 GameEventMgr::StartSystem() // return the next
return delay;
}
void GameEventMgr::StartArenaSeason()
{
uint8 season = sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID);
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_GAME_EVENT_ARENA_SEASON);
stmt->SetData(0, season);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
LOG_ERROR("gameevent", "ArenaSeason ({}) must be an existant Arena Season", season);
return;
}
Field* fields = result->Fetch();
uint16 eventId = fields[0].Get<uint8>();
if (eventId >= _gameEvent.size())
{
LOG_ERROR("gameevent", "EventEntry {} for ArenaSeason ({}) does not exists", eventId, season);
return;
}
StartEvent(eventId, true);
LOG_INFO("server.loading", "Arena Season {} started...", season);
LOG_INFO("server.loading", " ");
}
uint32 GameEventMgr::Update() // return the next event delay in ms
{
time_t currenttime = GameTime::GetGameTime().count();
@@ -1714,7 +1687,7 @@ void GameEventMgr::UpdateWorldStates(uint16 eventId, bool Activate)
WorldPackets::WorldState::UpdateWorldState worldstate;
worldstate.VariableID = bl->HolidayWorldStateId;
worldstate.Value = Activate ? 1 : 0;
sWorld->SendGlobalMessage(worldstate.Write());
sWorldSessionMgr->SendGlobalMessage(worldstate.Write());
}
}
}
+4 -5
View File
@@ -115,11 +115,10 @@ public:
bool IsActiveEvent(uint16 eventId) { return (_activeEvents.find(eventId) != _activeEvents.end()); }
uint32 StartSystem();
void Initialize();
void StartArenaSeason();
void StartInternalEvent(uint16 eventId);
bool StartEvent(uint16 eventId, bool overwrite = false);
void StopEvent(uint16 eventId, bool overwrite = false);
void HandleQuestComplete(uint32 questId); // called on world event type quest completions
void StartInternalEvent(uint16 event_id);
bool StartEvent(uint16 event_id, bool overwrite = false);
void StopEvent(uint16 event_id, bool overwrite = false);
void HandleQuestComplete(uint32 quest_id); // called on world event type quest completions
uint32 GetNPCFlag(Creature* cr);
// Load the game event npc vendor table from the DB
void LoadEventVendors();
+9 -9
View File
@@ -2341,8 +2341,8 @@ void ObjectMgr::AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const*
{
if (mask & 1)
{
CellCoord cellCoord = Acore::ComputeCellCoord(data->posX, data->posY);
CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()];
GridCoord gridCoord = Acore::ComputeGridCoord(data->posX, data->posY);
CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][gridCoord.GetId()];
cell_guids.creatures.insert(guid);
}
}
@@ -2355,8 +2355,8 @@ void ObjectMgr::RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData co
{
if (mask & 1)
{
CellCoord cellCoord = Acore::ComputeCellCoord(data->posX, data->posY);
CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()];
GridCoord gridCoord = Acore::ComputeGridCoord(data->posX, data->posY);
CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][gridCoord.GetId()];
cell_guids.creatures.erase(guid);
}
}
@@ -2454,7 +2454,7 @@ uint32 ObjectMgr::AddCreData(uint32 entry, uint32 mapId, float x, float y, float
AddCreatureToGrid(spawnId, &data);
// Spawn if necessary (loaded grids only)
if (!map->Instanceable() && !map->IsRemovalGrid(x, y))
if (!map->Instanceable() && !map->IsGridCreated(x, y))
{
Creature* creature = new Creature();
if (!creature->LoadCreatureFromDB(spawnId, map, true, true))
@@ -2644,8 +2644,8 @@ void ObjectMgr::AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData con
{
if (mask & 1)
{
CellCoord cellCoord = Acore::ComputeCellCoord(data->posX, data->posY);
CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()];
GridCoord gridCoord = Acore::ComputeGridCoord(data->posX, data->posY);
CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][gridCoord.GetId()];
cell_guids.gameobjects.insert(guid);
}
}
@@ -2658,8 +2658,8 @@ void ObjectMgr::RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectDat
{
if (mask & 1)
{
CellCoord cellCoord = Acore::ComputeCellCoord(data->posX, data->posY);
CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()];
GridCoord gridCoord = Acore::ComputeGridCoord(data->posX, data->posY);
CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][gridCoord.GetId()];
cell_guids.gameobjects.erase(guid);
}
}
+2 -2
View File
@@ -1151,12 +1151,12 @@ public:
return nullptr;
}
CellObjectGuids const& GetCellObjectGuids(uint16 mapid, uint8 spawnMode, uint32 cell_id)
CellObjectGuids const& GetGridObjectGuids(uint16 mapid, uint8 spawnMode, uint32 gridId)
{
MapObjectGuids::const_iterator itr1 = _mapObjectGuidsStore.find(MAKE_PAIR32(mapid, spawnMode));
if (itr1 != _mapObjectGuidsStore.end())
{
CellObjectGuidsMap::const_iterator itr2 = itr1->second.find(cell_id);
CellObjectGuidsMap::const_iterator itr2 = itr1->second.find(gridId);
if (itr2 != itr1->second.end())
return itr2->second;
}
+10 -14
View File
@@ -70,8 +70,6 @@ struct Cell
[[nodiscard]] uint32 CellY() const { return data.Part.cell_y; }
[[nodiscard]] uint32 GridX() const { return data.Part.grid_x; }
[[nodiscard]] uint32 GridY() const { return data.Part.grid_y; }
[[nodiscard]] bool NoCreate() const { return data.Part.nocreate; }
void SetNoCreate() { data.Part.nocreate = 1; }
[[nodiscard]] CellCoord GetCellCoord() const
{
@@ -92,12 +90,10 @@ struct Cell
{
struct
{
unsigned grid_x : 6;
unsigned grid_y : 6;
unsigned cell_x : 6;
unsigned cell_y : 6;
unsigned nocreate : 1;
unsigned reserved : 7;
unsigned grid_x : 8;
unsigned grid_y : 8;
unsigned cell_x : 8;
unsigned cell_y : 8;
} Part;
uint32 All;
} data;
@@ -107,13 +103,13 @@ struct Cell
static CellArea CalculateCellArea(float x, float y, float radius);
template<class T> static void VisitGridObjects(WorldObject const* obj, T& visitor, float radius, bool dont_load = true);
template<class T> static void VisitWorldObjects(WorldObject const* obj, T& visitor, float radius, bool dont_load = true);
template<class T> static void VisitAllObjects(WorldObject const* obj, T& visitor, float radius, bool dont_load = true);
template<class T> static void VisitGridObjects(WorldObject const* obj, T& visitor, float radius);
template<class T> static void VisitWorldObjects(WorldObject const* obj, T& visitor, float radius);
template<class T> static void VisitAllObjects(WorldObject const* obj, T& visitor, float radius);
template<class T> static void VisitGridObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load = true);
template<class T> static void VisitWorldObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load = true);
template<class T> static void VisitAllObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load = true);
template<class T> static void VisitGridObjects(float x, float y, Map* map, T& visitor, float radius);
template<class T> static void VisitWorldObjects(float x, float y, Map* map, T& visitor, float radius);
template<class T> static void VisitAllObjects(float x, float y, Map* map, T& visitor, float radius);
private:
template<class T, class CONTAINER> void VisitCircle(TypeContainerVisitor<T, CONTAINER>&, Map&, CellCoord const&, CellCoord const&) const;
+14 -51
View File
@@ -28,8 +28,6 @@ inline Cell::Cell(CellCoord const& p)
data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS;
data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS;
data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS;
data.Part.nocreate = 0;
data.Part.reserved = 0;
}
inline Cell::Cell(float x, float y)
@@ -39,8 +37,6 @@ inline Cell::Cell(float x, float y)
data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS;
data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS;
data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS;
data.Part.nocreate = 0;
data.Part.reserved = 0;
}
inline CellArea Cell::CalculateCellArea(float x, float y, float radius)
@@ -51,8 +47,8 @@ inline CellArea Cell::CalculateCellArea(float x, float y, float radius)
return CellArea(center, center);
}
CellCoord centerX = Acore::ComputeCellCoord(x - radius, y - radius).normalize();
CellCoord centerY = Acore::ComputeCellCoord(x + radius, y + radius).normalize();
CellCoord centerX = Acore::ComputeCellCoord(x + radius, y + radius).normalize();
CellCoord centerY = Acore::ComputeCellCoord(x - radius, y - radius).normalize();
return CellArea(centerX, centerY);
}
@@ -66,7 +62,8 @@ inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor<T,
}
template<class T, class CONTAINER>
inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor<T, CONTAINER>& visitor, Map& map, float x_off, float y_off, float radius) const{
inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor<T, CONTAINER>& visitor, Map& map, float x_off, float y_off, float radius) const
{
if (!standing_cell.IsCoordValid())
return;
@@ -101,23 +98,16 @@ inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor<T,
return;
}
//ALWAYS visit standing cell first!!! Since we deal with small radiuses
//it is very essential to call visitor for standing cell firstly...
map.Visit(*this, visitor);
// loop the cell range
ASSERT(area.high_bound.x_coord >= area.low_bound.x_coord);
ASSERT(area.high_bound.y_coord >= area.low_bound.y_coord);
for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
{
for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
{
CellCoord cellCoord(x, y);
//lets skip standing cell since we already visited it
if (cellCoord != standing_cell)
{
Cell r_zone(cellCoord);
r_zone.data.Part.nocreate = this->data.Part.nocreate;
map.Visit(r_zone, visitor);
}
Cell r_zone(cellCoord);
map.Visit(r_zone, visitor);
}
}
}
@@ -138,7 +128,6 @@ inline void Cell::VisitCircle(TypeContainerVisitor<T, CONTAINER>& visitor, Map&
{
CellCoord cellCoord(x, y);
Cell r_zone(cellCoord);
r_zone.data.Part.nocreate = this->data.Part.nocreate;
map.Visit(r_zone, visitor);
}
}
@@ -162,55 +151,41 @@ inline void Cell::VisitCircle(TypeContainerVisitor<T, CONTAINER>& visitor, Map&
//e.g. filling 2 trapezoids after filling central cell strip...
CellCoord cellCoord_left(x_start - step, y);
Cell r_zone_left(cellCoord_left);
r_zone_left.data.Part.nocreate = this->data.Part.nocreate;
map.Visit(r_zone_left, visitor);
//right trapezoid cell visit
CellCoord cellCoord_right(x_end + step, y);
Cell r_zone_right(cellCoord_right);
r_zone_right.data.Part.nocreate = this->data.Part.nocreate;
map.Visit(r_zone_right, visitor);
}
}
}
template<class T>
inline void Cell::VisitGridObjects(WorldObject const* center_obj, T& visitor, float radius, bool dont_load /*= true*/)
inline void Cell::VisitGridObjects(WorldObject const* center_obj, T& visitor, float radius)
{
CellCoord p(Acore::ComputeCellCoord(center_obj->GetPositionX(), center_obj->GetPositionY()));
Cell cell(p);
if (dont_load)
{
cell.SetNoCreate();
}
TypeContainerVisitor<T, GridTypeMapContainer> gnotifier(visitor);
cell.Visit(p, gnotifier, *center_obj->GetMap(), *center_obj, radius);
}
template<class T>
inline void Cell::VisitWorldObjects(WorldObject const* center_obj, T& visitor, float radius, bool dont_load /*= true*/)
inline void Cell::VisitWorldObjects(WorldObject const* center_obj, T& visitor, float radius)
{
CellCoord p(Acore::ComputeCellCoord(center_obj->GetPositionX(), center_obj->GetPositionY()));
Cell cell(p);
if (dont_load)
{
cell.SetNoCreate();
}
TypeContainerVisitor<T, WorldTypeMapContainer> wnotifier(visitor);
cell.Visit(p, wnotifier, *center_obj->GetMap(), *center_obj, radius);
}
template<class T>
inline void Cell::VisitAllObjects(WorldObject const* center_obj, T& visitor, float radius, bool dont_load /*= true*/)
inline void Cell::VisitAllObjects(WorldObject const* center_obj, T& visitor, float radius)
{
CellCoord p(Acore::ComputeCellCoord(center_obj->GetPositionX(), center_obj->GetPositionY()));
Cell cell(p);
if (dont_load)
{
cell.SetNoCreate();
}
TypeContainerVisitor<T, WorldTypeMapContainer> wnotifier(visitor);
cell.Visit(p, wnotifier, *center_obj->GetMap(), *center_obj, radius);
@@ -219,42 +194,30 @@ inline void Cell::VisitAllObjects(WorldObject const* center_obj, T& visitor, flo
}
template<class T>
inline void Cell::VisitGridObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load /*= true*/)
inline void Cell::VisitGridObjects(float x, float y, Map* map, T& visitor, float radius)
{
CellCoord p(Acore::ComputeCellCoord(x, y));
Cell cell(p);
if (dont_load)
{
cell.SetNoCreate();
}
TypeContainerVisitor<T, GridTypeMapContainer> gnotifier(visitor);
cell.Visit(p, gnotifier, *map, x, y, radius);
}
template<class T>
inline void Cell::VisitWorldObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load /*= true*/)
inline void Cell::VisitWorldObjects(float x, float y, Map* map, T& visitor, float radius)
{
CellCoord p(Acore::ComputeCellCoord(x, y));
Cell cell(p);
if (dont_load)
{
cell.SetNoCreate();
}
TypeContainerVisitor<T, WorldTypeMapContainer> wnotifier(visitor);
cell.Visit(p, wnotifier, *map, x, y, radius);
}
template<class T>
inline void Cell::VisitAllObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load /*= true*/)
inline void Cell::VisitAllObjects(float x, float y, Map* map, T& visitor, float radius)
{
CellCoord p(Acore::ComputeCellCoord(x, y));
Cell cell(p);
if (dont_load)
{
cell.SetNoCreate();
}
TypeContainerVisitor<T, WorldTypeMapContainer> wnotifier(visitor);
cell.Visit(p, wnotifier, *map, x, y, radius);
-131
View File
@@ -1,131 +0,0 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACORE_GRID_H
#define ACORE_GRID_H
/*
@class Grid
Grid is a logical segment of the game world represented inside TrinIty.
Grid is bind at compile time to a particular type of object which
we call it the object of interested. There are many types of loader,
specially, dynamic loader, static loader, or on-demand loader. There's
a subtle difference between dynamic loader and on-demand loader but
this is implementation specific to the loader class. From the
Grid's perspective, the loader meets its API requirement is suffice.
*/
#include "Define.h"
#include "TypeContainer.h"
#include "TypeContainerVisitor.h"
// forward declaration
template<class A, class T, class O> class GridLoader;
template
<
class ACTIVE_OBJECT,
class WORLD_OBJECT_TYPES,
class GRID_OBJECT_TYPES
>
class Grid
{
// allows the GridLoader to access its internals
template<class A, class T, class O> friend class GridLoader;
public:
/** destructor to clean up its resources. This includes unloading the
grid if it has not been unload.
*/
~Grid() = default;
/** an object of interested enters the grid
*/
template<class SPECIFIC_OBJECT> void AddWorldObject(SPECIFIC_OBJECT* obj)
{
i_objects.template insert<SPECIFIC_OBJECT>(obj);
ASSERT(obj->IsInGrid());
}
/** an object of interested exits the grid
*/
//Actually an unlink is enough, no need to go through the container
//template<class SPECIFIC_OBJECT> void RemoveWorldObject(SPECIFIC_OBJECT *obj)
//{
// ASSERT(obj->GetGridRef().isValid());
// i_objects.template remove<SPECIFIC_OBJECT>(obj);
// ASSERT(!obj->GetGridRef().isValid());
//}
/** Refreshes/update the grid. This required for remote grids.
*/
//void RefreshGrid(void) { /* TBI */}
/** Locks a grid. Any object enters must wait until the grid is unlock.
*/
//void LockGrid(void) { /* TBI */ }
/** Unlocks the grid.
*/
//void UnlockGrid(void) { /* TBI */ }
// Visit grid objects
template<class T>
void Visit(TypeContainerVisitor<T, TypeMapContainer<GRID_OBJECT_TYPES> >& visitor)
{
visitor.Visit(i_container);
}
// Visit world objects
template<class T>
void Visit(TypeContainerVisitor<T, TypeMapContainer<WORLD_OBJECT_TYPES> >& visitor)
{
visitor.Visit(i_objects);
}
/** Inserts a container type object into the grid.
*/
template<class SPECIFIC_OBJECT> void AddGridObject(SPECIFIC_OBJECT* obj)
{
i_container.template insert<SPECIFIC_OBJECT>(obj);
ASSERT(obj->IsInGrid());
}
/** Removes a containter type object from the grid
*/
//template<class SPECIFIC_OBJECT> void RemoveGridObject(SPECIFIC_OBJECT *obj)
//{
// ASSERT(obj->GetGridRef().isValid());
// i_container.template remove<SPECIFIC_OBJECT>(obj);
// ASSERT(!obj->GetGridRef().isValid());
//}
/*bool NoWorldObjectInGrid() const
{
return i_objects.GetElements().IsEmpty();
}
bool NoGridObjectInGrid() const
{
return i_container.GetElements().IsEmpty();
}*/
private:
TypeMapContainer<GRID_OBJECT_TYPES> i_container;
TypeMapContainer<WORLD_OBJECT_TYPES> i_objects;
//typedef std::set<void*> ActiveGridObjects;
//ActiveGridObjects m_activeGridObjects;
};
#endif
+75
View File
@@ -0,0 +1,75 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACORE_GRID_CELL_H
#define ACORE_GRID_CELL_H
/*
@class GridCell
Grid is a logical segment of the game world represented inside TrinIty.
Grid is bind at compile time to a particular type of object which
we call it the object of interested. There are many types of loader,
specially, dynamic loader, static loader, or on-demand loader. There's
a subtle difference between dynamic loader and on-demand loader but
this is implementation specific to the loader class. From the
Grid's perspective, the loader meets its API requirement is suffice.
*/
#include "Define.h"
#include "TypeContainer.h"
#include "TypeContainerVisitor.h"
template
<
class WORLD_OBJECT_TYPES,
class GRID_OBJECT_TYPES
>
class GridCell
{
public:
~GridCell() = default;
template<class SPECIFIC_OBJECT> void AddWorldObject(SPECIFIC_OBJECT* obj)
{
_worldObjects.template insert<SPECIFIC_OBJECT>(obj);
ASSERT(obj->IsInGrid());
}
template<class SPECIFIC_OBJECT> void AddGridObject(SPECIFIC_OBJECT* obj)
{
_gridObjects.template insert<SPECIFIC_OBJECT>(obj);
ASSERT(obj->IsInGrid());
}
// Visit grid objects
template<class T>
void Visit(TypeContainerVisitor<T, TypeMapContainer<GRID_OBJECT_TYPES> >& visitor)
{
visitor.Visit(_gridObjects);
}
// Visit world objects
template<class T>
void Visit(TypeContainerVisitor<T, TypeMapContainer<WORLD_OBJECT_TYPES> >& visitor)
{
visitor.Visit(_worldObjects);
}
private:
TypeMapContainer<GRID_OBJECT_TYPES> _gridObjects;
TypeMapContainer<WORLD_OBJECT_TYPES> _worldObjects;
};
#endif
+17 -26
View File
@@ -20,7 +20,8 @@
#include "Common.h"
#include "MapDefines.h"
#include "NGrid.h"
#include "GridCell.h"
#include "MapGrid.h"
// Forward class definitions
class Corpse;
@@ -31,8 +32,6 @@ class Pet;
class Player;
class ObjectGuid;
#define MAX_NUMBER_OF_CELLS 8
#define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2)
#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2)
@@ -73,8 +72,8 @@ enum GridMapTypeMask
GRID_MAP_TYPE_MASK_ALL = 0x1F
};
typedef Grid<Player, AllWorldObjectTypes, AllGridObjectTypes> GridType;
typedef NGrid<MAX_NUMBER_OF_CELLS, Player, AllWorldObjectTypes, AllGridObjectTypes> NGridType;
typedef GridCell<AllWorldObjectTypes, AllGridObjectTypes> GridCellType;
typedef MapGrid<AllWorldObjectTypes, AllGridObjectTypes> MapGridType;
typedef TypeMapContainer<AllGridObjectTypes> GridTypeMapContainer;
typedef TypeMapContainer<AllWorldObjectTypes> WorldTypeMapContainer;
@@ -171,37 +170,29 @@ typedef CoordPair<TOTAL_NUMBER_OF_CELLS_PER_MAP> CellCoord;
namespace Acore
{
template<class RET_TYPE, int CENTER_VAL>
inline RET_TYPE Compute(float x, float y, float center_offset, float size)
inline RET_TYPE Compute(float x, float y, float size)
{
// calculate and store temporary values in double format for having same result as same mySQL calculations
double x_offset = (double(x) - center_offset) / size;
double y_offset = (double(y) - center_offset) / size;
int gx = (int)(CENTER_VAL - x / size);
int gy = (int)(CENTER_VAL - y / size);
int x_val = int(x_offset + CENTER_VAL + 0.5f);
int y_val = int(y_offset + CENTER_VAL + 0.5f);
return RET_TYPE(x_val, y_val);
return RET_TYPE(gx, gy);
}
inline GridCoord ComputeGridCoord(float x, float y)
{
return Compute<GridCoord, CENTER_GRID_ID>(x, y, CENTER_GRID_OFFSET, SIZE_OF_GRIDS);
return Compute<GridCoord, CENTER_GRID_ID>(x, y, SIZE_OF_GRIDS);
}
inline GridCoord ComputeGridCoordSimple(float x, float y)
{
int gx = (int)(CENTER_GRID_ID - x / SIZE_OF_GRIDS);
int gy = (int)(CENTER_GRID_ID - y / SIZE_OF_GRIDS);
return GridCoord((MAX_NUMBER_OF_GRIDS - 1) - gx, (MAX_NUMBER_OF_GRIDS - 1) - gy);
}
inline CellCoord ComputeCellCoord(float x, float y)
{
return Compute<CellCoord, CENTER_GRID_CELL_ID>(x, y, CENTER_GRID_CELL_OFFSET, SIZE_OF_GRID_CELL);
}
inline CellCoord ComputeCellCoord(float x, float y, float& x_off, float& y_off)
{
double x_offset = (double(x) - CENTER_GRID_CELL_OFFSET) / SIZE_OF_GRID_CELL;
double y_offset = (double(y) - CENTER_GRID_CELL_OFFSET) / SIZE_OF_GRID_CELL;
int x_val = int(x_offset + CENTER_GRID_CELL_ID + 0.5f);
int y_val = int(y_offset + CENTER_GRID_CELL_ID + 0.5f);
x_off = (float(x_offset) - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL;
y_off = (float(y_offset) - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL;
return CellCoord(x_val, y_val);
return Compute<CellCoord, CENTER_GRID_CELL_ID>(x, y, SIZE_OF_GRID_CELL);
}
inline void NormalizeMapCoord(float& c)
-76
View File
@@ -1,76 +0,0 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACORE_GRIDLOADER_H
#define ACORE_GRIDLOADER_H
/**
@class GridLoader
The GridLoader is working in conjuction with the Grid and responsible
for loading and unloading object-types (one or more) when objects
enters a grid. Unloading is scheduled and might be canceled if
an interested object re-enters. GridLoader does not do the actuall
loading and unloading but implements as a template pattern that
delicate its loading and unloading for the actualy loader and unloader.
GridLoader manages the grid (both local and remote).
*/
//I cannot see why this cannot be replaced by a Grid::Visit
/*
#include "Define.h"
#include "Grid.h"
#include "TypeContainerVisitor.h"
template
<
class ACTIVE_OBJECT,
class WORLD_OBJECT_TYPES,
class GRID_OBJECT_TYPES
>
class GridLoader
{
public:
// Loads the grid
template<class LOADER>
void Load(Grid<ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> &grid, LOADER &loader)
{
grid.LockGrid();
loader.Load(grid);
grid.UnlockGrid();
}
// Stop the grid
template<class STOPER>
void Stop(Grid<ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> &grid, STOPER &stoper)
{
grid.LockGrid();
stoper.Stop(grid);
grid.UnlockGrid();
}
// Unloads the grid
template<class UNLOADER>
void Unload(Grid<ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> &grid, UNLOADER &unloader)
{
grid.LockGrid();
unloader.Unload(grid);
grid.UnlockGrid();
}
};
*/
#endif
+138
View File
@@ -0,0 +1,138 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GridObjectLoader.h"
#include "CellImpl.h"
#include "Corpse.h"
#include "Creature.h"
#include "DynamicObject.h"
#include "GameObject.h"
#include "GridNotifiers.h"
#include "Transport.h"
template <class T>
void GridObjectLoader::AddObjectHelper(Map* map, T* obj)
{
CellCoord cellCoord = Acore::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
Cell cell(cellCoord);
map->AddToGrid(obj, cell);
obj->AddToWorld();
if (obj->isActiveObject())
map->AddToActive(obj);
}
void GridObjectLoader::LoadCreatures(CellGuidSet const& guid_set, Map* map)
{
for (ObjectGuid::LowType const& guid : guid_set)
{
Creature* obj = new Creature();
if (!obj->LoadFromDB(guid, map))
{
delete obj;
continue;
}
AddObjectHelper<Creature>(map, obj);
if (!obj->IsMoveInLineOfSightDisabled() && obj->GetDefaultMovementType() == IDLE_MOTION_TYPE && !obj->isNeedNotify(NOTIFY_VISIBILITY_CHANGED | NOTIFY_AI_RELOCATION))
{
if (obj->IsAlive() && !obj->HasUnitState(UNIT_STATE_SIGHTLESS) && obj->HasReactState(REACT_AGGRESSIVE) && !obj->IsImmuneToNPC())
{
// call MoveInLineOfSight for nearby grid creatures
Acore::AIRelocationNotifier notifier(*obj);
Cell::VisitGridObjects(obj, notifier, 60.f);
}
}
}
}
void GridObjectLoader::LoadGameObjects(CellGuidSet const& guid_set, Map* map)
{
for (ObjectGuid::LowType const& guid : guid_set)
{
GameObjectData const* data = sObjectMgr->GetGameObjectData(guid);
GameObject* obj = data && sObjectMgr->IsGameObjectStaticTransport(data->id) ? new StaticTransport() : new GameObject();
if (!obj->LoadFromDB(guid, map))
{
delete obj;
continue;
}
AddObjectHelper<GameObject>(map, obj);
}
}
void GridObjectLoader::LoadAllCellsInGrid()
{
CellObjectGuids const& cell_guids = sObjectMgr->GetGridObjectGuids(_map->GetId(), _map->GetSpawnMode(), _grid.GetId());
LoadGameObjects(cell_guids.gameobjects, _map);
LoadCreatures(cell_guids.creatures, _map);
if (std::unordered_set<Corpse*> const* corpses = _map->GetCorpsesInCell(_grid.GetId()))
{
for (Corpse* corpse : *corpses)
{
if (corpse->IsInGrid())
continue;
CellCoord cellCoord = Acore::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY());
Cell cell(cellCoord);
if (corpse->IsWorldObject())
_grid.AddWorldObject(cell.CellX(), cell.CellY(), corpse);
else
_grid.AddGridObject(cell.CellX(), cell.CellY(), corpse);
}
}
}
template<class T>
void GridObjectUnloader::Visit(GridRefMgr<T>& m)
{
while (!m.IsEmpty())
{
T* obj = m.getFirst()->GetSource();
// if option set then object already saved at this moment
//if (!sWorld->getBoolConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY))
// obj->SaveRespawnTime();
//Some creatures may summon other temp summons in CleanupsBeforeDelete()
//So we need this even after cleaner (maybe we can remove cleaner)
//Example: Flame Leviathan Turret 33139 is summoned when a creature is deleted
//TODO: Check if that script has the correct logic. Do we really need to summons something before deleting?
obj->CleanupsBeforeDelete();
///- object will get delinked from the manager when deleted
delete obj;
}
}
template<class T>
void GridObjectCleaner::Visit(GridRefMgr<T>& m)
{
for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
iter->GetSource()->CleanupsBeforeDelete();
}
template void GridObjectUnloader::Visit(CreatureMapType&);
template void GridObjectUnloader::Visit(GameObjectMapType&);
template void GridObjectUnloader::Visit(DynamicObjectMapType&);
template void GridObjectCleaner::Visit(CreatureMapType&);
template void GridObjectCleaner::Visit<GameObject>(GameObjectMapType&);
template void GridObjectCleaner::Visit<DynamicObject>(DynamicObjectMapType&);
template void GridObjectCleaner::Visit<Corpse>(CorpseMapType&);
@@ -15,51 +15,42 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACORE_OBJECTGRIDLOADER_H
#define ACORE_OBJECTGRIDLOADER_H
#ifndef ACORE_GRID_OBJECT_LOADER_H
#define ACORE_GRID_OBJECT_LOADER_H
#include "Cell.h"
#include "Define.h"
#include "GridDefines.h"
#include "ObjectMgr.h"
class ObjectWorldLoader;
class ObjectGridLoader
class GridObjectLoader
{
friend class ObjectWorldLoader;
public:
ObjectGridLoader(NGridType& grid, Map* map, const Cell& cell)
: i_cell(cell), i_grid(grid), i_map(map), i_gameObjects(0), i_creatures(0), i_corpses (0)
{}
GridObjectLoader(MapGridType& grid, Map* map)
: _grid(grid), _map(map) { }
void Visit(GameObjectMapType& m);
void Visit(CreatureMapType& m);
void Visit(CorpseMapType&) const {}
void Visit(DynamicObjectMapType&) const {}
void LoadN(void);
template<class T> static void SetObjectCell(T* obj, CellCoord const& cellCoord);
void LoadAllCellsInGrid();
private:
Cell i_cell;
NGridType& i_grid;
Map* i_map;
uint32 i_gameObjects;
uint32 i_creatures;
uint32 i_corpses;
template<class T>
void AddObjectHelper(Map* map, T* obj);
void LoadCreatures(CellGuidSet const& guid_set, Map* map);
void LoadGameObjects(CellGuidSet const& guid_set, Map* map);
MapGridType& _grid;
Map* _map;
};
//Clean up and remove from world
class ObjectGridCleaner
// Clean up and remove from world
class GridObjectCleaner
{
public:
template<class T> void Visit(GridRefMgr<T>&);
};
//Delete objects before deleting NGrid
class ObjectGridUnloader
// Delete objects before deleting NGrid
class GridObjectUnloader
{
public:
void Visit(CorpseMapType&) { } // corpses are deleted with Map
+617
View File
@@ -0,0 +1,617 @@
#include "DBCStores.h"
#include "GridDefines.h"
#include "GridTerrainData.h"
#include "Log.h"
#include "MapDefines.h"
#include <filesystem>
#include <G3D/Ray.h>
uint16 const holetab_h[4] = { 0x1111, 0x2222, 0x4444, 0x8888 };
uint16 const holetab_v[4] = { 0x000F, 0x00F0, 0x0F00, 0xF000 };
GridTerrainData::GridTerrainData()
{
_gridGetHeight = &GridTerrainData::getHeightFromFlat;
}
TerrainMapDataReadResult GridTerrainData::Load(std::string const& mapFileName)
{
// Check if file exists, we do this first as we need to
// differentiate between file existing and any other file errors
if (!std::filesystem::exists(mapFileName))
return TerrainMapDataReadResult::NotFound;
// Start the input stream and check for any errors
std::ifstream fileStream(mapFileName, std::ios::binary);
if (fileStream.fail())
return TerrainMapDataReadResult::ReadError;
// Read the map header
map_fileheader header;
if (!fileStream.read(reinterpret_cast<char*>(&header), sizeof(header)))
return TerrainMapDataReadResult::ReadError;
// Check for valid map and version magics
if (header.mapMagic != MapMagic.asUInt || header.versionMagic != MapVersionMagic)
return TerrainMapDataReadResult::InvalidMagic;
// Load area data
if (header.areaMapOffset && !LoadAreaData(fileStream, header.areaMapOffset))
return TerrainMapDataReadResult::InvalidAreaData;
// Load height data
if (header.heightMapOffset && !LoadHeightData(fileStream, header.heightMapOffset))
return TerrainMapDataReadResult::InvalidHeightData;
// Load liquid data
if (header.liquidMapOffset && !LoadLiquidData(fileStream, header.liquidMapOffset))
return TerrainMapDataReadResult::InvalidLiquidData;
// Load hole data
if (header.holesSize && !LoadHolesData(fileStream, header.holesOffset))
return TerrainMapDataReadResult::InvalidHoleData;
return TerrainMapDataReadResult::Success;
}
bool GridTerrainData::LoadAreaData(std::ifstream& fileStream, uint32 const offset)
{
fileStream.seekg(offset);
map_areaHeader header;
if (!fileStream.read(reinterpret_cast<char*>(&header), sizeof(header)) || header.fourcc != MapAreaMagic.asUInt)
return false;
_loadedAreaData = std::make_unique<LoadedAreaData>();
_loadedAreaData->gridArea = header.gridArea;
if (!(header.flags & MAP_AREA_NO_AREA))
{
_loadedAreaData->areaMap = std::make_unique<LoadedAreaData::AreaMapType>();
if (!fileStream.read(reinterpret_cast<char*>(_loadedAreaData->areaMap.get()), sizeof(LoadedAreaData::AreaMapType)))
return false;
}
return true;
}
bool GridTerrainData::LoadHeightData(std::ifstream& fileStream, uint32 const offset)
{
fileStream.seekg(offset);
map_heightHeader header;
if (!fileStream.read(reinterpret_cast<char*>(&header), sizeof(header)) || header.fourcc != MapHeightMagic.asUInt)
return false;
_loadedHeightData = std::make_unique<LoadedHeightData>();
_loadedHeightData->gridHeight = header.gridHeight;
if (!(header.flags & MAP_HEIGHT_NO_HEIGHT))
{
if ((header.flags & MAP_HEIGHT_AS_INT16))
{
_loadedHeightData->uint16HeightData = std::make_unique<LoadedHeightData::Uint16HeightData>();
if (!fileStream.read(reinterpret_cast<char*>(&_loadedHeightData->uint16HeightData->v9), sizeof(_loadedHeightData->uint16HeightData->v9))
|| !fileStream.read(reinterpret_cast<char*>(&_loadedHeightData->uint16HeightData->v8), sizeof(_loadedHeightData->uint16HeightData->v8)))
return false;
_loadedHeightData->uint16HeightData->gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535;
_gridGetHeight = &GridTerrainData::getHeightFromUint16;
}
else if ((header.flags & MAP_HEIGHT_AS_INT8))
{
_loadedHeightData->uint8HeightData = std::make_unique<LoadedHeightData::Uint8HeightData>();
if (!fileStream.read(reinterpret_cast<char*>(&_loadedHeightData->uint8HeightData->v9), sizeof(_loadedHeightData->uint8HeightData->v9))
|| !fileStream.read(reinterpret_cast<char*>(&_loadedHeightData->uint8HeightData->v8), sizeof(_loadedHeightData->uint8HeightData->v8)))
return false;
_loadedHeightData->uint8HeightData->gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255;
_gridGetHeight = &GridTerrainData::getHeightFromUint8;
}
else
{
_loadedHeightData->floatHeightData = std::make_unique<LoadedHeightData::FloatHeightData>();
if (!fileStream.read(reinterpret_cast<char*>(&_loadedHeightData->floatHeightData->v9), sizeof(_loadedHeightData->floatHeightData->v9))
|| !fileStream.read(reinterpret_cast<char*>(&_loadedHeightData->floatHeightData->v8), sizeof(_loadedHeightData->floatHeightData->v8)))
return false;
_gridGetHeight = &GridTerrainData::getHeightFromFloat;
}
}
else
_gridGetHeight = &GridTerrainData::getHeightFromFlat;
if (header.flags & MAP_HEIGHT_HAS_FLIGHT_BOUNDS)
{
std::array<int16, 9> maxHeights;
std::array<int16, 9> minHeights;
if (!fileStream.read(reinterpret_cast<char*>(maxHeights.data()), sizeof(maxHeights)) ||
!fileStream.read(reinterpret_cast<char*>(minHeights.data()), sizeof(minHeights)))
return false;
static uint32 constexpr indices[8][3] =
{
{ 3, 0, 4 },
{ 0, 1, 4 },
{ 1, 2, 4 },
{ 2, 5, 4 },
{ 5, 8, 4 },
{ 8, 7, 4 },
{ 7, 6, 4 },
{ 6, 3, 4 }
};
static float constexpr boundGridCoords[9][2] =
{
{ 0.0f, 0.0f },
{ 0.0f, -266.66666f },
{ 0.0f, -533.33331f },
{ -266.66666f, 0.0f },
{ -266.66666f, -266.66666f },
{ -266.66666f, -533.33331f },
{ -533.33331f, 0.0f },
{ -533.33331f, -266.66666f },
{ -533.33331f, -533.33331f }
};
_loadedHeightData->minHeightPlanes = std::make_unique<LoadedHeightData::HeightPlanesType>();
for (uint32 quarterIndex = 0; quarterIndex < _loadedHeightData->minHeightPlanes->size(); ++quarterIndex)
_loadedHeightData->minHeightPlanes->at(quarterIndex) = G3D::Plane(
G3D::Vector3(boundGridCoords[indices[quarterIndex][0]][0], boundGridCoords[indices[quarterIndex][0]][1], minHeights[indices[quarterIndex][0]]),
G3D::Vector3(boundGridCoords[indices[quarterIndex][1]][0], boundGridCoords[indices[quarterIndex][1]][1], minHeights[indices[quarterIndex][1]]),
G3D::Vector3(boundGridCoords[indices[quarterIndex][2]][0], boundGridCoords[indices[quarterIndex][2]][1], minHeights[indices[quarterIndex][2]])
);
}
return true;
}
bool GridTerrainData::LoadLiquidData(std::ifstream& fileStream, uint32 const offset)
{
fileStream.seekg(offset);
map_liquidHeader header;
if (!fileStream.read(reinterpret_cast<char*>(&header), sizeof(header)) || header.fourcc != MapLiquidMagic.asUInt)
return false;
_loadedLiquidData = std::make_unique<LoadedLiquidData>();
_loadedLiquidData->liquidGlobalEntry = header.liquidType;
_loadedLiquidData->liquidGlobalFlags = header.liquidFlags;
_loadedLiquidData->liquidOffX = header.offsetX;
_loadedLiquidData->liquidOffY = header.offsetY;
_loadedLiquidData->liquidWidth = header.width;
_loadedLiquidData->liquidHeight = header.height;
_loadedLiquidData->liquidLevel = header.liquidLevel;
if (!(header.flags & MAP_LIQUID_NO_TYPE))
{
_loadedLiquidData->liquidEntry = std::make_unique<LoadedLiquidData::LiquidEntryType>();
if (!fileStream.read(reinterpret_cast<char*>(_loadedLiquidData->liquidEntry.get()), sizeof(LoadedLiquidData::LiquidEntryType)))
return false;
_loadedLiquidData->liquidFlags = std::make_unique<LoadedLiquidData::LiquidFlagsType>();
if (!fileStream.read(reinterpret_cast<char*>(_loadedLiquidData->liquidFlags.get()), sizeof(LoadedLiquidData::LiquidFlagsType)))
return false;
}
if (!(header.flags & MAP_LIQUID_NO_HEIGHT))
{
_loadedLiquidData->liquidMap = std::make_unique<LoadedLiquidData::LiquidMapType>();
_loadedLiquidData->liquidMap->resize(_loadedLiquidData->liquidWidth * _loadedLiquidData->liquidHeight);
if (!fileStream.read(reinterpret_cast<char*>(_loadedLiquidData->liquidMap->data()), _loadedLiquidData->liquidMap->size() * sizeof(float)))
return false;
}
return true;
}
bool GridTerrainData::LoadHolesData(std::ifstream& fileStream, uint32 const offset)
{
fileStream.seekg(offset);
_loadedHoleData = std::make_unique<LoadedHoleData>();
if (!fileStream.read(reinterpret_cast<char*>(&_loadedHoleData->holes), sizeof(_loadedHoleData->holes)))
return false;
return true;
}
uint16 GridTerrainData::getArea(float x, float y) const
{
if (!_loadedAreaData)
return 0;
if (!_loadedAreaData->areaMap)
return _loadedAreaData->gridArea;
x = 16 * (32 - x / SIZE_OF_GRIDS);
y = 16 * (32 - y / SIZE_OF_GRIDS);
int lx = (int)x & 15;
int ly = (int)y & 15;
return _loadedAreaData->areaMap->at(lx * 16 + ly);
}
float GridTerrainData::getHeightFromFlat(float /*x*/, float /*y*/) const
{
if (!_loadedHeightData)
return INVALID_HEIGHT;
return _loadedHeightData->gridHeight;
}
float GridTerrainData::getHeightFromFloat(float x, float y) const
{
if (!_loadedHeightData || !_loadedHeightData->floatHeightData)
return INVALID_HEIGHT;
x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
int x_int = (int)x;
int y_int = (int)y;
x -= x_int;
y -= y_int;
x_int &= (MAP_RESOLUTION - 1);
y_int &= (MAP_RESOLUTION - 1);
if (isHole(x_int, y_int))
return INVALID_HEIGHT;
// Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid
// +--------------> X
// | h1-------h2 Coordinates is:
// | | \ 1 / | h1 0, 0
// | | \ / | h2 0, 1
// | | 2 h5 3 | h3 1, 0
// | | / \ | h4 1, 1
// | | / 4 \ | h5 1/2, 1/2
// | h3-------h4
// V Y
// For find height need
// 1 - detect triangle
// 2 - solve linear equation from triangle points
// Calculate coefficients for solve h = a*x + b*y + c
float a, b, c;
// Select triangle:
if (x + y < 1)
{
if (x > y)
{
// 1 triangle (h1, h2, h5 points)
float h1 = _loadedHeightData->floatHeightData->v9[(x_int) * 129 + y_int];
float h2 = _loadedHeightData->floatHeightData->v9[(x_int + 1) * 129 + y_int];
float h5 = 2 * _loadedHeightData->floatHeightData->v8[x_int * 128 + y_int];
a = h2 - h1;
b = h5 - h1 - h2;
c = h1;
}
else
{
// 2 triangle (h1, h3, h5 points)
float h1 = _loadedHeightData->floatHeightData->v9[x_int * 129 + y_int];
float h3 = _loadedHeightData->floatHeightData->v9[x_int * 129 + y_int + 1];
float h5 = 2 * _loadedHeightData->floatHeightData->v8[x_int * 128 + y_int];
a = h5 - h1 - h3;
b = h3 - h1;
c = h1;
}
}
else
{
if (x > y)
{
// 3 triangle (h2, h4, h5 points)
float h2 = _loadedHeightData->floatHeightData->v9[(x_int + 1) * 129 + y_int];
float h4 = _loadedHeightData->floatHeightData->v9[(x_int + 1) * 129 + y_int + 1];
float h5 = 2 * _loadedHeightData->floatHeightData->v8[x_int * 128 + y_int];
a = h2 + h4 - h5;
b = h4 - h2;
c = h5 - h4;
}
else
{
// 4 triangle (h3, h4, h5 points)
float h3 = _loadedHeightData->floatHeightData->v9[(x_int) * 129 + y_int + 1];
float h4 = _loadedHeightData->floatHeightData->v9[(x_int + 1) * 129 + y_int + 1];
float h5 = 2 * _loadedHeightData->floatHeightData->v8[x_int * 128 + y_int];
a = h4 - h3;
b = h3 + h4 - h5;
c = h5 - h4;
}
}
// Calculate height
return a * x + b * y + c;
}
float GridTerrainData::getHeightFromUint8(float x, float y) const
{
if (!_loadedHeightData || !_loadedHeightData->uint8HeightData)
return INVALID_HEIGHT;
x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
int x_int = (int)x;
int y_int = (int)y;
x -= x_int;
y -= y_int;
x_int &= (MAP_RESOLUTION - 1);
y_int &= (MAP_RESOLUTION - 1);
if (isHole(x_int, y_int))
return INVALID_HEIGHT;
int32 a, b, c;
uint8* V9_h1_ptr = &_loadedHeightData->uint8HeightData->v9[x_int * 128 + x_int + y_int];
if (x + y < 1)
{
if (x > y)
{
// 1 triangle (h1, h2, h5 points)
int32 h1 = V9_h1_ptr[0];
int32 h2 = V9_h1_ptr[129];
int32 h5 = 2 * _loadedHeightData->uint8HeightData->v8[x_int * 128 + y_int];
a = h2 - h1;
b = h5 - h1 - h2;
c = h1;
}
else
{
// 2 triangle (h1, h3, h5 points)
int32 h1 = V9_h1_ptr[0];
int32 h3 = V9_h1_ptr[1];
int32 h5 = 2 * _loadedHeightData->uint8HeightData->v8[x_int * 128 + y_int];
a = h5 - h1 - h3;
b = h3 - h1;
c = h1;
}
}
else
{
if (x > y)
{
// 3 triangle (h2, h4, h5 points)
int32 h2 = V9_h1_ptr[129];
int32 h4 = V9_h1_ptr[130];
int32 h5 = 2 * _loadedHeightData->uint8HeightData->v8[x_int * 128 + y_int];
a = h2 + h4 - h5;
b = h4 - h2;
c = h5 - h4;
}
else
{
// 4 triangle (h3, h4, h5 points)
int32 h3 = V9_h1_ptr[1];
int32 h4 = V9_h1_ptr[130];
int32 h5 = 2 * _loadedHeightData->uint8HeightData->v8[x_int * 128 + y_int];
a = h4 - h3;
b = h3 + h4 - h5;
c = h5 - h4;
}
}
// Calculate height
return (float)((a * x) + (b * y) + c) * _loadedHeightData->uint8HeightData->gridIntHeightMultiplier + _loadedHeightData->gridHeight;
}
float GridTerrainData::getHeightFromUint16(float x, float y) const
{
if (!_loadedHeightData || !_loadedHeightData->uint16HeightData)
return INVALID_HEIGHT;
x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
int x_int = (int)x;
int y_int = (int)y;
x -= x_int;
y -= y_int;
x_int &= (MAP_RESOLUTION - 1);
y_int &= (MAP_RESOLUTION - 1);
if (isHole(x_int, y_int))
return INVALID_HEIGHT;
int32 a, b, c;
uint16* V9_h1_ptr = &_loadedHeightData->uint16HeightData->v9[x_int * 128 + x_int + y_int];
if (x + y < 1)
{
if (x > y)
{
// 1 triangle (h1, h2, h5 points)
int32 h1 = V9_h1_ptr[0];
int32 h2 = V9_h1_ptr[129];
int32 h5 = 2 * _loadedHeightData->uint16HeightData->v8[x_int * 128 + y_int];
a = h2 - h1;
b = h5 - h1 - h2;
c = h1;
}
else
{
// 2 triangle (h1, h3, h5 points)
int32 h1 = V9_h1_ptr[0];
int32 h3 = V9_h1_ptr[1];
int32 h5 = 2 * _loadedHeightData->uint16HeightData->v8[x_int * 128 + y_int];
a = h5 - h1 - h3;
b = h3 - h1;
c = h1;
}
}
else
{
if (x > y)
{
// 3 triangle (h2, h4, h5 points)
int32 h2 = V9_h1_ptr[129];
int32 h4 = V9_h1_ptr[130];
int32 h5 = 2 * _loadedHeightData->uint16HeightData->v8[x_int * 128 + y_int];
a = h2 + h4 - h5;
b = h4 - h2;
c = h5 - h4;
}
else
{
// 4 triangle (h3, h4, h5 points)
int32 h3 = V9_h1_ptr[1];
int32 h4 = V9_h1_ptr[130];
int32 h5 = 2 * _loadedHeightData->uint16HeightData->v8[x_int * 128 + y_int];
a = h4 - h3;
b = h3 + h4 - h5;
c = h5 - h4;
}
}
// Calculate height
return (float)((a * x) + (b * y) + c) * _loadedHeightData->uint16HeightData->gridIntHeightMultiplier + _loadedHeightData->gridHeight;
}
bool GridTerrainData::isHole(int row, int col) const
{
if (!_loadedHoleData)
return false;
int cellRow = row / 8; // 8 squares per cell
int cellCol = col / 8;
int holeRow = row % 8 / 2;
int holeCol = (col - (cellCol * 8)) / 2;
uint16 hole = _loadedHoleData->holes[cellRow * 16 + cellCol];
return (hole & holetab_h[holeCol] & holetab_v[holeRow]) != 0;
}
float GridTerrainData::getMinHeight(float x, float y) const
{
if (!_loadedHeightData || !_loadedHeightData->minHeightPlanes)
return MIN_HEIGHT;
GridCoord gridCoord = Acore::ComputeGridCoordSimple(x, y);
int32 doubleGridX = int32(std::floor(-(x - MAP_HALFSIZE) / CENTER_GRID_OFFSET));
int32 doubleGridY = int32(std::floor(-(y - MAP_HALFSIZE) / CENTER_GRID_OFFSET));
float gx = x - (int32(gridCoord.x_coord) - CENTER_GRID_ID + 1) * SIZE_OF_GRIDS;
float gy = y - (int32(gridCoord.y_coord) - CENTER_GRID_ID + 1) * SIZE_OF_GRIDS;
uint32 quarterIndex = 0;
if (doubleGridY & 1)
{
if (doubleGridX & 1)
quarterIndex = 4 + (gx <= gy);
else
quarterIndex = 2 + ((-SIZE_OF_GRIDS - gx) > gy);
}
else if (doubleGridX & 1)
quarterIndex = 6 + ((-SIZE_OF_GRIDS - gx) <= gy);
else
quarterIndex = gx > gy;
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(G3D::Vector3(gx, gy, 0.0f), G3D::Vector3::unitZ());
return ray.intersection(_loadedHeightData->minHeightPlanes->at(quarterIndex)).z;
}
float GridTerrainData::getLiquidLevel(float x, float y) const
{
if (!_loadedLiquidData)
return INVALID_HEIGHT;
if (!_loadedLiquidData->liquidMap)
return _loadedLiquidData->liquidLevel;
x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
int cx_int = ((int)x & (MAP_RESOLUTION - 1)) - _loadedLiquidData->liquidOffY;
int cy_int = ((int)y & (MAP_RESOLUTION - 1)) - _loadedLiquidData->liquidOffX;
if (cx_int < 0 || cx_int >= _loadedLiquidData->liquidHeight)
return INVALID_HEIGHT;
if (cy_int < 0 || cy_int >= _loadedLiquidData->liquidWidth)
return INVALID_HEIGHT;
return _loadedLiquidData->liquidMap->at(cx_int * _loadedLiquidData->liquidWidth + cy_int);
}
// Get water state on map
LiquidData const GridTerrainData::GetLiquidData(float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) const
{
LiquidData liquidData;
if (!_loadedLiquidData)
return liquidData;
// Check water type (if no water return)
if (_loadedLiquidData->liquidGlobalFlags || _loadedLiquidData->liquidFlags)
{
// Get cell
float cx = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
float cy = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
int x_int = (int)cx & (MAP_RESOLUTION - 1);
int y_int = (int)cy & (MAP_RESOLUTION - 1);
// Check water type in cell
int idx = (x_int >> 3) * 16 + (y_int >> 3);
uint8 type = _loadedLiquidData->liquidFlags ? _loadedLiquidData->liquidFlags->at(idx) : _loadedLiquidData->liquidGlobalFlags;
uint32 entry = _loadedLiquidData->liquidEntry ? _loadedLiquidData->liquidEntry->at(idx) : _loadedLiquidData->liquidGlobalEntry;
if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(entry))
{
type &= MAP_LIQUID_TYPE_DARK_WATER;
uint32 liqTypeIdx = liquidEntry->Type;
if (entry < 21)
{
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y)))
{
uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
if (!overrideLiquid && area->zone)
{
area = sAreaTableStore.LookupEntry(area->zone);
if (area)
overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
}
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
{
entry = overrideLiquid;
liqTypeIdx = liq->Type;
}
}
}
type |= 1 << liqTypeIdx;
}
// Check req liquid type mask
if (type != 0 && (!ReqLiquidType || (ReqLiquidType & type) != 0))
{
// Check water level:
// Check water height map
int lx_int = x_int - _loadedLiquidData->liquidOffY;
int ly_int = y_int - _loadedLiquidData->liquidOffX;
if (lx_int >= 0 && lx_int < _loadedLiquidData->liquidHeight && ly_int >= 0 && ly_int < _loadedLiquidData->liquidWidth)
{
// Get water level
float liquid_level = _loadedLiquidData->liquidMap ? _loadedLiquidData->liquidMap->at(lx_int * _loadedLiquidData->liquidWidth + ly_int) : _loadedLiquidData->liquidLevel;
// Get ground level
float ground_level = getHeight(x, y);
// Check water level and ground level (sub 0.2 for fix some errors)
if (liquid_level >= ground_level && z >= ground_level - 0.2f)
{
// All ok in water -> store data
liquidData.Entry = entry;
liquidData.Flags = type;
liquidData.Level = liquid_level;
liquidData.DepthLevel = ground_level;
// For speed check as int values
float delta = liquid_level - z;
if (delta > collisionHeight)
liquidData.Status = LIQUID_MAP_UNDER_WATER;
else if (delta > 0.0f)
liquidData.Status = LIQUID_MAP_IN_WATER;
else if (delta > -0.1f)
liquidData.Status = LIQUID_MAP_WATER_WALK;
else
liquidData.Status = LIQUID_MAP_ABOVE_WATER;
}
}
}
}
return liquidData;
}
+255
View File
@@ -0,0 +1,255 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRID_TERRAIN_DATA_H
#define GRID_TERRAIN_DATA_H
#include "Common.h"
#include <fstream>
#include <G3D/Plane.h>
#include <memory>
#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface
#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE
#define MAX_FALL_DISTANCE 250000.0f // "unlimited fall" to find VMap ground if it is available, just larger than MAX_HEIGHT - INVALID_HEIGHT
#define MIN_HEIGHT -500.0f
#define MAP_LIQUID_STATUS_SWIMMING (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)
#define MAP_LIQUID_STATUS_IN_CONTACT (MAP_LIQUID_STATUS_SWIMMING | LIQUID_MAP_WATER_WALK)
#define MAP_LIQUID_TYPE_NO_WATER 0x00
#define MAP_LIQUID_TYPE_WATER 0x01
#define MAP_LIQUID_TYPE_OCEAN 0x02
#define MAP_LIQUID_TYPE_MAGMA 0x04
#define MAP_LIQUID_TYPE_SLIME 0x08
#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
// ******************************************
// Map file format defines
// ******************************************
union u_map_magic
{
char asChar[4];
uint32 asUInt;
};
const u_map_magic MapMagic = { {'M', 'A', 'P', 'S'} };
const uint32 MapVersionMagic = 9;
const u_map_magic MapAreaMagic = { {'A', 'R', 'E', 'A'} };
const u_map_magic MapHeightMagic = { {'M', 'H', 'G', 'T'} };
const u_map_magic MapLiquidMagic = { {'M', 'L', 'I', 'Q'} };
struct map_fileheader
{
uint32 mapMagic;
uint32 versionMagic;
uint32 buildMagic;
uint32 areaMapOffset;
uint32 areaMapSize;
uint32 heightMapOffset;
uint32 heightMapSize;
uint32 liquidMapOffset;
uint32 liquidMapSize;
uint32 holesOffset;
uint32 holesSize;
};
#define MAP_AREA_NO_AREA 0x0001
struct map_areaHeader
{
uint32 fourcc;
uint16 flags;
uint16 gridArea;
};
#define MAP_HEIGHT_NO_HEIGHT 0x0001
#define MAP_HEIGHT_AS_INT16 0x0002
#define MAP_HEIGHT_AS_INT8 0x0004
#define MAP_HEIGHT_HAS_FLIGHT_BOUNDS 0x0008
struct map_heightHeader
{
uint32 fourcc;
uint32 flags;
float gridHeight;
float gridMaxHeight;
};
#define MAP_LIQUID_NO_TYPE 0x0001
#define MAP_LIQUID_NO_HEIGHT 0x0002
struct map_liquidHeader
{
uint32 fourcc;
uint8 flags;
uint8 liquidFlags;
uint16 liquidType;
uint8 offsetX;
uint8 offsetY;
uint8 width;
uint8 height;
float liquidLevel;
};
// ******************************************
// Loaded map data structures
// ******************************************
struct LoadedAreaData
{
typedef std::array<uint16, 16 * 16> AreaMapType;
uint16 gridArea;
std::unique_ptr<AreaMapType> areaMap;
};
struct LoadedHeightData
{
typedef std::array<G3D::Plane, 8> HeightPlanesType;
struct Uint16HeightData
{
typedef std::array<uint16, 129 * 129> V9Type;
typedef std::array<uint16, 128 * 128> V8Type;
V9Type v9;
V8Type v8;
float gridIntHeightMultiplier;
};
struct Uint8HeightData
{
typedef std::array<uint8, 129 * 129> V9Type;
typedef std::array<uint8, 128 * 128> V8Type;
V9Type v9;
V8Type v8;
float gridIntHeightMultiplier;
};
struct FloatHeightData
{
typedef std::array<float, 129 * 129> V9Type;
typedef std::array<float, 128 * 128> V8Type;
V9Type v9;
V8Type v8;
};
float gridHeight;
std::unique_ptr<Uint16HeightData> uint16HeightData;
std::unique_ptr<Uint8HeightData> uint8HeightData;
std::unique_ptr<FloatHeightData> floatHeightData;
std::unique_ptr<HeightPlanesType> minHeightPlanes;
};
struct LoadedLiquidData
{
typedef std::array<uint16, 16 * 16> LiquidEntryType;
typedef std::array<uint8, 16 * 16> LiquidFlagsType;
typedef std::vector<float> LiquidMapType;
uint16 liquidGlobalEntry;
uint8 liquidGlobalFlags;
uint8 liquidOffX;
uint8 liquidOffY;
uint8 liquidWidth;
uint8 liquidHeight;
float liquidLevel;
std::unique_ptr<LiquidEntryType> liquidEntry;
std::unique_ptr<LiquidFlagsType> liquidFlags;
std::unique_ptr<LiquidMapType> liquidMap;
};
struct LoadedHoleData
{
typedef std::array<uint16, 16 * 16> HolesType;
HolesType holes;
};
enum LiquidStatus
{
LIQUID_MAP_NO_WATER = 0x00000000,
LIQUID_MAP_ABOVE_WATER = 0x00000001,
LIQUID_MAP_WATER_WALK = 0x00000002,
LIQUID_MAP_IN_WATER = 0x00000004,
LIQUID_MAP_UNDER_WATER = 0x00000008
};
struct LiquidData
{
LiquidData() = default;
uint32 Entry{ 0 };
uint32 Flags{ 0 };
float Level{ INVALID_HEIGHT };
float DepthLevel{ INVALID_HEIGHT };
LiquidStatus Status{ LIQUID_MAP_NO_WATER };
};
enum class TerrainMapDataReadResult
{
Success,
NotFound,
ReadError,
InvalidMagic,
InvalidAreaData,
InvalidHeightData,
InvalidLiquidData,
InvalidHoleData
};
class GridTerrainData
{
bool LoadAreaData(std::ifstream& fileStream, uint32 const offset);
bool LoadHeightData(std::ifstream& fileStream, uint32 const offset);
bool LoadLiquidData(std::ifstream& fileStream, uint32 const offset);
bool LoadHolesData(std::ifstream& fileStream, uint32 const offset);
std::unique_ptr<LoadedAreaData> _loadedAreaData;
std::unique_ptr<LoadedHeightData> _loadedHeightData;
std::unique_ptr<LoadedLiquidData> _loadedLiquidData;
std::unique_ptr<LoadedHoleData> _loadedHoleData;
bool isHole(int row, int col) const;
// Get height functions and pointers
typedef float (GridTerrainData::* GetHeightPtr) (float x, float y) const;
GetHeightPtr _gridGetHeight;
float getHeightFromFloat(float x, float y) const;
float getHeightFromUint16(float x, float y) const;
float getHeightFromUint8(float x, float y) const;
float getHeightFromFlat(float x, float y) const;
public:
GridTerrainData();
~GridTerrainData() { };
TerrainMapDataReadResult Load(std::string const& mapFileName);
uint16 getArea(float x, float y) const;
inline float getHeight(float x, float y) const { return (this->*_gridGetHeight)(x, y); }
float getMinHeight(float x, float y) const;
float getLiquidLevel(float x, float y) const;
LiquidData const GetLiquidData(float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) const;
};
#endif
+157
View File
@@ -0,0 +1,157 @@
#include "DisableMgr.h"
#include "GridTerrainLoader.h"
#include "MMapFactory.h"
#include "MMapMgr.h"
#include "ScriptMgr.h"
#include "VMapFactory.h"
#include "VMapMgr2.h"
void GridTerrainLoader::LoadTerrain()
{
LoadMap();
if (_map->GetInstanceId() == 0)
{
LoadVMap();
LoadMMap();
}
}
void GridTerrainLoader::LoadMap()
{
// Instances will point to the parent maps terrain data
if (_map->GetInstanceId() != 0)
{
// load grid map for base map
Map* parentMap = const_cast<Map*>(_map->GetParent());
// GetGridTerrainData will create the parent map grid
_grid.SetTerrainData(parentMap->GetGridTerrainDataSharedPtr(GridCoord(_grid.GetX(), _grid.GetY())));
return;
}
// map file name
std::string const mapFileName = Acore::StringFormat("{}maps/{:03}{:02}{:02}.map", sWorld->GetDataPath(), _map->GetId(), _grid.GetX(), _grid.GetY());
// loading data
LOG_DEBUG("maps", "Loading map {}", mapFileName);
std::unique_ptr<GridTerrainData> terrainData = std::make_unique<GridTerrainData>();
TerrainMapDataReadResult loadResult = terrainData->Load(mapFileName);
if (loadResult == TerrainMapDataReadResult::Success)
_grid.SetTerrainData(std::move(terrainData));
else
{
if (loadResult == TerrainMapDataReadResult::InvalidMagic)
LOG_ERROR("maps", "Map file '{}' is from an incompatible clientversion. Please recreate using the mapextractor.", mapFileName);
else
LOG_DEBUG("maps", "Error (result: {}) loading map file: {}", uint32(loadResult), mapFileName);
}
sScriptMgr->OnLoadGridMap(_map, _grid.GetTerrainData(), _grid.GetX(), _grid.GetY());
}
void GridTerrainLoader::LoadVMap()
{
int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapMgr()->loadMap((sWorld->GetDataPath() + "vmaps").c_str(), _map->GetId(), _grid.GetX(), _grid.GetY());
switch (vmapLoadResult)
{
case VMAP::VMAP_LOAD_RESULT_OK:
LOG_DEBUG("maps", "VMAP loaded name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})",
_map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY());
break;
case VMAP::VMAP_LOAD_RESULT_ERROR:
LOG_DEBUG("maps", "Could not load VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})",
_map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY());
break;
case VMAP::VMAP_LOAD_RESULT_IGNORED:
LOG_DEBUG("maps", "Ignored VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})",
_map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY());
break;
}
}
void GridTerrainLoader::LoadMMap()
{
if (!DisableMgr::IsPathfindingEnabled(_map))
return;
int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(_map->GetId(), _grid.GetX(), _grid.GetY());
switch (mmapLoadResult)
{
case MMAP::MMAP_LOAD_RESULT_OK:
LOG_DEBUG("maps", "MMAP loaded name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})",
_map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY());
break;
case MMAP::MMAP_LOAD_RESULT_ERROR:
LOG_DEBUG("maps", "Could not load MMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})",
_map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY());
break;
case MMAP::MMAP_LOAD_RESULT_IGNORED:
LOG_DEBUG("maps", "Ignored MMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})",
_map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY());
break;
}
}
bool GridTerrainLoader::ExistMap(uint32 mapid, int gx, int gy)
{
std::string const mapFileName = Acore::StringFormat("{}maps/{:03}{:02}{:02}.map", sWorld->GetDataPath(), mapid, gx, gy);
std::ifstream fileStream(mapFileName, std::ios::binary);
if (fileStream.fail())
{
LOG_DEBUG("maps", "Map file '{}': error opening file", mapFileName);
return false;
}
map_fileheader header;
if (!fileStream.read(reinterpret_cast<char*>(&header), sizeof(header)))
{
LOG_DEBUG("maps", "Map file '{}': unable to read header", mapFileName);
return false;
}
if (header.mapMagic != MapMagic.asUInt || header.versionMagic != MapVersionMagic)
{
LOG_ERROR("maps", "Map file '{}' is from an incompatible map version ({:.4u} v{}), {:.4s} v{} is expected. Please pull your source, recompile tools and recreate maps using the updated mapextractor, then replace your old map files with new files.",
mapFileName, 4, header.mapMagic, header.versionMagic, 4, MapMagic.asChar, MapVersionMagic);
return false;
}
return true;
}
bool GridTerrainLoader::ExistVMap(uint32 mapid, int gx, int gy)
{
if (VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr())
{
if (vmgr->isMapLoadingEnabled())
{
VMAP::LoadResult result = vmgr->existsMap((sWorld->GetDataPath() + "vmaps").c_str(), mapid, gx, gy);
std::string name = vmgr->getDirFileName(mapid, gx, gy);
switch (result)
{
case VMAP::LoadResult::Success:
break;
case VMAP::LoadResult::FileNotFound:
LOG_DEBUG("maps", "VMap file '{}' does not exist", (sWorld->GetDataPath() + "vmaps/" + name));
LOG_DEBUG("maps", "Please place VMAP files (*.vmtree and *.vmtile) in the vmap directory ({}), or correct the DataDir setting in your worldserver.conf file.", (sWorld->GetDataPath() + "vmaps/"));
return false;
case VMAP::LoadResult::VersionMismatch:
LOG_ERROR("maps", "VMap file '{}' couldn't be loaded", (sWorld->GetDataPath() + "vmaps/" + name));
LOG_ERROR("maps", "This is because the version of the VMap file and the version of this module are different, please re-extract the maps with the tools compiled with this module.");
return false;
}
}
}
return true;
}
void GridTerrainUnloader::UnloadTerrain()
{
// Only parent maps manage terrain data
if (_map->GetInstanceId() != 0)
return;
VMAP::VMapFactory::createOrGetVMapMgr()->unloadMap(_map->GetId(), _grid.GetX(), _grid.GetY());
MMAP::MMapFactory::createOrGetMMapMgr()->unloadMap(_map->GetId(), _grid.GetX(), _grid.GetY());
}
@@ -15,13 +15,42 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptMgr.h"
#include "ScriptMgrMacros.h"
#ifndef ACORE_GRID_TERRAIN_LOADER_H
#define ACORE_GRID_TERRAIN_LOADER_H
void ScriptMgr::OnMetricLogging()
#include "GridDefines.h"
class GridTerrainLoader
{
ExecuteScript<MetricScript>([&](MetricScript* script)
{
script->OnMetricLogging();
});
}
public:
GridTerrainLoader(MapGridType& grid, Map* map)
: _grid(grid), _map(map) { }
void LoadTerrain();
static bool ExistMap(uint32 mapid, int gx, int gy);
static bool ExistVMap(uint32 mapid, int gx, int gy);
private:
void LoadMap();
void LoadVMap();
void LoadMMap();
MapGridType& _grid;
Map* _map;
};
class GridTerrainUnloader
{
public:
GridTerrainUnloader(MapGridType& grid, Map* map)
: _grid(grid), _map(map) { }
void UnloadTerrain();
private:
MapGridType& _grid;
Map* _map;
};
#endif
+154
View File
@@ -0,0 +1,154 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MAP_GRID_H
#define MAP_GRID_H
#include "GridCell.h"
#include "GridReference.h"
class GridTerrainData;
template
<
class WORLD_OBJECT_TYPES,
class GRID_OBJECT_TYPES
>
class MapGrid
{
public:
typedef GridCell<WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> GridCellType;
MapGrid(uint16 const x, uint16 const y)
: _x(x), _y(y), _objectDataLoaded(false), _terrainData(nullptr) { }
// Unique identifier for grid
uint32 GetId() const { return _y * MAX_NUMBER_OF_GRIDS + _x; }
uint16 GetX() const { return _x; }
uint16 GetY() const { return _y; }
bool IsObjectDataLoaded() const { return _objectDataLoaded; }
void SetObjectDataLoaded() { _objectDataLoaded = true; }
template<class SPECIFIC_OBJECT> void AddWorldObject(uint16 const x, uint16 const y, SPECIFIC_OBJECT* obj)
{
GetOrCreateCell(x, y).AddWorldObject(obj);
}
template<class SPECIFIC_OBJECT> void RemoveWorldObject(uint16 const x, uint16 const y, SPECIFIC_OBJECT* obj)
{
GetOrCreateCell(x, y).RemoveWorldObject(obj);
}
template<class SPECIFIC_OBJECT> void AddGridObject(uint16 const x, uint16 const y, SPECIFIC_OBJECT* obj)
{
GetOrCreateCell(x, y).AddGridObject(obj);
}
template<class SPECIFIC_OBJECT> void RemoveGridObject(uint16 const x, uint16 const y, SPECIFIC_OBJECT* obj)
{
GetOrCreateCell(x, y).RemoveGridObject(obj);
}
// Visit all cells
template<class T, class TT>
void VisitAllCells(TypeContainerVisitor<T, TypeMapContainer<TT> >& visitor)
{
for (auto& cellX : _cells)
{
for (auto& cellY : cellX)
{
if (!cellY)
continue;
cellY->Visit(visitor);
}
}
}
// Visit single cell
template<class T, class TT>
void VisitCell(uint16 const x, uint16 const y, TypeContainerVisitor<T, TypeMapContainer<TT> >& visitor)
{
GridCellType* gridCell = GetCell(x, y);
if (!gridCell)
return;
gridCell->Visit(visitor);
}
void link(GridRefMgr<MapGrid<WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES>>* pTo)
{
_gridReference.link(pTo, this);
}
GridTerrainData* GetTerrainData() const { return _terrainData.get(); }
std::shared_ptr<GridTerrainData> GetTerrainDataSharedPtr() { return _terrainData; }
void SetTerrainData(std::shared_ptr<GridTerrainData> terrainData) { _terrainData = terrainData; }
uint32 GetCreatedCellsCount()
{
uint32 count = 0;
for (auto& cellX : _cells)
{
for (auto& cellY : cellX)
{
if (!cellY)
continue;
++count;
}
}
return count;
}
private:
// Creates and returns the cell if not already created
GridCellType& GetOrCreateCell(uint16 const x, uint16 const y)
{
GridCellType* cell = GetCell(x, y);
if (!cell)
_cells[x][y] = std::make_unique<GridCellType>();
return *_cells[x][y];
}
GridCellType* GetCell(uint16 const x, uint16 const y)
{
ASSERT(x < MAX_NUMBER_OF_CELLS && y < MAX_NUMBER_OF_CELLS);
return _cells[x][y].get();
}
GridCellType const* GetCell(uint16 const x, uint16 const y) const
{
ASSERT(x < MAX_NUMBER_OF_CELLS && y < MAX_NUMBER_OF_CELLS);
return _cells[x][y].get();
}
uint16 _x;
uint16 _y;
bool _objectDataLoaded;
std::array<std::array<std::unique_ptr<GridCellType>, MAX_NUMBER_OF_CELLS>, MAX_NUMBER_OF_CELLS> _cells; // N * N array
GridReference<MapGrid<WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES>> _gridReference;
// Instances will share a copy of the parent maps terrainData
std::shared_ptr<GridTerrainData> _terrainData;
};
#endif
+129
View File
@@ -0,0 +1,129 @@
#include "MapGridManager.h"
#include "GridObjectLoader.h"
#include "GridTerrainLoader.h"
void MapGridManager::CreateGrid(uint16 const x, uint16 const y)
{
std::lock_guard<std::mutex> guard(_gridLock);
if (IsGridCreated(x, y))
return;
std::unique_ptr<MapGridType> grid = std::make_unique<MapGridType>(x, y);
grid->link(_map);
GridTerrainLoader loader(*grid, _map);
loader.LoadTerrain();
_mapGrid[x][y] = std::move(grid);
++_createdGridsCount;
}
bool MapGridManager::LoadGrid(uint16 const x, uint16 const y)
{
MapGridType* grid = GetGrid(x, y);
if (!grid || grid->IsObjectDataLoaded())
return false;
// Must mark as loaded first, as GridObjectLoader spawning objects can attempt to recursively load the grid
grid->SetObjectDataLoaded();
GridObjectLoader loader(*grid, _map);
loader.LoadAllCellsInGrid();
++_loadedGridsCount;
return true;
}
void MapGridManager::UnloadGrid(uint16 const x, uint16 const y)
{
MapGridType* grid = GetGrid(x, y);
if (!grid)
return;
{
GridObjectCleaner worker;
TypeContainerVisitor<GridObjectCleaner, GridTypeMapContainer> visitor(worker);
grid->VisitAllCells(visitor);
}
_map->RemoveAllObjectsInRemoveList();
{
GridObjectUnloader worker;
TypeContainerVisitor<GridObjectUnloader, GridTypeMapContainer> visitor(worker);
grid->VisitAllCells(visitor);
}
GridTerrainUnloader terrainUnloader(*grid, _map);
terrainUnloader.UnloadTerrain();
_mapGrid[x][y] = nullptr;
}
bool MapGridManager::IsGridCreated(uint16 const x, uint16 const y) const
{
if (!MapGridManager::IsValidGridCoordinates(x, y))
return false;
return _mapGrid[x][y].get();
}
bool MapGridManager::IsGridLoaded(uint16 const x, uint16 const y) const
{
if (!MapGridManager::IsValidGridCoordinates(x, y))
return false;
return _mapGrid[x][y].get() && _mapGrid[x][y]->IsObjectDataLoaded();
}
MapGridType* MapGridManager::GetGrid(uint16 const x, uint16 const y)
{
if (!MapGridManager::IsValidGridCoordinates(x, y))
return nullptr;
return _mapGrid[x][y].get();
}
uint32 MapGridManager::GetCreatedGridsCount()
{
return _createdGridsCount;
}
uint32 MapGridManager::GetLoadedGridsCount()
{
return _loadedGridsCount;
}
uint32 MapGridManager::GetCreatedCellsInGridCount(uint16 const x, uint16 const y)
{
MapGridType* grid = GetGrid(x, y);
if (grid)
return grid->GetCreatedCellsCount();
return 0;
}
uint32 MapGridManager::GetCreatedCellsInMapCount()
{
uint32 count = 0;
for (uint32 gridX = 0; gridX < MAX_NUMBER_OF_GRIDS; ++gridX)
{
for (uint32 gridY = 0; gridY < MAX_NUMBER_OF_GRIDS; ++gridY)
{
if (MapGridType* grid = GetGrid(gridX, gridY))
count += grid->GetCreatedCellsCount();
}
}
return count;
}
bool MapGridManager::IsGridsFullyCreated() const
{
return _createdGridsCount == (MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS);
}
bool MapGridManager::IsGridsFullyLoaded() const
{
return _loadedGridsCount == (MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS);
}
+62
View File
@@ -0,0 +1,62 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MAP_GRID_MANAGER_H
#define MAP_GRID_MANAGER_H
#include "Common.h"
#include "GridDefines.h"
#include "MapDefines.h"
#include "MapGrid.h"
#include <mutex>
class Map;
class MapGridManager
{
public:
MapGridManager(Map* map) : _map(map), _createdGridsCount(0), _loadedGridsCount(0) { }
void CreateGrid(uint16 const x, uint16 const y);
bool LoadGrid(uint16 const x, uint16 const y);
void UnloadGrid(uint16 const x, uint16 const y);
bool IsGridCreated(uint16 const x, uint16 const y) const;
bool IsGridLoaded(uint16 const x, uint16 const y) const;
MapGridType* GetGrid(uint16 const x, uint16 const y);
static bool IsValidGridCoordinates(uint16 const x, uint16 const y) { return (x < MAX_NUMBER_OF_GRIDS && y < MAX_NUMBER_OF_GRIDS); }
uint32 GetCreatedGridsCount();
uint32 GetLoadedGridsCount();
uint32 GetCreatedCellsInGridCount(uint16 const x, uint16 const y);
uint32 GetCreatedCellsInMapCount();
bool IsGridsFullyCreated() const;
bool IsGridsFullyLoaded() const;
private:
Map* _map;
uint32 _createdGridsCount;
uint32 _loadedGridsCount;
std::mutex _gridLock;
std::unique_ptr<MapGridType> _mapGrid[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
};
#endif
-113
View File
@@ -1,113 +0,0 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACORE_NGRID_H
#define ACORE_NGRID_H
/** NGrid is nothing more than a wrapper of the Grid with an NxN cells
*/
#include "Grid.h"
#include "GridReference.h"
#include "Timer.h"
template
<
uint32 N,
class ACTIVE_OBJECT,
class WORLD_OBJECT_TYPES,
class GRID_OBJECT_TYPES
>
class NGrid
{
public:
typedef Grid<ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> GridType;
NGrid(uint32 id, int32 x, int32 y)
: i_gridId(id), i_x(x), i_y(y), i_GridObjectDataLoaded(false)
{
}
GridType& GetGridType(const uint32 x, const uint32 y)
{
ASSERT(x < N && y < N);
return i_cells[x][y];
}
[[nodiscard]] GridType const& GetGridType(const uint32 x, const uint32 y) const
{
ASSERT(x < N && y < N);
return i_cells[x][y];
}
[[nodiscard]] uint32 GetGridId() const { return i_gridId; }
[[nodiscard]] int32 getX() const { return i_x; }
[[nodiscard]] int32 getY() const { return i_y; }
void link(GridRefMgr<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> >* pTo)
{
i_Reference.link(pTo, this);
}
[[nodiscard]] bool isGridObjectDataLoaded() const { return i_GridObjectDataLoaded; }
void setGridObjectDataLoaded(bool pLoaded) { i_GridObjectDataLoaded = pLoaded; }
/*
template<class SPECIFIC_OBJECT> void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj)
{
GetGridType(x, y).AddWorldObject(obj);
}
template<class SPECIFIC_OBJECT> void RemoveWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj)
{
GetGridType(x, y).RemoveWorldObject(obj);
}
template<class SPECIFIC_OBJECT> void AddGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj)
{
GetGridType(x, y).AddGridObject(obj);
}
template<class SPECIFIC_OBJECT> void RemoveGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj)
{
GetGridType(x, y).RemoveGridObject(obj);
}
*/
// Visit all Grids (cells) in NGrid (grid)
template<class T, class TT>
void VisitAllGrids(TypeContainerVisitor<T, TypeMapContainer<TT> >& visitor)
{
for (uint32 x = 0; x < N; ++x)
for (uint32 y = 0; y < N; ++y)
GetGridType(x, y).Visit(visitor);
}
// Visit a single Grid (cell) in NGrid (grid)
template<class T, class TT>
void VisitGrid(const uint32 x, const uint32 y, TypeContainerVisitor<T, TypeMapContainer<TT> >& visitor)
{
GetGridType(x, y).Visit(visitor);
}
private:
uint32 i_gridId;
GridReference<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> > i_Reference;
int32 i_x;
int32 i_y;
GridType i_cells[N][N];
bool i_GridObjectDataLoaded;
};
#endif
@@ -24,7 +24,7 @@
#include "GameObject.h"
#include "Group.h"
#include "Object.h"
#include "ObjectGridLoader.h"
#include "GridObjectLoader.h"
#include "Optional.h"
#include "Player.h"
#include "Spell.h"
-245
View File
@@ -1,245 +0,0 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ObjectGridLoader.h"
#include "CellImpl.h"
#include "Corpse.h"
#include "Creature.h"
#include "DynamicObject.h"
#include "GameObject.h"
#include "GridNotifiers.h"
#include "ObjectMgr.h"
#include "Transport.h"
// for loading world object at grid loading (Corpses)
//TODO: to implement npc on transport, also need to load npcs at grid loading
class ObjectWorldLoader
{
public:
explicit ObjectWorldLoader(ObjectGridLoader& gloader)
: i_cell(gloader.i_cell), i_map(gloader.i_map), i_grid(gloader.i_grid), i_corpses(gloader.i_corpses)
{}
void Visit(CorpseMapType& m);
template<class T> void Visit(GridRefMgr<T>&) { }
private:
Cell i_cell;
Map* i_map;
NGridType& i_grid;
public:
uint32& i_corpses;
};
template<class T> void ObjectGridLoader::SetObjectCell(T* /*obj*/, CellCoord const& /*cellCoord*/)
{
}
template<> void ObjectGridLoader::SetObjectCell(Creature* obj, CellCoord const& cellCoord)
{
Cell cell(cellCoord);
obj->SetCurrentCell(cell);
}
template<> void ObjectGridLoader::SetObjectCell(GameObject* obj, CellCoord const& cellCoord)
{
Cell cell(cellCoord);
obj->SetCurrentCell(cell);
}
template <class T>
void AddObjectHelper(CellCoord& cell, GridRefMgr<T>& m, uint32& count, Map* /*map*/, T* obj)
{
obj->AddToGrid(m);
ObjectGridLoader::SetObjectCell(obj, cell);
obj->AddToWorld();
++count;
}
template <>
void AddObjectHelper(CellCoord& cell, CreatureMapType& m, uint32& count, Map* map, Creature* obj)
{
obj->AddToGrid(m);
ObjectGridLoader::SetObjectCell(obj, cell);
obj->AddToWorld();
if (obj->isActiveObject())
map->AddToActive(obj);
++count;
}
template <>
void AddObjectHelper(CellCoord& cell, GameObjectMapType& m, uint32& count, Map* map, GameObject* obj)
{
obj->AddToGrid(m);
ObjectGridLoader::SetObjectCell(obj, cell);
obj->AddToWorld();
if (obj->isActiveObject())
map->AddToActive(obj);
++count;
}
template <class T>
void LoadHelper(CellGuidSet const& /*guid_set*/, CellCoord& /*cell*/, GridRefMgr<T>& /*m*/, uint32& /*count*/, Map* /*map*/)
{
}
template <>
void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr<Creature>& m, uint32& count, Map* map)
{
for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid)
{
Creature* obj = new Creature();
ObjectGuid::LowType guid = *i_guid;
if (!obj->LoadFromDB(guid, map))
{
delete obj;
continue;
}
AddObjectHelper(cell, m, count, map, obj);
if (!obj->IsMoveInLineOfSightDisabled() && obj->GetDefaultMovementType() == IDLE_MOTION_TYPE && !obj->isNeedNotify(NOTIFY_VISIBILITY_CHANGED | NOTIFY_AI_RELOCATION))
{
if (obj->IsAlive() && !obj->HasUnitState(UNIT_STATE_SIGHTLESS) && obj->HasReactState(REACT_AGGRESSIVE) && !obj->IsImmuneToNPC())
{
// call MoveInLineOfSight for nearby grid creatures
Acore::AIRelocationNotifier notifier(*obj);
Cell::VisitGridObjects(obj, notifier, 60.f);
}
}
}
}
template <>
void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr<GameObject>& m, uint32& count, Map* map)
{
for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid)
{
ObjectGuid::LowType guid = *i_guid;
GameObjectData const* data = sObjectMgr->GetGameObjectData(guid);
GameObject* obj = data && sObjectMgr->IsGameObjectStaticTransport(data->id) ? new StaticTransport() : new GameObject();
if (!obj->LoadFromDB(guid, map))
{
delete obj;
continue;
}
AddObjectHelper(cell, m, count, map, obj);
}
}
void ObjectGridLoader::Visit(GameObjectMapType& m)
{
CellCoord cellCoord = i_cell.GetCellCoord();
CellObjectGuids const& cell_guids = sObjectMgr->GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cellCoord.GetId());
LoadHelper(cell_guids.gameobjects, cellCoord, m, i_gameObjects, i_map);
}
void ObjectGridLoader::Visit(CreatureMapType& m)
{
CellCoord cellCoord = i_cell.GetCellCoord();
CellObjectGuids const& cell_guids = sObjectMgr->GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cellCoord.GetId());
LoadHelper(cell_guids.creatures, cellCoord, m, i_creatures, i_map);
}
void ObjectWorldLoader::Visit(CorpseMapType& /*m*/)
{
CellCoord cellCoord = i_cell.GetCellCoord();
if (std::unordered_set<Corpse*> const* corpses = i_map->GetCorpsesInCell(cellCoord.GetId()))
{
for (Corpse* corpse : *corpses)
{
corpse->AddToWorld();
GridType& cell = i_grid.GetGridType(i_cell.CellX(), i_cell.CellY());
if (corpse->IsWorldObject())
cell.AddWorldObject(corpse);
else
cell.AddGridObject(corpse);
++i_corpses;
}
}
}
void ObjectGridLoader::LoadN(void)
{
i_gameObjects = 0;
i_creatures = 0;
i_corpses = 0;
i_cell.data.Part.cell_y = 0;
for (uint32 x = 0; x < MAX_NUMBER_OF_CELLS; ++x)
{
i_cell.data.Part.cell_x = x;
for (uint32 y = 0; y < MAX_NUMBER_OF_CELLS; ++y)
{
i_cell.data.Part.cell_y = y;
//Load creatures and game objects
{
TypeContainerVisitor<ObjectGridLoader, GridTypeMapContainer> visitor(*this);
i_grid.VisitGrid(x, y, visitor);
}
//Load corpses (not bones)
{
ObjectWorldLoader worker(*this);
TypeContainerVisitor<ObjectWorldLoader, WorldTypeMapContainer> visitor(worker);
i_grid.VisitGrid(x, y, visitor);
}
}
}
LOG_DEBUG("maps", "{} GameObjects, {} Creatures, and {} Corpses/Bones loaded for grid {} on map {}", i_gameObjects, i_creatures, i_corpses, i_grid.GetGridId(), i_map->GetId());
}
template<class T>
void ObjectGridUnloader::Visit(GridRefMgr<T>& m)
{
while (!m.IsEmpty())
{
T* obj = m.getFirst()->GetSource();
// if option set then object already saved at this moment
//if (!sWorld->getBoolConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY))
// obj->SaveRespawnTime();
//Some creatures may summon other temp summons in CleanupsBeforeDelete()
//So we need this even after cleaner (maybe we can remove cleaner)
//Example: Flame Leviathan Turret 33139 is summoned when a creature is deleted
//TODO: Check if that script has the correct logic. Do we really need to summons something before deleting?
obj->CleanupsBeforeDelete();
///- object will get delinked from the manager when deleted
delete obj;
}
}
template<class T>
void ObjectGridCleaner::Visit(GridRefMgr<T>& m)
{
for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
iter->GetSource()->CleanupsBeforeDelete();
}
template void ObjectGridUnloader::Visit(CreatureMapType&);
template void ObjectGridUnloader::Visit(GameObjectMapType&);
template void ObjectGridUnloader::Visit(DynamicObjectMapType&);
template void ObjectGridCleaner::Visit(CreatureMapType&);
template void ObjectGridCleaner::Visit<GameObject>(GameObjectMapType&);
template void ObjectGridCleaner::Visit<DynamicObject>(DynamicObjectMapType&);
template void ObjectGridCleaner::Visit<Corpse>(CorpseMapType&);
+2 -2
View File
@@ -1478,7 +1478,7 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap)
AllowedLooterSet looters = item->GetAllowedLooters();
Item* _item = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters);
if (_item)
sScriptMgr->OnGroupRollRewardItem(player, _item, _item->GetCount(), NEED, roll);
sScriptMgr->OnPlayerGroupRollRewardItem(player, _item, _item->GetCount(), NEED, roll);
player->UpdateLootAchievements(item, roll->getLoot());
}
else
@@ -1548,7 +1548,7 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap)
AllowedLooterSet looters = item->GetAllowedLooters();
Item* _item = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters);
if (_item)
sScriptMgr->OnGroupRollRewardItem(player, _item, _item->GetCount(), GREED, roll);
sScriptMgr->OnPlayerGroupRollRewardItem(player, _item, _item->GetCount(), GREED, roll);
player->UpdateLootAchievements(item, roll->getLoot());
}
else
+4 -1
View File
@@ -1585,11 +1585,14 @@ void Guild::HandleRemoveMember(WorldSession* session, std::string_view name)
SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_RANK_TOO_HIGH_S, name);
else
{
// Copy values since everything will be deleted in DeleteMember().
ObjectGuid guid = member->GetGUID();
std::string memberName = member->GetName();
// After call to DeleteMember pointer to member becomes invalid
DeleteMember(guid, false, true);
_LogEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, player->GetGUID(), guid);
_BroadcastEvent(GE_REMOVED, ObjectGuid::Empty, member->GetName(), player->GetName());
_BroadcastEvent(GE_REMOVED, ObjectGuid::Empty, memberName, player->GetName());
}
}
}
@@ -417,7 +417,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
AuctionEntry* auction = auctionHouse->GetAuction(auctionId);
Player* player = GetPlayer();
if (!sScriptMgr->CanPlaceAuctionBid(player, auction))
if (!sScriptMgr->OnPlayerCanPlaceAuctionBid(player, auction))
{
SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_RESTRICTED_ACCOUNT);
return;
+6 -1
View File
@@ -26,7 +26,12 @@ void WorldSession::SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos)
packet << uint32(0); // BillingTimeRemaining
packet << uint8(0); // BillingPlanFlags
packet << uint32(0); // BillingTimeRested
packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, must be set in database manually for each account
uint8 exp = Expansion(); // 0 - normal, 1 - TBC, 2 - WOTLK, must be set in database manually for each account
if (exp >= MAX_EXPANSIONS)
exp = MAX_EXPANSIONS - 1;
packet << uint8(exp);
if (!shortForm)
{
@@ -17,6 +17,7 @@
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h"
#include "ArenaSeasonMgr.h"
#include "Battleground.h"
#include "BattlegroundMgr.h"
#include "Chat.h"
@@ -139,7 +140,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
// queue result (default ok)
GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult(bg->GetBgTypeID());
if (!sScriptMgr->CanJoinInBattlegroundQueue(_player, guid, bgTypeId, joinAsGroup, err) && err <= 0)
if (!sScriptMgr->OnPlayerCanJoinInBattlegroundQueue(_player, guid, bgTypeId, joinAsGroup, err) && err <= 0)
{
WorldPacket data;
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
@@ -423,7 +424,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData)
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenaType);
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
if (!sScriptMgr->CanBattleFieldPort(_player, arenaType, bgTypeId, action))
if (!sScriptMgr->OnPlayerCanBattleFieldPort(_player, arenaType, bgTypeId, action))
return;
// get group info from queue
@@ -578,11 +579,11 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData)
CharacterDatabase.Execute(stmt);
}
sScriptMgr->OnBattlegroundDesertion(_player, BG_DESERTION_TYPE_LEAVE_QUEUE);
sScriptMgr->OnPlayerBattlegroundDesertion(_player, BG_DESERTION_TYPE_LEAVE_QUEUE);
}
if (bg->isArena() && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN))
sScriptMgr->OnBattlegroundDesertion(_player, ARENA_DESERTION_TYPE_LEAVE_QUEUE);
sScriptMgr->OnPlayerBattlegroundDesertion(_player, ARENA_DESERTION_TYPE_LEAVE_QUEUE);
}
}
@@ -747,7 +748,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
// queue result (default ok)
GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult(bgt->GetBgTypeID());
if (!sScriptMgr->CanJoinInArenaQueue(_player, guid, arenaslot, bgTypeId, asGroup, isRated, err) && err <= 0)
if (!sScriptMgr->OnPlayerCanJoinInArenaQueue(_player, guid, arenaslot, bgTypeId, asGroup, isRated, err) && err <= 0)
{
WorldPacket data;
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
@@ -812,7 +813,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
if (isRated)
{
// pussywizard: for rated matches check if season is in progress!
if (!sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS))
if (sArenaSeasonMgr->GetSeasonState() == ARENA_SEASON_STATE_DISABLED)
return;
ateamId = _player->GetArenaTeamId(arenaslot);
+10 -9
View File
@@ -57,6 +57,7 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldSessionMgr.h"
LoginQueryHolder::LoginQueryHolder(uint32 accountId, ObjectGuid guid) : m_accountId(accountId), m_guid(guid)
{
@@ -607,7 +608,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
uint32 initAccountId = GetAccountId();
// can't delete loaded character
if (ObjectAccessor::FindConnectedPlayer(guid) || sWorld->FindOfflineSessionForCharacterGUID(guid.GetCounter()))
if (ObjectAccessor::FindConnectedPlayer(guid) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(guid.GetCounter()))
{
sScriptMgr->OnPlayerFailedDelete(guid, initAccountId);
return;
@@ -693,14 +694,14 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
};
// pussywizard:
if (WorldSession* sess = sWorld->FindOfflineSessionForCharacterGUID(playerGuid.GetCounter()))
if (WorldSession* sess = sWorldSessionMgr->FindOfflineSessionForCharacterGUID(playerGuid.GetCounter()))
if (sess->GetAccountId() != GetAccountId())
{
SendCharLogin(CHAR_LOGIN_DUPLICATE_CHARACTER);
return;
}
// pussywizard:
if (WorldSession* sess = sWorld->FindOfflineSession(GetAccountId()))
if (WorldSession* sess = sWorldSessionMgr->FindOfflineSession(GetAccountId()))
{
Player* p = sess->GetPlayer();
if (!p || sess->IsKicked())
@@ -956,7 +957,7 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
if (sWorld->IsFFAPvPRealm() && !pCurrChar->IsGameMaster() && !pCurrChar->HasPlayerFlag(PLAYER_FLAGS_RESTING))
if (!pCurrChar->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
sScriptMgr->OnFfaPvpStateUpdate(pCurrChar,true);
sScriptMgr->OnPlayerFfaPvpStateUpdate(pCurrChar,true);
pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
}
@@ -1096,7 +1097,7 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
{
bool isReferrer = pCurrChar->GetSession()->IsARecruiter();
for (auto const& [accID, session] : sWorld->GetAllSessions())
for (auto const& [accID, session] : sWorldSessionMgr->GetAllSessions())
{
if (!session->GetRecruiterId() && !session->IsARecruiter())
continue;
@@ -1118,7 +1119,7 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST))
{
pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST);
sScriptMgr->OnFirstLogin(pCurrChar);
sScriptMgr->OnPlayerFirstLogin(pCurrChar);
}
METRIC_EVENT("player_events", "Login", pCurrChar->GetName());
@@ -1385,7 +1386,7 @@ void WorldSession::HandleCharRenameCallBack(std::shared_ptr<CharacterRenameInfo>
atLoginFlags &= ~AT_LOGIN_RENAME;
// pussywizard:
if (ObjectAccessor::FindConnectedPlayer(ObjectGuid::Create<HighGuid::Player>(guidLow)) || sWorld->FindOfflineSessionForCharacterGUID(guidLow))
if (ObjectAccessor::FindConnectedPlayer(ObjectGuid::Create<HighGuid::Player>(guidLow)) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(guidLow))
{
SendCharRename(CHAR_CREATE_ERROR, renameInfo.get());
return;
@@ -1621,7 +1622,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
}
// pussywizard:
if (ObjectAccessor::FindConnectedPlayer(customizeInfo->Guid) || sWorld->FindOfflineSessionForCharacterGUID(customizeInfo->Guid.GetCounter()))
if (ObjectAccessor::FindConnectedPlayer(customizeInfo->Guid) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(customizeInfo->Guid.GetCounter()))
{
recvData.rfinish();
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
@@ -1923,7 +1924,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
>> factionChangeInfo->Race;
// pussywizard:
if (ObjectAccessor::FindConnectedPlayer(factionChangeInfo->Guid) || sWorld->FindOfflineSessionForCharacterGUID(factionChangeInfo->Guid.GetCounter()))
if (ObjectAccessor::FindConnectedPlayer(factionChangeInfo->Guid) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(factionChangeInfo->Guid.GetCounter()))
{
SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;

Some files were not shown because too many files have changed in this diff Show More