Merge branch 'master' into Playerbot
# Conflicts: # src/server/game/Entities/Player/Player.h
This commit is contained in:
@@ -577,6 +577,7 @@ void BossAI::_Reset()
|
||||
events.Reset();
|
||||
scheduler.CancelAll();
|
||||
summons.DespawnAll();
|
||||
_healthCheckEvents.clear();
|
||||
if (instance)
|
||||
instance->SetBossState(_bossId, NOT_STARTED);
|
||||
}
|
||||
@@ -586,6 +587,7 @@ void BossAI::_JustDied()
|
||||
events.Reset();
|
||||
scheduler.CancelAll();
|
||||
summons.DespawnAll();
|
||||
_healthCheckEvents.clear();
|
||||
if (instance)
|
||||
{
|
||||
instance->SetBossState(_bossId, DONE);
|
||||
@@ -667,6 +669,39 @@ void BossAI::UpdateAI(uint32 diff)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void BossAI::DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/)
|
||||
{
|
||||
if (!_healthCheckEvents.empty())
|
||||
{
|
||||
_healthCheckEvents.remove_if([&](HealthCheckEventData data) -> bool
|
||||
{
|
||||
return _ProccessHealthCheckEvent(data._healthPct, damage, data._exec);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Executes a function once the creature reaches the defined health point percent.
|
||||
*
|
||||
* @param healthPct The health percent at which the code will be executed.
|
||||
* @param exec The fuction to be executed.
|
||||
*/
|
||||
void BossAI::ScheduleHealthCheckEvent(uint32 healthPct, std::function<void()> exec)
|
||||
{
|
||||
_healthCheckEvents.push_back(HealthCheckEventData(healthPct, exec));
|
||||
};
|
||||
|
||||
bool BossAI::_ProccessHealthCheckEvent(uint8 healthPct, uint32 damage, std::function<void()> exec) const
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(healthPct, damage))
|
||||
{
|
||||
exec();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// WorldBossAI - for non-instanced bosses
|
||||
|
||||
WorldBossAI::WorldBossAI(Creature* creature) :
|
||||
|
||||
@@ -139,6 +139,20 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void DoForAllSummons(std::function<void(WorldObject*)> exec)
|
||||
{
|
||||
// We need to use a copy of SummonList here, otherwise original SummonList would be modified
|
||||
StorageType listCopy = storage_;
|
||||
|
||||
for (auto const& guid : listCopy)
|
||||
{
|
||||
if (WorldObject* summon = ObjectAccessor::GetWorldObject(*me, guid))
|
||||
{
|
||||
exec(summon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoZoneInCombat(uint32 entry = 0);
|
||||
void RemoveNotExisting();
|
||||
bool HasEntry(uint32 entry) const;
|
||||
@@ -430,6 +444,14 @@ private:
|
||||
bool _isHeroic;
|
||||
};
|
||||
|
||||
struct HealthCheckEventData
|
||||
{
|
||||
HealthCheckEventData(uint8 healthPct, std::function<void()> exec) : _healthPct(healthPct), _exec(exec) { };
|
||||
|
||||
uint8 _healthPct;
|
||||
std::function<void()> _exec;
|
||||
};
|
||||
|
||||
class BossAI : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
@@ -440,12 +462,15 @@ public:
|
||||
|
||||
bool CanRespawn() override;
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override;
|
||||
void JustSummoned(Creature* summon) override;
|
||||
void SummonedCreatureDespawn(Creature* summon) override;
|
||||
void SummonedCreatureDespawnAll() override;
|
||||
|
||||
void UpdateAI(uint32 diff) override;
|
||||
|
||||
void ScheduleHealthCheckEvent(uint32 healthPct, std::function<void()> exec);
|
||||
|
||||
// Hook used to execute events scheduled into EventMap without the need
|
||||
// to override UpdateAI
|
||||
// note: You must re-schedule the event within this method if the event
|
||||
@@ -464,6 +489,7 @@ protected:
|
||||
void _JustEngagedWith();
|
||||
void _JustDied();
|
||||
void _JustReachedHome() { me->setActive(false); }
|
||||
[[nodiscard]] bool _ProccessHealthCheckEvent(uint8 healthPct, uint32 damage, std::function<void()> exec) const;
|
||||
|
||||
void TeleportCheaters();
|
||||
|
||||
@@ -473,6 +499,7 @@ protected:
|
||||
|
||||
private:
|
||||
uint32 const _bossId;
|
||||
std::list<HealthCheckEventData> _healthCheckEvents;
|
||||
};
|
||||
|
||||
class WorldBossAI : public ScriptedAI
|
||||
|
||||
@@ -129,12 +129,12 @@ void AutobroadcastMgr::SendAutobroadcasts()
|
||||
LOG_DEBUG("autobroadcast", "AutobroadcastMgr::SendAutobroadcasts: '{}'", msg);
|
||||
}
|
||||
|
||||
void AutobroadcastMgr::SendWorldAnnouncement(std::string_view msg)
|
||||
void AutobroadcastMgr::SendWorldAnnouncement(std::string msg)
|
||||
{
|
||||
sWorld->SendWorldTextOptional(LANG_AUTO_BROADCAST, ANNOUNCER_FLAG_DISABLE_AUTOBROADCAST, msg.data());
|
||||
}
|
||||
|
||||
void AutobroadcastMgr::SendNotificationAnnouncement(std::string_view msg)
|
||||
void AutobroadcastMgr::SendNotificationAnnouncement(std::string msg)
|
||||
{
|
||||
WorldPacket data(SMSG_NOTIFICATION, (msg.size() + 1));
|
||||
data << msg.data();
|
||||
|
||||
@@ -37,8 +37,8 @@ public:
|
||||
void SendAutobroadcasts();
|
||||
|
||||
private:
|
||||
void SendWorldAnnouncement(std::string_view msg);
|
||||
void SendNotificationAnnouncement(std::string_view msg);
|
||||
void SendWorldAnnouncement(std::string msg);
|
||||
void SendNotificationAnnouncement(std::string msg);
|
||||
|
||||
typedef std::map<uint8, std::string> AutobroadcastsMap;
|
||||
typedef std::map<uint8, uint8> AutobroadcastsWeightMap;
|
||||
|
||||
@@ -281,7 +281,7 @@ bool ArenaTeam::LoadMembersFromDB(QueryResult result)
|
||||
|
||||
bool ArenaTeam::SetName(std::string const& name)
|
||||
{
|
||||
if (TeamName == name || name.empty() || name.length() > 24 || sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
if (TeamName == name || name.empty() || name.length() > 24 || sObjectMgr->IsReservedName(name) || sObjectMgr->IsProfanityName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
return false;
|
||||
|
||||
TeamName = name;
|
||||
|
||||
@@ -895,8 +895,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundTypeId
|
||||
{
|
||||
if (!(*itr3)->IsInvitedToBGInstanceGUID
|
||||
&& (((*itr3)->ArenaMatchmakerRating >= arenaMinRating && (*itr3)->ArenaMatchmakerRating <= arenaMaxRating) || (int32)(*itr3)->JoinTime < discardTime)
|
||||
&& ((*itr_teams[0])->ArenaTeamId != (*itr3)->PreviousOpponentsTeamId || ((int32)(*itr3)->JoinTime < discardOpponentsTime))
|
||||
&& (*itr_teams[0])->ArenaTeamId != (*itr3)->ArenaTeamId)
|
||||
&& ((*(itr_teams[0]))->ArenaTeamId != (*itr3)->PreviousOpponentsTeamId || ((int32)(*itr3)->JoinTime < discardOpponentsTime))
|
||||
&& (*(itr_teams[0]))->ArenaTeamId != (*itr3)->ArenaTeamId)
|
||||
{
|
||||
itr_teams[found++] = itr3;
|
||||
break;
|
||||
@@ -907,8 +907,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundTypeId
|
||||
//if we have 2 teams, then start new arena and invite players!
|
||||
if (found == 2)
|
||||
{
|
||||
GroupQueueInfo* aTeam = *itr_teams[TEAM_ALLIANCE];
|
||||
GroupQueueInfo* hTeam = *itr_teams[TEAM_HORDE];
|
||||
GroupQueueInfo* aTeam = *(itr_teams[TEAM_ALLIANCE]);
|
||||
GroupQueueInfo* hTeam = *(itr_teams[TEAM_HORDE]);
|
||||
|
||||
Battleground* arena = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, arenaType, true);
|
||||
if (!arena)
|
||||
|
||||
@@ -459,17 +459,8 @@ bool Creature::InitEntry(uint32 Entry, const CreatureData* data)
|
||||
|
||||
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f);
|
||||
|
||||
float runSpeed = cinfo->speed_run;
|
||||
if (Pet* pet = ToPet())
|
||||
{
|
||||
if (pet->isControlled() && pet->GetOwnerGUID().IsPlayer())
|
||||
{
|
||||
runSpeed = 1.15f;
|
||||
}
|
||||
}
|
||||
|
||||
SetSpeed(MOVE_WALK, cinfo->speed_walk);
|
||||
SetSpeed(MOVE_RUN, runSpeed);
|
||||
SetSpeed(MOVE_RUN, cinfo->speed_run);
|
||||
SetSpeed(MOVE_SWIM, cinfo->speed_swim);
|
||||
SetSpeed(MOVE_FLIGHT, cinfo->speed_flight);
|
||||
|
||||
|
||||
@@ -392,6 +392,12 @@ public:
|
||||
|
||||
void ModifyThreatPercentTemp(Unit* victim, int32 percent, Milliseconds duration);
|
||||
|
||||
/**
|
||||
* @brief Helper to resume chasing current victim.
|
||||
*
|
||||
* */
|
||||
void ResumeChasingVictim() { GetMotionMaster()->MoveChase(GetVictim()); };
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1344,7 +1344,7 @@ bool GameObject::ActivateToQuest(Player* target) const
|
||||
case GAMEOBJECT_TYPE_CHEST:
|
||||
{
|
||||
// scan GO chest with loot including quest items
|
||||
if (LootTemplates_Gameobject.HaveQuestLootForPlayer(GetGOInfo()->GetLootId(), target))
|
||||
if (target->GetQuestStatus(GetGOInfo()->chest.questId) == QUEST_STATUS_INCOMPLETE || LootTemplates_Gameobject.HaveQuestLootForPlayer(GetGOInfo()->GetLootId(), target))
|
||||
{
|
||||
//TODO: fix this hack
|
||||
//look for battlegroundAV for some objects which are only activated after mine gots captured by own team
|
||||
|
||||
@@ -1048,6 +1048,11 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
||||
else if (petType != SUMMON_PET)
|
||||
LOG_ERROR("entities.pet", "Unknown type pet {} is summoned by player class {}", GetEntry(), owner->getClass());
|
||||
}
|
||||
|
||||
if (petType == HUNTER_PET || petType == SUMMON_PET)
|
||||
{
|
||||
SetSpeed(MOVE_RUN, 1.15f);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 creature_ID = (petType == HUNTER_PET) ? 1 : cinfo->Entry;
|
||||
|
||||
@@ -9185,32 +9185,47 @@ Pet* Player::CreatePet(uint32 creatureEntry, uint32 spellID /*= 0*/)
|
||||
return pet;
|
||||
}
|
||||
|
||||
void Player::StopCastingCharm()
|
||||
void Player::StopCastingCharm(Aura* except /*= nullptr*/)
|
||||
{
|
||||
Unit* charm = GetCharm();
|
||||
if (!charm)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (charm->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
if (charm->ToCreature()->HasUnitTypeMask(UNIT_MASK_PUPPET))
|
||||
{
|
||||
((Puppet*)charm)->UnSummon();
|
||||
}
|
||||
else if (charm->IsVehicle())
|
||||
{
|
||||
ExitVehicle();
|
||||
}
|
||||
}
|
||||
|
||||
if (GetCharmGUID())
|
||||
charm->RemoveCharmAuras();
|
||||
{
|
||||
charm->RemoveAurasByType(SPELL_AURA_MOD_CHARM, ObjectGuid::Empty, except);
|
||||
charm->RemoveAurasByType(SPELL_AURA_MOD_POSSESS_PET, ObjectGuid::Empty, except);
|
||||
charm->RemoveAurasByType(SPELL_AURA_MOD_POSSESS, ObjectGuid::Empty, except);
|
||||
charm->RemoveAurasByType(SPELL_AURA_AOE_CHARM, ObjectGuid::Empty, except);
|
||||
}
|
||||
|
||||
if (GetCharmGUID())
|
||||
{
|
||||
LOG_FATAL("entities.player", "Player {} ({} is not able to uncharm unit ({})", GetName(), GetGUID().ToString(), GetCharmGUID().ToString());
|
||||
|
||||
if (charm->GetCharmerGUID())
|
||||
{
|
||||
LOG_FATAL("entities.player", "Charmed unit has charmer {}", charm->GetCharmerGUID().ToString());
|
||||
ABORT();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCharm(charm, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10800,7 +10815,6 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite
|
||||
// cooldown information stored in item prototype
|
||||
// This used in same way in WorldSession::HandleItemQuerySingleOpcode data sending to client.
|
||||
|
||||
bool useSpellCooldown = spellInfo->HasAttribute(SPELL_ATTR7_CAN_BE_MULTI_CAST);
|
||||
if (itemId)
|
||||
{
|
||||
if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId))
|
||||
@@ -10812,12 +10826,6 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite
|
||||
cat = proto->Spells[idx].SpellCategory;
|
||||
rec = proto->Spells[idx].SpellCooldown;
|
||||
catrec = proto->Spells[idx].SpellCategoryCooldown;
|
||||
|
||||
if (static_cast<int32>(cat) != catrec)
|
||||
{
|
||||
useSpellCooldown = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -10854,14 +10862,7 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite
|
||||
|
||||
// Now we have cooldown data (if found any), time to apply mods
|
||||
if (rec > 0)
|
||||
{
|
||||
int32 oldRec = rec;
|
||||
ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, rec, spell);
|
||||
if (oldRec != rec)
|
||||
{
|
||||
useSpellCooldown = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (catrec > 0 && !spellInfo->HasAttribute(SPELL_ATTR6_NO_CATEGORY_COOLDOWN_MODS))
|
||||
{
|
||||
@@ -10874,7 +10875,6 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite
|
||||
if (HasSpell(spellInfo->Id))
|
||||
{
|
||||
needsCooldownPacket = true;
|
||||
useSpellCooldown = true;
|
||||
rec += cooldownMod * IN_MILLISECONDS; // SPELL_AURA_MOD_COOLDOWN does not affect category cooldows, verified with shaman shocks
|
||||
}
|
||||
}
|
||||
@@ -10894,11 +10894,11 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite
|
||||
// category spells
|
||||
if (cat && catrec > 0)
|
||||
{
|
||||
_AddSpellCooldown(spellInfo->Id, cat, itemId, useSpellCooldown ? recTime : catrecTime, true, true);
|
||||
_AddSpellCooldown(spellInfo->Id, 0, itemId, recTime, true, true);
|
||||
if (needsCooldownPacket)
|
||||
{
|
||||
WorldPacket data;
|
||||
BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, spellInfo->Id, useSpellCooldown ? recTime : catrecTime);
|
||||
BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, spellInfo->Id, recTime);
|
||||
SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
@@ -13048,15 +13048,15 @@ bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void Player::StopCastingBindSight()
|
||||
void Player::StopCastingBindSight(Aura* except /*= nullptr*/)
|
||||
{
|
||||
if (WorldObject* target = GetViewpoint())
|
||||
{
|
||||
if (target->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
((Unit*)target)->RemoveAurasByType(SPELL_AURA_BIND_SIGHT, GetGUID());
|
||||
((Unit*)target)->RemoveAurasByType(SPELL_AURA_MOD_POSSESS, GetGUID());
|
||||
((Unit*)target)->RemoveAurasByType(SPELL_AURA_MOD_POSSESS_PET, GetGUID());
|
||||
((Unit*)target)->RemoveAurasByType(SPELL_AURA_BIND_SIGHT, GetGUID(), except);
|
||||
((Unit*)target)->RemoveAurasByType(SPELL_AURA_MOD_POSSESS, GetGUID(), except);
|
||||
((Unit*)target)->RemoveAurasByType(SPELL_AURA_MOD_POSSESS_PET, GetGUID(), except);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16237,3 +16237,8 @@ std::string Player::GetDebugInfo() const
|
||||
sstr << Unit::GetDebugInfo();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
void Player::SendSystemMessage(std::string_view msg, bool escapeCharacters)
|
||||
{
|
||||
ChatHandler(GetSession()).SendSysMessage(msg, escapeCharacters);
|
||||
}
|
||||
|
||||
@@ -2298,8 +2298,8 @@ public:
|
||||
void SetSeer(WorldObject* target) { m_seer = target; }
|
||||
void SetViewpoint(WorldObject* target, bool apply);
|
||||
[[nodiscard]] WorldObject* GetViewpoint() const;
|
||||
void StopCastingCharm();
|
||||
void StopCastingBindSight();
|
||||
void StopCastingCharm(Aura* except = nullptr);
|
||||
void StopCastingBindSight(Aura* except = nullptr);
|
||||
|
||||
[[nodiscard]] uint32 GetSaveTimer() const { return m_nextSave; }
|
||||
void SetSaveTimer(uint32 timer) { m_nextSave = timer; }
|
||||
@@ -2575,6 +2575,8 @@ public:
|
||||
[[nodiscard]] PlayerSetting GetPlayerSetting(std::string source, uint8 index);
|
||||
void UpdatePlayerSetting(std::string source, uint8 index, uint32 value);
|
||||
|
||||
void SendSystemMessage(std::string_view msg, bool escapeCharacters = false);
|
||||
|
||||
void ResetSpeakTimers();
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
@@ -1314,6 +1314,7 @@ bool Player::SatisfyQuestSeasonal(Quest const* qInfo, bool /*msg*/) const
|
||||
if (!qInfo->IsSeasonal() || m_seasonalquests.empty())
|
||||
return true;
|
||||
|
||||
// cppcheck-suppress mismatchingContainers
|
||||
Player::SeasonalEventQuestMap::iterator itr = ((Player*)this)->m_seasonalquests.find(qInfo->GetEventIdForQuest());
|
||||
|
||||
if (itr == m_seasonalquests.end() || itr->second.empty())
|
||||
|
||||
@@ -4990,7 +4990,7 @@ bool Player::LoadFromDB(ObjectGuid playerGuid, CharacterDatabaseQueryHolder cons
|
||||
|
||||
// check name limitations
|
||||
if (ObjectMgr::CheckPlayerName(m_name) != CHAR_NAME_SUCCESS ||
|
||||
(AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()) && sObjectMgr->IsReservedName(m_name)))
|
||||
(AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()) && (sObjectMgr->IsReservedName(m_name) || sObjectMgr->IsProfanityName(m_name))))
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
|
||||
stmt->SetData(0, uint16(AT_LOGIN_RENAME));
|
||||
|
||||
@@ -10717,11 +10717,6 @@ void Unit::SetMinion(Minion* minion, bool apply)
|
||||
// PvP, FFAPvP
|
||||
minion->SetByteValue(UNIT_FIELD_BYTES_2, 1, GetByteValue(UNIT_FIELD_BYTES_2, 1));
|
||||
|
||||
// FIXME: hack, speed must be set only at follow
|
||||
if (GetTypeId() == TYPEID_PLAYER && minion->IsPet())
|
||||
for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
|
||||
minion->SetSpeed(UnitMoveType(i), m_speed_rate[i], true);
|
||||
|
||||
// Ghoul pets have energy instead of mana (is anywhere better place for this code?)
|
||||
if (minion->IsPetGhoul() || minion->GetEntry() == 24207 /*ENTRY_ARMY_OF_THE_DEAD*/)
|
||||
minion->setPowerType(POWER_ENERGY);
|
||||
@@ -14268,7 +14263,17 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
|
||||
{
|
||||
// Set creature speed rate
|
||||
if (GetTypeId() == TYPEID_UNIT)
|
||||
speed *= ToCreature()->GetCreatureTemplate()->speed_run; // at this point, MOVE_WALK is never reached
|
||||
{
|
||||
if (IsPet() && ToPet()->isControlled() && IsControlledByPlayer())
|
||||
{
|
||||
// contant value for player pets
|
||||
speed *= 1.15f;
|
||||
}
|
||||
else
|
||||
{
|
||||
speed *= ToCreature()->GetCreatureTemplate()->speed_run; // at this point, MOVE_WALK is never reached
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize speed by 191 aura SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED if need
|
||||
/// @todo possible affect only on MOVE_RUN
|
||||
@@ -15397,7 +15402,7 @@ void Unit::SetHealth(uint32 val)
|
||||
SetUInt32Value(UNIT_FIELD_HEALTH, val);
|
||||
|
||||
// mobs that are now or were below 30% need to update their speed
|
||||
if (GetTypeId() == TYPEID_UNIT && (prevHealthPct < 30.0 || HealthBelowPct(30)))
|
||||
if (GetTypeId() == TYPEID_UNIT && !(IsPet() && ToPet()->isControlled() && IsControlledByPlayer()) && (prevHealthPct < 30.0 || HealthBelowPct(30)))
|
||||
{
|
||||
UpdateSpeed(MOVE_RUN, false);
|
||||
}
|
||||
@@ -15905,7 +15910,10 @@ bool CharmInfo::AddSpellToActionBar(SpellInfo const* spellInfo, ActiveStates new
|
||||
{
|
||||
WorldPacket data;
|
||||
creature->BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, spell_id, cooldown);
|
||||
creature->GetCharmer()->ToPlayer()->SendDirectMessage(&data);
|
||||
if (creature->GetCharmer() && creature->GetCharmer()->IsPlayer())
|
||||
{
|
||||
creature->GetCharmer()->ToPlayer()->SendDirectMessage(&data);
|
||||
}
|
||||
}
|
||||
}, 500ms);
|
||||
}
|
||||
@@ -18586,15 +18594,15 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
||||
// Charmer stop charming
|
||||
if (playerCharmer)
|
||||
{
|
||||
playerCharmer->StopCastingCharm();
|
||||
playerCharmer->StopCastingBindSight();
|
||||
playerCharmer->StopCastingCharm(aurApp ? aurApp->GetBase() : nullptr);
|
||||
playerCharmer->StopCastingBindSight(aurApp ? aurApp->GetBase() : nullptr);
|
||||
}
|
||||
|
||||
// Charmed stop charming
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
ToPlayer()->StopCastingCharm();
|
||||
ToPlayer()->StopCastingBindSight();
|
||||
ToPlayer()->StopCastingCharm(aurApp ? aurApp->GetBase() : nullptr);
|
||||
ToPlayer()->StopCastingBindSight(aurApp ? aurApp->GetBase() : nullptr);
|
||||
}
|
||||
|
||||
// StopCastingCharm may remove a possessed pet?
|
||||
@@ -18706,8 +18714,11 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
||||
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(GameTime::GetGameTime().count())); // cast can't be helped
|
||||
}
|
||||
}
|
||||
GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, GetFollowAngle());
|
||||
playerCharmer->CharmSpellInitialize();
|
||||
if (playerCharmer->m_seer != this)
|
||||
{
|
||||
GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, GetFollowAngle());
|
||||
playerCharmer->CharmSpellInitialize();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -19979,17 +19990,27 @@ void Unit::_ExitVehicle(Position const* exitPosition)
|
||||
pos = *exitPosition;
|
||||
|
||||
// HACK
|
||||
if (vehicle->GetVehicleInfo()->m_ID == 380) // Kologarn right arm
|
||||
pos.Relocate(1776.0f, -24.0f, 448.75f, 0.0f);
|
||||
else if (vehicle->GetVehicleInfo()->m_ID == 91) // Helsman's Ship
|
||||
pos.Relocate(2802.18f, 7054.91f, -0.6f, 4.67f);
|
||||
else if (vehicle->GetVehicleInfo()->m_ID == 349) // AT Mounts, dismount to the right
|
||||
VehicleEntry const* vehicleInfo = vehicle->GetVehicleInfo();
|
||||
if (vehicleInfo)
|
||||
{
|
||||
float x = pos.GetPositionX() + 2.0f * cos(pos.GetOrientation() - M_PI / 2.0f);
|
||||
float y = pos.GetPositionY() + 2.0f * std::sin(pos.GetOrientation() - M_PI / 2.0f);
|
||||
float z = GetMapHeight(x, y, pos.GetPositionZ());
|
||||
if (z > INVALID_HEIGHT)
|
||||
pos.Relocate(x, y, z);
|
||||
if (vehicleInfo->m_ID == 380) // Kologarn right arm
|
||||
{
|
||||
pos.Relocate(1776.0f, -24.0f, 448.75f, 0.0f);
|
||||
}
|
||||
else if (vehicleInfo->m_ID == 91) // Helsman's Ship
|
||||
{
|
||||
pos.Relocate(2802.18f, 7054.91f, -0.6f, 4.67f);
|
||||
}
|
||||
else if (vehicleInfo->m_ID == 349) // AT Mounts, dismount to the right
|
||||
{
|
||||
float x = pos.GetPositionX() + 2.0f * cos(pos.GetOrientation() - M_PI / 2.0f);
|
||||
float y = pos.GetPositionY() + 2.0f * std::sin(pos.GetOrientation() - M_PI / 2.0f);
|
||||
float z = GetMapHeight(x, y, pos.GetPositionZ());
|
||||
if (z > INVALID_HEIGHT)
|
||||
{
|
||||
pos.Relocate(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddUnitState(UNIT_STATE_MOVE);
|
||||
@@ -20009,7 +20030,7 @@ void Unit::_ExitVehicle(Position const* exitPosition)
|
||||
}
|
||||
|
||||
// xinef: hack for flameleviathan seat vehicle
|
||||
if (vehicle->GetVehicleInfo()->m_ID != 341)
|
||||
if (!vehicleInfo || vehicleInfo->m_ID != 341)
|
||||
{
|
||||
Movement::MoveSplineInit init(this);
|
||||
init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ());
|
||||
@@ -20031,16 +20052,18 @@ void Unit::_ExitVehicle(Position const* exitPosition)
|
||||
}
|
||||
|
||||
// xinef: move fall, should we support all creatures that exited vehicle in air? Currently Quest Drag and Drop only, Air Assault quest
|
||||
if (GetTypeId() == TYPEID_UNIT && !CanFly() &&
|
||||
(vehicle->GetVehicleInfo()->m_ID == 113 || vehicle->GetVehicleInfo()->m_ID == 8 || vehicle->GetVehicleInfo()->m_ID == 290 || vehicle->GetVehicleInfo()->m_ID == 298))
|
||||
if (GetTypeId() == TYPEID_UNIT && !CanFly() && vehicleInfo && (vehicleInfo->m_ID == 113 || vehicleInfo->m_ID == 8 || vehicleInfo->m_ID == 290 || vehicleInfo->m_ID == 298))
|
||||
{
|
||||
GetMotionMaster()->MoveFall();
|
||||
//GetMotionMaster()->MoveFall(); // Enable this once passenger positions are calculater properly (see above)
|
||||
}
|
||||
|
||||
if ((!player || !(player->GetDelayedOperations() & DELAYED_VEHICLE_TELEPORT)) && vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION))
|
||||
if (((Minion*)vehicleBase)->GetOwner() == this)
|
||||
{
|
||||
if (vehicle->GetVehicleInfo()->m_ID != 349)
|
||||
if (!vehicleInfo || vehicleInfo->m_ID != 349)
|
||||
{
|
||||
vehicle->Dismiss();
|
||||
}
|
||||
else if (vehicleBase->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
vehicle->Uninstall();
|
||||
|
||||
@@ -1337,7 +1337,7 @@ public:
|
||||
|
||||
void Update(uint32 time) override;
|
||||
|
||||
void setAttackTimer(WeaponAttackType type, int32 time) { m_attackTimer[type] = time; }
|
||||
void setAttackTimer(WeaponAttackType type, int32 time) { m_attackTimer[type] = time; } /// @todo - Look to convert to std::chrono
|
||||
void resetAttackTimer(WeaponAttackType type = BASE_ATTACK);
|
||||
[[nodiscard]] int32 getAttackTimer(WeaponAttackType type) const { return m_attackTimer[type]; }
|
||||
[[nodiscard]] bool isAttackReady(WeaponAttackType type = BASE_ATTACK) const { return m_attackTimer[type] <= 0; }
|
||||
@@ -2467,6 +2467,8 @@ public:
|
||||
|
||||
bool m_cannotReachTarget;
|
||||
|
||||
[[nodiscard]] uint32 GetOldFactionId() const { return _oldFactionId; }
|
||||
|
||||
protected:
|
||||
explicit Unit (bool isWorldObject);
|
||||
|
||||
|
||||
@@ -8204,6 +8204,81 @@ void ObjectMgr::AddReservedPlayerName(std::string const& name)
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadProfanityPlayersNames()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
_profanityNamesStore.clear(); // need for reload case
|
||||
|
||||
QueryResult result = CharacterDatabase.Query("SELECT name FROM profanity_name");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
LOG_WARN("server.loading", ">> Loaded 0 profanity player names. DB table `profanity_name` is empty!");
|
||||
LOG_INFO("server.loading", " ");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 count = 0;
|
||||
|
||||
Field* fields;
|
||||
do
|
||||
{
|
||||
fields = result->Fetch();
|
||||
std::string name = fields[0].Get<std::string>();
|
||||
|
||||
std::wstring wstr;
|
||||
if (!Utf8toWStr (name, wstr))
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `profanity_name` have invalid name: {}", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
wstrToLower(wstr);
|
||||
|
||||
_profanityNamesStore.insert(wstr);
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} profanity player names in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
bool ObjectMgr::IsProfanityName(std::string_view name) const
|
||||
{
|
||||
// pussywizard
|
||||
if (name.size() >= 2 && (name[name.size() - 2] == 'G' || name[name.size() - 2] == 'g') && (name[name.size() - 1] == 'M' || name[name.size() - 1] == 'm'))
|
||||
return true;
|
||||
|
||||
std::wstring wstr;
|
||||
if (!Utf8toWStr (name, wstr))
|
||||
return false;
|
||||
|
||||
wstrToLower(wstr);
|
||||
|
||||
return _profanityNamesStore.find(wstr) != _profanityNamesStore.end();
|
||||
}
|
||||
|
||||
void ObjectMgr::AddProfanityPlayerName(std::string const& name)
|
||||
{
|
||||
if (!IsProfanityName(name))
|
||||
{
|
||||
std::wstring wstr;
|
||||
if (!Utf8toWStr(name, wstr))
|
||||
{
|
||||
LOG_ERROR("server", "Could not add invalid name to profanity player names: {}", name);
|
||||
return;
|
||||
}
|
||||
wstrToLower(wstr);
|
||||
|
||||
_profanityNamesStore.insert(wstr);
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PROFANITY_PLAYER_NAME);
|
||||
stmt->SetData(0, name);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
enum LanguageType
|
||||
{
|
||||
LT_BASIC_LATIN = 0x0000,
|
||||
@@ -8311,6 +8386,11 @@ uint8 ObjectMgr::CheckPlayerName(std::string_view name, bool create)
|
||||
return CHAR_NAME_RESERVED;
|
||||
}
|
||||
|
||||
if (sObjectMgr->IsProfanityName(name))
|
||||
{
|
||||
return CHAR_NAME_PROFANE;
|
||||
}
|
||||
|
||||
// Check for Reserved Name from DBC
|
||||
if (sWorld->getBoolConfig(CONFIG_STRICT_NAMES_RESERVED))
|
||||
{
|
||||
|
||||
@@ -1338,6 +1338,11 @@ public:
|
||||
[[nodiscard]] bool IsReservedName(std::string_view name) const;
|
||||
void AddReservedPlayerName(std::string const& name);
|
||||
|
||||
// profanity names
|
||||
void LoadProfanityPlayersNames();
|
||||
[[nodiscard]] bool IsProfanityName(std::string_view name) const;
|
||||
void AddProfanityPlayerName(std::string const& name);
|
||||
|
||||
// name with valid structure and symbols
|
||||
static uint8 CheckPlayerName(std::string_view name, bool create = false);
|
||||
static PetNameInvalidReason CheckPetName(std::string_view name);
|
||||
@@ -1507,6 +1512,10 @@ private:
|
||||
typedef std::set<std::wstring> ReservedNamesContainer;
|
||||
ReservedNamesContainer _reservedNamesStore;
|
||||
|
||||
//character profanity names
|
||||
typedef std::set<std::wstring> ProfanityNamesContainer;
|
||||
ReservedNamesContainer _profanityNamesStore;
|
||||
|
||||
GameTeleContainer _gameTeleStore;
|
||||
|
||||
ScriptNameContainer _scriptNamesStore;
|
||||
|
||||
@@ -860,7 +860,7 @@ namespace Acore
|
||||
AnyUnfriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {}
|
||||
bool operator()(Unit* u)
|
||||
{
|
||||
if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u) &&
|
||||
if (u->IsAlive() && !u->IsCritter() && i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u) &&
|
||||
(i_funit->GetTypeId() != TYPEID_UNIT || !i_funit->ToCreature()->IsAvoidingAOE())) // pussywizard
|
||||
return true;
|
||||
else
|
||||
|
||||
@@ -1184,7 +1184,7 @@ void Guild::OnPlayerStatusChange(Player* player, uint32 flag, bool state)
|
||||
|
||||
bool Guild::SetName(std::string_view const& name)
|
||||
{
|
||||
if (m_name == name || name.empty() || name.length() > 24 || sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
if (m_name == name || name.empty() || name.length() > 24 || sObjectMgr->IsReservedName(name) || sObjectMgr->IsProfanityName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -409,7 +409,10 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
|
||||
}
|
||||
|
||||
//Player is not looking at loot list, he doesn't need to see updates on the loot list
|
||||
loot->RemoveLooter(player->GetGUID());
|
||||
if (!lguid.IsItem())
|
||||
{
|
||||
loot->RemoveLooter(player->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData)
|
||||
|
||||
@@ -289,10 +289,6 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket& recvData)
|
||||
if (unit->GetNpcFlags() == UNIT_NPC_FLAG_NONE)
|
||||
return;
|
||||
|
||||
// xinef: do not allow to open gossip when npc is in combat
|
||||
if (unit->GetNpcFlags() == UNIT_NPC_FLAG_GOSSIP && unit->IsInCombat()) // should work on all flags?
|
||||
return;
|
||||
|
||||
// set faction visible if needed
|
||||
if (FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->GetFaction()))
|
||||
_player->GetReputationMgr().SetVisible(factionTemplateEntry);
|
||||
|
||||
@@ -861,6 +861,12 @@ void WorldSession::HandlePetRename(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
if (sObjectMgr->IsProfanityName(name))
|
||||
{
|
||||
SendPetNameInvalid(PET_NAME_PROFANE, name, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
pet->SetName(name);
|
||||
|
||||
Unit* owner = pet->GetOwner();
|
||||
|
||||
@@ -137,7 +137,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
if (sObjectMgr->IsReservedName(name) || sObjectMgr->IsProfanityName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
{
|
||||
Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_INVALID, name);
|
||||
return;
|
||||
@@ -150,7 +150,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
|
||||
return;
|
||||
}
|
||||
if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
if (sObjectMgr->IsReservedName(name) || sObjectMgr->IsProfanityName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
|
||||
return;
|
||||
@@ -351,7 +351,7 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket& recvData)
|
||||
Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_EXISTS_S, newName);
|
||||
return;
|
||||
}
|
||||
if (sObjectMgr->IsReservedName(newName) || !ObjectMgr::IsValidCharterName(newName))
|
||||
if (sObjectMgr->IsReservedName(newName) || sObjectMgr->IsProfanityName(newName) || !ObjectMgr::IsValidCharterName(newName))
|
||||
{
|
||||
Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_INVALID, newName);
|
||||
return;
|
||||
@@ -364,7 +364,7 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket& recvData)
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newName, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
|
||||
return;
|
||||
}
|
||||
if (sObjectMgr->IsReservedName(newName) || !ObjectMgr::IsValidCharterName(newName))
|
||||
if (sObjectMgr->IsReservedName(newName) || sObjectMgr->IsProfanityName(newName) || !ObjectMgr::IsValidCharterName(newName))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newName, "", ERR_ARENA_TEAM_NAME_INVALID);
|
||||
return;
|
||||
|
||||
@@ -612,6 +612,35 @@ void InstanceScript::DoCastSpellOnPlayers(uint32 spell)
|
||||
player->CastSpell(player, spell, true);
|
||||
}
|
||||
|
||||
void InstanceScript::DoCastSpellOnPlayer(Player* player, uint32 spell, bool includePets /*= false*/, bool includeControlled /*= false*/)
|
||||
{
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
player->CastSpell(player, spell, true);
|
||||
|
||||
if (!includePets)
|
||||
return;
|
||||
|
||||
for (uint8 itr2 = 0; itr2 < MAX_SUMMON_SLOT; ++itr2)
|
||||
{
|
||||
ObjectGuid summonGUID = player->m_SummonSlot[itr2];
|
||||
if (!summonGUID.IsEmpty())
|
||||
if (Creature* summon = instance->GetCreature(summonGUID))
|
||||
summon->CastSpell(player, spell, true);
|
||||
}
|
||||
|
||||
if (!includeControlled)
|
||||
return;
|
||||
|
||||
for (auto itr2 = player->m_Controlled.begin(); itr2 != player->m_Controlled.end(); ++itr2)
|
||||
{
|
||||
if (Unit* controlled = *itr2)
|
||||
if (controlled->IsInWorld() && controlled->GetTypeId() == TYPEID_UNIT)
|
||||
controlled->CastSpell(player, spell, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool InstanceScript::CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/ /*= nullptr*/, uint32 /*miscvalue1*/ /*= 0*/)
|
||||
{
|
||||
LOG_ERROR("scripts.ai", "Achievement system call InstanceScript::CheckAchievementCriteriaMeet but instance script for map {} not have implementation for achievement criteria {}",
|
||||
|
||||
@@ -220,6 +220,9 @@ public:
|
||||
// Cast spell on all players in instance
|
||||
void DoCastSpellOnPlayers(uint32 spell);
|
||||
|
||||
// Cast spell on player
|
||||
void DoCastSpellOnPlayer(Player* player, uint32 spell, bool includePets /*= false*/, bool includeControlled /*= false*/);
|
||||
|
||||
// Return wether server allow two side groups or not
|
||||
bool ServerAllowsTwoSideGroups() { return sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP); }
|
||||
|
||||
|
||||
@@ -190,6 +190,7 @@ uint32 LootStore::LoadLootTable()
|
||||
|
||||
// Looking for the template of the entry
|
||||
// often entries are put together
|
||||
// cppcheck-suppress eraseDereference
|
||||
if (m_LootTemplates.empty() || tab->first != entry)
|
||||
{
|
||||
// Searching the template (in case template Id changed)
|
||||
|
||||
@@ -218,7 +218,7 @@ enum AcoreStrings
|
||||
LANG_GRID_POSITION = 178,
|
||||
// 179-185 used in other client versions
|
||||
LANG_TRANSPORT_POSITION = 186,
|
||||
// 187
|
||||
LANG_PROFANITY_NAME = 187,
|
||||
LANG_2FA_SECRET_TOO_LONG = 188,
|
||||
LANG_2FA_SECRET_INVALID = 189,
|
||||
LANG_2FA_SECRET_SET_COMPLETE = 190,
|
||||
|
||||
@@ -296,7 +296,13 @@ static Optional<float> GetVelocity(Unit* owner, Unit* target, G3D::Vector3 const
|
||||
if (!owner->IsInCombat() && !owner->IsVehicle() && !owner->HasUnitFlag(UNIT_FLAG_POSSESSED) &&
|
||||
(owner->IsPet() || owner->IsGuardian() || owner->GetGUID() == target->GetCritterGUID() || owner->GetCharmerOrOwnerGUID() == target->GetGUID()))
|
||||
{
|
||||
UnitMoveType moveType = Movement::SelectSpeedType(target->GetUnitMovementFlags());
|
||||
uint32 moveFlags = target->GetUnitMovementFlags();
|
||||
if (target->movespline->isWalking())
|
||||
{
|
||||
moveFlags |= MOVEMENTFLAG_WALKING;
|
||||
}
|
||||
|
||||
UnitMoveType moveType = Movement::SelectSpeedType(moveFlags);
|
||||
speed = std::max(target->GetSpeed(moveType), owner->GetSpeed(moveType));
|
||||
|
||||
if (playerPet)
|
||||
@@ -503,8 +509,8 @@ bool FollowMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MovebyPath(i_path->GetPath());
|
||||
init.SetWalk(target->IsWalking());
|
||||
if (Optional<float> velocity = GetVelocity(owner, target, i_path->GetActualEndPosition(), owner->IsGuardian() && target->GetTypeId() == TYPEID_PLAYER))
|
||||
init.SetWalk(target->IsWalking() || target->movespline->isWalking());
|
||||
if (Optional<float> velocity = GetVelocity(owner, target, i_path->GetActualEndPosition(), owner->IsGuardian()))
|
||||
init.SetVelocity(*velocity);
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
@@ -1102,8 +1102,12 @@ void WorldSession::ReadMovementInfo(WorldPacket& data, MovementInfo* mi)
|
||||
e.g. aerial combat.
|
||||
*/
|
||||
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && GetSecurity() == SEC_PLAYER && !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) && !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED),
|
||||
MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY);
|
||||
if (mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && GetSecurity() == SEC_PLAYER && !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) && !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED))
|
||||
{
|
||||
// Inform the client we can no longer fly, which is required if data mismatches for some reason
|
||||
// Like flight auras being removed but the client still sends flight movement packets.
|
||||
GetPlayer()->SetCanFly(false);
|
||||
}
|
||||
|
||||
//! Cannot fly and fall at the same time
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY) && mi->HasMovementFlag(MOVEMENTFLAG_FALLING),
|
||||
|
||||
@@ -6032,13 +6032,6 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster)
|
||||
Unit::Kill(target, target);
|
||||
return;
|
||||
}
|
||||
// Spellcloth
|
||||
case 31373:
|
||||
{
|
||||
// Summon Elemental after create item
|
||||
target->SummonCreature(17870, 0, 0, 0, target->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
return;
|
||||
}
|
||||
// Eye of Grillok
|
||||
case 38495:
|
||||
triggerSpellId = 38530;
|
||||
|
||||
@@ -131,7 +131,7 @@ public:
|
||||
int32 CalcMaxDuration() const { return CalcMaxDuration(GetCaster()); }
|
||||
int32 CalcMaxDuration(Unit* caster) const;
|
||||
int32 GetDuration() const { return m_duration; }
|
||||
void SetDuration(int32 duration, bool withMods = false);
|
||||
void SetDuration(int32 duration, bool withMods = false); /// @todo - Look to convert to std::chrono
|
||||
void RefreshDuration(bool withMods = false);
|
||||
void RefreshTimers(bool periodicReset = false);
|
||||
void RefreshTimersWithMods();
|
||||
|
||||
@@ -3352,6 +3352,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
|
||||
// some spell specific modifiers
|
||||
float totalDamagePercentMod = 100.0f; // applied to final bonus+weapon damage
|
||||
int32 spell_bonus = 0; // bonus specific for spell
|
||||
bool normalized = false;
|
||||
|
||||
switch (m_spellInfo->SpellFamilyName)
|
||||
{
|
||||
@@ -3438,6 +3439,18 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
|
||||
spell_bonus += int32(0.08f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
|
||||
spell_bonus += int32(0.13f * m_caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()));
|
||||
}
|
||||
|
||||
switch (m_spellInfo->Id)
|
||||
{
|
||||
case 20424: // Seal of Command
|
||||
case 42463: // Seal of Vengeance
|
||||
case 53739: // Seal of Corruption
|
||||
case 53385: // Divine Storm
|
||||
normalized = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_SHAMAN:
|
||||
@@ -3557,14 +3570,9 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
|
||||
}
|
||||
}
|
||||
|
||||
bool normalized = false;
|
||||
float weaponDamagePercentMod = 100.0f;
|
||||
int32 fixed_bonus = 0;
|
||||
|
||||
// xinef: Divine Storm deals normalized damage
|
||||
if (m_spellInfo->Id == 53385)
|
||||
normalized = true;
|
||||
|
||||
for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
|
||||
{
|
||||
switch (m_spellInfo->Effects[j].Effect)
|
||||
@@ -4939,7 +4947,8 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
|
||||
m_caster->ToPlayer()->SetFallInformation(GameTime::GetGameTime().count(), m_caster->GetPositionZ());
|
||||
|
||||
ObjectGuid targetGUID = ObjectGuid::Empty;
|
||||
if (!m_spellInfo->IsPositive() && m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->GetTarget() == unitTarget->GetGUID())
|
||||
if (!m_spellInfo->HasAttribute(SPELL_ATTR0_CANCELS_AUTO_ATTACK_COMBAT) && !m_spellInfo->IsPositive() && m_caster->GetTypeId() == TYPEID_PLAYER &&
|
||||
m_caster->GetTarget() == unitTarget->GetGUID())
|
||||
{
|
||||
targetGUID = unitTarget->GetGUID();
|
||||
}
|
||||
|
||||
@@ -4470,6 +4470,18 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
{
|
||||
spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT;
|
||||
});
|
||||
// Game In Session
|
||||
ApplySpellFix({ 39331 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->Effects[EFFECT_0].Effect = SPELL_EFFECT_APPLY_AURA;
|
||||
spellInfo->Attributes |= SPELL_ATTR0_NO_AURA_CANCEL;
|
||||
spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CHANGE_MAP;
|
||||
});
|
||||
// Death Ray Warning Visual, Death Ray Damage Visual
|
||||
ApplySpellFix({ 63882, 63886 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->AttributesEx5 |= SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL;
|
||||
});
|
||||
|
||||
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
||||
{
|
||||
|
||||
@@ -154,6 +154,11 @@ bool Warden::IsValidCheckSum(uint32 checksum, const uint8* data, const uint16 le
|
||||
}
|
||||
}
|
||||
|
||||
bool Warden::IsInitialized()
|
||||
{
|
||||
return _initialized;
|
||||
}
|
||||
|
||||
union keyData
|
||||
{
|
||||
std::array<uint8, 20> bytes;
|
||||
@@ -240,28 +245,28 @@ void Warden::ApplyPenalty(uint16 checkId, std::string const& reason)
|
||||
{
|
||||
if (Player const* plr = _session->GetPlayer())
|
||||
{
|
||||
std::string const reportFormat = "Player %s (guid %u, account id: %u) failed warden %u check (%s). Action: %s";
|
||||
reportMsg = Acore::StringFormat(reportFormat, plr->GetName().c_str(), plr->GetGUID().GetCounter(), _session->GetAccountId(),
|
||||
checkId, ((checkData && !checkData->Comment.empty()) ? checkData->Comment.c_str() : "<warden comment is not set>"),
|
||||
GetWardenActionStr(action).c_str());
|
||||
std::string const reportFormat = "Player {} (guid {}, account id: {}) failed warden {} check ({}). Action: {}";
|
||||
reportMsg = Acore::StringFormatFmt(reportFormat, plr->GetName(), plr->GetGUID().GetCounter(), _session->GetAccountId(),
|
||||
checkId, ((checkData && !checkData->Comment.empty()) ? checkData->Comment : "<warden comment is not set>"),
|
||||
GetWardenActionStr(action));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string const reportFormat = "Account id: %u failed warden %u check. Action: %s";
|
||||
reportMsg = Acore::StringFormat(reportFormat, _session->GetAccountId(), checkId, GetWardenActionStr(action).c_str());
|
||||
std::string const reportFormat = "Account id: {} failed warden {} check. Action: {}";
|
||||
reportMsg = Acore::StringFormatFmt(reportFormat, _session->GetAccountId(), checkId, GetWardenActionStr(action));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Player const* plr = _session->GetPlayer())
|
||||
{
|
||||
std::string const reportFormat = "Player %s (guid %u, account id: %u) triggered warden penalty by reason: %s. Action: %s";
|
||||
reportMsg = Acore::StringFormat(reportFormat, plr->GetName().c_str(), plr->GetGUID().GetCounter(), _session->GetAccountId(), causeMsg.c_str(), GetWardenActionStr(action).c_str());
|
||||
std::string const reportFormat = "Player {} (guid {}, account id: {}) triggered warden penalty by reason: {}. Action: {}";
|
||||
reportMsg = Acore::StringFormatFmt(reportFormat, plr->GetName(), plr->GetGUID().GetCounter(), _session->GetAccountId(), causeMsg, GetWardenActionStr(action));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string const reportFormat = "Account id: %u failed warden %u check. Action: %s";
|
||||
reportMsg = Acore::StringFormat(reportFormat, _session->GetAccountId(), causeMsg.c_str(), GetWardenActionStr(action).c_str());
|
||||
std::string const reportFormat = "Account id: {} failed warden {} check. Action: {}";
|
||||
reportMsg = Acore::StringFormatFmt(reportFormat, _session->GetAccountId(), causeMsg, GetWardenActionStr(action));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ public:
|
||||
virtual void RequestHash() = 0;
|
||||
virtual void HandleHashResult(ByteBuffer &buff) = 0;
|
||||
virtual bool IsCheckInProgress() = 0;
|
||||
virtual bool IsInitialized();
|
||||
virtual void ForceChecks() = 0;
|
||||
virtual void RequestChecks() = 0;
|
||||
virtual void HandleData(ByteBuffer &buff) = 0;
|
||||
|
||||
@@ -561,189 +561,197 @@ void WardenWin::RequestChecks()
|
||||
|
||||
void WardenWin::HandleData(ByteBuffer& buff)
|
||||
{
|
||||
if (!_interrupted)
|
||||
LOG_DEBUG("warden", "Handle data");
|
||||
|
||||
_dataSent = false;
|
||||
_clientResponseTimer = 0;
|
||||
|
||||
uint16 Length;
|
||||
buff >> Length;
|
||||
uint32 Checksum;
|
||||
buff >> Checksum;
|
||||
|
||||
if (Length != (buff.size() - buff.rpos()))
|
||||
{
|
||||
LOG_DEBUG("warden", "Handle data");
|
||||
buff.rfinish();
|
||||
|
||||
_dataSent = false;
|
||||
_clientResponseTimer = 0;
|
||||
|
||||
uint16 Length;
|
||||
buff >> Length;
|
||||
uint32 Checksum;
|
||||
buff >> Checksum;
|
||||
|
||||
if (Length != (buff.size() - buff.rpos()))
|
||||
if (!_interrupted)
|
||||
{
|
||||
buff.rfinish();
|
||||
ApplyPenalty(0, "Failed size checks in HandleData");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValidCheckSum(Checksum, buff.contents() + buff.rpos(), Length))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValidCheckSum(Checksum, buff.contents() + buff.rpos(), Length))
|
||||
{
|
||||
buff.rpos(buff.wpos());
|
||||
LOG_DEBUG("warden", "CHECKSUM FAIL");
|
||||
|
||||
if (!_interrupted)
|
||||
{
|
||||
buff.rpos(buff.wpos());
|
||||
LOG_DEBUG("warden", "CHECKSUM FAIL");
|
||||
ApplyPenalty(0, "Failed checksum in HandleData");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// TIMING_CHECK
|
||||
{
|
||||
uint8 result;
|
||||
buff >> result;
|
||||
/// @todo: test it.
|
||||
if (result == 0x00)
|
||||
{
|
||||
LOG_DEBUG("warden", "TIMING CHECK FAIL result 0x00");
|
||||
// ApplyPenalty(0, "TIMING CHECK FAIL result"); Commented out because of too many false postives. Mostly caused by client stutter.
|
||||
return;
|
||||
}
|
||||
|
||||
// TIMING_CHECK
|
||||
uint32 newClientTicks;
|
||||
buff >> newClientTicks;
|
||||
|
||||
uint32 ticksNow = GameTime::GetGameTimeMS().count();
|
||||
uint32 ourTicks = newClientTicks + (ticksNow - _serverTicks);
|
||||
|
||||
LOG_DEBUG("warden", "ServerTicks {}", ticksNow); // Now
|
||||
LOG_DEBUG("warden", "RequestTicks {}", _serverTicks); // At request
|
||||
LOG_DEBUG("warden", "Ticks {}", newClientTicks); // At response
|
||||
LOG_DEBUG("warden", "Ticks diff {}", ourTicks - newClientTicks);
|
||||
}
|
||||
|
||||
uint16 checkFailed = 0;
|
||||
|
||||
for (uint16 const checkId : _CurrentChecks)
|
||||
{
|
||||
WardenCheck const* rd = sWardenCheckMgr->GetWardenDataById(checkId);
|
||||
|
||||
// Custom payload should be loaded in if equal to over offset.
|
||||
if (!rd && checkId >= WardenPayloadMgr::WardenPayloadOffsetMin)
|
||||
{
|
||||
uint8 result;
|
||||
buff >> result;
|
||||
/// @todo: test it.
|
||||
if (result == 0x00)
|
||||
{
|
||||
LOG_DEBUG("warden", "TIMING CHECK FAIL result 0x00");
|
||||
// ApplyPenalty(0, "TIMING CHECK FAIL result"); Commented out because of too many false postives. Mostly caused by client stutter.
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 newClientTicks;
|
||||
buff >> newClientTicks;
|
||||
|
||||
uint32 ticksNow = GameTime::GetGameTimeMS().count();
|
||||
uint32 ourTicks = newClientTicks + (ticksNow - _serverTicks);
|
||||
|
||||
LOG_DEBUG("warden", "ServerTicks {}", ticksNow); // Now
|
||||
LOG_DEBUG("warden", "RequestTicks {}", _serverTicks); // At request
|
||||
LOG_DEBUG("warden", "Ticks {}", newClientTicks); // At response
|
||||
LOG_DEBUG("warden", "Ticks diff {}", ourTicks - newClientTicks);
|
||||
rd = &_payloadMgr.CachedChecks.at(checkId);
|
||||
}
|
||||
|
||||
uint16 checkFailed = 0;
|
||||
|
||||
for (uint16 const checkId : _CurrentChecks)
|
||||
uint8 const type = rd->Type;
|
||||
switch (type)
|
||||
{
|
||||
WardenCheck const* rd = sWardenCheckMgr->GetWardenDataById(checkId);
|
||||
case MEM_CHECK:
|
||||
{
|
||||
uint8 Mem_Result;
|
||||
buff >> Mem_Result;
|
||||
|
||||
// Custom payload should be loaded in if equal to over offset.
|
||||
if (!rd && checkId >= WardenPayloadMgr::WardenPayloadOffsetMin)
|
||||
if (Mem_Result != 0)
|
||||
{
|
||||
rd = &_payloadMgr.CachedChecks.at(checkId);
|
||||
LOG_DEBUG("warden", "RESULT MEM_CHECK not 0x00, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
checkFailed = checkId;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8 const type = rd->Type;
|
||||
switch (type)
|
||||
WardenCheckResult const* rs = sWardenCheckMgr->GetWardenResultById(checkId);
|
||||
|
||||
std::vector<uint8> result = rs->Result.ToByteVector(0, false);
|
||||
if (memcmp(buff.contents() + buff.rpos(), result.data(), rd->Length) != 0)
|
||||
{
|
||||
case MEM_CHECK:
|
||||
{
|
||||
uint8 Mem_Result;
|
||||
buff >> Mem_Result;
|
||||
|
||||
if (Mem_Result != 0)
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT MEM_CHECK not 0x00, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
checkFailed = checkId;
|
||||
continue;
|
||||
}
|
||||
|
||||
WardenCheckResult const* rs = sWardenCheckMgr->GetWardenResultById(checkId);
|
||||
|
||||
std::vector<uint8> result = rs->Result.ToByteVector(0, false);
|
||||
if (memcmp(buff.contents() + buff.rpos(), result.data(), rd->Length) != 0)
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT MEM_CHECK fail CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
checkFailed = checkId;
|
||||
buff.rpos(buff.rpos() + rd->Length);
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_DEBUG("warden", "RESULT MEM_CHECK fail CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
checkFailed = checkId;
|
||||
buff.rpos(buff.rpos() + rd->Length);
|
||||
LOG_DEBUG("warden", "RESULT MEM_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
case PAGE_CHECK_A:
|
||||
case PAGE_CHECK_B:
|
||||
case DRIVER_CHECK:
|
||||
case MODULE_CHECK:
|
||||
|
||||
buff.rpos(buff.rpos() + rd->Length);
|
||||
LOG_DEBUG("warden", "RESULT MEM_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
break;
|
||||
}
|
||||
case PAGE_CHECK_A:
|
||||
case PAGE_CHECK_B:
|
||||
case DRIVER_CHECK:
|
||||
case MODULE_CHECK:
|
||||
{
|
||||
uint8 const byte = 0xE9;
|
||||
if (memcmp(buff.contents() + buff.rpos(), &byte, sizeof(uint8)) != 0)
|
||||
{
|
||||
uint8 const byte = 0xE9;
|
||||
if (memcmp(buff.contents() + buff.rpos(), &byte, sizeof(uint8)) != 0)
|
||||
{
|
||||
if (type == PAGE_CHECK_A || type == PAGE_CHECK_B)
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT PAGE_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
}
|
||||
|
||||
if (type == MODULE_CHECK)
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT MODULE_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
}
|
||||
|
||||
if (type == DRIVER_CHECK)
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT DRIVER_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
}
|
||||
|
||||
checkFailed = checkId;
|
||||
buff.rpos(buff.rpos() + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
buff.rpos(buff.rpos() + 1);
|
||||
|
||||
if (type == PAGE_CHECK_A || type == PAGE_CHECK_B)
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT PAGE_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
LOG_DEBUG("warden", "RESULT PAGE_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
}
|
||||
else if (type == MODULE_CHECK)
|
||||
|
||||
if (type == MODULE_CHECK)
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT MODULE_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
LOG_DEBUG("warden", "RESULT MODULE_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
}
|
||||
else if (type == DRIVER_CHECK)
|
||||
|
||||
if (type == DRIVER_CHECK)
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT DRIVER_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
LOG_DEBUG("warden", "RESULT DRIVER_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
}
|
||||
break;
|
||||
|
||||
checkFailed = checkId;
|
||||
buff.rpos(buff.rpos() + 1);
|
||||
continue;
|
||||
}
|
||||
case LUA_EVAL_CHECK:
|
||||
|
||||
buff.rpos(buff.rpos() + 1);
|
||||
|
||||
if (type == PAGE_CHECK_A || type == PAGE_CHECK_B)
|
||||
{
|
||||
uint8 const result = buff.read<uint8>();
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
buff.read_skip(buff.read<uint8>()); // discard attached string
|
||||
}
|
||||
|
||||
LOG_DEBUG("warden", "LUA_EVAL_CHECK CheckId {} account Id {} got in-warden dummy response", checkId, _session->GetAccountId()/* , result */);
|
||||
break;
|
||||
LOG_DEBUG("warden", "RESULT PAGE_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
}
|
||||
case MPQ_CHECK:
|
||||
else if (type == MODULE_CHECK)
|
||||
{
|
||||
uint8 Mpq_Result;
|
||||
buff >> Mpq_Result;
|
||||
|
||||
if (Mpq_Result != 0)
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT MPQ_CHECK not 0x00 account id {}", _session->GetAccountId());
|
||||
checkFailed = checkId;
|
||||
continue;
|
||||
}
|
||||
|
||||
WardenCheckResult const* rs = sWardenCheckMgr->GetWardenResultById(checkId);
|
||||
if (memcmp(buff.contents() + buff.rpos(), rs->Result.ToByteArray<20>(false).data(), Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES) != 0) // SHA1
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT MPQ_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
checkFailed = checkId;
|
||||
buff.rpos(buff.rpos() + Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES); // 20 bytes SHA1
|
||||
continue;
|
||||
}
|
||||
|
||||
buff.rpos(buff.rpos() + Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES); // 20 bytes SHA1
|
||||
LOG_DEBUG("warden", "RESULT MPQ_CHECK passed, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
break;
|
||||
LOG_DEBUG("warden", "RESULT MODULE_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
}
|
||||
else if (type == DRIVER_CHECK)
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT DRIVER_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (checkFailed > 0)
|
||||
case LUA_EVAL_CHECK:
|
||||
{
|
||||
ApplyPenalty(checkFailed, "");
|
||||
uint8 const result = buff.read<uint8>();
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
buff.read_skip(buff.read<uint8>()); // discard attached string
|
||||
}
|
||||
|
||||
LOG_DEBUG("warden", "LUA_EVAL_CHECK CheckId {} account Id {} got in-warden dummy response", checkId, _session->GetAccountId()/* , result */);
|
||||
break;
|
||||
}
|
||||
case MPQ_CHECK:
|
||||
{
|
||||
uint8 Mpq_Result;
|
||||
buff >> Mpq_Result;
|
||||
|
||||
if (Mpq_Result != 0)
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT MPQ_CHECK not 0x00 account id {}", _session->GetAccountId());
|
||||
checkFailed = checkId;
|
||||
continue;
|
||||
}
|
||||
|
||||
WardenCheckResult const* rs = sWardenCheckMgr->GetWardenResultById(checkId);
|
||||
if (memcmp(buff.contents() + buff.rpos(), rs->Result.ToByteArray<20>(false).data(), Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES) != 0) // SHA1
|
||||
{
|
||||
LOG_DEBUG("warden", "RESULT MPQ_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
checkFailed = checkId;
|
||||
buff.rpos(buff.rpos() + Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES); // 20 bytes SHA1
|
||||
continue;
|
||||
}
|
||||
|
||||
buff.rpos(buff.rpos() + Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES); // 20 bytes SHA1
|
||||
LOG_DEBUG("warden", "RESULT MPQ_CHECK passed, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (checkFailed > 0 && !_interrupted)
|
||||
{
|
||||
ApplyPenalty(checkFailed, "");
|
||||
}
|
||||
|
||||
if (_interrupted)
|
||||
{
|
||||
LOG_DEBUG("warden", "Warden was interrupted by ForceChecks, ignoring results.");
|
||||
|
||||
|
||||
@@ -1912,9 +1912,12 @@ void World::SetInitialWorldSettings()
|
||||
LOG_INFO("server.loading", "Loading Groups...");
|
||||
sGroupMgr->LoadGroups();
|
||||
|
||||
LOG_INFO("server.loading", "Loading ReservedNames...");
|
||||
LOG_INFO("server.loading", "Loading Reserved Names...");
|
||||
sObjectMgr->LoadReservedPlayersNames();
|
||||
|
||||
LOG_INFO("server.loading", "Loading Profanity Names...");
|
||||
sObjectMgr->LoadProfanityPlayersNames();
|
||||
|
||||
LOG_INFO("server.loading", "Loading GameObjects for Quests...");
|
||||
sObjectMgr->LoadGameObjectForQuests();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user