Merge branch 'master' of github.com:azerothcore/azerothcore-wotlk into Playerbot

This commit is contained in:
Yunfan Li
2023-10-22 19:52:23 +08:00
203 changed files with 7031 additions and 2667 deletions
@@ -200,7 +200,6 @@ void npc_escortAI::ReturnToLastPoint()
void npc_escortAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->RemoveAllAuras();
me->GetThreatMgr().ClearAllThreat();
me->CombatStop(true);
me->SetLootRecipient(nullptr);
@@ -1041,7 +1041,7 @@ const WintergraspTowerCannonData TowerCannon[WG_MAX_TOWER_CANNON] =
2,
{
{ 4448.138184f, 1974.998779f, 441.995911f, 1.967238f },
{ 4448.713379f, 1955.148682f, 441.995178f, 0.380733f },
{ 4486.3257f, 1954.6545f, 442.0783f, 0.349065840244293212f },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
+13 -3
View File
@@ -242,6 +242,7 @@ void Arena::EndBattleground(TeamId winnerTeamId)
uint8 memberId = 0;
for (auto const& [playerGuid, arenaLogEntryData] : ArenaLogEntries)
{
auto const& score = PlayerScores.find(playerGuid.GetCounter());
stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_LOG_MEMBERSTATS);
stmt2->SetData(0, fightId);
stmt2->SetData(1, ++memberId);
@@ -250,9 +251,18 @@ void Arena::EndBattleground(TeamId winnerTeamId)
stmt2->SetData(4, arenaLogEntryData.ArenaTeamId);
stmt2->SetData(5, arenaLogEntryData.Acc);
stmt2->SetData(6, arenaLogEntryData.IP);
stmt2->SetData(7, arenaLogEntryData.DamageDone);
stmt2->SetData(8, arenaLogEntryData.HealingDone);
stmt2->SetData(9, arenaLogEntryData.KillingBlows);
if (score != PlayerScores.end())
{
stmt2->SetData(7, score->second->GetDamageDone());
stmt2->SetData(8, score->second->GetHealingDone());
stmt2->SetData(9, score->second->GetKillingBlows());
}
else
{
stmt2->SetData(7, 0);
stmt2->SetData(8, 0);
stmt2->SetData(9, 0);
}
trans->Append(stmt2);
}
+1 -1
View File
@@ -63,4 +63,4 @@ private:
void EndBattleground(TeamId winnerTeamId) override;
};
#endif // WARHEAD_ARENA_H
#endif // ACORE_ARENA_H
+1 -1
View File
@@ -72,4 +72,4 @@ protected:
std::string TeamName{};
};
#endif // WARHEAD_ARENA_SCORE_H
#endif // ACORE_ARENA_SCORE_H
@@ -268,9 +268,6 @@ public:
uint32 Acc{0};
uint32 ArenaTeamId{0};
std::string IP{};
uint32 DamageDone{0};
uint32 HealingDone{0};
uint32 KillingBlows{0};
};
enum BGHonorMode
@@ -551,6 +551,6 @@ void BattlegroundAB::ApplyPhaseMask()
for (auto const& itr : bgPlayerMap)
{
itr.second->SetPhaseMask(phaseMask, false);
itr.second->UpdateObjectVisibility(true, false);
itr.second->UpdateObjectVisibility(true);
}
}
+18 -4
View File
@@ -289,8 +289,22 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
}
case CONDITION_NEAR_GAMEOBJECT:
{
condMeets = static_cast<bool>(GetClosestGameObjectWithEntry(object, ConditionValue1, static_cast<float>(ConditionValue2)));
break;
if (!ConditionValue3)
{
condMeets = static_cast<bool>(GetClosestGameObjectWithEntry(object, ConditionValue1, static_cast<float>(ConditionValue2)));
break;
}
else
{
if (GameObject* go = GetClosestGameObjectWithEntry(object, ConditionValue1, static_cast<float>(ConditionValue2)))
{
if ((go->GetGoState() == GO_STATE_READY && ConditionValue3 == 1) || (go->GetGoState() != GO_STATE_READY && ConditionValue3 == 2))
condMeets = true;
else
condMeets = false;
}
break;
}
}
case CONDITION_OBJECT_ENTRY_GUID:
{
@@ -2124,8 +2138,8 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
LOG_ERROR("sql.sql", "NearGameObject condition has non existing gameobject template entry ({}), skipped", cond->ConditionValue1);
return false;
}
if (cond->ConditionValue3)
LOG_ERROR("sql.sql", "NearGameObject condition has useless data in value3 ({})!", cond->ConditionValue3);
if (cond->ConditionValue3 > 2)
LOG_ERROR("sql.sql", "NearGameObject condition for gameobject ID ({}) has data over 2 for value3 ({})!", cond->ConditionValue1, cond->ConditionValue3);
break;
}
case CONDITION_OBJECT_ENTRY_GUID:
+1 -1
View File
@@ -62,7 +62,7 @@ enum ConditionTypes
CONDITION_LEVEL = 27, // level ComparisonType 0 true if unit's level is equal to param1 (param2 can modify the statement)
CONDITION_QUEST_COMPLETE = 28, // quest_id 0 0 true if player has quest_id with all objectives complete, but not yet rewarded
CONDITION_NEAR_CREATURE = 29, // creature entry distance dead true if there is a creature of entry in range
CONDITION_NEAR_GAMEOBJECT = 30, // gameobject entry distance 0 true if there is a gameobject of entry in range
CONDITION_NEAR_GAMEOBJECT = 30, // gameobject entry distance GoState true if there is a gameobject of entry in range (param3 can check for GoState, 0 = dont't check, 1 = Ready , 2 = Not Ready)
CONDITION_OBJECT_ENTRY_GUID = 31, // TypeID entry guid/Attackable true if object is type TypeID and the entry is 0 or matches entry of the object or matches guid of the object
CONDITION_TYPE_MASK = 32, // TypeMask 0 0 true if object is type object's TypeMask matches provided TypeMask
CONDITION_RELATION_TO = 33, // ConditionTarget RelationType 0 true if object is in given relation with object specified by ConditionTarget
+26 -19
View File
@@ -365,17 +365,15 @@ void Creature::RemoveCorpse(bool setSpawnTime, bool skipVisibility)
//SaveRespawnTime();
}
float x, y, z, o;
GetRespawnPosition(x, y, z, &o);
SetHomePosition(x, y, z, o);
SetPosition(x, y, z, o);
// xinef: relocate notifier
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
// pussywizard: if corpse was removed during falling then the falling will continue after respawn, so stop falling is such case
if (IsFalling())
StopMoving();
float x, y, z, o;
GetRespawnPosition(x, y, z, &o);
UpdateAllowedPositionZ(x, y, z);
SetHomePosition(x, y, z, o);
GetMap()->CreatureRelocation(this, x, y, z, o);
}
/**
@@ -537,7 +535,7 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele
SetMeleeDamageSchool(SpellSchools(cInfo->dmgschool));
CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(GetLevel(), cInfo->unit_class);
float armor = (float)stats->GenerateArmor(cInfo); /// @todo: Why is this treated as uint32 when it's a float?
float armor = stats->GenerateArmor(cInfo);
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, armor);
SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY]));
SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE]));
@@ -580,13 +578,13 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele
ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
}
if (GetMovementTemplate().IsRooted())
{
SetControlled(true, UNIT_STATE_ROOT);
}
SetDetectionDistance(cInfo->detection_range);
// Update movement
if (IsRooted())
SetControlled(true, UNIT_STATE_ROOT);
UpdateMovementFlags();
LoadSpellTemplateImmunity();
if (updateAI)
@@ -1489,6 +1487,9 @@ void Creature::SelectLevel(bool changelevel)
uint8 minlevel = std::min(cInfo->maxlevel, cInfo->minlevel);
uint8 maxlevel = std::max(cInfo->maxlevel, cInfo->minlevel);
uint8 level = minlevel == maxlevel ? minlevel : urand(minlevel, maxlevel);
sScriptMgr->OnBeforeCreatureSelectLevel(cInfo, this, level);
if (changelevel)
SetLevel(level);
@@ -2078,9 +2079,7 @@ void Creature::Respawn(bool force)
m_respawnedTime = GameTime::GetGameTime().count();
}
m_respawnedTime = GameTime::GetGameTime().count();
// xinef: relocate notifier, fixes npc appearing in corpse position after forced respawn (instead of spawn)
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
UpdateObjectVisibility(false);
UpdateObjectVisibility();
}
void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer)
@@ -2753,6 +2752,14 @@ bool Creature::IsSpellProhibited(SpellSchoolMask idSchoolMask) const
return false;
}
void Creature::ClearProhibitedSpellTimers()
{
for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i)
{
m_ProhibitSchoolTime[i] = 0;
}
}
void Creature::_AddCreatureSpellCooldown(uint32 spell_id, uint16 categoryId, uint32 end_time)
{
CreatureSpellCooldown spellCooldown;
@@ -3110,7 +3117,7 @@ bool Creature::SetDisableGravity(bool disable, bool packetOnly /*= false*/, bool
return true;
}
if (updateAnimationTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT) && !GetMovementTemplate().IsRooted())
if (updateAnimationTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT) && !IsRooted())
{
if (IsLevitating())
SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_FLY);
@@ -3259,7 +3266,7 @@ bool Creature::SetHover(bool enable, bool packetOnly /*= false*/, bool updateAni
if (!packetOnly && !Unit::SetHover(enable))
return false;
if (updateAnimationTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT) && !GetMovementTemplate().IsRooted())
if (updateAnimationTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT) && !IsRooted())
{
if (IsLevitating())
SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_FLY);
@@ -82,6 +82,7 @@ public:
[[nodiscard]] bool CanEnterWater() const override;
[[nodiscard]] bool CanFly() const override { return GetMovementTemplate().IsFlightAllowed() || IsFlying(); }
[[nodiscard]] bool CanHover() const { return GetMovementTemplate().Ground == CreatureGroundMovementType::Hover || IsHovering(); }
[[nodiscard]] bool IsRooted() const { return GetMovementTemplate().IsRooted(); }
MovementGeneratorType GetDefaultMovementType() const override { return m_defaultMovementType; }
void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; }
@@ -165,6 +166,7 @@ public:
[[nodiscard]] uint32 GetSpellCooldown(uint32 spell_id) const;
void ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) override;
[[nodiscard]] bool IsSpellProhibited(SpellSchoolMask idSchoolMask) const;
void ClearProhibitedSpellTimers();
[[nodiscard]] bool HasSpell(uint32 spellID) const override;
@@ -292,7 +292,7 @@ struct CreatureBaseStats
{
uint32 BaseHealth[MAX_EXPANSIONS];
uint32 BaseMana;
uint32 BaseArmor;
float BaseArmor;
uint32 AttackPower;
uint32 RangedAttackPower;
float BaseDamage[MAX_EXPANSIONS];
@@ -313,9 +313,9 @@ struct CreatureBaseStats
return uint32(std::ceil(BaseMana * info->ModMana));
}
uint32 GenerateArmor(CreatureTemplate const* info) const
float GenerateArmor(CreatureTemplate const* info) const
{
return uint32(std::ceil(BaseArmor * info->ModArmor));
return std::ceil(BaseArmor * info->ModArmor);
}
float GenerateBaseDamage(CreatureTemplate const* info) const
@@ -2280,7 +2280,14 @@ void GameObject::ModifyHealth(int32 change, Unit* attackerOrHealer /*= nullptr*/
if (!IsDestructibleBuilding())
return;
if (!m_goValue.Building.MaxHealth || !change)
// if this building doesn't have health, return
if (!m_goValue.Building.MaxHealth)
return;
sScriptMgr->OnGameObjectModifyHealth(this, attackerOrHealer, change, sSpellMgr->GetSpellInfo(spellId));
// if the health isn't being changed, return
if (!change)
return;
if (!m_allowModifyDestructibleBuilding)
+3 -24
View File
@@ -65,7 +65,7 @@ constexpr float VisibilityDistances[AsUnderlyingType(VisibilityDistanceType::Max
VISIBILITY_DISTANCE_SMALL,
VISIBILITY_DISTANCE_LARGE,
VISIBILITY_DISTANCE_GIGANTIC,
VISIBILITY_DISTANCE_INFINITE
MAX_VISIBILITY_DISTANCE
};
Object::Object() : m_PackGUID(sizeof(uint64) + 1)
@@ -2922,7 +2922,7 @@ void WorldObject::DestroyForNearbyPlayers()
}
}
void WorldObject::UpdateObjectVisibility(bool /*forced*/, bool /*fromUpdate*/)
void WorldObject::UpdateObjectVisibility(bool /*forced*/)
{
//updates object's visibility for nearby players
Acore::VisibleChangesNotifier notifier(*this);
@@ -2931,28 +2931,7 @@ void WorldObject::UpdateObjectVisibility(bool /*forced*/, bool /*fromUpdate*/)
void WorldObject::AddToNotify(uint16 f)
{
if (!(m_notifyflags & f))
if (Unit* u = ToUnit())
{
if (f & NOTIFY_VISIBILITY_CHANGED)
{
uint32 EVENT_VISIBILITY_DELAY = u->FindMap() ? DynamicVisibilityMgr::GetVisibilityNotifyDelay(u->FindMap()->GetEntry()->map_type) : 1000;
uint32 diff = getMSTimeDiff(u->m_last_notify_mstime, GameTime::GetGameTimeMS().count());
if (diff >= EVENT_VISIBILITY_DELAY / 2)
EVENT_VISIBILITY_DELAY /= 2;
else
EVENT_VISIBILITY_DELAY -= diff;
u->m_delayed_unit_relocation_timer = EVENT_VISIBILITY_DELAY;
u->m_last_notify_mstime = GameTime::GetGameTimeMS().count() + EVENT_VISIBILITY_DELAY - 1;
}
else if (f & NOTIFY_AI_RELOCATION)
{
u->m_delayed_unit_ai_notify_timer = u->FindMap() ? DynamicVisibilityMgr::GetAINotifyDelay(u->FindMap()->GetEntry()->map_type) : 500;
}
m_notifyflags |= f;
}
m_notifyflags |= f;
}
struct WorldObjectChangeAccumulator
+13 -4
View File
@@ -379,14 +379,23 @@ class MovableMapObject
template<class T> friend class RandomMovementGenerator;
protected:
MovableMapObject() = default;
MovableMapObject() : _moveState(MAP_OBJECT_CELL_MOVE_NONE)
{
_newPosition.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
}
private:
Cell _currentCell;
[[nodiscard]] Cell const& GetCurrentCell() const { return _currentCell; }
void SetCurrentCell(Cell const& cell) { _currentCell = cell; }
Cell _currentCell;
MapObjectCellMoveState _moveState{MAP_OBJECT_CELL_MOVE_NONE};
MapObjectCellMoveState _moveState;
Position _newPosition;
void SetNewCellPosition(float x, float y, float z, float o)
{
_moveState = MAP_OBJECT_CELL_MOVE_ACTIVE;
_newPosition.Relocate(x, y, z, o);
}
};
class WorldObject : public Object, public WorldLocation
@@ -538,7 +547,7 @@ public:
void GetDeadCreatureListInGrid(std::list<Creature*>& lList, float maxSearchRange, bool alive = false) const;
void DestroyForNearbyPlayers();
virtual void UpdateObjectVisibility(bool forced = true, bool fromUpdate = false);
virtual void UpdateObjectVisibility(bool forced = true);
void BuildUpdate(UpdateDataMapType& data_map, UpdatePlayerSet& player_set) override;
void GetCreaturesWithEntryInRange(std::list<Creature*>& creatureList, float radius, uint32 entry);
@@ -28,16 +28,15 @@
#define VISIBILITY_INC_FOR_GOBJECTS 30.0f // pussywizard
#define SPELL_SEARCHER_COMPENSATION 30.0f // increase searchers size in case we have large npc near cell border
#define TRADE_DISTANCE 11.11f
#define MAX_VISIBILITY_DISTANCE 250.0f // max distance for visible objects, experimental
#define MAX_VISIBILITY_DISTANCE SIZE_OF_GRIDS // max distance for visible objects, experimental
#define SIGHT_RANGE_UNIT 50.0f
#define MAX_SEARCHER_DISTANCE 150.0f // pussywizard: replace the use of MAX_VISIBILITY_DISTANCE in searchers, because MAX_VISIBILITY_DISTANCE is quite too big for this purpose
#define VISIBILITY_DISTANCE_INFINITE 533.0f
#define VISIBILITY_DISTANCE_GIGANTIC 400.0f
#define VISIBILITY_DISTANCE_LARGE 200.0f
#define VISIBILITY_DISTANCE_NORMAL 100.0f
#define VISIBILITY_DISTANCE_SMALL 50.0f
#define VISIBILITY_DISTANCE_TINY 25.0f
#define DEFAULT_VISIBILITY_DISTANCE 100.0f // default visible distance, 100 yards on continents
#define DEFAULT_VISIBILITY_DISTANCE VISIBILITY_DISTANCE_NORMAL // default visible distance, 100 yards on continents
#define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards
#define VISIBILITY_DIST_WINTERGRASP 175.0f
#define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards
+3 -1
View File
@@ -1294,6 +1294,8 @@ uint8 Player::GetChatTag() const
tag |= CHAT_TAG_DND;
if (isAFK())
tag |= CHAT_TAG_AFK;
if (IsCommentator())
tag |= CHAT_TAG_COM;
if (IsDeveloper())
tag |= CHAT_TAG_DEV;
@@ -4653,7 +4655,7 @@ void Player::DurabilityLossAll(double percent, bool inventory)
void Player::DurabilityLoss(Item* item, double percent)
{
if(!item)
if(!item || percent == 0.0)
return;
uint32 pMaxDurability = item ->GetUInt32Value(ITEM_FIELD_MAXDURABILITY);
+5 -3
View File
@@ -839,7 +839,7 @@ enum PlayerChatTag
CHAT_TAG_AFK = 0x01,
CHAT_TAG_DND = 0x02,
CHAT_TAG_GM = 0x04,
CHAT_TAG_COM = 0x08, // Commentator
CHAT_TAG_COM = 0x08, // Commentator tag. Do not exist in clean client
CHAT_TAG_DEV = 0x10,
};
@@ -1139,6 +1139,8 @@ public:
void SendTaxiNodeStatusMultiple();
// mount_id can be used in scripting calls
[[nodiscard]] bool IsCommentator() const { return HasPlayerFlag(PLAYER_FLAGS_COMMENTATOR2); }
void SetCommentator(bool on) { ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_COMMENTATOR2, on); }
[[nodiscard]] bool IsDeveloper() const { return HasPlayerFlag(PLAYER_FLAGS_DEVELOPER); }
void SetDeveloper(bool on) { ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_DEVELOPER, on); }
[[nodiscard]] bool isAcceptWhispers() const { return m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS; }
@@ -1553,6 +1555,7 @@ public:
void SaveToDB(CharacterDatabaseTransaction trans, bool create, bool logout);
void SaveInventoryAndGoldToDB(CharacterDatabaseTransaction trans); // fast save function for item/money cheating preventing
void SaveGoldToDB(CharacterDatabaseTransaction trans);
void _SaveSkills(CharacterDatabaseTransaction trans);
static void Customize(CharacterCustomizeInfo const* customizeInfo, CharacterDatabaseTransaction trans);
static void SavePositionInDB(uint32 mapid, float x, float y, float z, float o, uint32 zone, ObjectGuid guid);
@@ -2349,7 +2352,7 @@ public:
bool IsVisibleGloballyFor(Player const* player) const;
void GetInitialVisiblePackets(Unit* target);
void UpdateObjectVisibility(bool forced = true, bool fromUpdate = false) override;
void UpdateObjectVisibility(bool forced = true) override;
void UpdateVisibilityForPlayer(bool mapChange = false);
void UpdateVisibilityOf(WorldObject* target);
void UpdateTriggerVisibility();
@@ -2696,7 +2699,6 @@ public:
void _SaveWeeklyQuestStatus(CharacterDatabaseTransaction trans);
void _SaveMonthlyQuestStatus(CharacterDatabaseTransaction trans);
void _SaveSeasonalQuestStatus(CharacterDatabaseTransaction trans);
void _SaveSkills(CharacterDatabaseTransaction trans);
void _SaveSpells(CharacterDatabaseTransaction trans);
void _SaveEquipmentSets(CharacterDatabaseTransaction trans);
void _SaveEntryPoint(CharacterDatabaseTransaction trans);
@@ -413,14 +413,6 @@ void Player::Update(uint32 p_time)
TeleportTo(teleportStore_dest, teleportStore_options);
}
if (!IsBeingTeleported() && bRequestForcedVisibilityUpdate)
{
bRequestForcedVisibilityUpdate = false;
UpdateObjectVisibility(true, true);
m_delayed_unit_relocation_timer = 0;
RemoveFromNotify(NOTIFY_VISIBILITY_CHANGED);
}
sScriptMgr->OnAfterPlayerUpdate(this, p_time);
}
@@ -1552,23 +1544,13 @@ void Player::UpdateVisibilityForPlayer(bool mapChange)
m_seer = this;
}
Acore::VisibleNotifier notifierNoLarge(
*this, mapChange,
false); // visit only objects which are not large; default distance
Cell::VisitAllObjects(m_seer, notifierNoLarge,
GetSightRange() + VISIBILITY_INC_FOR_GOBJECTS);
notifierNoLarge.SendToSelf();
Acore::VisibleNotifier notifierLarge(
*this, mapChange, true); // visit only large objects; maximum distance
Cell::VisitAllObjects(m_seer, notifierLarge, GetSightRange());
notifierLarge.SendToSelf();
if (mapChange)
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
// updates visibility of all objects around point of view for current player
Acore::VisibleNotifier notifier(*this, mapChange);
Cell::VisitAllObjects(m_seer, notifier, GetSightRange());
notifier.SendToSelf(); // send gathered data
}
void Player::UpdateObjectVisibility(bool forced, bool fromUpdate)
void Player::UpdateObjectVisibility(bool forced)
{
// Prevent updating visibility if player is not in world (example: LoadFromDB sets drunkstate which updates invisibility while player is not in map)
if (!IsInWorld())
@@ -1578,11 +1560,6 @@ void Player::UpdateObjectVisibility(bool forced, bool fromUpdate)
AddToNotify(NOTIFY_VISIBILITY_CHANGED);
else if (!isBeingLoaded())
{
if (!fromUpdate) // pussywizard:
{
bRequestForcedVisibilityUpdate = true;
return;
}
Unit::UpdateObjectVisibility(true);
UpdateVisibilityForPlayer();
}
+11 -165
View File
@@ -317,12 +317,6 @@ Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject),
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
m_last_notify_mstime = 0;
m_delayed_unit_relocation_timer = 0;
m_delayed_unit_ai_notify_timer = 0;
bRequestForcedVisibilityUpdate = false;
m_applyResilience = false;
_instantCast = false;
@@ -411,32 +405,6 @@ void Unit::Update(uint32 p_time)
if (!IsInWorld())
return;
// pussywizard:
if (GetTypeId() != TYPEID_PLAYER || (!ToPlayer()->IsBeingTeleported() && !bRequestForcedVisibilityUpdate))
{
if (m_delayed_unit_relocation_timer)
{
if (m_delayed_unit_relocation_timer <= p_time)
{
m_delayed_unit_relocation_timer = 0;
//ExecuteDelayedUnitRelocationEvent();
FindMap()->i_objectsForDelayedVisibility.insert(this);
}
else
m_delayed_unit_relocation_timer -= p_time;
}
if (m_delayed_unit_ai_notify_timer)
{
if (m_delayed_unit_ai_notify_timer <= p_time)
{
m_delayed_unit_ai_notify_timer = 0;
ExecuteDelayedUnitAINotifyEvent();
}
else
m_delayed_unit_ai_notify_timer -= p_time;
}
}
_UpdateSpells( p_time );
if (CanHaveThreatList() && GetThreatMgr().isNeedUpdateToClient(p_time))
@@ -8191,13 +8159,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
CastCustomSpell(this, triggered_spell_id, &basepoints0, nullptr, nullptr, true, castItem, triggeredByAura, originalCaster);
break;
}
// Shaman T8 Elemental 4P Bonus
case 64928:
{
basepoints0 = CalculatePct(int32(damage), triggerAmount);
triggered_spell_id = 64930; // Electrified
break;
}
// Shaman T9 Elemental 4P Bonus
case 67228:
{
@@ -17541,13 +17502,17 @@ void Unit::SetContestedPvP(Player* attackedPlayer, bool lookForNearContestedGuar
player->AddUnitState(UNIT_STATE_ATTACK_PLAYER);
player->SetPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP);
// call MoveInLineOfSight for nearby contested guards
AddToNotify(NOTIFY_AI_RELOCATION);
Acore::AIRelocationNotifier notifier(*this);
Cell::VisitWorldObjects(this, notifier, GetVisibilityRange());
}
if (!HasUnitState(UNIT_STATE_ATTACK_PLAYER))
for (Unit* unit : m_Controlled)
{
AddUnitState(UNIT_STATE_ATTACK_PLAYER);
// call MoveInLineOfSight for nearby contested guards
AddToNotify(NOTIFY_AI_RELOCATION);
if (!unit->HasUnitState(UNIT_STATE_ATTACK_PLAYER))
{
unit->AddUnitState(UNIT_STATE_ATTACK_PLAYER);
Acore::AIRelocationNotifier notifier(*unit);
Cell::VisitWorldObjects(this, notifier, GetVisibilityRange());
}
}
}
@@ -19408,7 +19373,7 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
}
}
void Unit::UpdateObjectVisibility(bool forced, bool /*fromUpdate*/)
void Unit::UpdateObjectVisibility(bool forced)
{
if (!forced)
AddToNotify(NOTIFY_VISIBILITY_CHANGED);
@@ -19416,8 +19381,7 @@ void Unit::UpdateObjectVisibility(bool forced, bool /*fromUpdate*/)
{
WorldObject::UpdateObjectVisibility(true);
Acore::AIRelocationNotifier notifier(*this);
float radius = 60.0f;
Cell::VisitAllObjects(this, notifier, radius);
Cell::VisitAllObjects(this, notifier, GetVisibilityRange());
}
}
@@ -20774,124 +20738,6 @@ bool ConflagrateAuraStateDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time
return true;
}
void Unit::ExecuteDelayedUnitRelocationEvent()
{
this->RemoveFromNotify(NOTIFY_VISIBILITY_CHANGED);
if (!this->IsInWorld() || this->IsDuringRemoveFromWorld())
return;
if (this->HasSharedVision())
for (SharedVisionList::const_iterator itr = this->GetSharedVisionList().begin(); itr != this->GetSharedVisionList().end(); ++itr)
if (Player* player = (*itr))
{
if (player->IsOnVehicle(this) || !player->IsInWorld() || player->IsDuringRemoveFromWorld()) // players on vehicles have their own event executed (due to passenger relocation)
continue;
WorldObject* viewPoint = player;
if (player->m_seer && player->m_seer->IsInWorld())
viewPoint = player->m_seer;
if (!viewPoint->IsPositionValid() || !player->IsPositionValid())
continue;
if (Unit* active = viewPoint->ToUnit())
{
//if (active->IsVehicle()) // always check original unit here, last notify position is not relocated
// active = player;
float dx = active->m_last_notify_position.GetPositionX() - active->GetPositionX();
float dy = active->m_last_notify_position.GetPositionY() - active->GetPositionY();
float dz = active->m_last_notify_position.GetPositionZ() - active->GetPositionZ();
float distsq = dx * dx + dy * dy + dz * dz;
float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(active->FindMap()->GetEntry()->map_type);
if (distsq < mindistsq)
continue;
// this will be relocated below sharedvision!
//active->m_last_notify_position.Relocate(active->GetPositionX(), active->GetPositionY(), active->GetPositionZ());
}
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();
Acore::PlayerRelocationNotifier relocateLarge(*player, true); // visit only large objects; maximum distance
Cell::VisitAllObjects(viewPoint, relocateLarge, MAX_VISIBILITY_DISTANCE);
relocateLarge.SendToSelf();
}
if (Player* player = this->ToPlayer())
{
WorldObject* viewPoint = player;
if (player->m_seer && player->m_seer->IsInWorld())
viewPoint = player->m_seer;
if (viewPoint->GetMapId() != player->GetMapId() || !viewPoint->IsPositionValid() || !player->IsPositionValid())
return;
if (Unit* active = viewPoint->ToUnit())
{
if (active->IsVehicle())
active = player;
if (!player->GetFarSightDistance())
{
float dx = active->m_last_notify_position.GetPositionX() - active->GetPositionX();
float dy = active->m_last_notify_position.GetPositionY() - active->GetPositionY();
float dz = active->m_last_notify_position.GetPositionZ() - active->GetPositionZ();
float distsq = dx * dx + dy * dy + dz * dz;
float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(active->FindMap()->GetEntry()->map_type);
if (distsq < mindistsq)
return;
active->m_last_notify_position.Relocate(active->GetPositionX(), active->GetPositionY(), active->GetPositionZ());
}
}
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();
if (!player->GetFarSightDistance())
{
Acore::PlayerRelocationNotifier relocateLarge(*player, true); // visit only large objects; maximum distance
Cell::VisitAllObjects(viewPoint, relocateLarge, MAX_VISIBILITY_DISTANCE);
relocateLarge.SendToSelf();
}
this->AddToNotify(NOTIFY_AI_RELOCATION);
}
else if (Creature* unit = this->ToCreature())
{
if (!unit->IsPositionValid())
return;
float dx = unit->m_last_notify_position.GetPositionX() - unit->GetPositionX();
float dy = unit->m_last_notify_position.GetPositionY() - unit->GetPositionY();
float dz = unit->m_last_notify_position.GetPositionZ() - unit->GetPositionZ();
float distsq = dx * dx + dy * dy + dz * dz;
float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(unit->FindMap()->GetEntry()->map_type);
if (distsq < mindistsq)
return;
unit->m_last_notify_position.Relocate(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ());
Acore::CreatureRelocationNotifier relocate(*unit);
Cell::VisitAllObjects(unit, relocate, unit->GetVisibilityRange() + VISIBILITY_COMPENSATION);
this->AddToNotify(NOTIFY_AI_RELOCATION);
}
}
void Unit::ExecuteDelayedUnitAINotifyEvent()
{
this->RemoveFromNotify(NOTIFY_AI_RELOCATION);
if (!this->IsInWorld() || this->IsDuringRemoveFromWorld())
return;
Acore::AIRelocationNotifier notifier(*this);
float radius = 60.0f;
Cell::VisitAllObjects(this, notifier, radius);
}
void Unit::SetInFront(WorldObject const* target)
{
if (!HasUnitState(UNIT_STATE_CANNOT_TURN))
+1 -9
View File
@@ -2145,7 +2145,7 @@ public:
// common function for visibility checks for player/creatures with detection code
[[nodiscard]] uint32 GetPhaseByAuras() const;
void SetPhaseMask(uint32 newPhaseMask, bool update) override;// overwrite WorldObject::SetPhaseMask
void UpdateObjectVisibility(bool forced = true, bool fromUpdate = false) override;
void UpdateObjectVisibility(bool forced = true) override;
SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY];
uint32 m_lastSanctuaryTime;
@@ -2419,14 +2419,6 @@ public:
void AddPointedBy(SafeUnitPointer* sup) { SafeUnitPointerSet.insert(sup); }
void RemovePointedBy(SafeUnitPointer* sup) { SafeUnitPointerSet.erase(sup); }
static void HandleSafeUnitPointersOnDelete(Unit* thisUnit);
// Relocation Nofier optimization
Position m_last_notify_position;
uint32 m_last_notify_mstime;
uint16 m_delayed_unit_relocation_timer;
uint16 m_delayed_unit_ai_notify_timer;
bool bRequestForcedVisibilityUpdate;
void ExecuteDelayedUnitRelocationEvent();
void ExecuteDelayedUnitAINotifyEvent();
// cooldowns
[[nodiscard]] virtual bool HasSpellCooldown(uint32 /*spell_id*/) const { return false; }
+8 -2
View File
@@ -7676,8 +7676,8 @@ void ObjectMgr::LoadReputationSpilloverTemplate()
_repSpilloverTemplateStore.clear(); // for reload case
uint32 count = 0; // 0 1 2 3 4 5 6 7 8 9 10 11 12
QueryResult result = WorldDatabase.Query("SELECT faction, faction1, rate_1, rank_1, faction2, rate_2, rank_2, faction3, rate_3, rank_3, faction4, rate_4, rank_4 FROM reputation_spillover_template");
uint32 count = 0; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
QueryResult result = WorldDatabase.Query("SELECT faction, faction1, rate_1, rank_1, faction2, rate_2, rank_2, faction3, rate_3, rank_3, faction4, rate_4, rank_4, faction5, rate_5, rank_5, faction6, rate_6, rank_6 FROM reputation_spillover_template");
if (!result)
{
@@ -7706,6 +7706,12 @@ void ObjectMgr::LoadReputationSpilloverTemplate()
repTemplate.faction[3] = fields[10].Get<uint16>();
repTemplate.faction_rate[3] = fields[11].Get<float>();
repTemplate.faction_rank[3] = fields[12].Get<uint8>();
repTemplate.faction[4] = fields[13].Get<uint16>();
repTemplate.faction_rate[4] = fields[14].Get<float>();
repTemplate.faction_rank[4] = fields[15].Get<uint8>();
repTemplate.faction[5] = fields[16].Get<uint16>();
repTemplate.faction_rate[5] = fields[17].Get<float>();
repTemplate.faction_rank[5] = fields[18].Get<uint8>();
FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId);
+6
View File
@@ -96,6 +96,12 @@ public:
visitor.Visit(i_objects);
}
template<class T>
uint32 GetWorldObjectCountInGrid() const
{
return i_objects.template Count<T>();
}
/** Inserts a container type object into the grid.
*/
template<class SPECIFIC_OBJECT> void AddGridObject(SPECIFIC_OBJECT* obj)
+65
View File
@@ -0,0 +1,65 @@
/*
* 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 "GridStates.h"
#include "GridNotifiers.h"
#include "Log.h"
#include "Map.h"
#include "ObjectGridLoader.h"
void InvalidState::Update(Map&, NGridType&, GridInfo&, uint32) const
{
}
void ActiveState::Update(Map& map, NGridType& grid, GridInfo& info, uint32 diff) const
{
// Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle
info.UpdateTimeTracker(diff);
if (info.getTimeTracker().Passed())
{
if (!grid.GetWorldObjectCountInNGrid<Player>() && !map.ActiveObjectsNearGrid(grid))
{
ObjectGridStoper worker;
TypeContainerVisitor<ObjectGridStoper, GridTypeMapContainer> visitor(worker);
grid.VisitAllGrids(visitor);
grid.SetGridState(GRID_STATE_IDLE);
LOG_DEBUG("maps", "Grid[{}, {}] on map {} moved to IDLE state", grid.getX(), grid.getY(), map.GetId());
}
else
map.ResetGridExpiry(grid, 0.1f);
}
}
void IdleState::Update(Map& map, NGridType& grid, GridInfo&, uint32) const
{
map.ResetGridExpiry(grid);
grid.SetGridState(GRID_STATE_REMOVAL);
LOG_DEBUG("maps", "Grid[{}, {}] on map {} moved to REMOVAL state", grid.getX(), grid.getY(), map.GetId());
}
void RemovalState::Update(Map& map, NGridType& grid, GridInfo& info, uint32 diff) const
{
if (!info.getUnloadLock())
{
info.UpdateTimeTracker(diff);
if (info.getTimeTracker().Passed() && !map.UnloadGrid(grid, false))
{
LOG_DEBUG("maps", "Grid[{}, {}] for map {} differed unloading due to players or active objects nearby", grid.getX(), grid.getY(), map.GetId());
map.ResetGridExpiry(grid);
}
}
}
+56
View File
@@ -0,0 +1,56 @@
/*
* 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_GRIDSTATES_H
#define ACORE_GRIDSTATES_H
#include "GridDefines.h"
#include "NGrid.h"
class Map;
class AC_GAME_API GridState
{
public:
virtual ~GridState() { };
virtual void Update(Map &, NGridType&, GridInfo &, uint32 t_diff) const = 0;
};
class AC_GAME_API InvalidState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
};
class AC_GAME_API ActiveState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
};
class AC_GAME_API IdleState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
};
class AC_GAME_API RemovalState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
};
#endif
+29
View File
@@ -0,0 +1,29 @@
/*
* 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 "NGrid.h"
#include "Random.h"
GridInfo::GridInfo() : i_timer(0), vis_Update(0, irand(0, DEFAULT_VISIBILITY_NOTIFY_PERIOD)),
i_unloadActiveLockCount(0), i_unloadExplicitLock(false), i_unloadReferenceLock(false)
{
}
GridInfo::GridInfo(std::chrono::seconds expiry, bool unload /*= true */) : i_timer(expiry.count()), vis_Update(0, irand(0, DEFAULT_VISIBILITY_NOTIFY_PERIOD)),
i_unloadActiveLockCount(0), i_unloadExplicitLock(!unload), i_unloadReferenceLock(false)
{
}
+65 -4
View File
@@ -26,6 +26,42 @@
#include "Timer.h"
#include "Util.h"
#define DEFAULT_VISIBILITY_NOTIFY_PERIOD 1000
class AC_GAME_API GridInfo
{
public:
GridInfo();
GridInfo(std::chrono::seconds expiry, bool unload = true);
TimeTracker const& getTimeTracker() const { return i_timer; }
bool getUnloadLock() const { return i_unloadActiveLockCount || i_unloadExplicitLock || i_unloadReferenceLock; }
void setUnloadExplicitLock(bool on) { i_unloadExplicitLock = on; }
void setUnloadReferenceLock(bool on) { i_unloadReferenceLock = on; }
void incUnloadActiveLock() { ++i_unloadActiveLockCount; }
void decUnloadActiveLock() { if (i_unloadActiveLockCount) --i_unloadActiveLockCount; }
void setTimer(TimeTracker const& pTimer) { i_timer = pTimer; }
void ResetTimeTracker(time_t interval) { i_timer.Reset(interval); }
void UpdateTimeTracker(time_t diff) { i_timer.Update(diff); }
PeriodicTimer& getRelocationTimer() { return vis_Update; }
private:
TimeTracker i_timer;
PeriodicTimer vis_Update;
uint16 i_unloadActiveLockCount : 16; // lock from active object spawn points (prevent clone loading)
bool i_unloadExplicitLock : 1; // explicit manual lock or config setting
bool i_unloadReferenceLock : 1; // lock from instance map copy
};
typedef enum
{
GRID_STATE_INVALID = 0,
GRID_STATE_ACTIVE = 1,
GRID_STATE_IDLE = 2,
GRID_STATE_REMOVAL = 3,
MAX_GRID_STATE = 4
} grid_state_t;
template
<
uint32 N,
@@ -37,10 +73,10 @@ 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)
{
}
NGrid(uint32 id, int32 x, int32 y, std::chrono::seconds expiry, bool unload = true) :
i_gridId(id), i_GridInfo(GridInfo(expiry, unload)), i_x(x), i_y(y),
i_cellstate(GRID_STATE_INVALID), i_GridObjectDataLoaded(false)
{ }
GridType& GetGridType(const uint32 x, const uint32 y)
{
@@ -55,6 +91,9 @@ public:
}
[[nodiscard]] uint32 GetGridId() const { return i_gridId; }
void SetGridId(uint32 id) { i_gridId = id; }
[[nodiscard]] grid_state_t GetGridState() const { return i_cellstate; }
void SetGridState(grid_state_t s) { i_cellstate = s; }
[[nodiscard]] int32 getX() const { return i_x; }
[[nodiscard]] int32 getY() const { return i_y; }
@@ -65,6 +104,16 @@ public:
[[nodiscard]] bool isGridObjectDataLoaded() const { return i_GridObjectDataLoaded; }
void setGridObjectDataLoaded(bool pLoaded) { i_GridObjectDataLoaded = pLoaded; }
GridInfo* getGridInfoRef() { return &i_GridInfo; }
TimeTracker const& getTimeTracker() const { return i_GridInfo.getTimeTracker(); }
bool getUnloadLock() const { return i_GridInfo.getUnloadLock(); }
void setUnloadExplicitLock(bool on) { i_GridInfo.setUnloadExplicitLock(on); }
void setUnloadReferenceLock(bool on) { i_GridInfo.setUnloadReferenceLock(on); }
void incUnloadActiveLock() { i_GridInfo.incUnloadActiveLock(); }
void decUnloadActiveLock() { i_GridInfo.decUnloadActiveLock(); }
void ResetTimeTracker(std::chrono::seconds interval) { i_GridInfo.ResetTimeTracker(interval.count()); }
void UpdateTimeTracker(std::chrono::seconds diff) { i_GridInfo.UpdateTimeTracker(diff.count()); }
/*
template<class SPECIFIC_OBJECT> void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj)
{
@@ -103,11 +152,23 @@ public:
GetGridType(x, y).Visit(visitor);
}
template<class T>
uint32 GetWorldObjectCountInNGrid() const
{
uint32 count = 0;
for (uint32 x = 0; x < N; ++x)
for (uint32 y = 0; y < N; ++y)
count += i_cells[x][y].template GetWorldObjectCountInGrid<T>();
return count;
}
private:
uint32 i_gridId;
GridInfo i_GridInfo;
GridReference<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> > i_Reference;
int32 i_x;
int32 i_y;
grid_state_t i_cellstate;
GridType i_cells[N][N];
bool i_GridObjectDataLoaded;
};
@@ -16,6 +16,7 @@
*/
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "Map.h"
#include "ObjectAccessor.h"
#include "SpellInfo.h"
@@ -23,22 +24,10 @@
#include "Transport.h"
#include "UpdateData.h"
#include "WorldPacket.h"
#include "CellImpl.h"
using namespace Acore;
void VisibleNotifier::Visit(GameObjectMapType& m)
{
for (GameObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
GameObject* go = iter->GetSource();
if (i_largeOnly != go->IsVisibilityOverridden())
continue;
vis_guids.erase(go->GetGUID());
i_player.UpdateVisibilityOf(go, i_data, i_visibleNow);
}
}
void VisibleNotifier::SendToSelf()
{
// at this moment i_clientGUIDs have guids that not iterate at grid level checks
@@ -46,9 +35,6 @@ void VisibleNotifier::SendToSelf()
if (Transport* transport = i_player.GetTransport())
for (Transport::PassengerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
{
if (i_largeOnly != (*itr)->IsVisibilityOverridden())
continue;
if (vis_guids.find((*itr)->GetGUID()) != vis_guids.end())
{
vis_guids.erase((*itr)->GetGUID());
@@ -65,6 +51,9 @@ void VisibleNotifier::SendToSelf()
case TYPEID_UNIT:
i_player.UpdateVisibilityOf((*itr)->ToCreature(), i_data, i_visibleNow);
break;
case TYPEID_DYNAMICOBJECT:
i_player.UpdateVisibilityOf((*itr)->ToDynObject(), i_data, i_visibleNow);
break;
default:
break;
}
@@ -73,12 +62,6 @@ void VisibleNotifier::SendToSelf()
for (GuidUnorderedSet::const_iterator it = vis_guids.begin(); it != vis_guids.end(); ++it)
{
if (WorldObject* obj = ObjectAccessor::GetWorldObject(i_player, *it))
{
if (i_largeOnly != obj->IsVisibilityOverridden())
continue;
}
// pussywizard: static transports are removed only in RemovePlayerFromMap and here if can no longer detect (eg. phase changed)
if ((*it).IsTransport())
if (GameObject* staticTrans = i_player.GetMap()->GetGameObject(*it))
@@ -105,9 +88,6 @@ void VisibleNotifier::SendToSelf()
for (std::vector<Unit*>::const_iterator it = i_visibleNow.begin(); it != i_visibleNow.end(); ++it)
{
if (i_largeOnly != (*it)->IsVisibilityOverridden())
continue;
i_player.GetInitialVisiblePackets(*it);
}
}
@@ -178,6 +158,23 @@ void PlayerRelocationNotifier::Visit(PlayerMapType& m)
}
}
void PlayerRelocationNotifier::Visit(CreatureMapType& m)
{
bool relocated_for_ai = (&i_player == i_player.m_seer);
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Creature* c = iter->GetSource();
vis_guids.erase(c->GetGUID());
i_player.UpdateVisibilityOf(c, i_data, i_visibleNow);
if (relocated_for_ai && !c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED))
CreatureUnitRelocationWorker(c, &i_player);
}
}
void CreatureRelocationNotifier::Visit(PlayerMapType& m)
{
for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
@@ -194,6 +191,58 @@ void CreatureRelocationNotifier::Visit(PlayerMapType& m)
}
}
void CreatureRelocationNotifier::Visit(CreatureMapType& m)
{
if (!i_creature.IsAlive())
return;
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Creature* c = iter->GetSource();
CreatureUnitRelocationWorker(&i_creature, c);
if (!c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED))
CreatureUnitRelocationWorker(c, &i_creature);
}
}
void DelayedUnitRelocation::Visit(CreatureMapType& m)
{
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Creature* unit = iter->GetSource();
if (!unit->isNeedNotify(NOTIFY_VISIBILITY_CHANGED))
continue;
CreatureRelocationNotifier relocate(*unit);
TypeContainerVisitor<CreatureRelocationNotifier, WorldTypeMapContainer > c2world_relocation(relocate);
TypeContainerVisitor<CreatureRelocationNotifier, GridTypeMapContainer > c2grid_relocation(relocate);
cell.Visit(p, c2world_relocation, i_map, *unit, i_radius);
cell.Visit(p, c2grid_relocation, i_map, *unit, i_radius);
}
}
void DelayedUnitRelocation::Visit(PlayerMapType& m)
{
for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Player* player = iter->GetSource();
WorldObject const* viewPoint = player->m_seer;
if (!viewPoint->isNeedNotify(NOTIFY_VISIBILITY_CHANGED))
continue;
if (player != viewPoint && !viewPoint->IsPositionValid())
continue;
PlayerRelocationNotifier relocate(*player);
Cell::VisitAllObjects(viewPoint, relocate, i_radius, false);
relocate.SendToSelf();
}
}
void AIRelocationNotifier::Visit(CreatureMapType& m)
{
bool self = isCreature && !((Creature*)(&i_unit))->IsMoveInLineOfSightStrictlyDisabled();
@@ -341,14 +390,9 @@ void MessageDistDelivererToHostile::Visit(DynamicObjectMapType& m)
template<class T>
void ObjectUpdater::Visit(GridRefMgr<T>& m)
{
T* obj;
for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); )
{
obj = iter->GetSource();
++iter;
if (obj->IsInWorld() && (i_largeOnly == obj->IsVisibilityOverridden()))
obj->Update(i_timeDiff);
}
for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
if (iter->GetSource()->IsInWorld())
iter->GetSource()->Update(i_timeDiff);
}
bool AnyDeadUnitObjectInRangeCheck::operator()(Player* u)
@@ -44,16 +44,14 @@ namespace Acore
GuidUnorderedSet vis_guids;
std::vector<Unit*>& i_visibleNow;
bool i_gobjOnly;
bool i_largeOnly;
UpdateData i_data;
VisibleNotifier(Player& player, bool gobjOnly, bool largeOnly) :
i_player(player), vis_guids(player.m_clientGUIDs), i_visibleNow(player.m_newVisible), i_gobjOnly(gobjOnly), i_largeOnly(largeOnly)
VisibleNotifier(Player& player, bool gobjOnly) :
i_player(player), vis_guids(player.m_clientGUIDs), i_visibleNow(player.m_newVisible), i_gobjOnly(gobjOnly)
{
i_visibleNow.clear();
}
void Visit(GameObjectMapType&);
template<class T> void Visit(GridRefMgr<T>& m);
void SendToSelf(void);
};
@@ -71,9 +69,10 @@ namespace Acore
struct PlayerRelocationNotifier : public VisibleNotifier
{
PlayerRelocationNotifier(Player& player, bool largeOnly): VisibleNotifier(player, false, largeOnly) { }
PlayerRelocationNotifier(Player& player) : VisibleNotifier(player, false) { }
template<class T> void Visit(GridRefMgr<T>& m) { VisibleNotifier::Visit(m); }
void Visit(CreatureMapType&);
void Visit(PlayerMapType&);
};
@@ -82,6 +81,20 @@ namespace Acore
Creature& i_creature;
CreatureRelocationNotifier(Creature& c) : i_creature(c) {}
template<class T> void Visit(GridRefMgr<T>&) {}
void Visit(CreatureMapType&);
void Visit(PlayerMapType&);
};
struct DelayedUnitRelocation
{
Map& i_map;
Cell& cell;
CellCoord& p;
const float i_radius;
DelayedUnitRelocation(Cell& c, CellCoord& pair, Map& map, float radius) :
i_map(map), cell(c), p(pair), i_radius(radius) { }
template<class T> void Visit(GridRefMgr<T>&) { }
void Visit(CreatureMapType&);
void Visit(PlayerMapType&);
};
@@ -94,6 +107,25 @@ namespace Acore
void Visit(CreatureMapType&);
};
struct GridUpdater
{
GridType& i_grid;
uint32 i_timeDiff;
GridUpdater(GridType& grid, uint32 diff) : i_grid(grid), i_timeDiff(diff) { }
template<class T> void updateObjects(GridRefMgr<T>& m)
{
for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
iter->GetSource()->Update(i_timeDiff);
}
void Visit(PlayerMapType& m) { updateObjects<Player>(m); }
void Visit(CreatureMapType& m) { updateObjects<Creature>(m); }
void Visit(GameObjectMapType& m) { updateObjects<GameObject>(m); }
void Visit(DynamicObjectMapType& m) { updateObjects<DynamicObject>(m); }
void Visit(CorpseMapType& m) { updateObjects<Corpse>(m); }
};
struct MessageDistDeliverer
{
WorldObject const* i_source;
@@ -154,8 +186,7 @@ namespace Acore
struct ObjectUpdater
{
uint32 i_timeDiff;
bool i_largeOnly;
explicit ObjectUpdater(const uint32 diff, bool largeOnly) : i_timeDiff(diff), i_largeOnly(largeOnly) {}
explicit ObjectUpdater(const uint32 diff) : i_timeDiff(diff) {}
template<class T> void Visit(GridRefMgr<T>& m);
void Visit(PlayerMapType&) {}
void Visit(CorpseMapType&) {}
@@ -38,9 +38,6 @@ inline void Acore::VisibleNotifier::Visit(GridRefMgr<T>& m)
for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
{
if (i_largeOnly != iter->GetSource()->IsVisibilityOverridden())
continue;
vis_guids.erase(iter->GetSource()->GetGUID());
i_player.UpdateVisibilityOf(iter->GetSource(), i_data, i_visibleNow);
}
@@ -26,6 +26,35 @@
#include "Transport.h"
#include "Vehicle.h"
void ObjectGridEvacuator::Visit(CreatureMapType& m)
{
// creature in unloading grid can have respawn point in another grid
// if it will be unloaded then it will not respawn in original grid until unload/load original grid
// move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn.
for (CreatureMapType::iterator iter = m.begin(); iter != m.end();)
{
Creature* c = iter->GetSource();
++iter;
ASSERT(!c->IsPet() && "ObjectGridRespawnMover must not be called for pets");
c->GetMap()->CreatureRespawnRelocation(c, true);
}
}
void ObjectGridEvacuator::Visit(GameObjectMapType& m)
{
// gameobject in unloading grid can have respawn point in another grid
// if it will be unloaded then it will not respawn in original grid until unload/load original grid
// move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn.
for (GameObjectMapType::iterator iter = m.begin(); iter != m.end();)
{
GameObject* go = iter->GetSource();
++iter;
go->GetMap()->GameObjectRespawnRelocation(go, true);
}
}
// for loading world object at grid loading (Corpses)
//TODO: to implement npc on transport, also need to load npcs at grid loading
class ObjectWorldLoader
@@ -229,6 +258,17 @@ void ObjectGridUnloader::Visit(GridRefMgr<T>& m)
}
}
void ObjectGridStoper::Visit(CreatureMapType& m)
{
// stop any fights at grid de-activation and remove dynobjects created at cast by creatures
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
iter->GetSource()->RemoveAllDynObjects();
if (iter->GetSource()->IsInCombat())
iter->GetSource()->CombatStop();
}
}
template<class T>
void ObjectGridCleaner::Visit(GridRefMgr<T>& m)
{
+17
View File
@@ -53,6 +53,23 @@ private:
uint32 i_corpses;
};
//Stop the creatures before unloading the NGrid
class AC_GAME_API ObjectGridStoper
{
public:
void Visit(CreatureMapType& m);
template<class T> void Visit(GridRefMgr<T>&) { }
};
//Move the foreign creatures back to respawn positions before unloading the NGrid
class AC_GAME_API ObjectGridEvacuator
{
public:
void Visit(CreatureMapType& m);
void Visit(GameObjectMapType& m);
template<class T> void Visit(GridRefMgr<T>&) { }
};
//Clean up and remove from world
class ObjectGridCleaner
{
+2 -2
View File
@@ -225,9 +225,9 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
break;
}
}
// but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used)
// Overwritten by SPELL_AURA_MOD_LANGUAGE auras (Affects only Say and Yell)
Unit::AuraEffectList const& ModLangAuras = sender->GetAuraEffectsByType(SPELL_AURA_MOD_LANGUAGE);
if (!ModLangAuras.empty())
if (!ModLangAuras.empty() && (type == CHAT_MSG_SAY || type == CHAT_MSG_YELL))
lang = ModLangAuras.front()->GetMiscValue();
}
@@ -20,6 +20,7 @@
#include "Config.h"
#include "GameTime.h"
#include "GridNotifiers.h"
#include "GridStates.h"
#include "Group.h"
#include "InstanceScript.h"
#include "Log.h"
+3 -1
View File
@@ -1738,7 +1738,9 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint16 lootMode,
// Rate.Drop.Item.GroupAmount is only in effect for the top loot template level
if (isTopLevel)
{
group->Process(loot, player, store, lootMode, sWorld->getRate(RATE_DROP_ITEM_GROUP_AMOUNT));
uint32 groupAmount = sWorld->getRate(RATE_DROP_ITEM_GROUP_AMOUNT);
sScriptMgr->OnAfterCalculateLootGroupAmount(player, loot, lootMode, groupAmount, store);
group->Process(loot, player, store, lootMode, groupAmount);
}
else
{
File diff suppressed because it is too large Load Diff
+47 -20
View File
@@ -71,7 +71,6 @@ namespace VMAP
namespace Acore
{
struct ObjectUpdater;
struct LargeObjectUpdater;
}
struct ScriptAction
@@ -312,7 +311,7 @@ class Map : public GridRefMgr<NGridType>
{
friend class MapReference;
public:
Map(uint32 id, uint32 InstanceId, uint8 SpawnMode, Map* _parent = nullptr);
Map(uint32 id, std::chrono::seconds, uint32 InstanceId, uint8 SpawnMode, Map* _parent = nullptr);
~Map() override;
[[nodiscard]] MapEntry const* GetEntry() const { return i_mapEntry; }
@@ -337,13 +336,7 @@ public:
template<class T> void RemoveFromMap(T*, bool);
void VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& gridVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& largeGridVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& largeWorldVisitor);
void VisitNearbyCellsOfPlayer(Player* player, TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& gridVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& largeGridVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& largeWorldVisitor);
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor);
virtual void Update(const uint32, const uint32, bool thread = true);
@@ -362,7 +355,7 @@ public:
[[nodiscard]] bool IsRemovalGrid(float x, float y) const
{
GridCoord p = Acore::ComputeGridCoord(x, y);
return !getNGrid(p.x_coord, p.y_coord);
return !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL;
}
[[nodiscard]] bool IsGridLoaded(float x, float y) const
@@ -370,13 +363,26 @@ public:
return IsGridLoaded(Acore::ComputeGridCoord(x, y));
}
bool GetUnloadLock(GridCoord const& p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); }
void SetUnloadLock(GridCoord const& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); }
void LoadGrid(float x, float y);
void LoadAllCells();
bool UnloadGrid(NGridType& ngrid);
bool UnloadGrid(NGridType& ngrid, bool pForce);
void GridMarkNoUnload(uint32 x, uint32 y);
void GridUnmarkNoUnload(uint32 x, uint32 y);
virtual void UnloadAll();
void ResetGridExpiry(NGridType& grid, float factor = 1) const
{
grid.ResetTimeTracker(std::chrono::duration_cast<std::chrono::seconds>(i_gridExpiry * factor));
}
[[nodiscard]] std::chrono::seconds GetGridExpiry(void) const { return i_gridExpiry; }
[[nodiscard]] uint32 GetId() const { return i_mapEntry->MapID; }
static void InitStateMachine();
static void DeleteStateMachine();
static bool ExistMap(uint32 mapid, int gx, int gy);
static bool ExistVMap(uint32 mapid, int gx, int gy);
@@ -415,6 +421,10 @@ public:
void RemoveAllObjectsInRemoveList();
virtual void RemoveAllPlayers();
// used only in MoveAllCreaturesInMoveList and ObjectGridUnloader
bool CreatureRespawnRelocation(Creature* c, bool diffGridOnly);
bool GameObjectRespawnRelocation(GameObject* go, bool diffGridOnly);
[[nodiscard]] uint32 GetInstanceId() const { return i_InstanceId; }
[[nodiscard]] uint8 GetSpawnMode() const { return (i_spawnMode); }
@@ -468,12 +478,10 @@ public:
void resetMarkedCells() { marked_cells.reset(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
void resetMarkedCellsLarge() { marked_cells_large.reset(); }
bool isCellMarkedLarge(uint32 pCellId) { return marked_cells_large.test(pCellId); }
void markCellLarge(uint32 pCellId) { marked_cells_large.set(pCellId); }
[[nodiscard]] bool HavePlayers() const { return !m_mapRefMgr.IsEmpty(); }
[[nodiscard]] uint32 GetPlayersCountExceptGMs() const;
[[nodiscard]] bool ActiveObjectsNearGrid(NGridType const& ngrid) const;
void AddWorldObject(WorldObject* obj) { i_worldObjects.insert(obj); }
void RemoveWorldObject(WorldObject* obj) { i_worldObjects.erase(obj); }
@@ -660,20 +668,30 @@ private:
// Load MMap Data
void LoadMMap(int gx, int gy);
bool CreatureCellRelocation(Creature* creature, Cell new_cell);
bool GameObjectCellRelocation(GameObject* go, Cell new_cell);
bool DynamicObjectCellRelocation(DynamicObject* go, Cell new_cell);
template<class T> void InitializeObject(T* obj);
void AddCreatureToMoveList(Creature* c);
void AddCreatureToMoveList(Creature* c, float x, float y, float z, float ang);
void RemoveCreatureFromMoveList(Creature* c);
void AddGameObjectToMoveList(GameObject* go);
void AddGameObjectToMoveList(GameObject* go, float x, float y, float z, float ang);
void RemoveGameObjectFromMoveList(GameObject* go);
void AddDynamicObjectToMoveList(DynamicObject* go);
void AddDynamicObjectToMoveList(DynamicObject* go, float x, float y, float z, float ang);
void RemoveDynamicObjectFromMoveList(DynamicObject* go);
bool _creatureToMoveLock;
std::vector<Creature*> _creaturesToMove;
bool _gameObjectsToMoveLock;
std::vector<GameObject*> _gameObjectsToMove;
bool _dynamicObjectsToMoveLock;
std::vector<DynamicObject*> _dynamicObjectsToMove;
[[nodiscard]] bool IsGridLoaded(const GridCoord&) const;
void EnsureGridCreated_i(const GridCoord&);
void EnsureGridLoadedForActiveObject(Cell const&, WorldObject* object);
void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); }
@@ -695,6 +713,8 @@ private:
void SendObjectUpdates();
protected:
void SetUnloadReferenceLock(GridCoord const& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); }
std::mutex Lock;
std::mutex GridLock;
std::shared_mutex MMapLock;
@@ -710,6 +730,8 @@ protected:
MapRefMgr m_mapRefMgr;
MapRefMgr::iterator m_mapRefIter;
int32 m_VisibilityNotifyPeriod;
typedef std::set<WorldObject*> ActiveNonPlayers;
ActiveNonPlayers m_activeNonPlayers;
ActiveNonPlayers::iterator m_activeNonPlayersIter;
@@ -728,6 +750,8 @@ private:
void _ScriptProcessDoor(Object* source, Object* target, const ScriptInfo* scriptInfo) const;
GameObject* _FindGameObject(WorldObject* pWorldObject, ObjectGuid::LowType guid) const;
std::chrono::seconds i_gridExpiry;
//used for fast base_map (e.g. MapInstanced class object) search for
//InstanceMaps and BattlegroundMaps...
Map* m_parentMap;
@@ -735,7 +759,10 @@ private:
NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
GridMap* GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
std::bitset<TOTAL_NUMBER_OF_CELLS_PER_MAP* TOTAL_NUMBER_OF_CELLS_PER_MAP> marked_cells;
std::bitset<TOTAL_NUMBER_OF_CELLS_PER_MAP* TOTAL_NUMBER_OF_CELLS_PER_MAP> marked_cells_large;
//these functions used to process player/mob aggro reactions and
//visibility calculations. Highly optimized for massive calculations
void ProcessRelocationNotifies(uint32 diff);
bool i_scriptLock;
std::unordered_set<WorldObject*> i_objectsToRemove;
@@ -812,7 +839,7 @@ enum InstanceResetMethod
class InstanceMap : public Map
{
public:
InstanceMap(uint32 id, uint32 InstanceId, uint8 SpawnMode, Map* _parent);
InstanceMap(uint32 id, std::chrono::seconds, uint32 InstanceId, uint8 SpawnMode, Map* _parent);
~InstanceMap() override;
bool AddPlayerToMap(Player*) override;
void RemovePlayerFromMap(Player*, bool) override;
@@ -846,7 +873,7 @@ private:
class BattlegroundMap : public Map
{
public:
BattlegroundMap(uint32 id, uint32 InstanceId, Map* _parent, uint8 spawnMode);
BattlegroundMap(uint32 id, std::chrono::seconds, uint32 InstanceId, Map* _parent, uint8 spawnMode);
~BattlegroundMap() override;
bool AddPlayerToMap(Player*) override;
+5 -5
View File
@@ -26,10 +26,10 @@
#include "ScriptMgr.h"
#include "VMapFactory.h"
MapInstanced::MapInstanced(uint32 id) : Map(id, 0, DUNGEON_DIFFICULTY_NORMAL)
MapInstanced::MapInstanced(uint32 id, std::chrono::seconds expiry) : Map(id, expiry, 0, DUNGEON_DIFFICULTY_NORMAL)
{
// initialize instanced maps list
m_InstancedMaps.clear();
// fill with zero
memset(&GridMapReference, 0, MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS * sizeof(uint16));
}
void MapInstanced::InitVisibilityDistance()
@@ -203,7 +203,7 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save,
LOG_DEBUG("maps", "MapInstanced::CreateInstance: {} map instance {} for {} created with difficulty {}", save ? "" : "new ", InstanceId, GetId(), difficulty ? "heroic" : "normal");
InstanceMap* map = new InstanceMap(GetId(), InstanceId, difficulty, this);
InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this);
ASSERT(map->IsDungeon());
map->LoadRespawnTimes();
@@ -237,7 +237,7 @@ BattlegroundMap* MapInstanced::CreateBattleground(uint32 InstanceId, Battlegroun
else
spawnMode = REGULAR_DIFFICULTY;
BattlegroundMap* map = new BattlegroundMap(GetId(), InstanceId, this, spawnMode);
BattlegroundMap* map = new BattlegroundMap(GetId(), GetGridExpiry(), InstanceId, this, spawnMode);
ASSERT(map->IsBattlegroundOrArena());
map->SetBG(bg);
bg->SetBgMap(map);
+16 -1
View File
@@ -28,7 +28,7 @@ class MapInstanced : public Map
public:
using InstancedMaps = std::unordered_map<uint32, Map*>;
MapInstanced(uint32 id);
MapInstanced(uint32 id, std::chrono::seconds expiry);
~MapInstanced() override {}
// functions overwrite Map versions
@@ -46,6 +46,19 @@ public:
}
bool DestroyInstance(InstancedMaps::iterator& itr);
void AddGridMapReference(GridCoord const& p)
{
++GridMapReference[p.x_coord][p.y_coord];
SetUnloadReferenceLock(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - p.x_coord, (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord), true);
}
void RemoveGridMapReference(GridCoord const& p)
{
--GridMapReference[p.x_coord][p.y_coord];
if (!GridMapReference[p.x_coord][p.y_coord])
SetUnloadReferenceLock(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - p.x_coord, (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord), false);
}
InstancedMaps& GetInstancedMaps() { return m_InstancedMaps; }
void InitVisibilityDistance() override;
@@ -54,5 +67,7 @@ private:
BattlegroundMap* CreateBattleground(uint32 InstanceId, Battleground* bg);
InstancedMaps m_InstancedMaps;
uint16 GridMapReference[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
};
#endif
+7 -2
View File
@@ -36,6 +36,7 @@
MapMgr::MapMgr()
{
i_gridCleanUpDelay = sWorld->getIntConfig(CONFIG_INTERVAL_GRIDCLEAN);
i_timer[3].SetInterval(sWorld->getIntConfig(CONFIG_INTERVAL_MAPUPDATE));
mapUpdateStep = 0;
_nextInstanceId = 0;
@@ -53,6 +54,8 @@ MapMgr* MapMgr::instance()
void MapMgr::Initialize()
{
Map::InitStateMachine();
int num_threads(sWorld->getIntConfig(CONFIG_NUMTHREADS));
// Start mtmaps if needed
@@ -81,10 +84,10 @@ Map* MapMgr::CreateBaseMap(uint32 id)
ASSERT(entry);
if (entry->Instanceable())
map = new MapInstanced(id);
map = new MapInstanced(id, std::chrono::seconds(i_gridCleanUpDelay));
else
{
map = new Map(id, 0, REGULAR_DIFFICULTY);
map = new Map(id, std::chrono::seconds(i_gridCleanUpDelay), 0, REGULAR_DIFFICULTY);
map->LoadRespawnTimes();
map->LoadCorpseData();
}
@@ -333,6 +336,8 @@ void MapMgr::UnloadAll()
if (m_updater.activated())
m_updater.deactivate();
Map::DeleteStateMachine();
}
void MapMgr::GetNumInstances(uint32& dungeons, uint32& battlegrounds, uint32& arenas)
+10
View File
@@ -24,6 +24,7 @@
#include "MapInstanced.h"
#include "MapUpdater.h"
#include "Object.h"
#include "GridStates.h"
#include <mutex>
@@ -73,6 +74,14 @@ public:
void Initialize(void);
void Update(uint32);
void SetGridCleanUpDelay(uint32 t)
{
if (t < MIN_GRID_DELAY)
i_gridCleanUpDelay = MIN_GRID_DELAY;
else
i_gridCleanUpDelay = t;
}
void SetMapUpdateInterval(uint32 t)
{
if (t < MIN_MAP_UPDATE_DELAY)
@@ -170,6 +179,7 @@ private:
MapMgr& operator=(const MapMgr&);
std::mutex Lock;
uint32 i_gridCleanUpDelay;
MapMapType i_maps;
IntervalTimer i_timer[4]; // continents, bgs/arenas, instances, total from the beginning
uint8 mapUpdateStep;
+1 -1
View File
@@ -38,7 +38,7 @@ Quest::Quest(Field* questRecord)
Type = questRecord[5].Get<uint16>();
SuggestedPlayers = questRecord[6].Get<uint8>();
TimeAllowed = questRecord[7].Get<uint32>();
AllowableRaces = questRecord[8].Get<uint16>();
AllowableRaces = questRecord[8].Get<uint32>();
RequiredFactionId1 = questRecord[9].Get<uint16>();
RequiredFactionId2 = questRecord[10].Get<uint16>();
RequiredFactionValue1 = questRecord[11].Get<int32>();
@@ -48,6 +48,15 @@ void ScriptMgr::OnCreatureSaveToDB(Creature* creature)
});
}
void ScriptMgr::OnBeforeCreatureSelectLevel(const CreatureTemplate* cinfo, Creature* creature, uint8& level)
{
ExecuteScript<AllCreatureScript>([&](AllCreatureScript* script)
{
script->OnBeforeCreatureSelectLevel(cinfo, creature, level);
});
}
void ScriptMgr::Creature_SelectLevel(const CreatureTemplate* cinfo, Creature* creature)
{
ExecuteScript<AllCreatureScript>([&](AllCreatureScript* script)
@@ -160,6 +160,21 @@ void ScriptMgr::OnGameObjectDamaged(GameObject* go, Player* player)
}
}
void ScriptMgr::OnGameObjectModifyHealth(GameObject* go, Unit* attackerOrHealer, int32& change, SpellInfo const* spellInfo)
{
ASSERT(go);
ExecuteScript<AllGameObjectScript>([&](AllGameObjectScript* script)
{
script->OnGameObjectModifyHealth(go, attackerOrHealer, change, spellInfo);
});
if (auto tempScript = ScriptRegistry<GameObjectScript>::GetScriptById(go->GetScriptId()))
{
tempScript->OnModifyHealth(go, attackerOrHealer, change, spellInfo);
}
}
void ScriptMgr::OnGameObjectLootStateChanged(GameObject* go, uint32 state, Unit* unit)
{
ASSERT(go);
@@ -55,6 +55,14 @@ void ScriptMgr::OnAfterRefCount(Player const* player, Loot& loot, bool canRate,
});
}
void ScriptMgr::OnAfterCalculateLootGroupAmount(Player const* player, Loot& loot, uint16 lootMode, uint32& groupAmount, LootStore const& store)
{
ExecuteScript<GlobalScript>([&](GlobalScript* script)
{
script->OnAfterCalculateLootGroupAmount(player, loot, lootMode, groupAmount, store);
});
}
void ScriptMgr::OnBeforeDropAddItem(Player const* player, Loot& loot, bool canRate, uint16 lootMode, LootStoreItem* LootStoreItem, LootStore const& store)
{
ExecuteScript<GlobalScript>([&](GlobalScript* script)
+13
View File
@@ -556,6 +556,9 @@ public:
// Called from End of Creature Update.
virtual void OnAllCreatureUpdate(Creature* /*creature*/, uint32 /*diff*/) { }
// Called just before the level of the creature is set.
virtual void OnBeforeCreatureSelectLevel(const CreatureTemplate* /*cinfo*/, Creature* /*creature*/, uint8& /*level*/) { }
// Called from End of Creature SelectLevel.
virtual void Creature_SelectLevel(const CreatureTemplate* /*cinfo*/, Creature* /*creature*/) { }
@@ -706,6 +709,9 @@ public:
// Called when the game object is damaged (destructible buildings only).
virtual void OnGameObjectDamaged(GameObject* /*go*/, Player* /*player*/) { }
// Called when the health of a game object is modified (destructible buildings only).
virtual void OnGameObjectModifyHealth(GameObject* /*go*/, Unit* /*attackerOrHealer*/, int32& /*change*/, SpellInfo const* /*spellInfo*/) { }
// Called when the game object loot state is changed.
virtual void OnGameObjectLootStateChanged(GameObject* /*go*/, uint32 /*state*/, Unit* /*unit*/) { }
@@ -788,6 +794,9 @@ public:
// Called when the game object is damaged (destructible buildings only).
virtual void OnDamaged(GameObject* /*go*/, Player* /*player*/) { }
// Called when the health of a game object is modified (destructible buildings only).
virtual void OnModifyHealth(GameObject* /*go*/, Unit* /*attackerOrHealer*/, int32& /*change*/, SpellInfo const* /*spellInfo*/) { }
// Called when the game object loot state is changed.
virtual void OnLootStateChanged(GameObject* /*go*/, uint32 /*state*/, Unit* /*unit*/) { }
@@ -1634,6 +1643,7 @@ public:
// loot
virtual void OnAfterRefCount(Player const* /*player*/, LootStoreItem* /*LootStoreItem*/, Loot& /*loot*/, bool /*canRate*/, uint16 /*lootMode*/, uint32& /*maxcount*/, LootStore const& /*store*/) { }
virtual void OnAfterCalculateLootGroupAmount(Player const* /*player*/, Loot& /*loot*/, uint16 /*lootMode*/, uint32& /*groupAmount*/, LootStore const& /*store*/) { }
virtual void OnBeforeDropAddItem(Player const* /*player*/, Loot& /*loot*/, bool /*canRate*/, uint16 /*lootMode*/, LootStoreItem* /*LootStoreItem*/, LootStore const& /*store*/) { }
virtual bool OnItemRoll(Player const* /*player*/, LootStoreItem const* /*LootStoreItem*/, float& /*chance*/, Loot& /*loot*/, LootStore const& /*store*/) { return true; };
virtual bool OnBeforeLootEqualChanced(Player const* /*player*/, LootStoreItemList /*EqualChanced*/, Loot& /*loot*/, LootStore const& /*store*/) { return true; }
@@ -2268,6 +2278,7 @@ public: /* GameObjectScript */
uint32 GetDialogStatus(Player* player, GameObject* go);
void OnGameObjectDestroyed(GameObject* go, Player* player);
void OnGameObjectDamaged(GameObject* go, Player* player);
void OnGameObjectModifyHealth(GameObject* go, Unit* attackerOrHealer, int32& change, SpellInfo const* spellInfo);
void OnGameObjectLootStateChanged(GameObject* go, uint32 state, Unit* unit);
void OnGameObjectStateChanged(GameObject* go, uint32 state);
void OnGameObjectUpdate(GameObject* go, uint32 diff);
@@ -2538,6 +2549,7 @@ public: /* GlobalScript */
void OnGlobalMirrorImageDisplayItem(Item const* item, uint32& display);
void OnBeforeUpdateArenaPoints(ArenaTeam* at, std::map<ObjectGuid, uint32>& ap);
void OnAfterRefCount(Player const* player, Loot& loot, bool canRate, uint16 lootMode, LootStoreItem* LootStoreItem, uint32& maxcount, LootStore const& store);
void OnAfterCalculateLootGroupAmount(Player const* player, Loot& loot, uint16 lootMode, uint32& groupAmount, LootStore const& store);
void OnBeforeDropAddItem(Player const* player, Loot& loot, bool canRate, uint16 lootMode, LootStoreItem* LootStoreItem, LootStore const& store);
bool OnItemRoll(Player const* player, LootStoreItem const* LootStoreItem, float& chance, Loot& loot, LootStore const& store);
bool OnBeforeLootEqualChanced(Player const* player, LootStoreItemList EqualChanced, Loot& loot, LootStore const& store);
@@ -2589,6 +2601,7 @@ public: /* MovementHandlerScript */
public: /* AllCreatureScript */
//listener function (OnAllCreatureUpdate) is called by OnCreatureUpdate
//void OnAllCreatureUpdate(Creature* creature, uint32 diff);
void OnBeforeCreatureSelectLevel(const CreatureTemplate* cinfo, Creature* creature, uint8& level);
void Creature_SelectLevel(const CreatureTemplate* cinfo, Creature* creature);
void OnCreatureSaveToDB(Creature* creature);
@@ -381,8 +381,8 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS] =
AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32* baseAmount, Unit* caster):
m_base(base), m_spellInfo(base->GetSpellInfo()),
m_baseAmount(baseAmount ? * baseAmount : m_spellInfo->Effects[effIndex].BasePoints), m_critChance(0),
m_oldAmount(0), m_isAuraEnabled(true), m_channelData(nullptr), m_spellmod(nullptr), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex),
m_baseAmount(baseAmount ? * baseAmount : m_spellInfo->Effects[effIndex].BasePoints), m_dieSides(m_spellInfo->Effects[effIndex].DieSides),
m_critChance(0), m_oldAmount(0), m_isAuraEnabled(true), m_channelData(nullptr), m_spellmod(nullptr), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex),
m_canBeRecalculated(true), m_isPeriodic(false)
{
CalculatePeriodic(caster, true, false);
@@ -1602,8 +1602,8 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
}
target->UpdateObjectVisibility(target->GetTypeId() == TYPEID_PLAYER || target->GetOwnerGUID().IsPlayer() || target->GetMap()->Instanceable(), true);
target->bRequestForcedVisibilityUpdate = false;
if (target->IsInWorld())
target->UpdateObjectVisibility();
}
void AuraEffect::HandleModStealthDetect(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -1676,8 +1676,8 @@ void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, boo
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
}
target->UpdateObjectVisibility(target->GetTypeId() == TYPEID_PLAYER || target->GetOwnerGUID().IsPlayer() || target->GetMap()->Instanceable(), true);
target->bRequestForcedVisibilityUpdate = false;
if (target->IsInWorld())
target->UpdateObjectVisibility();
}
void AuraEffect::HandleModStealthLevel(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -1841,7 +1841,6 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app
if (!target->GetMap()->Instanceable())
{
target->UpdateObjectVisibility(false);
target->m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f);
}
else
target->UpdateObjectVisibility();
@@ -6299,6 +6298,13 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
// ignore non positive values (can be result apply spellmods to aura damage
uint32 damage = std::max(GetAmount(), 0);
// If the damage is percent-max-health based, calculate damage before the Modify hook
if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE_PERCENT)
{
// xinef: ceil obtained value, it may happen that 10 ticks for 10% damage may not kill owner
damage = uint32(std::ceil(CalculatePct<float, float>(target->GetMaxHealth(), damage)));
}
// Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage, GetSpellInfo());
@@ -6330,8 +6336,6 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
// 5..8 ticks have normal tick damage
}
}
else // xinef: ceil obtained value, it may happen that 10 ticks for 10% damage may not kill owner
damage = uint32(std::ceil(CalculatePct<float, float>(target->GetMaxHealth(), damage)));
// calculate crit chance
bool crit = false;
@@ -55,6 +55,7 @@ public:
uint32 GetId() const;
uint32 GetEffIndex() const { return m_effIndex; }
int32 GetBaseAmount() const { return m_baseAmount; }
int32 GetDieSides() const { return m_dieSides; }
int32 GetAmplitude() const { return m_amplitude; }
int32 GetMiscValueB() const;
@@ -121,6 +122,7 @@ private:
SpellInfo const* const m_spellInfo;
int32 const m_baseAmount;
int32 const m_dieSides;
bool m_applyResilience;
uint8 m_casterLevel;
+2 -2
View File
@@ -6637,8 +6637,8 @@ SpellCastResult Spell::CheckCast(bool strict)
}
case SPELL_AURA_MOUNTED:
{
// Xinef: disallow casting in water for mounts not increasing water movement Speed
if (m_caster->IsInWater() && !m_spellInfo->HasAura(SPELL_AURA_MOD_INCREASE_SWIM_SPEED))
// Disallow casting flying mounts in water
if (m_caster->IsInWater() && m_spellInfo->HasAura(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED))
return SPELL_FAILED_ONLY_ABOVEWATER;
// Ignore map check if spell have AreaId. AreaId already checked and this prevent special mount spells
+5 -2
View File
@@ -6057,8 +6057,11 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const*
Position pos;
// xinef: do not use precalculated position for effect summon pet in this function
// it means it was cast by NPC and should have its position overridden
if (totalNumGuardians == 1 && GetSpellInfo()->Effects[i].Effect != SPELL_EFFECT_SUMMON_PET)
// it means it was cast by NPC and should have its position overridden unless the
// target position is specified in the DB AND the effect has no or zero radius
if ((totalNumGuardians == 1 && GetSpellInfo()->Effects[i].Effect != SPELL_EFFECT_SUMMON_PET) ||
(GetSpellInfo()->Effects[i].TargetA.GetTarget() == TARGET_DEST_DB &&
(!GetSpellInfo()->Effects[i].HasRadius() || GetSpellInfo()->Effects[i].RadiusEntry->RadiusMax == 0)))
{
pos = *destTarget;
}
@@ -416,7 +416,7 @@ void SpellMgr::LoadSpellInfoCorrections()
// Marked for Death
ApplySpellFix({ 53241, 53243, 53244, 53245, 53246 }, [](SpellInfo* spellInfo)
{
spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(423937, 276955137, 2049);
spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(399361, 276955137, 1);
});
ApplySpellFix({
@@ -4572,6 +4572,18 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(13); // 50000yd
});
// Instill Lord Valthalak's Spirit DND
ApplySpellFix({ 27360 }, [](SpellInfo* spellInfo)
{
spellInfo->ChannelInterruptFlags |= AURA_INTERRUPT_FLAG_MOVE;
});
// Holiday - Midsummer, Ribbon Pole Periodic Visual
ApplySpellFix({ 45406 }, [](SpellInfo* spellInfo)
{
spellInfo->AuraInterruptFlags |= ( AURA_INTERRUPT_FLAG_MOUNT | AURA_INTERRUPT_FLAG_CAST );
});
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];
+1 -1
View File
@@ -208,6 +208,7 @@ enum WorldFloatConfigs
enum WorldIntConfigs
{
CONFIG_COMPRESSION = 0,
CONFIG_INTERVAL_GRIDCLEAN,
CONFIG_INTERVAL_MAPUPDATE,
CONFIG_INTERVAL_CHANGEWEATHER,
CONFIG_INTERVAL_DISCONNECT_TOLERANCE,
@@ -505,7 +506,6 @@ enum Rates
RATE_TALENT,
RATE_CORPSE_DECAY_LOOTED,
RATE_INSTANCE_RESET_TIME,
RATE_TARGET_POS_RECALCULATION_RANGE,
RATE_DURABILITY_LOSS_ON_DEATH,
RATE_DURABILITY_LOSS_DAMAGE,
RATE_DURABILITY_LOSS_PARRY,
+16 -12
View File
@@ -110,6 +110,10 @@ float World::_maxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
float World::_maxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE;
float World::_maxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
int32 World::m_visibility_notify_periodOnContinents = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
int32 World::m_visibility_notify_periodInInstances = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
int32 World::m_visibility_notify_periodInBGArenas = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
Realm realm;
/// World constructor
@@ -583,18 +587,6 @@ void World::LoadConfigSettings(bool reload)
for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) playerBaseMoveSpeed[i] = baseMoveSpeed[i] * _rate_values[RATE_MOVESPEED];
_rate_values[RATE_CORPSE_DECAY_LOOTED] = sConfigMgr->GetOption<float>("Rate.Corpse.Decay.Looted", 0.5f);
_rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = sConfigMgr->GetOption<float>("TargetPosRecalculateRange", 1.5f);
if (_rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] < CONTACT_DISTANCE)
{
LOG_ERROR("server.loading", "TargetPosRecalculateRange ({}) must be >= {}. Using {} instead.", _rate_values[RATE_TARGET_POS_RECALCULATION_RANGE], CONTACT_DISTANCE, CONTACT_DISTANCE);
_rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = CONTACT_DISTANCE;
}
else if (_rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] > NOMINAL_MELEE_RANGE)
{
LOG_ERROR("server.loading", "TargetPosRecalculateRange ({}) must be <= {}. Using {} instead.", _rate_values[RATE_TARGET_POS_RECALCULATION_RANGE], NOMINAL_MELEE_RANGE, NOMINAL_MELEE_RANGE);
_rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = NOMINAL_MELEE_RANGE;
}
_rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = sConfigMgr->GetOption<float>("DurabilityLoss.OnDeath", 10.0f);
if (_rate_values[RATE_DURABILITY_LOSS_ON_DEATH] < 0.0f)
{
@@ -667,6 +659,14 @@ void World::LoadConfigSettings(bool reload)
LOG_ERROR("server.loading", "PlayerSave.Stats.MinLevel ({}) must be in range 0..80. Using default, do not save character stats (0).", _int_configs[CONFIG_MIN_LEVEL_STAT_SAVE]);
_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = 0;
}
_int_configs[CONFIG_INTERVAL_GRIDCLEAN] = sConfigMgr->GetOption("GridCleanUpDelay", 5 * MINUTE * IN_MILLISECONDS);
if (_int_configs[CONFIG_INTERVAL_GRIDCLEAN] < MIN_GRID_DELAY)
{
LOG_ERROR("server.loading", "GridCleanUpDelay ({}) must be greater {}. Use this minimal value.", _int_configs[CONFIG_INTERVAL_GRIDCLEAN], MIN_GRID_DELAY);
_int_configs[CONFIG_INTERVAL_GRIDCLEAN] = MIN_GRID_DELAY;
}
if (reload)
sMapMgr->SetGridCleanUpDelay(_int_configs[CONFIG_INTERVAL_GRIDCLEAN]);
_int_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfigMgr->GetOption<int32>("MapUpdateInterval", 10);
if (_int_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY)
@@ -1261,6 +1261,10 @@ void World::LoadConfigSettings(bool reload)
_maxVisibleDistanceInBGArenas = MAX_VISIBILITY_DISTANCE;
}
m_visibility_notify_periodOnContinents = sConfigMgr->GetOption<int32>("Visibility.Notify.Period.OnContinents", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
m_visibility_notify_periodInInstances = sConfigMgr->GetOption<int32>("Visibility.Notify.Period.InInstances", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
m_visibility_notify_periodInBGArenas = sConfigMgr->GetOption<int32>("Visibility.Notify.Period.InBGArenas", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
///- Load the CharDelete related config options
_int_configs[CONFIG_CHARDELETE_METHOD] = sConfigMgr->GetOption<int32>("CharDelete.Method", 0);
_int_configs[CONFIG_CHARDELETE_MIN_LEVEL] = sConfigMgr->GetOption<int32>("CharDelete.MinLevel", 0);
+8
View File
@@ -322,6 +322,10 @@ public:
static float GetMaxVisibleDistanceInInstances() { return _maxVisibleDistanceInInstances; }
static float GetMaxVisibleDistanceInBGArenas() { return _maxVisibleDistanceInBGArenas; }
static int32 GetVisibilityNotifyPeriodOnContinents() { return m_visibility_notify_periodOnContinents; }
static int32 GetVisibilityNotifyPeriodInInstances() { return m_visibility_notify_periodInInstances; }
static int32 GetVisibilityNotifyPeriodInBGArenas() { return m_visibility_notify_periodInBGArenas; }
// our: needed for arena spectator subscriptions
uint32 GetNextWhoListUpdateDelaySecs() override;
@@ -415,6 +419,10 @@ private:
static float _maxVisibleDistanceInInstances;
static float _maxVisibleDistanceInBGArenas;
static int32 m_visibility_notify_periodOnContinents;
static int32 m_visibility_notify_periodInInstances;
static int32 m_visibility_notify_periodInBGArenas;
std::string _realmName;
// CLI command holder to be thread safe