Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2024-07-07 13:32:00 +08:00
87 changed files with 1928 additions and 1062 deletions

View File

@@ -2173,15 +2173,6 @@ bool GameObject::IsInRange(float x, float y, float z, float radius) const
&& dz < (info->maxZ * scale) + radius && dz > (info->minZ * scale) - radius;
}
void GameObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin, Player const* skipped_rcvr) const
{
dist += GetObjectSize();
if (includeMargin)
dist += VISIBILITY_COMPENSATION * 2.0f; // pussywizard: to ensure everyone receives all important packets
Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr);
Cell::VisitWorldObjects(this, notifier, dist);
}
void GameObject::EventInform(uint32 eventId)
{
if (!eventId)

View File

@@ -289,8 +289,6 @@ public:
void SendCustomAnim(uint32 anim);
[[nodiscard]] bool IsInRange(float x, float y, float z, float radius) const;
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const override; // pussywizard!
void ModifyHealth(int32 change, Unit* attackerOrHealer = nullptr, uint32 spellId = 0);
void SetDestructibleBuildingModifyState(bool allow) { m_allowModifyDestructibleBuilding = allow; }
// sets GameObject type 33 destruction flags and optionally default health for that state

View File

@@ -15,8 +15,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Define.h"
#include "Item.h"
#include "Define.h"
#include "SmartEnum.h"
#include <stdexcept>

View File

@@ -2077,15 +2077,24 @@ void Unit::BuildHeartBeatMsg(WorldPacket* data) const
BuildMovementPacket(data);
}
void WorldObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin, Player const* skipped_rcvr) const
void WorldObject::SendMessageToSet(WorldPacket const* data, bool self) const
{
dist += GetObjectSize();
if (includeMargin)
dist += VISIBILITY_COMPENSATION; // pussywizard: to ensure everyone receives all important packets
Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr);
if (IsInWorld())
SendMessageToSetInRange(data, GetVisibilityRange(), self);
}
void WorldObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/) const
{
Acore::MessageDistDeliverer notifier(this, data, dist);
Cell::VisitWorldObjects(this, notifier, dist);
}
void WorldObject::SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const
{
Acore::MessageDistDeliverer notifier(this, data, GetVisibilityRange(), false, skipped_rcvr);
Cell::VisitWorldObjects(this, notifier, GetVisibilityRange());
}
void WorldObject::SendObjectDeSpawnAnim(ObjectGuid guid)
{
WorldPacket data(SMSG_GAMEOBJECT_DESPAWN_ANIM, 8);

View File

@@ -479,9 +479,9 @@ public:
virtual void CleanupsBeforeDelete(bool finalCleanup = true); // used in destructor or explicitly before mass creature delete to remove cross-references to already deleted units
virtual void SendMessageToSet(WorldPacket const* data, bool self) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), self, true); } // pussywizard!
virtual void SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const; // pussywizard!
virtual void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), false, true, skipped_rcvr); } // pussywizard!
virtual void SendMessageToSet(WorldPacket const* data, bool self) const;
virtual void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self) const;
virtual void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const;
virtual uint8 getLevelForTarget(WorldObject const* /*target*/) const { return 1; }

View File

