diff --git a/src/server/game/Combat/ThreatMgr.h b/src/server/game/Combat/ThreatMgr.h index bcc6d1614..6269d7326 100644 --- a/src/server/game/Combat/ThreatMgr.h +++ b/src/server/game/Combat/ThreatMgr.h @@ -290,6 +290,30 @@ private: //================================================= +struct RedirectThreatInfo +{ + RedirectThreatInfo() = default; + ObjectGuid _targetGUID; + uint32 _threatPct{ 0 }; + + [[nodiscard]] ObjectGuid GetTargetGUID() const { return _targetGUID; } + [[nodiscard]] uint32 GetThreatPct() const { return _threatPct; } + + void Set(ObjectGuid guid, uint32 pct) + { + _targetGUID = guid; + _threatPct = pct; + } + + void ModifyThreatPct(int32 amount) + { + amount += _threatPct; + _threatPct = uint32(std::max(0, amount)); + } +}; + +//================================================= + namespace Acore { // Binary predicate for sorting HostileReferences based on threat value diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 31ff02f56..877f8e2ec 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -19,6 +19,7 @@ #define AZEROTHCORE_CREATURE_H #include "Cell.h" +#include "CharmInfo.h" #include "Common.h" #include "CreatureData.h" #include "DatabaseEnv.h" diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index e7da6c7a8..4ce4c1072 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -35,6 +35,12 @@ struct ItemSetEffect SpellInfo const* spells[8]; }; +enum InventorySlot +{ + NULL_BAG = 0, + NULL_SLOT = 255 +}; + // EnumUtils: DESCRIBE THIS enum InventoryResult : uint8 { diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index a38baf814..9329a0b07 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -18,6 +18,7 @@ #ifndef AZEROTHCORE_PET_H #define AZEROTHCORE_PET_H +#include "CharmInfo.h" #include "PetDefines.h" #include "TemporarySummon.h" diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 9bacc9133..0bf34ab62 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -28,6 +28,7 @@ #include "BattlegroundAV.h" #include "BattlegroundMgr.h" #include "CellImpl.h" +#include "CharmInfo.h" #include "Channel.h" #include "CharacterCache.h" #include "CharacterDatabaseCleaner.h" diff --git a/src/server/game/Entities/Unit/CharmInfo.cpp b/src/server/game/Entities/Unit/CharmInfo.cpp new file mode 100644 index 000000000..6ef15a907 --- /dev/null +++ b/src/server/game/Entities/Unit/CharmInfo.cpp @@ -0,0 +1,392 @@ +/* + * 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 . + */ + +#include "CharmInfo.h" +#include "Creature.h" +#include "Map.h" +#include "SpellInfo.h" +#include "Player.h" +#include "SpellMgr.h" +#include "StringConvert.h" +#include "Tokenize.h" +#include "Unit.h" + +CharmInfo::CharmInfo(Unit* unit) + : _unit(unit), _CommandState(COMMAND_FOLLOW), _petnumber(0), _oldReactState(REACT_PASSIVE), + _isCommandAttack(false), _isCommandFollow(false), _isAtStay(false), _isFollowing(false), _isReturning(false), + _forcedSpellId(0), _stayX(0.0f), _stayY(0.0f), _stayZ(0.0f) +{ + for (uint8 i = 0; i < MAX_SPELL_CHARM; ++i) + _charmspells[i].SetActionAndType(0, ACT_DISABLED); + + if (_unit->GetTypeId() == TYPEID_UNIT) + { + _oldReactState = _unit->ToCreature()->GetReactState(); + _unit->ToCreature()->SetReactState(REACT_PASSIVE); + } +} + +CharmInfo::~CharmInfo() = default; + +void CharmInfo::RestoreState() +{ + if (Creature* creature = _unit->ToCreature()) + creature->SetReactState(_oldReactState); +} + +void CharmInfo::InitPetActionBar() +{ + // the first 3 SpellOrActions are attack, follow and stay + for (uint32 i = 0; i < ACTION_BAR_INDEX_PET_SPELL_START - ACTION_BAR_INDEX_START; ++i) + SetActionBar(ACTION_BAR_INDEX_START + i, COMMAND_ATTACK - i, ACT_COMMAND); + + // middle 4 SpellOrActions are spells/special attacks/abilities + for (uint32 i = 0; i < ACTION_BAR_INDEX_PET_SPELL_END - ACTION_BAR_INDEX_PET_SPELL_START; ++i) + SetActionBar(ACTION_BAR_INDEX_PET_SPELL_START + i, 0, ACT_PASSIVE); + + // last 3 SpellOrActions are reactions + for (uint32 i = 0; i < ACTION_BAR_INDEX_END - ACTION_BAR_INDEX_PET_SPELL_END; ++i) + SetActionBar(ACTION_BAR_INDEX_PET_SPELL_END + i, COMMAND_ATTACK - i, ACT_REACTION); +} + +void CharmInfo::InitEmptyActionBar(bool withAttack) +{ + if (withAttack) + SetActionBar(ACTION_BAR_INDEX_START, COMMAND_ATTACK, ACT_COMMAND); + else + SetActionBar(ACTION_BAR_INDEX_START, 0, ACT_PASSIVE); + for (uint32 x = ACTION_BAR_INDEX_START + 1; x < ACTION_BAR_INDEX_END; ++x) + SetActionBar(x, 0, ACT_PASSIVE); +} + +void CharmInfo::InitPossessCreateSpells() +{ + if (_unit->GetTypeId() == TYPEID_UNIT) + { + // Adding switch until better way is found. Malcrom + // Adding entrys to this switch will prevent COMMAND_ATTACK being added to pet bar. + switch (_unit->GetEntry()) + { + case 23575: // Mindless Abomination + case 24783: // Trained Rock Falcon + case 27664: // Crashin' Thrashin' Racer + case 40281: // Crashin' Thrashin' Racer + case 23109: // Vengeful Spirit + break; + default: + InitEmptyActionBar(); + break; + } + + for (uint32 i = 0; i < MAX_CREATURE_SPELLS; ++i) + { + uint32 spellId = _unit->ToCreature()->m_spells[i]; + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (spellInfo) + { + if (spellInfo->IsPassive()) + _unit->CastSpell(_unit, spellInfo, true); + else + AddSpellToActionBar(spellInfo, ACT_PASSIVE); + } + } + } + else + InitEmptyActionBar(); +} + +void CharmInfo::InitCharmCreateSpells() +{ + InitPetActionBar(); + + if (_unit->GetTypeId() == TYPEID_PLAYER) // charmed players don't have spells + return; + + for (uint32 i = 0; i < MAX_SPELL_CHARM; ++i) + { + uint32 spellId = _unit->ToCreature()->m_spells[i]; + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + + if (!spellInfo) + { + _charmspells[i].SetActionAndType(spellId, ACT_DISABLED); + continue; + } + + if (spellInfo->IsPassive()) + { + _unit->CastSpell(_unit, spellInfo, true); + _charmspells[i].SetActionAndType(spellId, ACT_PASSIVE); + } + else + { + _charmspells[i].SetActionAndType(spellId, ACT_DISABLED); + + ActiveStates newstate = ACT_PASSIVE; + + if (!spellInfo->IsAutocastable()) + newstate = ACT_PASSIVE; + else + { + if (spellInfo->NeedsExplicitUnitTarget()) + { + newstate = ACT_ENABLED; + ToggleCreatureAutocast(spellInfo, true); + } + else + newstate = ACT_DISABLED; + } + + AddSpellToActionBar(spellInfo, newstate); + } + } +} + +bool CharmInfo::AddSpellToActionBar(SpellInfo const* spellInfo, ActiveStates newstate) +{ + uint32 spell_id = spellInfo->Id; + uint32 first_id = spellInfo->GetFirstRankSpell()->Id; + + // new spell rank can be already listed + for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) + { + if (uint32 action = PetActionBar[i].GetAction()) + { + if (PetActionBar[i].IsActionBarForSpell() && sSpellMgr->GetFirstSpellInChain(action) == first_id) + { + PetActionBar[i].SetAction(spell_id); + return true; + } + } + } + + // or use empty slot in other case + for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) + { + if (!PetActionBar[i].GetAction() && PetActionBar[i].IsActionBarForSpell()) + { + SetActionBar(i, spell_id, newstate == ACT_DECIDE ? spellInfo->IsAutocastable() ? ACT_DISABLED : ACT_PASSIVE : newstate); + + if (_unit->GetCharmer() && _unit->GetCharmer()->IsPlayer()) + { + if (Creature* creature = _unit->ToCreature()) + { + // Processing this packet needs to be delayed + _unit->m_Events.AddEventAtOffset([creature, spell_id]() + { + if (uint32 cooldown = creature->GetSpellCooldown(spell_id)) + { + WorldPacket data; + creature->BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, spell_id, cooldown); + if (creature->GetCharmer() && creature->GetCharmer()->IsPlayer()) + { + creature->GetCharmer()->ToPlayer()->SendDirectMessage(&data); + } + } + }, 500ms); + } + } + + return true; + } + } + return false; +} + +bool CharmInfo::RemoveSpellFromActionBar(uint32 spell_id) +{ + uint32 first_id = sSpellMgr->GetFirstSpellInChain(spell_id); + + for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) + { + if (uint32 action = PetActionBar[i].GetAction()) + { + if (PetActionBar[i].IsActionBarForSpell() && sSpellMgr->GetFirstSpellInChain(action) == first_id) + { + SetActionBar(i, 0, ACT_PASSIVE); + return true; + } + } + } + + return false; +} + +void CharmInfo::ToggleCreatureAutocast(SpellInfo const* spellInfo, bool apply) +{ + if (spellInfo->IsPassive()) + return; + + for (uint32 i = 0; i < MAX_SPELL_CHARM; ++i) + if (spellInfo->Id == _charmspells[i].GetAction()) + _charmspells[i].SetType(apply ? ACT_ENABLED : ACT_DISABLED); +} + +void CharmInfo::SetPetNumber(uint32 petnumber, bool statwindow) +{ + _petnumber = petnumber; + if (statwindow) + _unit->SetUInt32Value(UNIT_FIELD_PETNUMBER, _petnumber); + else + _unit->SetUInt32Value(UNIT_FIELD_PETNUMBER, 0); +} + +void CharmInfo::LoadPetActionBar(const std::string& data) +{ + std::vector tokens = Acore::Tokenize(data, ' ', false); + + if (tokens.size() != (ACTION_BAR_INDEX_END - ACTION_BAR_INDEX_START) * 2) + return; // non critical, will reset to default + + auto iter = tokens.begin(); + for (uint8 index = ACTION_BAR_INDEX_START; index < ACTION_BAR_INDEX_END; ++index) + { + Optional type = Acore::StringTo(*(iter++)); + Optional action = Acore::StringTo(*(iter++)); + + if (!type || !action) + { + continue; + } + + PetActionBar[index].SetActionAndType(*action, static_cast(*type)); + + // check correctness + if (PetActionBar[index].IsActionBarForSpell()) + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(PetActionBar[index].GetAction()); + if (!spellInfo) + { + SetActionBar(index, 0, ACT_PASSIVE); + } + else if (!spellInfo->IsAutocastable()) + { + SetActionBar(index, PetActionBar[index].GetAction(), ACT_PASSIVE); + } + } + } +} + +void CharmInfo::BuildActionBar(WorldPacket* data) +{ + for (uint32 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) + *data << uint32(PetActionBar[i].packedData); +} + +void CharmInfo::SetSpellAutocast(SpellInfo const* spellInfo, bool state) +{ + for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) + { + if (spellInfo->Id == PetActionBar[i].GetAction() && PetActionBar[i].IsActionBarForSpell()) + { + PetActionBar[i].SetType(state ? ACT_ENABLED : ACT_DISABLED); + break; + } + } +} + +void CharmInfo::SetIsCommandAttack(bool val) +{ + _isCommandAttack = val; +} + +bool CharmInfo::IsCommandAttack() +{ + return _isCommandAttack; +} + +void CharmInfo::SetIsCommandFollow(bool val) +{ + _isCommandFollow = val; +} + +bool CharmInfo::IsCommandFollow() +{ + return _isCommandFollow; +} + +void CharmInfo::SaveStayPosition(bool atCurrentPos) +{ + //! At this point a new spline destination is enabled because of Unit::StopMoving() + G3D::Vector3 stayPos = G3D::Vector3(); + + if (atCurrentPos) + { + float z = INVALID_HEIGHT; + _unit->UpdateAllowedPositionZ(_unit->GetPositionX(), _unit->GetPositionY(), z); + stayPos = G3D::Vector3(_unit->GetPositionX(), _unit->GetPositionY(), z != INVALID_HEIGHT ? z : _unit->GetPositionZ()); + } + else + stayPos = _unit->movespline->FinalDestination(); + + if (_unit->movespline->onTransport) + if (TransportBase* transport = _unit->GetDirectTransport()) + transport->CalculatePassengerPosition(stayPos.x, stayPos.y, stayPos.z); + + _stayX = stayPos.x; + _stayY = stayPos.y; + _stayZ = stayPos.z; +} + +void CharmInfo::GetStayPosition(float& x, float& y, float& z) +{ + x = _stayX; + y = _stayY; + z = _stayZ; +} + +void CharmInfo::RemoveStayPosition() +{ + _stayX = 0.0f; + _stayY = 0.0f; + _stayZ = 0.0f; +} + +bool CharmInfo::HasStayPosition() +{ + return _stayX && _stayY && _stayZ; +} + +void CharmInfo::SetIsAtStay(bool val) +{ + _isAtStay = val; +} + +bool CharmInfo::IsAtStay() +{ + return _isAtStay; +} + +void CharmInfo::SetIsFollowing(bool val) +{ + _isFollowing = val; +} + +bool CharmInfo::IsFollowing() +{ + return _isFollowing; +} + +void CharmInfo::SetIsReturning(bool val) +{ + _isReturning = val; +} + +bool CharmInfo::IsReturning() +{ + return _isReturning; +} diff --git a/src/server/game/Entities/Unit/CharmInfo.h b/src/server/game/Entities/Unit/CharmInfo.h new file mode 100644 index 000000000..9246394b4 --- /dev/null +++ b/src/server/game/Entities/Unit/CharmInfo.h @@ -0,0 +1,184 @@ +/* + * 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 . + */ + +#ifndef _CHARMINFO_H +#define _CHARMINFO_H + +#include "Object.h" + +#define MAX_SPELL_CHARM 4 +#define MAX_SPELL_VEHICLE 6 +#define MAX_SPELL_POSSESS 8 +#define MAX_SPELL_CONTROL_BAR 10 + +#define MAX_UNIT_ACTION_BAR_INDEX (ACTION_BAR_INDEX_END-ACTION_BAR_INDEX_START) + +#define UNIT_ACTION_BUTTON_ACTION(X) (uint32(X) & 0x00FFFFFF) +#define UNIT_ACTION_BUTTON_TYPE(X) ((uint32(X) & 0xFF000000) >> 24) +#define MAKE_UNIT_ACTION_BUTTON(A, T) (uint32(A) | (uint32(T) << 24)) + +class GlobalCooldownMgr; +class SpellInfo; +class Unit; +class WorldPacket; + +enum CommandStates : uint8; +enum ReactStates : uint8; + +enum CharmType : uint8 +{ + CHARM_TYPE_CHARM, + CHARM_TYPE_POSSESS, + CHARM_TYPE_VEHICLE, + CHARM_TYPE_CONVERT, +}; + +enum ActionBarIndex +{ + ACTION_BAR_INDEX_START = 0, + ACTION_BAR_INDEX_PET_SPELL_START = 3, + ACTION_BAR_INDEX_PET_SPELL_END = 7, + ACTION_BAR_INDEX_END = 10, +}; + +enum ActiveStates : uint8 +{ + ACT_PASSIVE = 0x01, // 0x01 - passive + ACT_DISABLED = 0x81, // 0x80 - castable + ACT_ENABLED = 0xC1, // 0x40 | 0x80 - auto cast + castable + ACT_COMMAND = 0x07, // 0x01 | 0x02 | 0x04 + ACT_REACTION = 0x06, // 0x02 | 0x04 + ACT_DECIDE = 0x00 // custom +}; + +struct UnitActionBarEntry +{ + UnitActionBarEntry() : packedData(uint32(ACT_DISABLED) << 24) {} + + uint32 packedData; + + // helper + [[nodiscard]] ActiveStates GetType() const { return ActiveStates(UNIT_ACTION_BUTTON_TYPE(packedData)); } + [[nodiscard]] uint32 GetAction() const { return UNIT_ACTION_BUTTON_ACTION(packedData); } + [[nodiscard]] bool IsActionBarForSpell() const + { + ActiveStates Type = GetType(); + return Type == ACT_DISABLED || Type == ACT_ENABLED || Type == ACT_PASSIVE; + } + + void SetActionAndType(uint32 action, ActiveStates type) + { + packedData = MAKE_UNIT_ACTION_BUTTON(action, type); + } + + void SetType(ActiveStates type) + { + packedData = MAKE_UNIT_ACTION_BUTTON(UNIT_ACTION_BUTTON_ACTION(packedData), type); + } + + void SetAction(uint32 action) + { + packedData = (packedData & 0xFF000000) | UNIT_ACTION_BUTTON_ACTION(action); + } +}; +typedef UnitActionBarEntry CharmSpellInfo; + +struct CharmInfo +{ +public: + explicit CharmInfo(Unit* unit); + ~CharmInfo(); + void RestoreState(); + [[nodiscard]] uint32 GetPetNumber() const { return _petnumber; } + void SetPetNumber(uint32 petnumber, bool statwindow); + + void SetCommandState(CommandStates st) { _CommandState = st; } + [[nodiscard]] CommandStates GetCommandState() const { return _CommandState; } + [[nodiscard]] bool HasCommandState(CommandStates state) const { return (_CommandState == state); } + + void InitPossessCreateSpells(); + void InitCharmCreateSpells(); + void InitPetActionBar(); + void InitEmptyActionBar(bool withAttack = true); + + //return true if successful + bool AddSpellToActionBar(SpellInfo const* spellInfo, ActiveStates newstate = ACT_DECIDE); + bool RemoveSpellFromActionBar(uint32 spell_id); + void LoadPetActionBar(const std::string& data); + void BuildActionBar(WorldPacket* data); + void SetSpellAutocast(SpellInfo const* spellInfo, bool state); + void SetActionBar(uint8 index, uint32 spellOrAction, ActiveStates type) + { + PetActionBar[index].SetActionAndType(spellOrAction, type); + } + [[nodiscard]] UnitActionBarEntry const* GetActionBarEntry(uint8 index) const { return &(PetActionBar[index]); } + + void ToggleCreatureAutocast(SpellInfo const* spellInfo, bool apply); + + CharmSpellInfo* GetCharmSpell(uint8 index) { return &(_charmspells[index]); } + + GlobalCooldownMgr& GetGlobalCooldownMgr() { return *_GlobalCooldownMgr; } + + void SetIsCommandAttack(bool val); + bool IsCommandAttack(); + void SetIsCommandFollow(bool val); + bool IsCommandFollow(); + void SetIsAtStay(bool val); + bool IsAtStay(); + void SetIsFollowing(bool val); + bool IsFollowing(); + void SetIsReturning(bool val); + bool IsReturning(); + void SaveStayPosition(bool atCurrentPos); + void GetStayPosition(float& x, float& y, float& z); + void RemoveStayPosition(); + bool HasStayPosition(); + + void SetForcedSpell(uint32 id) { _forcedSpellId = id; } + int32 GetForcedSpell() { return _forcedSpellId; } + void SetForcedTargetGUID(ObjectGuid guid = ObjectGuid::Empty) { _forcedTargetGUID = guid; } + ObjectGuid GetForcedTarget() { return _forcedTargetGUID; } + + // Player react states + void SetPlayerReactState(ReactStates s) { _oldReactState = s; } + [[nodiscard]] ReactStates GetPlayerReactState() const { return _oldReactState; } + +private: + Unit* _unit; + UnitActionBarEntry PetActionBar[MAX_UNIT_ACTION_BAR_INDEX]; + CharmSpellInfo _charmspells[4]; + CommandStates _CommandState; + uint32 _petnumber; + + //for restoration after charmed + ReactStates _oldReactState; + + bool _isCommandAttack; + bool _isCommandFollow; + bool _isAtStay; + bool _isFollowing; + bool _isReturning; + int32 _forcedSpellId; + ObjectGuid _forcedTargetGUID; + float _stayX; + float _stayY; + float _stayZ; + + std::unique_ptr _GlobalCooldownMgr; +}; + +#endif // _CHARMINFO_H diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 5293d76bf..1400e2d39 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -23,6 +23,7 @@ #include "Battleground.h" #include "CellImpl.h" #include "CharacterCache.h" +#include "CharmInfo.h" #include "Chat.h" #include "ChatPackets.h" #include "ChatTextBuilder.h" @@ -15763,287 +15764,6 @@ void Unit::DeleteCharmInfo() m_charmInfo = nullptr; } -CharmInfo::CharmInfo(Unit* unit) - : _unit(unit), _CommandState(COMMAND_FOLLOW), _petnumber(0), _oldReactState(REACT_PASSIVE), - _isCommandAttack(false), _isCommandFollow(false), _isAtStay(false), _isFollowing(false), _isReturning(false), - _forcedSpellId(0), _stayX(0.0f), _stayY(0.0f), _stayZ(0.0f) -{ - for (uint8 i = 0; i < MAX_SPELL_CHARM; ++i) - _charmspells[i].SetActionAndType(0, ACT_DISABLED); - - if (_unit->GetTypeId() == TYPEID_UNIT) - { - _oldReactState = _unit->ToCreature()->GetReactState(); - _unit->ToCreature()->SetReactState(REACT_PASSIVE); - } -} - -CharmInfo::~CharmInfo() -{ -} - -void CharmInfo::RestoreState() -{ - if (Creature* creature = _unit->ToCreature()) - creature->SetReactState(_oldReactState); -} - -void CharmInfo::InitPetActionBar() -{ - // the first 3 SpellOrActions are attack, follow and stay - for (uint32 i = 0; i < ACTION_BAR_INDEX_PET_SPELL_START - ACTION_BAR_INDEX_START; ++i) - SetActionBar(ACTION_BAR_INDEX_START + i, COMMAND_ATTACK - i, ACT_COMMAND); - - // middle 4 SpellOrActions are spells/special attacks/abilities - for (uint32 i = 0; i < ACTION_BAR_INDEX_PET_SPELL_END - ACTION_BAR_INDEX_PET_SPELL_START; ++i) - SetActionBar(ACTION_BAR_INDEX_PET_SPELL_START + i, 0, ACT_PASSIVE); - - // last 3 SpellOrActions are reactions - for (uint32 i = 0; i < ACTION_BAR_INDEX_END - ACTION_BAR_INDEX_PET_SPELL_END; ++i) - SetActionBar(ACTION_BAR_INDEX_PET_SPELL_END + i, COMMAND_ATTACK - i, ACT_REACTION); -} - -void CharmInfo::InitEmptyActionBar(bool withAttack) -{ - if (withAttack) - SetActionBar(ACTION_BAR_INDEX_START, COMMAND_ATTACK, ACT_COMMAND); - else - SetActionBar(ACTION_BAR_INDEX_START, 0, ACT_PASSIVE); - for (uint32 x = ACTION_BAR_INDEX_START + 1; x < ACTION_BAR_INDEX_END; ++x) - SetActionBar(x, 0, ACT_PASSIVE); -} - -void CharmInfo::InitPossessCreateSpells() -{ - if (_unit->GetTypeId() == TYPEID_UNIT) - { - // Adding switch until better way is found. Malcrom - // Adding entrys to this switch will prevent COMMAND_ATTACK being added to pet bar. - switch (_unit->GetEntry()) - { - case 23575: // Mindless Abomination - case 24783: // Trained Rock Falcon - case 27664: // Crashin' Thrashin' Racer - case 40281: // Crashin' Thrashin' Racer - case 23109: // Vengeful Spirit - break; - default: - InitEmptyActionBar(); - break; - } - - for (uint32 i = 0; i < MAX_CREATURE_SPELLS; ++i) - { - uint32 spellId = _unit->ToCreature()->m_spells[i]; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (spellInfo) - { - if (spellInfo->IsPassive()) - _unit->CastSpell(_unit, spellInfo, true); - else - AddSpellToActionBar(spellInfo, ACT_PASSIVE); - } - } - } - else - InitEmptyActionBar(); -} - -void CharmInfo::InitCharmCreateSpells() -{ - InitPetActionBar(); - - if (_unit->GetTypeId() == TYPEID_PLAYER) // charmed players don't have spells - { - //InitEmptyActionBar(); - return; - } - - //InitPetActionBar(); - - for (uint32 x = 0; x < MAX_SPELL_CHARM; ++x) - { - uint32 spellId = _unit->ToCreature()->m_spells[x]; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - - if (!spellInfo) - { - _charmspells[x].SetActionAndType(spellId, ACT_DISABLED); - continue; - } - - if (spellInfo->IsPassive()) - { - _unit->CastSpell(_unit, spellInfo, true); - _charmspells[x].SetActionAndType(spellId, ACT_PASSIVE); - } - else - { - _charmspells[x].SetActionAndType(spellId, ACT_DISABLED); - - ActiveStates newstate = ACT_PASSIVE; - - if (!spellInfo->IsAutocastable()) - newstate = ACT_PASSIVE; - else - { - if (spellInfo->NeedsExplicitUnitTarget()) - { - newstate = ACT_ENABLED; - ToggleCreatureAutocast(spellInfo, true); - } - else - newstate = ACT_DISABLED; - } - - AddSpellToActionBar(spellInfo, newstate); - } - } -} - -bool CharmInfo::AddSpellToActionBar(SpellInfo const* spellInfo, ActiveStates newstate) -{ - uint32 spell_id = spellInfo->Id; - uint32 first_id = spellInfo->GetFirstRankSpell()->Id; - - // new spell rank can be already listed - for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) - { - if (uint32 action = PetActionBar[i].GetAction()) - { - if (PetActionBar[i].IsActionBarForSpell() && sSpellMgr->GetFirstSpellInChain(action) == first_id) - { - PetActionBar[i].SetAction(spell_id); - return true; - } - } - } - - // or use empty slot in other case - for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) - { - if (!PetActionBar[i].GetAction() && PetActionBar[i].IsActionBarForSpell()) - { - SetActionBar(i, spell_id, newstate == ACT_DECIDE ? spellInfo->IsAutocastable() ? ACT_DISABLED : ACT_PASSIVE : newstate); - - if (_unit->GetCharmer() && _unit->GetCharmer()->IsPlayer()) - { - if (Creature* creature = _unit->ToCreature()) - { - // Processing this packet needs to be delayed - _unit->m_Events.AddEventAtOffset([creature, spell_id]() - { - if (uint32 cooldown = creature->GetSpellCooldown(spell_id)) - { - WorldPacket data; - creature->BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, spell_id, cooldown); - if (creature->GetCharmer() && creature->GetCharmer()->IsPlayer()) - { - creature->GetCharmer()->ToPlayer()->SendDirectMessage(&data); - } - } - }, 500ms); - } - } - - return true; - } - } - return false; -} - -bool CharmInfo::RemoveSpellFromActionBar(uint32 spell_id) -{ - uint32 first_id = sSpellMgr->GetFirstSpellInChain(spell_id); - - for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) - { - if (uint32 action = PetActionBar[i].GetAction()) - { - if (PetActionBar[i].IsActionBarForSpell() && sSpellMgr->GetFirstSpellInChain(action) == first_id) - { - SetActionBar(i, 0, ACT_PASSIVE); - return true; - } - } - } - - return false; -} - -void CharmInfo::ToggleCreatureAutocast(SpellInfo const* spellInfo, bool apply) -{ - if (spellInfo->IsPassive()) - return; - - for (uint32 x = 0; x < MAX_SPELL_CHARM; ++x) - if (spellInfo->Id == _charmspells[x].GetAction()) - _charmspells[x].SetType(apply ? ACT_ENABLED : ACT_DISABLED); -} - -void CharmInfo::SetPetNumber(uint32 petnumber, bool statwindow) -{ - _petnumber = petnumber; - if (statwindow) - _unit->SetUInt32Value(UNIT_FIELD_PETNUMBER, _petnumber); - else - _unit->SetUInt32Value(UNIT_FIELD_PETNUMBER, 0); -} - -void CharmInfo::LoadPetActionBar(const std::string& data) -{ - std::vector tokens = Acore::Tokenize(data, ' ', false); - - if (tokens.size() != (ACTION_BAR_INDEX_END - ACTION_BAR_INDEX_START) * 2) - return; // non critical, will reset to default - - auto iter = tokens.begin(); - for (uint8 index = ACTION_BAR_INDEX_START; index < ACTION_BAR_INDEX_END; ++index) - { - Optional type = Acore::StringTo(*(iter++)); - Optional action = Acore::StringTo(*(iter++)); - - if (!type || !action) - { - continue; - } - - PetActionBar[index].SetActionAndType(*action, static_cast(*type)); - - // check correctness - if (PetActionBar[index].IsActionBarForSpell()) - { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(PetActionBar[index].GetAction()); - if (!spellInfo) - { - SetActionBar(index, 0, ACT_PASSIVE); - } - else if (!spellInfo->IsAutocastable()) - { - SetActionBar(index, PetActionBar[index].GetAction(), ACT_PASSIVE); - } - } - } -} - -void CharmInfo::BuildActionBar(WorldPacket* data) -{ - for (uint32 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) - *data << uint32(PetActionBar[i].packedData); -} - -void CharmInfo::SetSpellAutocast(SpellInfo const* spellInfo, bool state) -{ - for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) - { - if (spellInfo->Id == PetActionBar[i].GetAction() && PetActionBar[i].IsActionBarForSpell()) - { - PetActionBar[i].SetType(state ? ACT_ENABLED : ACT_DISABLED); - break; - } - } -} - bool Unit::isFrozen() const { return HasAuraState(AURA_STATE_FROZEN); @@ -20534,98 +20254,6 @@ uint32 Unit::GetResistance(SpellSchoolMask mask) const return uint32(resist); } -void CharmInfo::SetIsCommandAttack(bool val) -{ - _isCommandAttack = val; -} - -bool CharmInfo::IsCommandAttack() -{ - return _isCommandAttack; -} - -void CharmInfo::SetIsCommandFollow(bool val) -{ - _isCommandFollow = val; -} - -bool CharmInfo::IsCommandFollow() -{ - return _isCommandFollow; -} - -void CharmInfo::SaveStayPosition(bool atCurrentPos) -{ - //! At this point a new spline destination is enabled because of Unit::StopMoving() - G3D::Vector3 stayPos = G3D::Vector3(); - - if (atCurrentPos) - { - float z = INVALID_HEIGHT; - _unit->UpdateAllowedPositionZ(_unit->GetPositionX(), _unit->GetPositionY(), z); - stayPos = G3D::Vector3(_unit->GetPositionX(), _unit->GetPositionY(), z != INVALID_HEIGHT ? z : _unit->GetPositionZ()); - } - else - stayPos = _unit->movespline->FinalDestination(); - - if (_unit->movespline->onTransport) - if (TransportBase* transport = _unit->GetDirectTransport()) - transport->CalculatePassengerPosition(stayPos.x, stayPos.y, stayPos.z); - - _stayX = stayPos.x; - _stayY = stayPos.y; - _stayZ = stayPos.z; -} - -void CharmInfo::GetStayPosition(float& x, float& y, float& z) -{ - x = _stayX; - y = _stayY; - z = _stayZ; -} - -void CharmInfo::RemoveStayPosition() -{ - _stayX = 0.0f; - _stayY = 0.0f; - _stayZ = 0.0f; -} - -bool CharmInfo::HasStayPosition() -{ - return _stayX && _stayY && _stayZ; -} - -void CharmInfo::SetIsAtStay(bool val) -{ - _isAtStay = val; -} - -bool CharmInfo::IsAtStay() -{ - return _isAtStay; -} - -void CharmInfo::SetIsFollowing(bool val) -{ - _isFollowing = val; -} - -bool CharmInfo::IsFollowing() -{ - return _isFollowing; -} - -void CharmInfo::SetIsReturning(bool val) -{ - _isReturning = val; -} - -bool CharmInfo::IsReturning() -{ - return _isReturning; -} - void Unit::PetSpellFail(SpellInfo const* spellInfo, Unit* target, uint32 result) { CharmInfo* charmInfo = GetCharmInfo(); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 9ed7c5f66..61c6b29fa 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -29,6 +29,8 @@ #include "SpellAuraDefines.h" #include "SpellDefines.h" #include "ThreatMgr.h" +#include "UnitDefines.h" +#include "UnitUtils.h" #include #include @@ -38,127 +40,43 @@ #define BASE_MAXDAMAGE 2.0f #define BASE_ATTACK_TIME 2000 -enum UnitBytes1Offsets : uint8 -{ - UNIT_BYTES_1_OFFSET_STAND_STATE = 0, - UNIT_BYTES_1_OFFSET_PET_TALENTS = 1, - UNIT_BYTES_1_OFFSET_VIS_FLAG = 2, - UNIT_BYTES_1_OFFSET_ANIM_TIER = 3 -}; - -// byte value (UNIT_FIELD_BYTES_1, 0) -enum UnitStandStateType -{ - UNIT_STAND_STATE_STAND = 0, - UNIT_STAND_STATE_SIT = 1, - UNIT_STAND_STATE_SIT_CHAIR = 2, - UNIT_STAND_STATE_SLEEP = 3, - UNIT_STAND_STATE_SIT_LOW_CHAIR = 4, - UNIT_STAND_STATE_SIT_MEDIUM_CHAIR = 5, - UNIT_STAND_STATE_SIT_HIGH_CHAIR = 6, - UNIT_STAND_STATE_DEAD = 7, - UNIT_STAND_STATE_KNEEL = 8, - UNIT_STAND_STATE_SUBMERGED = 9 -}; - -// byte flag value (UNIT_FIELD_BYTES_1, 2) -enum UnitStandFlags -{ - UNIT_STAND_FLAGS_UNK1 = 0x01, - UNIT_STAND_FLAGS_CREEP = 0x02, - UNIT_STAND_FLAGS_UNTRACKABLE = 0x04, - UNIT_STAND_FLAGS_UNK4 = 0x08, - UNIT_STAND_FLAGS_UNK5 = 0x10, - UNIT_STAND_FLAGS_ALL = 0xFF -}; - -// byte flags value (UNIT_FIELD_BYTES_1, 3) -enum UnitBytes1_Flags -{ - UNIT_BYTE1_FLAG_GROUND = 0x00, - UNIT_BYTE1_FLAG_ALWAYS_STAND = 0x01, - UNIT_BYTE1_FLAG_HOVER = 0x02, - UNIT_BYTE1_FLAG_FLY = 0x03, - UNIT_BYTE1_FLAG_SUBMERGED = 0x04, - UNIT_BYTE1_FLAG_ALL = 0xFF -}; - -// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2 -enum ShapeshiftForm -{ - FORM_NONE = 0x00, - FORM_CAT = 0x01, - FORM_TREE = 0x02, - FORM_TRAVEL = 0x03, - FORM_AQUA = 0x04, - FORM_BEAR = 0x05, - FORM_AMBIENT = 0x06, - FORM_GHOUL = 0x07, - FORM_DIREBEAR = 0x08, - FORM_STEVES_GHOUL = 0x09, - FORM_THARONJA_SKELETON = 0x0A, - FORM_TEST_OF_STRENGTH = 0x0B, - FORM_BLB_PLAYER = 0x0C, - FORM_SHADOW_DANCE = 0x0D, - FORM_CREATUREBEAR = 0x0E, - FORM_CREATURECAT = 0x0F, - FORM_GHOSTWOLF = 0x10, - FORM_BATTLESTANCE = 0x11, - FORM_DEFENSIVESTANCE = 0x12, - FORM_BERSERKERSTANCE = 0x13, - FORM_TEST = 0x14, - FORM_ZOMBIE = 0x15, - FORM_METAMORPHOSIS = 0x16, - FORM_UNDEAD = 0x19, - FORM_MASTER_ANGLER = 0x1A, - FORM_FLIGHT_EPIC = 0x1B, - FORM_SHADOW = 0x1C, - FORM_FLIGHT = 0x1D, - FORM_STEALTH = 0x1E, - FORM_MOONKIN = 0x1F, - FORM_SPIRITOFREDEMPTION = 0x20 -}; - -// low byte (0 from 0..3) of UNIT_FIELD_BYTES_2 -enum SheathState -{ - SHEATH_STATE_UNARMED = 0, // non prepared weapon - SHEATH_STATE_MELEE = 1, // prepared melee weapon - SHEATH_STATE_RANGED = 2 // prepared ranged weapon -}; - -#define MAX_SHEATH_STATE 3 - -// byte (1 from 0..3) of UNIT_FIELD_BYTES_2 -enum UnitPVPStateFlags -{ - UNIT_BYTE2_FLAG_PVP = 0x01, - UNIT_BYTE2_FLAG_UNK1 = 0x02, - UNIT_BYTE2_FLAG_FFA_PVP = 0x04, - UNIT_BYTE2_FLAG_SANCTUARY = 0x08, - UNIT_BYTE2_FLAG_UNK4 = 0x10, - UNIT_BYTE2_FLAG_UNK5 = 0x20, - UNIT_BYTE2_FLAG_UNK6 = 0x40, - UNIT_BYTE2_FLAG_UNK7 = 0x80 -}; - -// byte (2 from 0..3) of UNIT_FIELD_BYTES_2 -enum UnitRename -{ - UNIT_CAN_BE_RENAMED = 0x01, - UNIT_CAN_BE_ABANDONED = 0x02, -}; +#define MAX_AGGRO_RADIUS 45.0f // yards static constexpr uint32 MAX_CREATURE_SPELLS = 8; static constexpr uint32 infinityCooldownDelay = 0x9A7EC800; // used for set "infinity cooldowns" for spells and check, MONTH*IN_MILLISECONDS static constexpr uint32 infinityCooldownDelayCheck = 0x4D3F6400; // MONTH*IN_MILLISECONDS/2; -#define MAX_SPELL_CHARM 4 -#define MAX_SPELL_VEHICLE 6 -#define MAX_SPELL_POSSESS 8 -#define MAX_SPELL_CONTROL_BAR 10 +struct CharmInfo; +struct FactionTemplateEntry; +struct SpellValue; -#define MAX_AGGRO_RADIUS 45.0f // yards +class AuraApplication; +class Aura; +class UnitAura; +class AuraEffect; +class Creature; +class Spell; +class SpellInfo; +class DynamicObject; +class GameObject; +class Item; +class Pet; +class PetAura; +class Minion; +class Guardian; +class UnitAI; +class Totem; +class Transport; +class StaticTransport; +class MotionTransport; +class Vehicle; +class TransportBase; +class SpellCastTargets; + +typedef std::list UnitList; +typedef std::list< std::pair > DispelChargesList; + +enum CharmType : uint8; enum VictimState { @@ -203,42 +121,6 @@ enum HitInfo HITINFO_FAKE_DAMAGE = 0x01000000 // enables damage animation even if no damage done, set only if no damage }; -//i would like to remove this: (it is defined in item.h -enum InventorySlot -{ - NULL_BAG = 0, - NULL_SLOT = 255 -}; - -struct FactionTemplateEntry; -struct SpellValue; - -class AuraApplication; -class Aura; -class UnitAura; -class AuraEffect; -class Creature; -class Spell; -class SpellInfo; -class DynamicObject; -class GameObject; -class Item; -class Pet; -class PetAura; -class Minion; -class Guardian; -class UnitAI; -class Totem; -class Transport; -class StaticTransport; -class MotionTransport; -class Vehicle; -class TransportBase; -class SpellCastTargets; - -typedef std::list UnitList; -typedef std::list< std::pair > DispelChargesList; - enum UnitModifierType { BASE_VALUE = 0, @@ -319,74 +201,6 @@ enum class DeathState : uint8 JustRespawned = 4, }; -enum UnitState -{ - UNIT_STATE_DIED = 0x00000001, // player has fake death aura - UNIT_STATE_MELEE_ATTACKING = 0x00000002, // player is melee attacking someone - //UNIT_STATE_MELEE_ATTACK_BY = 0x00000004, // player is melee attack by someone - UNIT_STATE_STUNNED = 0x00000008, - UNIT_STATE_ROAMING = 0x00000010, - UNIT_STATE_CHASE = 0x00000020, - //UNIT_STATE_SEARCHING = 0x00000040, - UNIT_STATE_FLEEING = 0x00000080, - UNIT_STATE_IN_FLIGHT = 0x00000100, // player is in flight mode - UNIT_STATE_FOLLOW = 0x00000200, - UNIT_STATE_ROOT = 0x00000400, - UNIT_STATE_CONFUSED = 0x00000800, - UNIT_STATE_DISTRACTED = 0x00001000, - UNIT_STATE_ISOLATED = 0x00002000, // area auras do not affect other players - UNIT_STATE_ATTACK_PLAYER = 0x00004000, - UNIT_STATE_CASTING = 0x00008000, - UNIT_STATE_POSSESSED = 0x00010000, - UNIT_STATE_CHARGING = 0x00020000, - UNIT_STATE_JUMPING = 0x00040000, - UNIT_STATE_MOVE = 0x00100000, - UNIT_STATE_ROTATING = 0x00200000, - UNIT_STATE_EVADE = 0x00400000, - UNIT_STATE_ROAMING_MOVE = 0x00800000, - UNIT_STATE_CONFUSED_MOVE = 0x01000000, - UNIT_STATE_FLEEING_MOVE = 0x02000000, - UNIT_STATE_CHASE_MOVE = 0x04000000, - UNIT_STATE_FOLLOW_MOVE = 0x08000000, - UNIT_STATE_IGNORE_PATHFINDING = 0x10000000, // do not use pathfinding in any MovementGenerator - UNIT_STATE_NO_ENVIRONMENT_UPD = 0x20000000, // pussywizard - - UNIT_STATE_ALL_STATE_SUPPORTED = UNIT_STATE_DIED | UNIT_STATE_MELEE_ATTACKING | UNIT_STATE_STUNNED | UNIT_STATE_ROAMING | UNIT_STATE_CHASE - | UNIT_STATE_FLEEING | UNIT_STATE_IN_FLIGHT | UNIT_STATE_FOLLOW | UNIT_STATE_ROOT | UNIT_STATE_CONFUSED - | UNIT_STATE_DISTRACTED | UNIT_STATE_ISOLATED | UNIT_STATE_ATTACK_PLAYER | UNIT_STATE_CASTING - | UNIT_STATE_POSSESSED | UNIT_STATE_CHARGING | UNIT_STATE_JUMPING | UNIT_STATE_MOVE | UNIT_STATE_ROTATING - | UNIT_STATE_EVADE | UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE - | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE | UNIT_STATE_IGNORE_PATHFINDING | UNIT_STATE_NO_ENVIRONMENT_UPD, - - UNIT_STATE_UNATTACKABLE = UNIT_STATE_IN_FLIGHT, - // for real move using movegen check and stop (except unstoppable flight) - UNIT_STATE_MOVING = UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE, - UNIT_STATE_CONTROLLED = (UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING), - UNIT_STATE_LOST_CONTROL = (UNIT_STATE_CONTROLLED | UNIT_STATE_JUMPING | UNIT_STATE_CHARGING), - UNIT_STATE_SIGHTLESS = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_EVADE), - UNIT_STATE_CANNOT_AUTOATTACK = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_CASTING), - UNIT_STATE_CANNOT_TURN = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_ROTATING | UNIT_STATE_ROOT), - // stay by different reasons - UNIT_STATE_NOT_MOVE = UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DIED | UNIT_STATE_DISTRACTED, - UNIT_STATE_IGNORE_ANTISPEEDHACK = UNIT_STATE_FLEEING | UNIT_STATE_CONFUSED | UNIT_STATE_CHARGING | UNIT_STATE_DISTRACTED | UNIT_STATE_POSSESSED, - UNIT_STATE_ALL_STATE = 0xffffffff //(UNIT_STATE_STOPPED | UNIT_STATE_MOVING | UNIT_STATE_IN_COMBAT | UNIT_STATE_IN_FLIGHT) -}; - -enum UnitMoveType -{ - MOVE_WALK = 0, - MOVE_RUN = 1, - MOVE_RUN_BACK = 2, - MOVE_SWIM = 3, - MOVE_SWIM_BACK = 4, - MOVE_TURN_RATE = 5, - MOVE_FLIGHT = 6, - MOVE_FLIGHT_BACK = 7, - MOVE_PITCH_RATE = 8 -}; - -#define MAX_MOVE_TYPE 9 - extern float baseMoveSpeed[MAX_MOVE_TYPE]; extern float playerBaseMoveSpeed[MAX_MOVE_TYPE]; @@ -439,273 +253,6 @@ enum DamageEffectType : uint8 SELF_DAMAGE = 5 }; -// Used for IsClass hook -enum ClassContext : uint8 -{ - CLASS_CONTEXT_NONE = 0, // Default - CLASS_CONTEXT_INIT = 1, - CLASS_CONTEXT_TELEPORT = 2, - CLASS_CONTEXT_QUEST = 3, - CLASS_CONTEXT_STATS = 4, - CLASS_CONTEXT_TAXI = 5, - CLASS_CONTEXT_SKILL = 6, - CLASS_CONTEXT_TALENT_POINT_CALC = 7, - CLASS_CONTEXT_ABILITY = 8, - CLASS_CONTEXT_ABILITY_REACTIVE = 9, - CLASS_CONTEXT_PET = 10, - CLASS_CONTEXT_PET_CHARM = 11, - CLASS_CONTEXT_EQUIP_RELIC = 12, - CLASS_CONTEXT_EQUIP_SHIELDS = 13, - CLASS_CONTEXT_EQUIP_ARMOR_CLASS = 14, - CLASS_CONTEXT_WEAPON_SWAP = 15, - CLASS_CONTEXT_GRAVEYARD = 16, - CLASS_CONTEXT_CLASS_TRAINER = 17 -}; - -// Value masks for UNIT_FIELD_FLAGS -// EnumUtils: DESCRIBE THIS -enum UnitFlags : uint32 -{ - UNIT_FLAG_NONE = 0x00000000, - UNIT_FLAG_SERVER_CONTROLLED = 0x00000001, // set only when unit movement is controlled by server - by SPLINE/MONSTER_MOVE packets, together with UNIT_FLAG_STUNNED; only set to units controlled by client; client function CGUnit_C::IsClientControlled returns false when set for owner - UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable - UNIT_FLAG_DISABLE_MOVE = 0x00000004, - UNIT_FLAG_PLAYER_CONTROLLED = 0x00000008, // controlled by player, use _IMMUNE_TO_PC instead of _IMMUNE_TO_NPC - UNIT_FLAG_RENAME = 0x00000010, - UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR5_NO_REAGENT_COST_WITH_AURA - UNIT_FLAG_UNK_6 = 0x00000040, - UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PLAYER_CONTROLLED | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE - UNIT_FLAG_IMMUNE_TO_PC = 0x00000100, // disables combat/assistance with PlayerCharacters (PC) - see Unit::_IsValidAttackTarget, Unit::_IsValidAssistTarget - UNIT_FLAG_IMMUNE_TO_NPC = 0x00000200, // disables combat/assistance with NonPlayerCharacters (NPC) - see Unit::_IsValidAttackTarget, Unit::_IsValidAssistTarget - UNIT_FLAG_LOOTING = 0x00000400, // loot animation - UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8 - UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3 - UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1 - UNIT_FLAG_CANNOT_SWIM = 0x00004000, // 2.0.8 - UNIT_FLAG_SWIMMING = 0x00008000, // shows swim animation in water - UNIT_FLAG_NON_ATTACKABLE_2 = 0x00010000, // removes attackable icon, if on yourself, cannot assist self but can cast TARGET_SELF spells - added by SPELL_AURA_MOD_UNATTACKABLE - UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok - UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok - UNIT_FLAG_IN_COMBAT = 0x00080000, - UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag - UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. - UNIT_FLAG_CONFUSED = 0x00400000, - UNIT_FLAG_FLEEING = 0x00800000, - UNIT_FLAG_POSSESSED = 0x01000000, // under direct client control by a player (possess or vehicle) - UNIT_FLAG_NOT_SELECTABLE = 0x02000000, - UNIT_FLAG_SKINNABLE = 0x04000000, - UNIT_FLAG_MOUNT = 0x08000000, - UNIT_FLAG_UNK_28 = 0x10000000, - UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT = 0x20000000, // Prevent automatically playing emotes from parsing chat text, for example "lol" in /say, ending message with ? or !, or using /yell - UNIT_FLAG_SHEATHE = 0x40000000, - UNIT_FLAG_IMMUNE = 0x80000000, // Immune to damage -}; - -DEFINE_ENUM_FLAG(UnitFlags); - -// Value masks for UNIT_FIELD_FLAGS_2 -enum UnitFlags2 : uint32 -{ - UNIT_FLAG2_NONE = 0x00000000, - UNIT_FLAG2_FEIGN_DEATH = 0x00000001, - UNIT_FLAG2_HIDE_BODY = 0x00000002, // Hide unit model (show only player equip) - UNIT_FLAG2_IGNORE_REPUTATION = 0x00000004, - UNIT_FLAG2_COMPREHEND_LANG = 0x00000008, - UNIT_FLAG2_MIRROR_IMAGE = 0x00000010, - UNIT_FLAG2_DO_NOT_FADE_IN = 0x00000020, // Unit model instantly appears when summoned (does not fade in) - UNIT_FLAG2_FORCE_MOVEMENT = 0x00000040, - UNIT_FLAG2_DISARM_OFFHAND = 0x00000080, - UNIT_FLAG2_DISABLE_PRED_STATS = 0x00000100, // Player has disabled predicted stats (Used by raid frames) - UNIT_FLAG2_DISARM_RANGED = 0x00000400, // this does not disable ranged weapon display (maybe additional flag needed?) - UNIT_FLAG2_REGENERATE_POWER = 0x00000800, - UNIT_FLAG2_RESTRICT_PARTY_INTERACTION = 0x00001000, // Restrict interaction to party or raid - UNIT_FLAG2_PREVENT_SPELL_CLICK = 0x00002000, // Prevent spellclick - UNIT_FLAG2_ALLOW_ENEMY_INTERACT = 0x00004000, - UNIT_FLAG2_CANNOT_TURN = 0x00008000, - UNIT_FLAG2_UNK2 = 0x00010000, - UNIT_FLAG2_PLAY_DEATH_ANIM = 0x00020000, // Plays special death animation upon death - UNIT_FLAG2_ALLOW_CHEAT_SPELLS = 0x00040000, // Allows casting spells with AttributesEx7 & SPELL_ATTR7_DEBUG_SPELL - UNIT_FLAG2_UNUSED_6 = 0x01000000, -}; - -DEFINE_ENUM_FLAG(UnitFlags2); - -/// Non Player Character flags -// EnumUtils: DESCRIBE THIS -enum NPCFlags : uint32 -{ - UNIT_NPC_FLAG_NONE = 0x00000000, // SKIP - UNIT_NPC_FLAG_GOSSIP = 0x00000001, // TITLE has gossip menu DESCRIPTION 100% - UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // TITLE is quest giver DESCRIPTION guessed, probably ok - UNIT_NPC_FLAG_UNK1 = 0x00000004, - UNIT_NPC_FLAG_UNK2 = 0x00000008, - UNIT_NPC_FLAG_TRAINER = 0x00000010, // TITLE is trainer DESCRIPTION 100% - UNIT_NPC_FLAG_TRAINER_CLASS = 0x00000020, // TITLE is class trainer DESCRIPTION 100% - UNIT_NPC_FLAG_TRAINER_PROFESSION = 0x00000040, // TITLE is profession trainer DESCRIPTION 100% - UNIT_NPC_FLAG_VENDOR = 0x00000080, // TITLE is vendor (generic) DESCRIPTION 100% - UNIT_NPC_FLAG_VENDOR_AMMO = 0x00000100, // TITLE is vendor (ammo) DESCRIPTION 100%, general goods vendor - UNIT_NPC_FLAG_VENDOR_FOOD = 0x00000200, // TITLE is vendor (food) DESCRIPTION 100% - UNIT_NPC_FLAG_VENDOR_POISON = 0x00000400, // TITLE is vendor (poison) DESCRIPTION guessed - UNIT_NPC_FLAG_VENDOR_REAGENT = 0x00000800, // TITLE is vendor (reagents) DESCRIPTION 100% - UNIT_NPC_FLAG_REPAIR = 0x00001000, // TITLE can repair DESCRIPTION 100% - UNIT_NPC_FLAG_FLIGHTMASTER = 0x00002000, // TITLE is flight master DESCRIPTION 100% - UNIT_NPC_FLAG_SPIRITHEALER = 0x00004000, // TITLE is spirit healer DESCRIPTION guessed - UNIT_NPC_FLAG_SPIRITGUIDE = 0x00008000, // TITLE is spirit guide DESCRIPTION guessed - UNIT_NPC_FLAG_INNKEEPER = 0x00010000, // TITLE is innkeeper - UNIT_NPC_FLAG_BANKER = 0x00020000, // TITLE is banker DESCRIPTION 100% - UNIT_NPC_FLAG_PETITIONER = 0x00040000, // TITLE handles guild/arena petitions DESCRIPTION 100% 0xC0000 = guild petitions, 0x40000 = arena team petitions - UNIT_NPC_FLAG_TABARDDESIGNER = 0x00080000, // TITLE is guild tabard designer DESCRIPTION 100% - UNIT_NPC_FLAG_BATTLEMASTER = 0x00100000, // TITLE is battlemaster DESCRIPTION 100% - UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, // TITLE is auctioneer DESCRIPTION 100% - UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // TITLE is stable master DESCRIPTION 100% - UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // TITLE is guild banker DESCRIPTION cause client to send 997 opcode - UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // TITLE has spell click enabled DESCRIPTION cause client to send 1015 opcode (spell click) - UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // TITLE is player vehicle DESCRIPTION players with mounts that have vehicle data should have it set - UNIT_NPC_FLAG_MAILBOX = 0x04000000, // TITLE is mailbox - - UNIT_NPC_FLAG_VENDOR_MASK = UNIT_NPC_FLAG_VENDOR | UNIT_NPC_FLAG_VENDOR_AMMO | UNIT_NPC_FLAG_VENDOR_POISON | UNIT_NPC_FLAG_VENDOR_REAGENT -}; - -DEFINE_ENUM_FLAG(NPCFlags); - -enum MovementFlags -{ - MOVEMENTFLAG_NONE = 0x00000000, - MOVEMENTFLAG_FORWARD = 0x00000001, - MOVEMENTFLAG_BACKWARD = 0x00000002, - MOVEMENTFLAG_STRAFE_LEFT = 0x00000004, - MOVEMENTFLAG_STRAFE_RIGHT = 0x00000008, - MOVEMENTFLAG_LEFT = 0x00000010, - MOVEMENTFLAG_RIGHT = 0x00000020, - MOVEMENTFLAG_PITCH_UP = 0x00000040, - MOVEMENTFLAG_PITCH_DOWN = 0x00000080, - MOVEMENTFLAG_WALKING = 0x00000100, // Walking - MOVEMENTFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures - MOVEMENTFLAG_DISABLE_GRAVITY = 0x00000400, // Former MOVEMENTFLAG_LEVITATING. This is used when walking is not possible. - MOVEMENTFLAG_ROOT = 0x00000800, // Must not be set along with MOVEMENTFLAG_MASK_MOVING - MOVEMENTFLAG_FALLING = 0x00001000, // damage dealt on that type of falling - MOVEMENTFLAG_FALLING_FAR = 0x00002000, - MOVEMENTFLAG_PENDING_STOP = 0x00004000, - MOVEMENTFLAG_PENDING_STRAFE_STOP = 0x00008000, - MOVEMENTFLAG_PENDING_FORWARD = 0x00010000, - MOVEMENTFLAG_PENDING_BACKWARD = 0x00020000, - MOVEMENTFLAG_PENDING_STRAFE_LEFT = 0x00040000, - MOVEMENTFLAG_PENDING_STRAFE_RIGHT = 0x00080000, - MOVEMENTFLAG_PENDING_ROOT = 0x00100000, - MOVEMENTFLAG_SWIMMING = 0x00200000, // appears with fly flag also - MOVEMENTFLAG_ASCENDING = 0x00400000, // press "space" when flying - MOVEMENTFLAG_DESCENDING = 0x00800000, - MOVEMENTFLAG_CAN_FLY = 0x01000000, // Appears when unit can fly AND also walk - MOVEMENTFLAG_FLYING = 0x02000000, // unit is actually flying. pretty sure this is only used for players. creatures use disable_gravity - MOVEMENTFLAG_SPLINE_ELEVATION = 0x04000000, // used for flight paths - MOVEMENTFLAG_SPLINE_ENABLED = 0x08000000, // used for flight paths - MOVEMENTFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water - MOVEMENTFLAG_FALLING_SLOW = 0x20000000, // active rogue safe fall spell (passive) - MOVEMENTFLAG_HOVER = 0x40000000, // hover, cannot jump - - /// @todo: Check if PITCH_UP and PITCH_DOWN really belong here.. - MOVEMENTFLAG_MASK_MOVING = - MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD | MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT | - MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN | MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR | MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING | - MOVEMENTFLAG_SPLINE_ELEVATION, - - MOVEMENTFLAG_MASK_TURNING = - MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT, - - MOVEMENTFLAG_MASK_MOVING_FLY = - MOVEMENTFLAG_FLYING | MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING, - - /// @todo if needed: add more flags to this masks that are exclusive to players - MOVEMENTFLAG_MASK_PLAYER_ONLY = - MOVEMENTFLAG_FLYING, - - /// Movement flags that have change status opcodes associated for players - MOVEMENTFLAG_MASK_HAS_PLAYER_STATUS_OPCODE = MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_ROOT | - MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_WATERWALKING | MOVEMENTFLAG_FALLING_SLOW | MOVEMENTFLAG_HOVER -}; - -enum MovementFlags2 -{ - MOVEMENTFLAG2_NONE = 0x00000000, - MOVEMENTFLAG2_NO_STRAFE = 0x00000001, - MOVEMENTFLAG2_NO_JUMPING = 0x00000002, - MOVEMENTFLAG2_UNK3 = 0x00000004, // Overrides various clientside checks - MOVEMENTFLAG2_FULL_SPEED_TURNING = 0x00000008, - MOVEMENTFLAG2_FULL_SPEED_PITCHING = 0x00000010, - MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING = 0x00000020, - MOVEMENTFLAG2_UNK7 = 0x00000040, - MOVEMENTFLAG2_UNK8 = 0x00000080, - MOVEMENTFLAG2_UNK9 = 0x00000100, - MOVEMENTFLAG2_UNK10 = 0x00000200, - MOVEMENTFLAG2_INTERPOLATED_MOVEMENT = 0x00000400, - MOVEMENTFLAG2_INTERPOLATED_TURNING = 0x00000800, - MOVEMENTFLAG2_INTERPOLATED_PITCHING = 0x00001000, - MOVEMENTFLAG2_UNK14 = 0x00002000, - MOVEMENTFLAG2_UNK15 = 0x00004000, - MOVEMENTFLAG2_UNK16 = 0x00008000, -}; - -enum SplineFlags -{ - SPLINEFLAG_NONE = 0x00000000, - SPLINEFLAG_FORWARD = 0x00000001, - SPLINEFLAG_BACKWARD = 0x00000002, - SPLINEFLAG_STRAFE_LEFT = 0x00000004, - SPLINEFLAG_STRAFE_RIGHT = 0x00000008, - SPLINEFLAG_TURN_LEFT = 0x00000010, - SPLINEFLAG_TURN_RIGHT = 0x00000020, - SPLINEFLAG_PITCH_UP = 0x00000040, - SPLINEFLAG_PITCH_DOWN = 0x00000080, - SPLINEFLAG_DONE = 0x00000100, - SPLINEFLAG_FALLING = 0x00000200, - SPLINEFLAG_NO_SPLINE = 0x00000400, - SPLINEFLAG_TRAJECTORY = 0x00000800, - SPLINEFLAG_WALK_MODE = 0x00001000, - SPLINEFLAG_FLYING = 0x00002000, - SPLINEFLAG_KNOCKBACK = 0x00004000, - SPLINEFLAG_FINAL_POINT = 0x00008000, - SPLINEFLAG_FINAL_TARGET = 0x00010000, - SPLINEFLAG_FINAL_FACING = 0x00020000, - SPLINEFLAG_CATMULL_ROM = 0x00040000, - SPLINEFLAG_CYCLIC = 0x00080000, - SPLINEFLAG_ENTER_CYCLE = 0x00100000, - SPLINEFLAG_ANIMATION_TIER = 0x00200000, - SPLINEFLAG_FROZEN = 0x00400000, - SPLINEFLAG_TRANSPORT = 0x00800000, - SPLINEFLAG_TRANSPORT_EXIT = 0x01000000, - SPLINEFLAG_UNKNOWN7 = 0x02000000, - SPLINEFLAG_UNKNOWN8 = 0x04000000, - SPLINEFLAG_ORIENTATION_INVERTED = 0x08000000, - SPLINEFLAG_USE_PATH_SMOOTHING = 0x10000000, - SPLINEFLAG_ANIMATION = 0x20000000, - SPLINEFLAG_UNCOMPRESSED_PATH = 0x40000000, - SPLINEFLAG_UNKNOWN10 = 0x80000000, -}; - -enum SplineType -{ - SPLINETYPE_NORMAL = 0, - SPLINETYPE_STOP = 1, - SPLINETYPE_FACING_SPOT = 2, - SPLINETYPE_FACING_TARGET = 3, - SPLINETYPE_FACING_ANGLE = 4, -}; - -enum UnitTypeMask -{ - UNIT_MASK_NONE = 0x00000000, - UNIT_MASK_SUMMON = 0x00000001, - UNIT_MASK_MINION = 0x00000002, - UNIT_MASK_GUARDIAN = 0x00000004, - UNIT_MASK_TOTEM = 0x00000008, - UNIT_MASK_PET = 0x00000010, - UNIT_MASK_VEHICLE = 0x00000020, - UNIT_MASK_PUPPET = 0x00000040, - UNIT_MASK_HUNTER_PET = 0x00000080, - UNIT_MASK_CONTROLABLE_GUARDIAN = 0x00000100, - UNIT_MASK_ACCESSORY = 0x00000200, -}; - namespace Movement { class MoveSpline; @@ -978,28 +525,6 @@ struct SpellPeriodicAuraLogInfo void createProcFlags(SpellInfo const* spellInfo, WeaponAttackType attackType, bool positive, uint32& procAttacker, uint32& procVictim); uint32 createProcExtendMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missCondition); -struct RedirectThreatInfo -{ - RedirectThreatInfo() = default; - ObjectGuid _targetGUID; - uint32 _threatPct{0}; - - [[nodiscard]] ObjectGuid GetTargetGUID() const { return _targetGUID; } - [[nodiscard]] uint32 GetThreatPct() const { return _threatPct; } - - void Set(ObjectGuid guid, uint32 pct) - { - _targetGUID = guid; - _threatPct = pct; - } - - void ModifyThreatPct(int32 amount) - { - amount += _threatPct; - _threatPct = uint32(std::max(0, amount)); - } -}; - #define MAX_DECLINED_NAME_CASES 5 struct DeclinedName @@ -1042,16 +567,6 @@ private: GlobalCooldownList m_GlobalCooldowns; }; -enum ActiveStates : uint8 -{ - ACT_PASSIVE = 0x01, // 0x01 - passive - ACT_DISABLED = 0x81, // 0x80 - castable - ACT_ENABLED = 0xC1, // 0x40 | 0x80 - auto cast + castable - ACT_COMMAND = 0x07, // 0x01 | 0x02 | 0x04 - ACT_REACTION = 0x06, // 0x02 | 0x04 - ACT_DECIDE = 0x00 // custom -}; - enum ReactStates : uint8 { REACT_PASSIVE = 0, @@ -1059,7 +574,7 @@ enum ReactStates : uint8 REACT_AGGRESSIVE = 2 }; -enum CommandStates +enum CommandStates : uint8 { COMMAND_STAY = 0, COMMAND_FOLLOW = 1, @@ -1067,147 +582,8 @@ enum CommandStates COMMAND_ABANDON = 3 }; -#define UNIT_ACTION_BUTTON_ACTION(X) (uint32(X) & 0x00FFFFFF) -#define UNIT_ACTION_BUTTON_TYPE(X) ((uint32(X) & 0xFF000000) >> 24) -#define MAKE_UNIT_ACTION_BUTTON(A, T) (uint32(A) | (uint32(T) << 24)) - -struct UnitActionBarEntry -{ - UnitActionBarEntry() : packedData(uint32(ACT_DISABLED) << 24) {} - - uint32 packedData; - - // helper - [[nodiscard]] ActiveStates GetType() const { return ActiveStates(UNIT_ACTION_BUTTON_TYPE(packedData)); } - [[nodiscard]] uint32 GetAction() const { return UNIT_ACTION_BUTTON_ACTION(packedData); } - [[nodiscard]] bool IsActionBarForSpell() const - { - ActiveStates Type = GetType(); - return Type == ACT_DISABLED || Type == ACT_ENABLED || Type == ACT_PASSIVE; - } - - void SetActionAndType(uint32 action, ActiveStates type) - { - packedData = MAKE_UNIT_ACTION_BUTTON(action, type); - } - - void SetType(ActiveStates type) - { - packedData = MAKE_UNIT_ACTION_BUTTON(UNIT_ACTION_BUTTON_ACTION(packedData), type); - } - - void SetAction(uint32 action) - { - packedData = (packedData & 0xFF000000) | UNIT_ACTION_BUTTON_ACTION(action); - } -}; - typedef std::list SharedVisionList; -enum CharmType -{ - CHARM_TYPE_CHARM, - CHARM_TYPE_POSSESS, - CHARM_TYPE_VEHICLE, - CHARM_TYPE_CONVERT, -}; - -typedef UnitActionBarEntry CharmSpellInfo; - -enum ActionBarIndex -{ - ACTION_BAR_INDEX_START = 0, - ACTION_BAR_INDEX_PET_SPELL_START = 3, - ACTION_BAR_INDEX_PET_SPELL_END = 7, - ACTION_BAR_INDEX_END = 10, -}; - -#define MAX_UNIT_ACTION_BAR_INDEX (ACTION_BAR_INDEX_END-ACTION_BAR_INDEX_START) - -struct CharmInfo -{ -public: - explicit CharmInfo(Unit* unit); - ~CharmInfo(); - void RestoreState(); - [[nodiscard]] uint32 GetPetNumber() const { return _petnumber; } - void SetPetNumber(uint32 petnumber, bool statwindow); - - void SetCommandState(CommandStates st) { _CommandState = st; } - [[nodiscard]] CommandStates GetCommandState() const { return _CommandState; } - [[nodiscard]] bool HasCommandState(CommandStates state) const { return (_CommandState == state); } - - void InitPossessCreateSpells(); - void InitCharmCreateSpells(); - void InitPetActionBar(); - void InitEmptyActionBar(bool withAttack = true); - - //return true if successful - bool AddSpellToActionBar(SpellInfo const* spellInfo, ActiveStates newstate = ACT_DECIDE); - bool RemoveSpellFromActionBar(uint32 spell_id); - void LoadPetActionBar(const std::string& data); - void BuildActionBar(WorldPacket* data); - void SetSpellAutocast(SpellInfo const* spellInfo, bool state); - void SetActionBar(uint8 index, uint32 spellOrAction, ActiveStates type) - { - PetActionBar[index].SetActionAndType(spellOrAction, type); - } - [[nodiscard]] UnitActionBarEntry const* GetActionBarEntry(uint8 index) const { return &(PetActionBar[index]); } - - void ToggleCreatureAutocast(SpellInfo const* spellInfo, bool apply); - - CharmSpellInfo* GetCharmSpell(uint8 index) { return &(_charmspells[index]); } - - GlobalCooldownMgr& GetGlobalCooldownMgr() { return _GlobalCooldownMgr; } - - void SetIsCommandAttack(bool val); - bool IsCommandAttack(); - void SetIsCommandFollow(bool val); - bool IsCommandFollow(); - void SetIsAtStay(bool val); - bool IsAtStay(); - void SetIsFollowing(bool val); - bool IsFollowing(); - void SetIsReturning(bool val); - bool IsReturning(); - void SaveStayPosition(bool atCurrentPos); - void GetStayPosition(float& x, float& y, float& z); - void RemoveStayPosition(); - bool HasStayPosition(); - - void SetForcedSpell(uint32 id) { _forcedSpellId = id; } - int32 GetForcedSpell() { return _forcedSpellId; } - void SetForcedTargetGUID(ObjectGuid guid = ObjectGuid::Empty) { _forcedTargetGUID = guid; } - ObjectGuid GetForcedTarget() { return _forcedTargetGUID; } - - // Player react states - void SetPlayerReactState(ReactStates s) { _oldReactState = s; } - [[nodiscard]] ReactStates GetPlayerReactState() const { return _oldReactState; } - -private: - Unit* _unit; - UnitActionBarEntry PetActionBar[MAX_UNIT_ACTION_BAR_INDEX]; - CharmSpellInfo _charmspells[4]; - CommandStates _CommandState; - uint32 _petnumber; - - //for restoration after charmed - ReactStates _oldReactState; - - bool _isCommandAttack; - bool _isCommandFollow; - bool _isAtStay; - bool _isFollowing; - bool _isReturning; - int32 _forcedSpellId; - ObjectGuid _forcedTargetGUID; - float _stayX; - float _stayY; - float _stayZ; - - GlobalCooldownMgr _GlobalCooldownMgr; -}; - struct AttackPosition { AttackPosition(Position pos) : _pos(std::move(pos)), _taken(false) {} bool operator==(const int val) @@ -1274,108 +650,6 @@ typedef std::unordered_map PacketCooldowns; struct SpellProcEventEntry; // used only privately -// pussywizard: -class MMapTargetData -{ -public: - MMapTargetData() = default; - MMapTargetData(uint32 endTime, const Position* o, const Position* t) - { - _endTime = endTime; - _posOwner.Relocate(o); - _posTarget.Relocate(t); - } - MMapTargetData(const MMapTargetData& c) - { - _endTime = c._endTime; - _posOwner.Relocate(c._posOwner); - _posTarget.Relocate(c._posTarget); - } - MMapTargetData(MMapTargetData&&) = default; - MMapTargetData& operator=(const MMapTargetData&) = default; - MMapTargetData& operator=(MMapTargetData&&) = default; - [[nodiscard]] bool PosChanged(const Position& o, const Position& t) const - { - return _posOwner.GetExactDistSq(&o) > 0.5f * 0.5f || _posTarget.GetExactDistSq(&t) > 0.5f * 0.5f; - } - uint32 _endTime; - Position _posOwner; - Position _posTarget; -}; - -class SafeUnitPointer -{ -public: - explicit SafeUnitPointer(Unit* defVal) : ptr(defVal), defaultValue(defVal) {} - SafeUnitPointer(const SafeUnitPointer& /*p*/) { ABORT(); } - void Initialize(Unit* defVal) { defaultValue = defVal; ptr = defVal; } - ~SafeUnitPointer(); - void SetPointedTo(Unit* u); - void UnitDeleted(); - Unit* operator->() const { return ptr; } - void operator=(Unit* u) { SetPointedTo(u); } - operator Unit* () const { return ptr; } -private: - Unit* ptr; - Unit* defaultValue; -}; - -// BuildValuesCachePosPointers is marks of the position of some data inside of BuildValue cache. -struct BuildValuesCachePosPointers -{ - BuildValuesCachePosPointers() : - UnitNPCFlagsPos(-1), UnitFieldAuraStatePos(-1), UnitFieldFlagsPos(-1), UnitFieldDisplayPos(-1), - UnitDynamicFlagsPos(-1), UnitFieldBytes2Pos(-1), UnitFieldFactionTemplatePos(-1) {} - - void ApplyOffset(uint32 offset) - { - if (UnitNPCFlagsPos >= 0) - UnitNPCFlagsPos += offset; - - if (UnitFieldAuraStatePos >= 0) - UnitFieldAuraStatePos += offset; - - if (UnitFieldFlagsPos >= 0) - UnitFieldFlagsPos += offset; - - if (UnitFieldDisplayPos >= 0) - UnitFieldDisplayPos += offset; - - if (UnitDynamicFlagsPos >= 0) - UnitDynamicFlagsPos += offset; - - if (UnitFieldBytes2Pos >= 0) - UnitFieldBytes2Pos += offset; - - if (UnitFieldFactionTemplatePos >= 0) - UnitFieldFactionTemplatePos += offset; - - for (auto it = other.begin(); it != other.end(); ++it) - it->second += offset; - } - - int32 UnitNPCFlagsPos; - int32 UnitFieldAuraStatePos; - int32 UnitFieldFlagsPos; - int32 UnitFieldDisplayPos; - int32 UnitDynamicFlagsPos; - int32 UnitFieldBytes2Pos; - int32 UnitFieldFactionTemplatePos; - - std::unordered_map other; -}; - -// BuildValuesCachedBuffer cache for calculated BuildValue. -struct BuildValuesCachedBuffer -{ - BuildValuesCachedBuffer(uint32 bufferSize) : - buffer(bufferSize), posPointers() {} - - ByteBuffer buffer; - - BuildValuesCachePosPointers posPointers; -}; - class Unit : public WorldObject { public: @@ -1881,7 +1155,6 @@ public: virtual bool SetFeatherFall(bool enable, bool packetOnly = false); virtual bool SetHover(bool enable, bool packetOnly = false, bool updateAnimationTier = true); - // pussywizard: void SendMovementWaterWalking(Player* sendTo); void SendMovementFeatherFall(Player* sendTo); void SendMovementHover(Player* sendTo); @@ -2766,15 +2039,4 @@ protected: AuraEffect* _auraEffect; }; -class VehicleDespawnEvent : public BasicEvent -{ -public: - VehicleDespawnEvent(Unit& self, uint32 duration) : _self(self), _duration(duration) { } - bool Execute(uint64 e_time, uint32 p_time) override; - -protected: - Unit& _self; - uint32 _duration; -}; - #endif diff --git a/src/server/game/Entities/Unit/UnitDefines.h b/src/server/game/Entities/Unit/UnitDefines.h new file mode 100644 index 000000000..b694bbcd9 --- /dev/null +++ b/src/server/game/Entities/Unit/UnitDefines.h @@ -0,0 +1,462 @@ +/* + * 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 . + */ + +#include "Define.h" +#include "EnumFlag.h" + +enum UnitBytes1Offsets : uint8 +{ + UNIT_BYTES_1_OFFSET_STAND_STATE = 0, + UNIT_BYTES_1_OFFSET_PET_TALENTS = 1, + UNIT_BYTES_1_OFFSET_VIS_FLAG = 2, + UNIT_BYTES_1_OFFSET_ANIM_TIER = 3 +}; + +// byte value (UNIT_FIELD_BYTES_1, 0) +enum UnitStandStateType +{ + UNIT_STAND_STATE_STAND = 0, + UNIT_STAND_STATE_SIT = 1, + UNIT_STAND_STATE_SIT_CHAIR = 2, + UNIT_STAND_STATE_SLEEP = 3, + UNIT_STAND_STATE_SIT_LOW_CHAIR = 4, + UNIT_STAND_STATE_SIT_MEDIUM_CHAIR = 5, + UNIT_STAND_STATE_SIT_HIGH_CHAIR = 6, + UNIT_STAND_STATE_DEAD = 7, + UNIT_STAND_STATE_KNEEL = 8, + UNIT_STAND_STATE_SUBMERGED = 9 +}; + +// byte flag value (UNIT_FIELD_BYTES_1, 2) +enum UnitStandFlags +{ + UNIT_STAND_FLAGS_UNK1 = 0x01, + UNIT_STAND_FLAGS_CREEP = 0x02, + UNIT_STAND_FLAGS_UNTRACKABLE = 0x04, + UNIT_STAND_FLAGS_UNK4 = 0x08, + UNIT_STAND_FLAGS_UNK5 = 0x10, + UNIT_STAND_FLAGS_ALL = 0xFF +}; + +// byte flags value (UNIT_FIELD_BYTES_1, 3) +enum UnitBytes1_Flags +{ + UNIT_BYTE1_FLAG_GROUND = 0x00, + UNIT_BYTE1_FLAG_ALWAYS_STAND = 0x01, + UNIT_BYTE1_FLAG_HOVER = 0x02, + UNIT_BYTE1_FLAG_FLY = 0x03, + UNIT_BYTE1_FLAG_SUBMERGED = 0x04, + UNIT_BYTE1_FLAG_ALL = 0xFF +}; + +// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2 +enum ShapeshiftForm +{ + FORM_NONE = 0x00, + FORM_CAT = 0x01, + FORM_TREE = 0x02, + FORM_TRAVEL = 0x03, + FORM_AQUA = 0x04, + FORM_BEAR = 0x05, + FORM_AMBIENT = 0x06, + FORM_GHOUL = 0x07, + FORM_DIREBEAR = 0x08, + FORM_STEVES_GHOUL = 0x09, + FORM_THARONJA_SKELETON = 0x0A, + FORM_TEST_OF_STRENGTH = 0x0B, + FORM_BLB_PLAYER = 0x0C, + FORM_SHADOW_DANCE = 0x0D, + FORM_CREATUREBEAR = 0x0E, + FORM_CREATURECAT = 0x0F, + FORM_GHOSTWOLF = 0x10, + FORM_BATTLESTANCE = 0x11, + FORM_DEFENSIVESTANCE = 0x12, + FORM_BERSERKERSTANCE = 0x13, + FORM_TEST = 0x14, + FORM_ZOMBIE = 0x15, + FORM_METAMORPHOSIS = 0x16, + FORM_UNDEAD = 0x19, + FORM_MASTER_ANGLER = 0x1A, + FORM_FLIGHT_EPIC = 0x1B, + FORM_SHADOW = 0x1C, + FORM_FLIGHT = 0x1D, + FORM_STEALTH = 0x1E, + FORM_MOONKIN = 0x1F, + FORM_SPIRITOFREDEMPTION = 0x20 +}; + +// low byte (0 from 0..3) of UNIT_FIELD_BYTES_2 +enum SheathState +{ + SHEATH_STATE_UNARMED = 0, // non prepared weapon + SHEATH_STATE_MELEE = 1, // prepared melee weapon + SHEATH_STATE_RANGED = 2 // prepared ranged weapon +}; + +#define MAX_SHEATH_STATE 3 + +// byte (1 from 0..3) of UNIT_FIELD_BYTES_2 +enum UnitPVPStateFlags +{ + UNIT_BYTE2_FLAG_PVP = 0x01, + UNIT_BYTE2_FLAG_UNK1 = 0x02, + UNIT_BYTE2_FLAG_FFA_PVP = 0x04, + UNIT_BYTE2_FLAG_SANCTUARY = 0x08, + UNIT_BYTE2_FLAG_UNK4 = 0x10, + UNIT_BYTE2_FLAG_UNK5 = 0x20, + UNIT_BYTE2_FLAG_UNK6 = 0x40, + UNIT_BYTE2_FLAG_UNK7 = 0x80 +}; + +// byte (2 from 0..3) of UNIT_FIELD_BYTES_2 +enum UnitRename +{ + UNIT_CAN_BE_RENAMED = 0x01, + UNIT_CAN_BE_ABANDONED = 0x02 +}; + +enum UnitTypeMask +{ + UNIT_MASK_NONE = 0x00000000, + UNIT_MASK_SUMMON = 0x00000001, + UNIT_MASK_MINION = 0x00000002, + UNIT_MASK_GUARDIAN = 0x00000004, + UNIT_MASK_TOTEM = 0x00000008, + UNIT_MASK_PET = 0x00000010, + UNIT_MASK_VEHICLE = 0x00000020, + UNIT_MASK_PUPPET = 0x00000040, + UNIT_MASK_HUNTER_PET = 0x00000080, + UNIT_MASK_CONTROLABLE_GUARDIAN = 0x00000100, + UNIT_MASK_ACCESSORY = 0x00000200 +}; + +enum UnitState +{ + UNIT_STATE_DIED = 0x00000001, // player has fake death aura + UNIT_STATE_MELEE_ATTACKING = 0x00000002, // player is melee attacking someone + //UNIT_STATE_MELEE_ATTACK_BY = 0x00000004, // player is melee attack by someone + UNIT_STATE_STUNNED = 0x00000008, + UNIT_STATE_ROAMING = 0x00000010, + UNIT_STATE_CHASE = 0x00000020, + //UNIT_STATE_SEARCHING = 0x00000040, + UNIT_STATE_FLEEING = 0x00000080, + UNIT_STATE_IN_FLIGHT = 0x00000100, // player is in flight mode + UNIT_STATE_FOLLOW = 0x00000200, + UNIT_STATE_ROOT = 0x00000400, + UNIT_STATE_CONFUSED = 0x00000800, + UNIT_STATE_DISTRACTED = 0x00001000, + UNIT_STATE_ISOLATED = 0x00002000, // area auras do not affect other players + UNIT_STATE_ATTACK_PLAYER = 0x00004000, + UNIT_STATE_CASTING = 0x00008000, + UNIT_STATE_POSSESSED = 0x00010000, + UNIT_STATE_CHARGING = 0x00020000, + UNIT_STATE_JUMPING = 0x00040000, + UNIT_STATE_MOVE = 0x00100000, + UNIT_STATE_ROTATING = 0x00200000, + UNIT_STATE_EVADE = 0x00400000, + UNIT_STATE_ROAMING_MOVE = 0x00800000, + UNIT_STATE_CONFUSED_MOVE = 0x01000000, + UNIT_STATE_FLEEING_MOVE = 0x02000000, + UNIT_STATE_CHASE_MOVE = 0x04000000, + UNIT_STATE_FOLLOW_MOVE = 0x08000000, + UNIT_STATE_IGNORE_PATHFINDING = 0x10000000, // do not use pathfinding in any MovementGenerator + UNIT_STATE_NO_ENVIRONMENT_UPD = 0x20000000, + + UNIT_STATE_ALL_STATE_SUPPORTED = UNIT_STATE_DIED | UNIT_STATE_MELEE_ATTACKING | UNIT_STATE_STUNNED | UNIT_STATE_ROAMING | UNIT_STATE_CHASE + | UNIT_STATE_FLEEING | UNIT_STATE_IN_FLIGHT | UNIT_STATE_FOLLOW | UNIT_STATE_ROOT | UNIT_STATE_CONFUSED + | UNIT_STATE_DISTRACTED | UNIT_STATE_ISOLATED | UNIT_STATE_ATTACK_PLAYER | UNIT_STATE_CASTING + | UNIT_STATE_POSSESSED | UNIT_STATE_CHARGING | UNIT_STATE_JUMPING | UNIT_STATE_MOVE | UNIT_STATE_ROTATING + | UNIT_STATE_EVADE | UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE + | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE | UNIT_STATE_IGNORE_PATHFINDING | UNIT_STATE_NO_ENVIRONMENT_UPD, + + UNIT_STATE_UNATTACKABLE = UNIT_STATE_IN_FLIGHT, + + // for real move using movegen check and stop (except unstoppable flight) + UNIT_STATE_MOVING = UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE, + UNIT_STATE_CONTROLLED = (UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING), + UNIT_STATE_LOST_CONTROL = (UNIT_STATE_CONTROLLED | UNIT_STATE_JUMPING | UNIT_STATE_CHARGING), + UNIT_STATE_SIGHTLESS = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_EVADE), + UNIT_STATE_CANNOT_AUTOATTACK = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_CASTING), + UNIT_STATE_CANNOT_TURN = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_ROTATING | UNIT_STATE_ROOT), + + // stay by different reasons + UNIT_STATE_NOT_MOVE = UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DIED | UNIT_STATE_DISTRACTED, + UNIT_STATE_IGNORE_ANTISPEEDHACK = UNIT_STATE_FLEEING | UNIT_STATE_CONFUSED | UNIT_STATE_CHARGING | UNIT_STATE_DISTRACTED | UNIT_STATE_POSSESSED, + UNIT_STATE_ALL_STATE = 0xffffffff //(UNIT_STATE_STOPPED | UNIT_STATE_MOVING | UNIT_STATE_IN_COMBAT | UNIT_STATE_IN_FLIGHT) +}; + +// Used for IsClass hook +enum ClassContext : uint8 +{ + CLASS_CONTEXT_NONE = 0, // Default + CLASS_CONTEXT_INIT = 1, + CLASS_CONTEXT_TELEPORT = 2, + CLASS_CONTEXT_QUEST = 3, + CLASS_CONTEXT_STATS = 4, + CLASS_CONTEXT_TAXI = 5, + CLASS_CONTEXT_SKILL = 6, + CLASS_CONTEXT_TALENT_POINT_CALC = 7, + CLASS_CONTEXT_ABILITY = 8, + CLASS_CONTEXT_ABILITY_REACTIVE = 9, + CLASS_CONTEXT_PET = 10, + CLASS_CONTEXT_PET_CHARM = 11, + CLASS_CONTEXT_EQUIP_RELIC = 12, + CLASS_CONTEXT_EQUIP_SHIELDS = 13, + CLASS_CONTEXT_EQUIP_ARMOR_CLASS = 14, + CLASS_CONTEXT_WEAPON_SWAP = 15, + CLASS_CONTEXT_GRAVEYARD = 16, + CLASS_CONTEXT_CLASS_TRAINER = 17 +}; + +// Value masks for UNIT_FIELD_FLAGS +enum UnitFlags : uint32 +{ + UNIT_FLAG_NONE = 0x00000000, + UNIT_FLAG_SERVER_CONTROLLED = 0x00000001, // set only when unit movement is controlled by server - by SPLINE/MONSTER_MOVE packets, together with UNIT_FLAG_STUNNED; only set to units controlled by client; client function CGUnit_C::IsClientControlled returns false when set for owner + UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable + UNIT_FLAG_DISABLE_MOVE = 0x00000004, + UNIT_FLAG_PLAYER_CONTROLLED = 0x00000008, // controlled by player, use _IMMUNE_TO_PC instead of _IMMUNE_TO_NPC + UNIT_FLAG_RENAME = 0x00000010, + UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR5_NO_REAGENT_COST_WITH_AURA + UNIT_FLAG_UNK_6 = 0x00000040, + UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PLAYER_CONTROLLED | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE + UNIT_FLAG_IMMUNE_TO_PC = 0x00000100, // disables combat/assistance with PlayerCharacters (PC) - see Unit::_IsValidAttackTarget, Unit::_IsValidAssistTarget + UNIT_FLAG_IMMUNE_TO_NPC = 0x00000200, // disables combat/assistance with NonPlayerCharacters (NPC) - see Unit::_IsValidAttackTarget, Unit::_IsValidAssistTarget + UNIT_FLAG_LOOTING = 0x00000400, // loot animation + UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8 + UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3 + UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1 + UNIT_FLAG_CANNOT_SWIM = 0x00004000, // 2.0.8 + UNIT_FLAG_SWIMMING = 0x00008000, // shows swim animation in water + UNIT_FLAG_NON_ATTACKABLE_2 = 0x00010000, // removes attackable icon, if on yourself, cannot assist self but can cast TARGET_SELF spells - added by SPELL_AURA_MOD_UNATTACKABLE + UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok + UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok + UNIT_FLAG_IN_COMBAT = 0x00080000, + UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag + UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. + UNIT_FLAG_CONFUSED = 0x00400000, + UNIT_FLAG_FLEEING = 0x00800000, + UNIT_FLAG_POSSESSED = 0x01000000, // under direct client control by a player (possess or vehicle) + UNIT_FLAG_NOT_SELECTABLE = 0x02000000, + UNIT_FLAG_SKINNABLE = 0x04000000, + UNIT_FLAG_MOUNT = 0x08000000, + UNIT_FLAG_UNK_28 = 0x10000000, + UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT = 0x20000000, // Prevent automatically playing emotes from parsing chat text, for example "lol" in /say, ending message with ? or !, or using /yell + UNIT_FLAG_SHEATHE = 0x40000000, + UNIT_FLAG_IMMUNE = 0x80000000 // Immune to damage +}; +DEFINE_ENUM_FLAG(UnitFlags); + +// Value masks for UNIT_FIELD_FLAGS_2 +enum UnitFlags2 : uint32 +{ + UNIT_FLAG2_NONE = 0x00000000, + UNIT_FLAG2_FEIGN_DEATH = 0x00000001, + UNIT_FLAG2_HIDE_BODY = 0x00000002, // Hide unit model (show only player equip) + UNIT_FLAG2_IGNORE_REPUTATION = 0x00000004, + UNIT_FLAG2_COMPREHEND_LANG = 0x00000008, + UNIT_FLAG2_MIRROR_IMAGE = 0x00000010, + UNIT_FLAG2_DO_NOT_FADE_IN = 0x00000020, // Unit model instantly appears when summoned (does not fade in) + UNIT_FLAG2_FORCE_MOVEMENT = 0x00000040, + UNIT_FLAG2_DISARM_OFFHAND = 0x00000080, + UNIT_FLAG2_DISABLE_PRED_STATS = 0x00000100, // Player has disabled predicted stats (Used by raid frames) + UNIT_FLAG2_DISARM_RANGED = 0x00000400, // this does not disable ranged weapon display (maybe additional flag needed?) + UNIT_FLAG2_REGENERATE_POWER = 0x00000800, + UNIT_FLAG2_RESTRICT_PARTY_INTERACTION = 0x00001000, // Restrict interaction to party or raid + UNIT_FLAG2_PREVENT_SPELL_CLICK = 0x00002000, // Prevent spellclick + UNIT_FLAG2_ALLOW_ENEMY_INTERACT = 0x00004000, + UNIT_FLAG2_CANNOT_TURN = 0x00008000, + UNIT_FLAG2_UNK2 = 0x00010000, + UNIT_FLAG2_PLAY_DEATH_ANIM = 0x00020000, // Plays special death animation upon death + UNIT_FLAG2_ALLOW_CHEAT_SPELLS = 0x00040000, // Allows casting spells with AttributesEx7 & SPELL_ATTR7_DEBUG_SPELL + UNIT_FLAG2_UNUSED_6 = 0x01000000 +}; +DEFINE_ENUM_FLAG(UnitFlags2); + +/// Non Player Character flags +enum NPCFlags : uint32 +{ + UNIT_NPC_FLAG_NONE = 0x00000000, // SKIP + UNIT_NPC_FLAG_GOSSIP = 0x00000001, // TITLE has gossip menu DESCRIPTION 100% + UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // TITLE is quest giver DESCRIPTION guessed, probably ok + UNIT_NPC_FLAG_UNK1 = 0x00000004, + UNIT_NPC_FLAG_UNK2 = 0x00000008, + UNIT_NPC_FLAG_TRAINER = 0x00000010, // TITLE is trainer DESCRIPTION 100% + UNIT_NPC_FLAG_TRAINER_CLASS = 0x00000020, // TITLE is class trainer DESCRIPTION 100% + UNIT_NPC_FLAG_TRAINER_PROFESSION = 0x00000040, // TITLE is profession trainer DESCRIPTION 100% + UNIT_NPC_FLAG_VENDOR = 0x00000080, // TITLE is vendor (generic) DESCRIPTION 100% + UNIT_NPC_FLAG_VENDOR_AMMO = 0x00000100, // TITLE is vendor (ammo) DESCRIPTION 100%, general goods vendor + UNIT_NPC_FLAG_VENDOR_FOOD = 0x00000200, // TITLE is vendor (food) DESCRIPTION 100% + UNIT_NPC_FLAG_VENDOR_POISON = 0x00000400, // TITLE is vendor (poison) DESCRIPTION guessed + UNIT_NPC_FLAG_VENDOR_REAGENT = 0x00000800, // TITLE is vendor (reagents) DESCRIPTION 100% + UNIT_NPC_FLAG_REPAIR = 0x00001000, // TITLE can repair DESCRIPTION 100% + UNIT_NPC_FLAG_FLIGHTMASTER = 0x00002000, // TITLE is flight master DESCRIPTION 100% + UNIT_NPC_FLAG_SPIRITHEALER = 0x00004000, // TITLE is spirit healer DESCRIPTION guessed + UNIT_NPC_FLAG_SPIRITGUIDE = 0x00008000, // TITLE is spirit guide DESCRIPTION guessed + UNIT_NPC_FLAG_INNKEEPER = 0x00010000, // TITLE is innkeeper + UNIT_NPC_FLAG_BANKER = 0x00020000, // TITLE is banker DESCRIPTION 100% + UNIT_NPC_FLAG_PETITIONER = 0x00040000, // TITLE handles guild/arena petitions DESCRIPTION 100% 0xC0000 = guild petitions, 0x40000 = arena team petitions + UNIT_NPC_FLAG_TABARDDESIGNER = 0x00080000, // TITLE is guild tabard designer DESCRIPTION 100% + UNIT_NPC_FLAG_BATTLEMASTER = 0x00100000, // TITLE is battlemaster DESCRIPTION 100% + UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, // TITLE is auctioneer DESCRIPTION 100% + UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // TITLE is stable master DESCRIPTION 100% + UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // TITLE is guild banker DESCRIPTION cause client to send 997 opcode + UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // TITLE has spell click enabled DESCRIPTION cause client to send 1015 opcode (spell click) + UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // TITLE is player vehicle DESCRIPTION players with mounts that have vehicle data should have it set + UNIT_NPC_FLAG_MAILBOX = 0x04000000, // TITLE is mailbox + + UNIT_NPC_FLAG_VENDOR_MASK = UNIT_NPC_FLAG_VENDOR | UNIT_NPC_FLAG_VENDOR_AMMO | UNIT_NPC_FLAG_VENDOR_POISON | UNIT_NPC_FLAG_VENDOR_REAGENT +}; +DEFINE_ENUM_FLAG(NPCFlags); + +enum UnitMoveType +{ + MOVE_WALK = 0, + MOVE_RUN = 1, + MOVE_RUN_BACK = 2, + MOVE_SWIM = 3, + MOVE_SWIM_BACK = 4, + MOVE_TURN_RATE = 5, + MOVE_FLIGHT = 6, + MOVE_FLIGHT_BACK = 7, + MOVE_PITCH_RATE = 8 +}; + +#define MAX_MOVE_TYPE 9 + +enum MovementFlags +{ + MOVEMENTFLAG_NONE = 0x00000000, + MOVEMENTFLAG_FORWARD = 0x00000001, + MOVEMENTFLAG_BACKWARD = 0x00000002, + MOVEMENTFLAG_STRAFE_LEFT = 0x00000004, + MOVEMENTFLAG_STRAFE_RIGHT = 0x00000008, + MOVEMENTFLAG_LEFT = 0x00000010, + MOVEMENTFLAG_RIGHT = 0x00000020, + MOVEMENTFLAG_PITCH_UP = 0x00000040, + MOVEMENTFLAG_PITCH_DOWN = 0x00000080, + MOVEMENTFLAG_WALKING = 0x00000100, // Walking + MOVEMENTFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures + MOVEMENTFLAG_DISABLE_GRAVITY = 0x00000400, // Former MOVEMENTFLAG_LEVITATING. This is used when walking is not possible. + MOVEMENTFLAG_ROOT = 0x00000800, // Must not be set along with MOVEMENTFLAG_MASK_MOVING + MOVEMENTFLAG_FALLING = 0x00001000, // damage dealt on that type of falling + MOVEMENTFLAG_FALLING_FAR = 0x00002000, + MOVEMENTFLAG_PENDING_STOP = 0x00004000, + MOVEMENTFLAG_PENDING_STRAFE_STOP = 0x00008000, + MOVEMENTFLAG_PENDING_FORWARD = 0x00010000, + MOVEMENTFLAG_PENDING_BACKWARD = 0x00020000, + MOVEMENTFLAG_PENDING_STRAFE_LEFT = 0x00040000, + MOVEMENTFLAG_PENDING_STRAFE_RIGHT = 0x00080000, + MOVEMENTFLAG_PENDING_ROOT = 0x00100000, + MOVEMENTFLAG_SWIMMING = 0x00200000, // appears with fly flag also + MOVEMENTFLAG_ASCENDING = 0x00400000, // press "space" when flying + MOVEMENTFLAG_DESCENDING = 0x00800000, + MOVEMENTFLAG_CAN_FLY = 0x01000000, // Appears when unit can fly AND also walk + MOVEMENTFLAG_FLYING = 0x02000000, // unit is actually flying. pretty sure this is only used for players. creatures use disable_gravity + MOVEMENTFLAG_SPLINE_ELEVATION = 0x04000000, // used for flight paths + MOVEMENTFLAG_SPLINE_ENABLED = 0x08000000, // used for flight paths + MOVEMENTFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water + MOVEMENTFLAG_FALLING_SLOW = 0x20000000, // active rogue safe fall spell (passive) + MOVEMENTFLAG_HOVER = 0x40000000, // hover, cannot jump + + /// @todo: Check if PITCH_UP and PITCH_DOWN really belong here.. + MOVEMENTFLAG_MASK_MOVING = + MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD | MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT | + MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN | MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR | MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING | + MOVEMENTFLAG_SPLINE_ELEVATION, + + MOVEMENTFLAG_MASK_TURNING = + MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT, + + MOVEMENTFLAG_MASK_MOVING_FLY = + MOVEMENTFLAG_FLYING | MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING, + + /// @todo if needed: add more flags to this masks that are exclusive to players + MOVEMENTFLAG_MASK_PLAYER_ONLY = + MOVEMENTFLAG_FLYING, + + /// Movement flags that have change status opcodes associated for players + MOVEMENTFLAG_MASK_HAS_PLAYER_STATUS_OPCODE = MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_ROOT | + MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_WATERWALKING | MOVEMENTFLAG_FALLING_SLOW | MOVEMENTFLAG_HOVER +}; + +enum MovementFlags2 +{ + MOVEMENTFLAG2_NONE = 0x00000000, + MOVEMENTFLAG2_NO_STRAFE = 0x00000001, + MOVEMENTFLAG2_NO_JUMPING = 0x00000002, + MOVEMENTFLAG2_UNK3 = 0x00000004, // Overrides various clientside checks + MOVEMENTFLAG2_FULL_SPEED_TURNING = 0x00000008, + MOVEMENTFLAG2_FULL_SPEED_PITCHING = 0x00000010, + MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING = 0x00000020, + MOVEMENTFLAG2_UNK7 = 0x00000040, + MOVEMENTFLAG2_UNK8 = 0x00000080, + MOVEMENTFLAG2_UNK9 = 0x00000100, + MOVEMENTFLAG2_UNK10 = 0x00000200, + MOVEMENTFLAG2_INTERPOLATED_MOVEMENT = 0x00000400, + MOVEMENTFLAG2_INTERPOLATED_TURNING = 0x00000800, + MOVEMENTFLAG2_INTERPOLATED_PITCHING = 0x00001000, + MOVEMENTFLAG2_UNK14 = 0x00002000, + MOVEMENTFLAG2_UNK15 = 0x00004000, + MOVEMENTFLAG2_UNK16 = 0x00008000 +}; + +enum SplineFlags +{ + SPLINEFLAG_NONE = 0x00000000, + SPLINEFLAG_FORWARD = 0x00000001, + SPLINEFLAG_BACKWARD = 0x00000002, + SPLINEFLAG_STRAFE_LEFT = 0x00000004, + SPLINEFLAG_STRAFE_RIGHT = 0x00000008, + SPLINEFLAG_TURN_LEFT = 0x00000010, + SPLINEFLAG_TURN_RIGHT = 0x00000020, + SPLINEFLAG_PITCH_UP = 0x00000040, + SPLINEFLAG_PITCH_DOWN = 0x00000080, + SPLINEFLAG_DONE = 0x00000100, + SPLINEFLAG_FALLING = 0x00000200, + SPLINEFLAG_NO_SPLINE = 0x00000400, + SPLINEFLAG_TRAJECTORY = 0x00000800, + SPLINEFLAG_WALK_MODE = 0x00001000, + SPLINEFLAG_FLYING = 0x00002000, + SPLINEFLAG_KNOCKBACK = 0x00004000, + SPLINEFLAG_FINAL_POINT = 0x00008000, + SPLINEFLAG_FINAL_TARGET = 0x00010000, + SPLINEFLAG_FINAL_FACING = 0x00020000, + SPLINEFLAG_CATMULL_ROM = 0x00040000, + SPLINEFLAG_CYCLIC = 0x00080000, + SPLINEFLAG_ENTER_CYCLE = 0x00100000, + SPLINEFLAG_ANIMATION_TIER = 0x00200000, + SPLINEFLAG_FROZEN = 0x00400000, + SPLINEFLAG_TRANSPORT = 0x00800000, + SPLINEFLAG_TRANSPORT_EXIT = 0x01000000, + SPLINEFLAG_UNKNOWN7 = 0x02000000, + SPLINEFLAG_UNKNOWN8 = 0x04000000, + SPLINEFLAG_ORIENTATION_INVERTED = 0x08000000, + SPLINEFLAG_USE_PATH_SMOOTHING = 0x10000000, + SPLINEFLAG_ANIMATION = 0x20000000, + SPLINEFLAG_UNCOMPRESSED_PATH = 0x40000000, + SPLINEFLAG_UNKNOWN10 = 0x80000000 +}; + +enum SplineType +{ + SPLINETYPE_NORMAL = 0, + SPLINETYPE_STOP = 1, + SPLINETYPE_FACING_SPOT = 2, + SPLINETYPE_FACING_TARGET = 3, + SPLINETYPE_FACING_ANGLE = 4 +}; diff --git a/src/server/game/Entities/Unit/UnitUtils.h b/src/server/game/Entities/Unit/UnitUtils.h new file mode 100644 index 000000000..42f0ba1a0 --- /dev/null +++ b/src/server/game/Entities/Unit/UnitUtils.h @@ -0,0 +1,117 @@ +/* + * 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 . + */ + +class MMapTargetData +{ +public: + MMapTargetData() = default; + MMapTargetData(uint32 endTime, const Position* o, const Position* t) + { + _endTime = endTime; + _posOwner.Relocate(o); + _posTarget.Relocate(t); + } + MMapTargetData(const MMapTargetData& c) + { + _endTime = c._endTime; + _posOwner.Relocate(c._posOwner); + _posTarget.Relocate(c._posTarget); + } + MMapTargetData(MMapTargetData&&) = default; + MMapTargetData& operator=(const MMapTargetData&) = default; + MMapTargetData& operator=(MMapTargetData&&) = default; + [[nodiscard]] bool PosChanged(const Position& o, const Position& t) const + { + return _posOwner.GetExactDistSq(&o) > 0.5f * 0.5f || _posTarget.GetExactDistSq(&t) > 0.5f * 0.5f; + } + uint32 _endTime; + Position _posOwner; + Position _posTarget; +}; + +class SafeUnitPointer +{ +public: + explicit SafeUnitPointer(Unit* defVal) : ptr(defVal), defaultValue(defVal) {} + SafeUnitPointer(const SafeUnitPointer& /*p*/) { ABORT(); } + void Initialize(Unit* defVal) { defaultValue = defVal; ptr = defVal; } + ~SafeUnitPointer(); + void SetPointedTo(Unit* u); + void UnitDeleted(); + Unit* operator->() const { return ptr; } + void operator=(Unit* u) { SetPointedTo(u); } + operator Unit* () const { return ptr; } +private: + Unit* ptr; + Unit* defaultValue; +}; + +// BuildValuesCachePosPointers is marks of the position of some data inside of BuildValue cache. +struct BuildValuesCachePosPointers +{ + BuildValuesCachePosPointers() : + UnitNPCFlagsPos(-1), UnitFieldAuraStatePos(-1), UnitFieldFlagsPos(-1), UnitFieldDisplayPos(-1), + UnitDynamicFlagsPos(-1), UnitFieldBytes2Pos(-1), UnitFieldFactionTemplatePos(-1) {} + + void ApplyOffset(uint32 offset) + { + if (UnitNPCFlagsPos >= 0) + UnitNPCFlagsPos += offset; + + if (UnitFieldAuraStatePos >= 0) + UnitFieldAuraStatePos += offset; + + if (UnitFieldFlagsPos >= 0) + UnitFieldFlagsPos += offset; + + if (UnitFieldDisplayPos >= 0) + UnitFieldDisplayPos += offset; + + if (UnitDynamicFlagsPos >= 0) + UnitDynamicFlagsPos += offset; + + if (UnitFieldBytes2Pos >= 0) + UnitFieldBytes2Pos += offset; + + if (UnitFieldFactionTemplatePos >= 0) + UnitFieldFactionTemplatePos += offset; + + for (auto it = other.begin(); it != other.end(); ++it) + it->second += offset; + } + + int32 UnitNPCFlagsPos; + int32 UnitFieldAuraStatePos; + int32 UnitFieldFlagsPos; + int32 UnitFieldDisplayPos; + int32 UnitDynamicFlagsPos; + int32 UnitFieldBytes2Pos; + int32 UnitFieldFactionTemplatePos; + + std::unordered_map other; +}; + +// BuildValuesCachedBuffer cache for calculated BuildValue. +struct BuildValuesCachedBuffer +{ + BuildValuesCachedBuffer(uint32 bufferSize) : + buffer(bufferSize), posPointers() {} + + ByteBuffer buffer; + + BuildValuesCachePosPointers posPointers; +}; diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index 694efb9fd..b7bb2bf1d 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -96,4 +96,15 @@ private: Status _status; }; +class VehicleDespawnEvent : public BasicEvent +{ +public: + VehicleDespawnEvent(Unit& self, uint32 duration) : _self(self), _duration(duration) { } + bool Execute(uint64 e_time, uint32 p_time) override; + +protected: + Unit& _self; + uint32 _duration; +}; + #endif diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 9c0b4d4a6..2f313c701 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -16,6 +16,7 @@ */ #include "Common.h" +#include "CharmInfo.h" #include "CreatureAI.h" #include "DisableMgr.h" #include "GameTime.h" diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 2bc4495ba..ac239941e 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -19,6 +19,7 @@ #include "BattlefieldMgr.h" #include "Battleground.h" #include "CellImpl.h" +#include "CharmInfo.h" #include "Common.h" #include "GameTime.h" #include "GridNotifiers.h"