diff options
author | Ovahlord <dreadkiller@gmx.de> | 2024-01-16 18:43:32 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-16 18:43:32 +0100 |
commit | ea093fef2787121549f864b8b177d88ad8b54464 (patch) | |
tree | 60b96d06175e35df753f03d0df0e0f6c716b0dea | |
parent | 25dc8de3eb3e35271d820a50ae926bdf0c182a3c (diff) |
Core/Units: moved CharmInfo class and its definitions into a own file (#29583)
-rw-r--r-- | src/server/game/AI/CoreAI/PetAI.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 6 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/TemporarySummon.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Pet/Pet.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/CharmInfo.cpp | 283 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/CharmInfo.h | 157 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 260 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 130 | ||||
-rw-r--r-- | src/server/game/Entities/Vehicle/Vehicle.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Handlers/PetHandler.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Spells/SpellHistory.cpp | 1 | ||||
-rw-r--r-- | src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp | 1 | ||||
-rw-r--r-- | src/server/scripts/World/npcs_special.cpp | 1 |
18 files changed, 462 insertions, 388 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 16e9356f646..fb2d3848946 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -17,6 +17,7 @@ #include "PetAI.h" #include "AIException.h" +#include "CharmInfo.h" #include "Creature.h" #include "Errors.h" #include "Group.h" diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 86a31159b61..d83653c9bcf 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -18,6 +18,7 @@ #include "Creature.h" #include "BattlegroundMgr.h" #include "CellImpl.h" +#include "CharmInfo.h" #include "CombatPackets.h" #include "Containers.h" #include "CreatureAI.h" @@ -3220,6 +3221,11 @@ std::string Creature::GetNameForLocaleIdx(LocaleConstant locale) const return GetName(); } +uint8 Creature::GetPetAutoSpellSize() const +{ + return MAX_SPELL_CHARM; +} + uint32 Creature::GetPetAutoSpellOnPos(uint8 pos) const { if (pos >= MAX_SPELL_CHARM || !m_charmInfo || m_charmInfo->GetCharmSpell(pos)->GetType() != ACT_ENABLED) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index dc96e8becca..7e9764b1331 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -323,7 +323,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma bool CanRegenerateHealth() const { return !_staticFlags.HasFlag(CREATURE_STATIC_FLAG_5_NO_HEALTH_REGEN) && _regenerateHealth; } void SetRegenerateHealth(bool value) { _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_5_NO_HEALTH_REGEN, !value); } - virtual uint8 GetPetAutoSpellSize() const { return MAX_SPELL_CHARM; } + virtual uint8 GetPetAutoSpellSize() const; virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const; float GetPetChaseDistance() const; diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp index 919f62262a8..f3a6f35770d 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.cpp +++ b/src/server/game/Entities/Creature/TemporarySummon.cpp @@ -17,6 +17,7 @@ #include "TemporarySummon.h" #include "CellImpl.h" +#include "CharmInfo.h" #include "CreatureAI.h" #include "DB2Stores.h" #include "GameObject.h" diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 35da121270d..a71c3e7e4d5 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -16,6 +16,7 @@ */ #include "Pet.h" +#include "CharmInfo.h" #include "Common.h" #include "DatabaseEnv.h" #include "DB2Stores.h" diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 63c6172a3db..360e1c52cef 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -38,6 +38,7 @@ #include "CharacterDatabaseCleaner.h" #include "CharacterTemplateDataStore.h" #include "CharacterPackets.h" +#include "CharmInfo.h" #include "Chat.h" #include "ChatPackets.h" #include "ChatTextBuilder.h" diff --git a/src/server/game/Entities/Unit/CharmInfo.cpp b/src/server/game/Entities/Unit/CharmInfo.cpp new file mode 100644 index 00000000000..ed440785cc1 --- /dev/null +++ b/src/server/game/Entities/Unit/CharmInfo.cpp @@ -0,0 +1,283 @@ +/* + * This file is part of the TrinityCore 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 General Public License as published by the + * Free Software Foundation; either version 2 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "CharmInfo.h" +#include "Creature.h" +#include "Map.h" +#include "SpellInfo.h" +#include "SpellMgr.h" +#include "StringConvert.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), + _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 (Creature* creature = _unit->ToCreature()) + { + _oldReactState = creature->GetReactState(); + creature->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 28511: // Eye of Acherus + break; + default: + InitEmptyActionBar(); + break; + } + + for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i) + { + uint32 spellId = _unit->ToCreature()->m_spells[i]; + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, _unit->GetMap()->GetDifficultyID()); + if (spellInfo) + { + if (spellInfo->HasAttribute(SPELL_ATTR5_NOT_AVAILABLE_WHILE_CHARMED)) + continue; + + if (spellInfo->IsPassive()) + _unit->CastSpell(_unit, spellInfo->Id, true); + else + AddSpellToActionBar(spellInfo, ACT_PASSIVE, i % MAX_UNIT_ACTION_BAR_INDEX); + } + } + } + else + InitEmptyActionBar(); +} + +void CharmInfo::InitCharmCreateSpells() +{ + 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, _unit->GetMap()->GetDifficultyID()); + + if (!spellInfo) + { + _charmspells[x].SetActionAndType(spellId, ACT_DISABLED); + continue; + } + + if (spellInfo->HasAttribute(SPELL_ATTR5_NOT_AVAILABLE_WHILE_CHARMED)) + continue; + + if (spellInfo->IsPassive()) + { + _unit->CastSpell(_unit, spellInfo->Id, 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, uint8 preferredSlot) +{ + uint32 spell_id = spellInfo->Id; + uint32 first_id = spellInfo->GetFirstRankSpell()->Id; + + ASSERT(preferredSlot < MAX_UNIT_ACTION_BAR_INDEX); + // 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) + { + uint8 j = (preferredSlot + i) % MAX_UNIT_ACTION_BAR_INDEX; + if (!PetActionBar[j].GetAction() && PetActionBar[j].IsActionBarForSpell()) + { + SetActionBar(j, spell_id, newstate == ACT_DECIDE ? spellInfo->IsAutocastable() ? ACT_DISABLED : ACT_PASSIVE : newstate); + 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->SetPetNumberForClient(_petnumber); + else + _unit->SetPetNumberForClient(0); +} + +void CharmInfo::LoadPetActionBar(const std::string& data) +{ + InitPetActionBar(); + + std::vector<std::string_view> tokens = Trinity::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<uint8> type = Trinity::StringTo<uint8>(*(iter++)); + Optional<uint32> action = Trinity::StringTo<uint32>(*(iter++)); + + if (!type || !action) + continue; + + PetActionBar[index].SetActionAndType(*action, static_cast<ActiveStates>(*type)); + + // check correctness + if (PetActionBar[index].IsActionBarForSpell()) + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(PetActionBar[index].GetAction(), _unit->GetMap()->GetDifficultyID()); + 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; + } + } +} diff --git a/src/server/game/Entities/Unit/CharmInfo.h b/src/server/game/Entities/Unit/CharmInfo.h new file mode 100644 index 00000000000..e21cf4f0f7d --- /dev/null +++ b/src/server/game/Entities/Unit/CharmInfo.h @@ -0,0 +1,157 @@ +/* + * This file is part of the TrinityCore 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 General Public License as published by the + * Free Software Foundation; either version 2 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _CharmInfo_h__ +#define _CharmInfo_h__ + +#include "Define.h" +#include "UnitDefines.h" + +class SpellInfo; +class Unit; +class WorldPacket; + +constexpr uint8 MAX_SPELL_CHARM = 4; +constexpr uint8 MAX_SPELL_VEHICLE = 6; +constexpr uint8 MAX_SPELL_POSSESS = 8; +constexpr uint8 MAX_SPELL_CONTROL_BAR = 10; + +#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 + ActiveStates GetType() const { return ActiveStates(UNIT_ACTION_BUTTON_TYPE(packedData)); } + uint32 GetAction() const { return UNIT_ACTION_BUTTON_ACTION(packedData); } + 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); + } +}; + +enum CharmType : uint8 +{ + CHARM_TYPE_CHARM = 0, + 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 TC_GAME_API CharmInfo +{ + public: + explicit CharmInfo(Unit* unit); + ~CharmInfo(); + void RestoreState(); + uint32 GetPetNumber() const { return _petnumber; } + void SetPetNumber(uint32 petnumber, bool statwindow); + + void SetCommandState(CommandStates st) { _CommandState = st; } + CommandStates GetCommandState() const { return _CommandState; } + 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, uint8 preferredSlot = 0); + 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); + } + + UnitActionBarEntry const* GetActionBarEntry(uint8 index) const { return &(PetActionBar[index]); } + + void ToggleCreatureAutocast(SpellInfo const* spellInfo, bool apply); + + CharmSpellInfo* GetCharmSpell(uint8 index) { return &(_charmspells[index]); } + + 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(); + void GetStayPosition(float &x, float &y, float &z); + + 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; + float _stayX; + float _stayY; + float _stayZ; +}; + +#endif // _CharmInfo_h__ diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 84273e7b8c2..8189d5c8bec 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -25,6 +25,7 @@ #include "BattlePetMgr.h" #include "CellImpl.h" #include "CharacterCache.h" +#include "CharmInfo.h" #include "ChatPackets.h" #include "ChatTextBuilder.h" #include "CombatLogPackets.h" @@ -9664,265 +9665,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), - _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 (Creature* creature = _unit->ToCreature()) - { - _oldReactState = creature->GetReactState(); - creature->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 28511: // Eye of Acherus - break; - default: - InitEmptyActionBar(); - break; - } - - for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i) - { - uint32 spellId = _unit->ToCreature()->m_spells[i]; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, _unit->GetMap()->GetDifficultyID()); - if (spellInfo) - { - if (spellInfo->HasAttribute(SPELL_ATTR5_NOT_AVAILABLE_WHILE_CHARMED)) - continue; - - if (spellInfo->IsPassive()) - _unit->CastSpell(_unit, spellInfo->Id, true); - else - AddSpellToActionBar(spellInfo, ACT_PASSIVE, i % MAX_UNIT_ACTION_BAR_INDEX); - } - } - } - else - InitEmptyActionBar(); -} - -void CharmInfo::InitCharmCreateSpells() -{ - 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, _unit->GetMap()->GetDifficultyID()); - - if (!spellInfo) - { - _charmspells[x].SetActionAndType(spellId, ACT_DISABLED); - continue; - } - - if (spellInfo->HasAttribute(SPELL_ATTR5_NOT_AVAILABLE_WHILE_CHARMED)) - continue; - - if (spellInfo->IsPassive()) - { - _unit->CastSpell(_unit, spellInfo->Id, 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, uint8 preferredSlot) -{ - uint32 spell_id = spellInfo->Id; - uint32 first_id = spellInfo->GetFirstRankSpell()->Id; - - ASSERT(preferredSlot < MAX_UNIT_ACTION_BAR_INDEX); - // 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) - { - uint8 j = (preferredSlot + i) % MAX_UNIT_ACTION_BAR_INDEX; - if (!PetActionBar[j].GetAction() && PetActionBar[j].IsActionBarForSpell()) - { - SetActionBar(j, spell_id, newstate == ACT_DECIDE ? spellInfo->IsAutocastable() ? ACT_DISABLED : ACT_PASSIVE : newstate); - 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->SetPetNumberForClient(_petnumber); - else - _unit->SetPetNumberForClient(0); -} - -void CharmInfo::LoadPetActionBar(const std::string& data) -{ - InitPetActionBar(); - - std::vector<std::string_view> tokens = Trinity::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<uint8> type = Trinity::StringTo<uint8>(*(iter++)); - Optional<uint32> action = Trinity::StringTo<uint32>(*(iter++)); - - if (!type || !action) - continue; - - PetActionBar[index].SetActionAndType(*action, static_cast<ActiveStates>(*type)); - - // check correctness - if (PetActionBar[index].IsActionBarForSpell()) - { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(PetActionBar[index].GetAction(), _unit->GetMap()->GetDifficultyID()); - 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 Unit::SetMovedUnit(Unit* target) { m_unitMovedByMe->m_playerMovingMe = nullptr; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 70124a92542..f49fc6f4511 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -40,11 +40,6 @@ #define WARMODE_ENLISTED_SPELL_OUTSIDE 269083 -#define MAX_SPELL_CHARM 4 -#define MAX_SPELL_VEHICLE 6 -#define MAX_SPELL_POSSESS 8 -#define MAX_SPELL_CONTROL_BAR 10 - #define MAX_AGGRO_RESET_TIME 10 // in seconds #define MAX_AGGRO_RADIUS 45.0f // yards @@ -69,6 +64,7 @@ enum InventorySlot }; struct AbstractFollower; +struct CharmInfo; struct FactionTemplateEntry; struct LiquidData; struct LiquidTypeEntry; @@ -99,6 +95,7 @@ class UnitAura; class Vehicle; class VehicleJoinEvent; +enum CharmType : uint8; enum class EncounterType : uint8; enum class PetActionFeedback : uint8; enum MovementGeneratorType : uint8; @@ -592,131 +589,8 @@ enum CurrentSpellTypes : uint8 #define CURRENT_FIRST_NON_MELEE_SPELL 1 #define CURRENT_MAX_SPELL 4 -#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 - ActiveStates GetType() const { return ActiveStates(UNIT_ACTION_BUTTON_TYPE(packedData)); } - uint32 GetAction() const { return UNIT_ACTION_BUTTON_ACTION(packedData); } - 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<Player*> 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 TC_GAME_API CharmInfo -{ - public: - explicit CharmInfo(Unit* unit); - ~CharmInfo(); - void RestoreState(); - uint32 GetPetNumber() const { return _petnumber; } - void SetPetNumber(uint32 petnumber, bool statwindow); - - void SetCommandState(CommandStates st) { _CommandState = st; } - CommandStates GetCommandState() const { return _CommandState; } - 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, uint8 preferredSlot = 0); - 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); - } - UnitActionBarEntry const* GetActionBarEntry(uint8 index) const { return &(PetActionBar[index]); } - - void ToggleCreatureAutocast(SpellInfo const* spellInfo, bool apply); - - CharmSpellInfo* GetCharmSpell(uint8 index) { return &(_charmspells[index]); } - - 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(); - void GetStayPosition(float &x, float &y, float &z); - - 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; - float _stayX; - float _stayY; - float _stayZ; -}; - // for clearing special attacks #define REACTIVE_TIMER_START 4000 diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 24f7dfcbf95..d00f313e56d 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -17,6 +17,7 @@ #include "Vehicle.h" #include "Battleground.h" +#include "CharmInfo.h" #include "Common.h" #include "CreatureAI.h" #include "DB2Stores.h" diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 268c839f237..cd680f4a973 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -16,6 +16,7 @@ */ #include "WorldSession.h" +#include "CharmInfo.h" #include "Common.h" #include "CreatureAI.h" #include "DatabaseEnv.h" diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 2d973be8d99..fad5900f433 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -21,6 +21,7 @@ #include "Battleground.h" #include "BattlegroundPackets.h" #include "CellImpl.h" +#include "CharmInfo.h" #include "Common.h" #include "Containers.h" #include "DB2Stores.h" diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 3d95e2890d1..6f3e829f799 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -22,6 +22,7 @@ #include "Battleground.h" #include "BattlePetMgr.h" #include "CellImpl.h" +#include "CharmInfo.h" #include "CollectionMgr.h" #include "CombatLogPackets.h" #include "Common.h" diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 1d14560266b..93a6b015504 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -24,6 +24,7 @@ #include "BattlegroundMgr.h" #include "BattlePetMgr.h" #include "CellImpl.h" +#include "CharmInfo.h" #include "CombatLogPackets.h" #include "CombatPackets.h" #include "Common.h" diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp index 7e090101530..4f8fc96e378 100644 --- a/src/server/game/Spells/SpellHistory.cpp +++ b/src/server/game/Spells/SpellHistory.cpp @@ -16,6 +16,7 @@ */ #include "SpellHistory.h" +#include "CharmInfo.h" #include "DatabaseEnv.h" #include "DB2Stores.h" #include "Duration.h" diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index fe9054503a9..9c2969e0704 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -17,6 +17,7 @@ #include "CreatureAIImpl.h" #include "ScriptMgr.h" +#include "CharmInfo.h" #include "CombatAI.h" #include "CreatureTextMgr.h" #include "G3DPosition.hpp" diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index afefcc42ba9..a3db8c19c6b 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -17,6 +17,7 @@ #include "ScriptMgr.h" #include "CellImpl.h" +#include "CharmInfo.h" #include "CombatAI.h" #include "Containers.h" #include "CreatureTextMgr.h" |