@@ -394,7 +394,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
// Send fake summon spell cast - this is needed for correct cooldown application for spells
// Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside
/// @todo pets should be summoned from real cast instead of just faking it?
if (petInfo->CreatedBySpellId)
if (petInfo->CreatedBySpellId && spellInfo && (spellInfo->CategoryRecoveryTime > 0 || spellInfo->RecoveryTime > 0))
{
WorldPacket data(SMSG_SPELL_GO, (8 + 8 + 4 + 4 + 2));
data << owner->GetPackGUID();
@@ -2499,11 +2499,6 @@ float Pet::GetNativeObjectScale() const
{
uint8 ctFamily = GetCreatureTemplate()->family;
// hackfix: Edge case where DBC scale values for DEVILSAUR pets make them too small.
// Therefore we take data from spirit beast instead.
if (ctFamily && ctFamily == CREATURE_FAMILY_DEVILSAUR)
ctFamily = CREATURE_FAMILY_SPIRIT_BEAST;
CreatureFamilyEntry const* creatureFamily = sCreatureFamilyStore.LookupEntry(ctFamily);
if (creatureFamily && creatureFamily->minScale > 0.0f && getPetType() & HUNTER_PET)
{
@@ -2520,6 +2515,13 @@ float Pet::GetNativeObjectScale() const
float scale = (creatureFamily->maxScale - creatureFamily->minScale) * scaleMod + creatureFamily->minScale;
scale = std::min(scale, creatureFamily->maxScale);
if (CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(GetNativeDisplayId()))
{
if (scale < 1.f && displayInfo->scale > 1.f)
scale *= displayInfo->scale;
}
return scale;
}

View File

@@ -5612,25 +5612,40 @@ void Player::SaveRecallPosition()
m_recallO = GetOrientation();
}
void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin, Player const* skipped_rcvr) const
void Player::SendMessageToSet(WorldPacket const* data, bool self) const
{
SendMessageToSetInRange(data, GetVisibilityRange(), self);
}
void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool self) const
{
if (self)
GetSession()->SendPacket(data);
SendDirectMessage(data);
Acore::MessageDistDeliverer notifier(this, data, dist);
Cell::VisitWorldObjects(this, notifier, dist);
}
void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin, bool ownTeamOnly, bool required3dDist) const
{
if (self)
SendDirectMessage(data);
dist += GetObjectSize();
if (includeMargin)
dist += VISIBILITY_COMPENSATION; // pussywizard: to ensure everyone receives all important packets
Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr);
Acore::MessageDistDeliverer notifier(this, data, dist, ownTeamOnly, nullptr, required3dDist);
Cell::VisitWorldObjects(this, notifier, dist);
}
void Player::SendMessageToSetInRange_OwnTeam(WorldPacket const* data, float dist, bool self) const
void Player::SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const
{
if (self)
GetSession()->SendPacket(data);
if (skipped_rcvr != this)
SendDirectMessage(data);
Acore::MessageDistDeliverer notifier(this, data, dist, true);
Cell::VisitWorldObjects(this, notifier, dist);
Acore::MessageDistDeliverer notifier(this, data, GetVisibilityRange(), false, skipped_rcvr);
Cell::VisitWorldObjects(this, notifier, GetVisibilityRange());
}
void Player::SendDirectMessage(WorldPacket const* data) const
@@ -9291,7 +9306,7 @@ void Player::Say(std::string_view text, Language language, WorldObject const* /*
WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_SAY, language, this, this, _text);
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true);
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true, false, false, true);
}
void Player::Say(uint32 textId, WorldObject const* target /*= nullptr*/)
@@ -9312,7 +9327,7 @@ void Player::Yell(std::string_view text, Language language, WorldObject const* /
WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_YELL, language, this, this, _text);
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), true);
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), true, false, false, true);
}
void Player::Yell(uint32 textId, WorldObject const* target /*= nullptr*/)
@@ -9334,14 +9349,7 @@ void Player::TextEmote(std::string_view text, WorldObject const* /*= nullptr*/,
WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, _text);
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE))
{
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true);
}
else
{
SendMessageToSetInRange_OwnTeam(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true);
}
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, false, !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE), true);
}
void Player::TextEmote(uint32 textId, WorldObject const* target /*= nullptr*/, bool /*isBossEmote = false*/)
@@ -10521,7 +10529,7 @@ void Player::InitDataForForm(bool reapplyMods)
{
ShapeshiftForm form = GetShapeshiftForm();
SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(form);
SpellShapeshiftFormEntry const* ssEntry = sSpellShapeshiftFormStore.LookupEntry(form);
if (ssEntry && ssEntry->attackSpeed)
{
SetAttackTime(BASE_ATTACK, ssEntry->attackSpeed);

View File

@@ -2000,11 +2000,10 @@ public:
void ProcessTerrainStatusUpdate() override;
void SendMessageToSet(WorldPacket const* data, bool self) const override { SendMessageToSetInRange(data, GetVisibilityRange(), self, true); } // pussywizard!
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const override; // pussywizard!
void SendMessageToSetInRange_OwnTeam(WorldPacket const* data, float dist, bool self) const; // pussywizard! param includeMargin not needed here
void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const override { SendMessageToSetInRange(data, GetVisibilityRange(), skipped_rcvr != this, true, skipped_rcvr); } // pussywizard!
void SendMessageToSet(WorldPacket const* data, bool self) const override;
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self) const override;
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin, bool ownTeamOnly, bool required3dDist = false) const;
void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const override;
void SendTeleportAckPacket();
[[nodiscard]] Corpse* GetCorpse() const;

View File

@@ -753,7 +753,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
else
{
sScriptMgr->OnGivePlayerXP(this, XP, nullptr, isLFGReward ? PlayerXPSource::XPSOURCE_QUEST_DF : PlayerXPSource::XPSOURCE_QUEST);
GiveXP(XP, nullptr, isLFGReward);
GiveXP(XP, nullptr, 1.0f, isLFGReward);
}
// Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative

View File

