aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOvahlord <dreadkiller@gmx.de>2024-01-16 18:43:32 +0100
committerfunjoker <funjoker109@gmail.com>2024-01-29 21:44:59 +0100
commit3e39828f0a43e3bc7c402a9f2f66ed1f6b915e4d (patch)
tree7d5550face369fc6ae975c8e9899947e4ed7e1ff /src
parentdbd2350686656011b4505121ba8240937140fae7 (diff)
Core/Units: moved CharmInfo class and its definitions into a own file (#29583)
(cherry picked from commit ea093fef2787121549f864b8b177d88ad8b54464)
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp1
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp6
-rw-r--r--src/server/game/Entities/Creature/Creature.h2
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.cpp1
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp1
-rw-r--r--src/server/game/Entities/Player/Player.cpp1
-rw-r--r--src/server/game/Entities/Unit/CharmInfo.cpp283
-rw-r--r--src/server/game/Entities/Unit/CharmInfo.h157
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp260
-rw-r--r--src/server/game/Entities/Unit/Unit.h130
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.cpp1
-rw-r--r--src/server/game/Handlers/PetHandler.cpp1
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp1
-rw-r--r--src/server/game/Spells/Spell.cpp1
-rw-r--r--src/server/game/Spells/SpellEffects.cpp1
-rw-r--r--src/server/game/Spells/SpellHistory.cpp1
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp1
-rw-r--r--src/server/scripts/World/npcs_special.cpp1
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 3f287ea5d51..f82d87dbe11 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"
@@ -3107,6 +3108,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 84865873963..ff513e0dae0 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -312,7 +312,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 fe40abcf830..9c00423f941 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 29afb42274b..5c36b15a7ea 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -36,6 +36,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 db256630584..a4be7be9173 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"
@@ -9621,265 +9622,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 d440615ba87..847e594b99c 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -39,11 +39,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
@@ -68,6 +63,7 @@ enum InventorySlot
};
struct AbstractFollower;
+struct CharmInfo;
struct FactionTemplateEntry;
struct LiquidData;
struct LiquidTypeEntry;
@@ -98,6 +94,7 @@ class UnitAura;
class Vehicle;
class VehicleJoinEvent;
+enum CharmType : uint8;
enum class EncounterType : uint8;
enum class PetActionFeedback : uint8;
enum MovementGeneratorType : uint8;
@@ -585,131 +582,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 339de289d64..cef5073b2ba 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 ed187e2c597..0817ecfd383 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -21,6 +21,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 450bcfd7757..d056efd70c6 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -22,6 +22,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"