@@ -3453,7 +3453,8 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spell, bool Ca
return SPELL_MISS_NONE;
// Return evade for units in evade mode
if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks() && !spell->HasAura(SPELL_AURA_CONTROL_VEHICLE) && !spell->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE))
if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks() && !spell->HasAura(SPELL_AURA_CONTROL_VEHICLE)
&& !spell->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) && !spell->HasAttribute(SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT))
return SPELL_MISS_EVADE;
// Try victim reflect spell
@@ -3528,7 +3529,7 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, Spell const* spell, bool CanRef
// Return evade for units in evade mode
if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks() && !spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE) &&
!spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE))
!spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) && !spellInfo->HasAttribute(SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT))
{
return SPELL_MISS_EVADE;
}
@@ -5384,7 +5385,8 @@ void Unit::RemoveEvadeAuras()
{
Aura const* aura = iter->second->GetBase();
SpellInfo const* spellInfo = aura->GetSpellInfo();
if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) || spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE) || spellInfo->HasAura(SPELL_AURA_CLONE_CASTER) || (aura->IsPassive() && GetOwnerGUID().IsPlayer()))
if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) || spellInfo->HasAttribute(SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT) || spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)
|| spellInfo->HasAura(SPELL_AURA_CLONE_CASTER) || (aura->IsPassive() && GetOwnerGUID().IsPlayer()))
++iter;
else
_UnapplyAura(iter, AURA_REMOVE_BY_DEFAULT);
@@ -5394,7 +5396,8 @@ void Unit::RemoveEvadeAuras()
{
Aura* aura = iter->second;
SpellInfo const* spellInfo = aura->GetSpellInfo();
if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) || spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE) || spellInfo->HasAura(SPELL_AURA_CLONE_CASTER) || (aura->IsPassive() && GetOwnerGUID().IsPlayer()))
if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_EVADE) || spellInfo->HasAttribute(SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT) || spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)
|| spellInfo->HasAura(SPELL_AURA_CLONE_CASTER) || (aura->IsPassive() && GetOwnerGUID().IsPlayer()))
++iter;
else
RemoveOwnedAura(iter, AURA_REMOVE_BY_DEFAULT);
@@ -15190,7 +15193,7 @@ uint32 Unit::GetCreatureType() const
if (GetTypeId() == TYPEID_PLAYER)
{
ShapeshiftForm form = GetShapeshiftForm();
SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(form);
SpellShapeshiftFormEntry const* ssEntry = sSpellShapeshiftFormStore.LookupEntry(form);
if (ssEntry && ssEntry->creatureType > 0)
return ssEntry->creatureType;
else
@@ -19677,7 +19680,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form, uint32 spellId) const
}
uint32 modelid = 0;
SpellShapeshiftEntry const* formEntry = sSpellShapeshiftStore.LookupEntry(form);
SpellShapeshiftFormEntry const* formEntry = sSpellShapeshiftFormStore.LookupEntry(form);
if (formEntry && formEntry->modelID_A)
{
// Take the alliance modelid as default
@@ -21613,7 +21616,7 @@ bool Unit::IsInDisallowedMountForm() const
if (ShapeshiftForm form = GetShapeshiftForm())
{
SpellShapeshiftEntry const* shapeshift = sSpellShapeshiftStore.LookupEntry(form);
SpellShapeshiftFormEntry const* shapeshift = sSpellShapeshiftFormStore.LookupEntry(form);
if (!shapeshift)
{
return true;
@@ -21656,6 +21659,20 @@ bool Unit::IsInDisallowedMountForm() const
return false;
}
void Unit::SetUInt32Value(uint16 index, uint32 value)
{
Object::SetUInt32Value(index, value);
switch (index)
{
// Invalidating the cache on health change should fix an issue where the client sees dead NPCs when they are not.
// We might also need to invalidate the cache for some other fields as well.
case UNIT_FIELD_HEALTH:
InvalidateValuesUpdateCache();
break;
}
}
std::string Unit::GetDebugInfo() const
{
std::stringstream sstr;

View File

@@ -1571,6 +1571,8 @@ public:
void ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply);
void ApplyCastTimePercentMod(float val, bool apply);
void SetUInt32Value(uint16 index, uint32 value);
UnitFlags GetUnitFlags() const { return UnitFlags(GetUInt32Value(UNIT_FIELD_FLAGS)); }
bool HasUnitFlag(UnitFlags flags) const { return HasFlag(UNIT_FIELD_FLAGS, flags); }
void SetUnitFlag(UnitFlags flags) { SetFlag(UNIT_FIELD_FLAGS, flags); }

View File

@@ -15,9 +15,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Unit.h"
#include "Define.h"
#include "SmartEnum.h"
#include "Unit.h"
#include <stdexcept>
namespace Acore::Impl::EnumUtilsImpl