Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2024-08-18 23:02:22 +08:00
50 changed files with 2365 additions and 1344 deletions
+1
View File
@@ -16,6 +16,7 @@
*/
#include "PetAI.h"
#include "CharmInfo.h"
#include "Creature.h"
#include "Errors.h"
#include "Group.h"
+5
View File
@@ -45,6 +45,11 @@ char const* ChatHandler::GetAcoreString(uint32 entry) const
return m_session->GetAcoreString(entry);
}
std::string const* ChatHandler::GetModuleString(std::string module, uint32 id) const
{
return m_session->GetModuleString(module, id);
}
bool ChatHandler::IsAvailable(uint32 securityLevel) const
{
// check security level only for simple command (without child commands)
+15
View File
@@ -176,6 +176,21 @@ public:
return Acore::StringFormatFmt(GetAcoreString(entry), std::forward<Args>(args)...);
}
std::string const* GetModuleString(std::string module, uint32 id) const;
template<typename... Args>
void PSendModuleSysMessage(std::string module, uint32 id, Args&&... args)
{
if (HasSession())
SendSysMessage(PGetParseModuleString(module, id, std::forward<Args>(args)...));
}
template<typename... Args>
std::string PGetParseModuleString(std::string module, uint32 id, Args&&... args) const
{
return Acore::StringFormatFmt(GetModuleString(module, id)->c_str(), std::forward<Args>(args)...);
}
void SendErrorMessage(uint32 entry);
void SendErrorMessage(std::string_view str, bool escapeCharacters);
+24
View File
@@ -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
@@ -246,7 +246,8 @@ namespace lfg
{
// xinef: fixed dungeon deserter
if (method != GROUP_REMOVEMETHOD_KICK_LFG && state != LFG_STATE_FINISHED_DUNGEON &&
player->HasAura(LFG_SPELL_DUNGEON_COOLDOWN) && players >= LFG_GROUP_KICK_VOTES_NEEDED)
player->HasAura(LFG_SPELL_DUNGEON_COOLDOWN) && players >= LFG_GROUP_KICK_VOTES_NEEDED &&
sWorld->getBoolConfig(CONFIG_LFG_CAST_DESERTER))
{
player->AddAura(LFG_SPELL_DUNGEON_DESERTER, player);
}
@@ -19,6 +19,7 @@
#define AZEROTHCORE_CREATURE_H
#include "Cell.h"
#include "CharmInfo.h"
#include "Common.h"
#include "CreatureData.h"
#include "DatabaseEnv.h"
@@ -319,12 +319,16 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, std::string const
if (QuestGreeting const* questGreeting = sObjectMgr->GetQuestGreeting(guid.GetTypeId(), guid.GetEntry()))
{
std::string strGreeting = questGreeting->Text;
LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex();
if (localeConstant != LOCALE_enUS)
if (QuestGreetingLocale const* questGreetingLocale = sObjectMgr->GetQuestGreetingLocale(guid.GetTypeId(), guid.GetEntry()))
ObjectMgr::GetLocaleString(questGreetingLocale->Greeting, localeConstant, strGreeting);
std::string strGreeting;
// Check if greeting exists. Blizzlike that some creatures have empty greeting
if (!questGreeting->Greeting.empty())
{
LocaleConstant locale = _session->GetSessionDbLocaleIndex();
if (questGreeting->Greeting.size() > size_t(locale))
strGreeting = questGreeting->Greeting[locale];
else
strGreeting = questGreeting->Greeting[DEFAULT_LOCALE];
}
data << strGreeting;
data << uint32(questGreeting->EmoteDelay);
@@ -203,6 +203,10 @@ void GameObject::CheckRitualList()
if (m_unique_users.empty())
return;
uint32 animSpell = GetGOInfo()->summoningRitual.animSpell;
if (!animSpell)
animSpell = GetSpellId();
for (GuidSet::iterator itr = m_unique_users.begin(); itr != m_unique_users.end();)
{
if (*itr == GetOwnerGUID())
@@ -214,7 +218,7 @@ void GameObject::CheckRitualList()
bool erase = true;
if (Player* channeler = ObjectAccessor::GetPlayer(*this, *itr))
if (Spell* spell = channeler->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
if (spell->m_spellInfo->Id == GetGOInfo()->summoningRitual.animSpell)
if (spell->m_spellInfo->Id == animSpell)
erase = false;
if (erase)
@@ -226,10 +230,13 @@ void GameObject::CheckRitualList()
void GameObject::ClearRitualList()
{
uint32 animSpell = GetGOInfo()->summoningRitual.animSpell;
if (!animSpell || m_unique_users.empty())
if (m_unique_users.empty())
return;
uint32 animSpell = GetGOInfo()->summoningRitual.animSpell;
if (!animSpell)
animSpell = GetSpellId();
for (ObjectGuid const& guid : m_unique_users)
{
if (Player* channeler = ObjectAccessor::GetPlayer(*this, guid))
@@ -526,18 +533,15 @@ void GameObject::Update(uint32 diff)
if (GameTime::GetGameTimeMS().count() < m_cooldownTime)
return;
GameObjectTemplate const* info = GetGOInfo();
if (info->summoningRitual.animSpell)
{
// xinef: if ritual requires animation, ensure that all users performs channel
CheckRitualList();
}
CheckRitualList();
if (GetUniqueUseCount() < info->summoningRitual.reqParticipants)
{
SetLootState(GO_READY);
return;
}
bool triggered = info->summoningRitual.animSpell;
Unit* owner = GetOwner();
Unit* spellCaster = owner ? owner : ObjectAccessor::GetPlayer(*this, m_ritualOwnerGUID);
if (!spellCaster)
@@ -553,7 +557,6 @@ void GameObject::Update(uint32 diff)
// spell have reagent and mana cost but it not expected use its
// it triggered spell in fact casted at currently channeled GO
spellId = 61993;
triggered = true;
}
// Cast casterTargetSpell at a random GO user
@@ -583,7 +586,7 @@ void GameObject::Update(uint32 diff)
SetLootState(GO_READY);
ClearRitualList();
spellCaster->CastSpell(spellCaster, spellId, triggered);
spellCaster->CastSpell(spellCaster, spellId, true);
return;
}
case GAMEOBJECT_TYPE_CHEST:
@@ -1848,17 +1851,18 @@ void GameObject::Use(Unit* user)
return;
}
CheckRitualList();
if (GetUniqueUseCount() == info->summoningRitual.reqParticipants)
return;
if (info->summoningRitual.animSpell)
{
// xinef: if ritual requires animation, ensure that all users performs channel
CheckRitualList();
// xinef: all participants found
if (GetUniqueUseCount() == info->summoningRitual.reqParticipants)
return;
player->CastSpell(player, info->summoningRitual.animSpell, true);
}
else
player->CastSpell(player, GetSpellId(),
TriggerCastFlags(TRIGGERED_IGNORE_EFFECTS
| TRIGGERED_IGNORE_POWER_AND_REAGENT_COST
| TRIGGERED_CAST_DIRECTLY));
AddUniqueUse(player);
@@ -1866,11 +1870,9 @@ void GameObject::Use(Unit* user)
if (GetUniqueUseCount() == info->summoningRitual.reqParticipants)
{
SetLootState(GO_NOT_READY);
// can be deleted now, if
if (!info->summoningRitual.animSpell)
m_cooldownTime = 0;
else // channel ready, maintain this
m_cooldownTime = GameTime::GetGameTimeMS().count() + 5 * IN_MILLISECONDS;
// channel ready, maintain this
m_cooldownTime = GameTime::GetGameTimeMS().count() + 5 * IN_MILLISECONDS;
}
return;
@@ -1891,7 +1893,6 @@ void GameObject::Use(Unit* user)
user->RemoveAurasByType(SPELL_AURA_MOUNTED);
spellId = info->spellcaster.spellId;
AddUse();
break;
}
case GAMEOBJECT_TYPE_MEETINGSTONE: //23
@@ -1905,8 +1906,8 @@ void GameObject::Use(Unit* user)
Player* targetPlayer = ObjectAccessor::FindPlayer(player->GetTarget());
// accept only use by player from same raid as caster, except caster itself
if (!targetPlayer || targetPlayer == player || !targetPlayer->IsInSameRaidWith(player))
// accept only use by player from same raid as caster
if (!targetPlayer || !targetPlayer->IsInSameRaidWith(player))
return;
//required lvl checks!
@@ -1917,10 +1918,7 @@ void GameObject::Use(Unit* user)
if (level < info->meetingstone.minLevel)
return;
if (info->entry == 194097)
spellId = 61994; // Ritual of Summoning
else
spellId = 23598; // Meeting Stone Summon
spellId = 23598; // Meeting Stone Summon
break;
}
@@ -2067,7 +2065,10 @@ void GameObject::Use(Unit* user)
sOutdoorPvPMgr->HandleCustomSpell(player, spellId, this);
if (spellCaster)
spellCaster->CastSpell(user, spellInfo, triggered);
{
if ((spellCaster->CastSpell(user, spellInfo, triggered) == SPELL_CAST_OK) && GetGoType() == GAMEOBJECT_TYPE_SPELLCASTER)
AddUse();
}
else
CastSpell(user, spellId);
}
+6
View File
@@ -35,6 +35,12 @@ struct ItemSetEffect
SpellInfo const* spells[8];
};
enum InventorySlot
{
NULL_BAG = 0,
NULL_SLOT = 255
};
// EnumUtils: DESCRIBE THIS
enum InventoryResult : uint8
{
+1
View File
@@ -17,6 +17,7 @@
#include "Pet.h"
#include "ArenaSpectator.h"
#include "CharmInfo.h"
#include "Common.h"
#include "DatabaseEnv.h"
#include "GameTime.h"
+1
View File
@@ -18,6 +18,7 @@
#ifndef AZEROTHCORE_PET_H
#define AZEROTHCORE_PET_H
#include "CharmInfo.h"
#include "PetDefines.h"
#include "TemporarySummon.h"
@@ -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"
+1
View File
@@ -20,6 +20,7 @@
#include "ArenaTeam.h"
#include "Battleground.h"
#include "CharmInfo.h"
#include "CharacterCache.h"
#include "CinematicMgr.h"
#include "DBCStores.h"
@@ -1017,7 +1017,7 @@ void Player::UpdateCombatSkills(Unit* victim, WeaponAttackType attType, bool def
chance = chance < 1.0f ? 1.0f : chance; // minimum chance to increase skill is 1%
LOG_DEBUG("entities.player", "Player::UpdateCombatSkills(defence:{}, playerLevel:{}, moblevel:{}) -> ({}/{}) chance to increase skill is {}\%", defence, playerLevel, moblevel, currentSkillValue, currentSkillMax, chance);
LOG_DEBUG("entities.player", "Player::UpdateCombatSkills(defence:{}, playerLevel:{}, moblevel:{}) -> ({}/{}) chance to increase skill is {}%", defence, playerLevel, moblevel, currentSkillValue, currentSkillMax, chance);
if (roll_chance_f(chance))
{
+411
View File
@@ -0,0 +1,411 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "CharmInfo.h"
#include "Creature.h"
#include "GameTime.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<std::string_view> 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<uint8> type = Acore::StringTo<uint8>(*(iter++));
Optional<uint32> action = Acore::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());
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;
}
////////////////////////////////////////////////////////////
// Methods of class GlobalCooldownMgr
bool GlobalCooldownMgr::HasGlobalCooldown(SpellInfo const* spellInfo) const
{
GlobalCooldownList::const_iterator itr = m_GlobalCooldowns.find(spellInfo->StartRecoveryCategory);
return itr != m_GlobalCooldowns.end() && itr->second.duration && getMSTimeDiff(itr->second.cast_time, GameTime::GetGameTimeMS().count()) < itr->second.duration;
}
void GlobalCooldownMgr::AddGlobalCooldown(SpellInfo const* spellInfo, uint32 gcd)
{
m_GlobalCooldowns[spellInfo->StartRecoveryCategory] = GlobalCooldown(gcd, GameTime::GetGameTimeMS().count());
}
void GlobalCooldownMgr::CancelGlobalCooldown(SpellInfo const* spellInfo)
{
m_GlobalCooldowns[spellInfo->StartRecoveryCategory].duration = 0;
}
+208
View File
@@ -0,0 +1,208 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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 GlobalCooldown
{
explicit GlobalCooldown(uint32 _dur = 0, uint32 _time = 0) : duration(_dur), cast_time(_time) {}
uint32 duration;
uint32 cast_time;
};
typedef std::unordered_map<uint32 /*category*/, GlobalCooldown> GlobalCooldownList;
class GlobalCooldownMgr // Shared by Player and CharmInfo
{
public:
GlobalCooldownMgr() = default;
public:
bool HasGlobalCooldown(SpellInfo const* spellInfo) const;
void AddGlobalCooldown(SpellInfo const* spellInfo, uint32 gcd);
void CancelGlobalCooldown(SpellInfo const* spellInfo);
private:
GlobalCooldownList m_GlobalCooldowns;
};
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;
GlobalCooldownMgr _GlobalCooldownMgr;
};
#endif // _CHARMINFO_H
+1 -391
View File
@@ -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"
@@ -333,24 +334,6 @@ Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject),
_lastExtraAttackSpell = 0;
}
////////////////////////////////////////////////////////////
// Methods of class GlobalCooldownMgr
bool GlobalCooldownMgr::HasGlobalCooldown(SpellInfo const* spellInfo) const
{
GlobalCooldownList::const_iterator itr = m_GlobalCooldowns.find(spellInfo->StartRecoveryCategory);
return itr != m_GlobalCooldowns.end() && itr->second.duration && getMSTimeDiff(itr->second.cast_time, GameTime::GetGameTimeMS().count()) < itr->second.duration;
}
void GlobalCooldownMgr::AddGlobalCooldown(SpellInfo const* spellInfo, uint32 gcd)
{
m_GlobalCooldowns[spellInfo->StartRecoveryCategory] = GlobalCooldown(gcd, GameTime::GetGameTimeMS().count());
}
void GlobalCooldownMgr::CancelGlobalCooldown(SpellInfo const* spellInfo)
{
m_GlobalCooldowns[spellInfo->StartRecoveryCategory].duration = 0;
}
////////////////////////////////////////////////////////////
// Methods of class Unit
Unit::~Unit()
@@ -15780,287 +15763,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<std::string_view> 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<uint8> type = Acore::StringTo<uint8>(*(iter++));
Optional<uint32> action = Acore::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());
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);
@@ -20565,98 +20267,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();
+34 -796
View File
@@ -29,6 +29,8 @@
#include "SpellAuraDefines.h"
#include "SpellDefines.h"
#include "ThreatMgr.h"
#include "UnitDefines.h"
#include "UnitUtils.h"
#include <functional>
#include <utility>
@@ -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<Unit*> UnitList;
typedef std::list< std::pair<Aura*, uint8> > 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<Unit*> UnitList;
typedef std::list< std::pair<Aura*, uint8> > 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
@@ -1018,40 +543,6 @@ enum CurrentSpellTypes
#define CURRENT_FIRST_NON_MELEE_SPELL 1
#define CURRENT_MAX_SPELL 4
struct GlobalCooldown
{
explicit GlobalCooldown(uint32 _dur = 0, uint32 _time = 0) : duration(_dur), cast_time(_time) {}
uint32 duration;
uint32 cast_time;
};
typedef std::unordered_map<uint32 /*category*/, GlobalCooldown> GlobalCooldownList;
class GlobalCooldownMgr // Shared by Player and CharmInfo
{
public:
GlobalCooldownMgr() = default;
public:
bool HasGlobalCooldown(SpellInfo const* spellInfo) const;
void AddGlobalCooldown(SpellInfo const* spellInfo, uint32 gcd);
void CancelGlobalCooldown(SpellInfo const* spellInfo);
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 +550,7 @@ enum ReactStates : uint8
REACT_AGGRESSIVE = 2
};
enum CommandStates
enum CommandStates : uint8
{
COMMAND_STAY = 0,
COMMAND_FOLLOW = 1,
@@ -1067,147 +558,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<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 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 +626,6 @@ typedef std::unordered_map<uint32, uint32> 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<uint16 /*index*/, uint32 /*pos*/> other;
};
// BuildValuesCachedBuffer cache for calculated BuildValue.
struct BuildValuesCachedBuffer
{
BuildValuesCachedBuffer(uint32 bufferSize) :
buffer(bufferSize), posPointers() {}
ByteBuffer buffer;
BuildValuesCachePosPointers posPointers;
};
class Unit : public WorldObject
{
public:
@@ -1883,7 +1133,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);
@@ -2772,15 +2021,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
+462
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
#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
};
+117
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
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<uint16 /*index*/, uint32 /*pos*/> other;
};
// BuildValuesCachedBuffer cache for calculated BuildValue.
struct BuildValuesCachedBuffer
{
BuildValuesCachedBuffer(uint32 bufferSize) :
buffer(bufferSize), posPointers() {}
ByteBuffer buffer;
BuildValuesCachePosPointers posPointers;
};
@@ -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
+135 -34
View File
@@ -6213,7 +6213,7 @@ void ObjectMgr::LoadQuestAreaTriggers()
QuestGreeting const* ObjectMgr::GetQuestGreeting(TypeID type, uint32 id) const
{
uint32 typeIndex;
uint8 typeIndex;
if (type == TYPEID_UNIT)
typeIndex = 0;
else if (type == TYPEID_GAMEOBJECT)
@@ -6221,15 +6221,19 @@ QuestGreeting const* ObjectMgr::GetQuestGreeting(TypeID type, uint32 id) const
else
return nullptr;
return Acore::Containers::MapGetValuePtr(_questGreetingStore[typeIndex], id);
std::pair<uint32, uint8> pairKey = std::make_pair(id, typeIndex);
QuestGreetingContainer::const_iterator itr = _questGreetingStore.find(pairKey);
if (itr == _questGreetingStore.end())
return nullptr;
return &itr->second;
}
void ObjectMgr::LoadQuestGreetings()
{
uint32 oldMSTime = getMSTime();
for (std::size_t i = 0; i < _questGreetingStore.size(); ++i)
_questGreetingStore[i].clear();
_questGreetingStore.clear(); // For reload case
// 0 1 2 3 4
QueryResult result = WorldDatabase.Query("SELECT ID, Type, GreetEmoteType, GreetEmoteDelay, Greeting FROM quest_greeting");
@@ -6239,8 +6243,6 @@ void ObjectMgr::LoadQuestGreetings()
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
@@ -6249,35 +6251,35 @@ void ObjectMgr::LoadQuestGreetings()
uint8 type = fields[1].Get<uint8>();
switch (type)
{
case 0: // Creature
if (!sObjectMgr->GetCreatureTemplate(id))
{
LOG_ERROR("sql.sql", "Table `quest_greeting`: creature template entry {} does not exist.", id);
case 0: // Creature
if (!sObjectMgr->GetCreatureTemplate(id))
{
LOG_ERROR("sql.sql", "Table `quest_greeting`: creature template entry {} does not exist.", id);
continue;
}
break;
case 1: // GameObject
if (!sObjectMgr->GetGameObjectTemplate(id))
{
LOG_ERROR("sql.sql", "Table `quest_greeting`: gameobject template entry {} does not exist.", id);
continue;
}
break;
default:
LOG_ERROR("sql.sql", "Table `quest_greeting` has unknown type {} for id {}, skipped.", type, id);
continue;
}
break;
case 1: // GameObject
if (!sObjectMgr->GetGameObjectTemplate(id))
{
LOG_ERROR("sql.sql", "Table `quest_greeting`: gameobject template entry {} does not exist.", id);
continue;
}
break;
default:
continue;
}
uint16 greetEmoteType = fields[2].Get<uint16>();
uint32 greetEmoteDelay = fields[3].Get<uint32>();
std::string greeting = fields[4].Get<std::string>();
std::pair<uint32, uint8> pairKey = std::make_pair(id, type);
QuestGreeting& data = _questGreetingStore[pairKey];
_questGreetingStore[type].emplace(std::piecewise_construct, std::forward_as_tuple(id), std::forward_as_tuple(greetEmoteType, greetEmoteDelay, std::move(greeting)));
++count;
data.EmoteType = fields[2].Get<uint16>();
data.EmoteDelay = fields[3].Get<uint32>();
AddLocaleString(fields[4].Get<std::string>(), LOCALE_enUS, data.Greeting);
}
while (result->NextRow());
LOG_INFO("server.loading", ">> Loaded {} quest_greeting in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", ">> Loaded {} quest_greeting in {} ms", _questGreetingStore.size(), GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
}
@@ -6285,8 +6287,6 @@ void ObjectMgr::LoadQuestGreetingsLocales()
{
uint32 oldMSTime = getMSTime();
_questGreetingLocaleStore.clear();
// 0 1 2 3
QueryResult result = WorldDatabase.Query("SELECT ID, Type, Locale, Greeting FROM quest_greeting_locale");
if (!result)
@@ -6295,6 +6295,7 @@ void ObjectMgr::LoadQuestGreetingsLocales()
return;
}
uint32 localeCount = 0;
do
{
Field* fields = result->Fetch();
@@ -6321,17 +6322,25 @@ void ObjectMgr::LoadQuestGreetingsLocales()
continue;
}
std::string localeName = fields[2].Get<std::string>();
std::pair<uint32, uint8> pairKey = std::make_pair(id, type);
QuestGreeting& data = _questGreetingStore[pairKey];
LocaleConstant locale = GetLocaleByName(localeName);
QuestGreetingContainer::iterator qgc = _questGreetingStore.find(pairKey);
if (qgc == _questGreetingStore.end())
{
LOG_ERROR("sql.sql", "QuestGreeting (Id: {} Type: {}) found in table `quest_greeting_locale` but does not exist in `quest_greeting`. Skipped!", id, type);
continue;
}
LocaleConstant locale = GetLocaleByName(fields[2].Get<std::string>());
if (locale == LOCALE_enUS)
continue;
QuestGreetingLocale& data = _questGreetingLocaleStore[MAKE_PAIR32(type, id)];
AddLocaleString(fields[3].Get<std::string>(), locale, data.Greeting);
localeCount++;
} while (result->NextRow());
LOG_INFO("server.loading", ">> Loaded {} quest greeting Locale Strings in {} ms", (uint32)_questGreetingLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", ">> Loaded {} quest greeting Locale Strings in {} ms", localeCount, GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
}
@@ -8544,6 +8553,98 @@ void ObjectMgr::LoadGameObjectForQuests()
LOG_INFO("server.loading", " ");
}
bool ObjectMgr::LoadModuleStrings()
{
uint32 oldMSTime = getMSTime();
_moduleStringStore.clear(); // for reload case
QueryResult result = WorldDatabase.Query("SELECT module, id, string FROM module_string");
if (!result)
{
LOG_WARN("server.loading", ">> Loaded 0 module strings. DB table `module_string` is empty.");
LOG_INFO("server.loading", " ");
return false;
}
do
{
Field* fields = result->Fetch();
std::string module = fields[0].Get<std::string>();
uint32 id = fields[1].Get<uint32>();
std::pair<std::string, uint32> pairKey = std::make_pair(module, id);
ModuleString& data = _moduleStringStore[pairKey];
AddLocaleString(fields[2].Get<std::string>(), LOCALE_enUS, data.Content);
} while (result->NextRow());
LOG_INFO("server.loading", ">> Loaded {} Module Strings in {} ms", _moduleStringStore.size(), GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
return true;
}
bool ObjectMgr::LoadModuleStringsLocale()
{
uint32 oldMSTime = getMSTime();
QueryResult result = WorldDatabase.Query("SELECT module, id, locale, string FROM module_string_locale");
if (!result)
{
LOG_WARN("server.loading", ">> Loaded 0 module strings locale. DB table `module_string_locale` is empty.");
LOG_INFO("server.loading", " ");
return false;
}
uint32 localeCount = 0;
do
{
Field* fields = result->Fetch();
std::string module = fields[0].Get<std::string>();
uint32 id = fields[1].Get<uint32>();
std::pair<std::string, uint32> pairKey = std::make_pair(module, id);
ModuleString& data = _moduleStringStore[pairKey];
ModuleStringContainer::iterator ms = _moduleStringStore.find(pairKey);
if (ms == _moduleStringStore.end())
{
LOG_ERROR("sql.sql", "ModuleString (Module: {} Id: {}) found in table `module_string_locale` but does not exist in `module_string`. Skipped!", module, id);
continue;
}
LocaleConstant locale = GetLocaleByName(fields[2].Get<std::string>());
if (locale == LOCALE_enUS)
continue;
AddLocaleString(fields[3].Get<std::string>(), locale, data.Content);
localeCount++;
} while (result->NextRow());
LOG_INFO("server.loading", ">> Loaded {} Module Strings Locales in {} ms", localeCount, GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
return true;
}
std::string const* ObjectMgr::GetModuleString(std::string module, uint32 id, LocaleConstant locale) const
{
ModuleString const* ms = GetModuleString(module, id);
if (ms->Content.size())
{
if (ms->Content.size() > size_t(locale) && !ms->Content[locale].empty())
return &ms->Content[locale];
return &ms->Content[DEFAULT_LOCALE];
}
LOG_ERROR("sql.sql", "Module string module {} id {} not found in DB.", module, id);
return (std::string*)"error";
}
bool ObjectMgr::LoadAcoreStrings()
{
uint32 oldMSTime = getMSTime();
+22 -34
View File
@@ -493,6 +493,11 @@ typedef std::unordered_map<uint32/*(mapid, spawnMode) pair*/, CellObjectGuidsMap
// Acore Trainer Reference start range
#define ACORE_TRAINER_START_REF 200000
struct ModuleString
{
std::vector<std::string> Content;
};
struct AcoreString
{
std::vector<std::string> Content;
@@ -511,6 +516,7 @@ typedef std::unordered_map<uint32, QuestOfferRewardLocale> QuestOfferRewardLocal
typedef std::unordered_map<uint32, QuestRequestItemsLocale> QuestRequestItemsLocaleContainer;
typedef std::unordered_map<uint32, NpcTextLocale> NpcTextLocaleContainer;
typedef std::unordered_map<uint32, PageTextLocale> PageTextLocaleContainer;
typedef std::map<std::pair<std::string, uint32>, ModuleString> ModuleStringContainer;
typedef std::unordered_map<int32, AcoreString> AcoreStringContainer;
typedef std::unordered_map<uint32, GossipMenuItemsLocale> GossipMenuItemsLocaleContainer;
typedef std::unordered_map<uint32, PointOfInterestLocale> PointOfInterestLocaleContainer;
@@ -593,20 +599,9 @@ struct QuestGreeting
{
uint16 EmoteType;
uint32 EmoteDelay;
std::string Text;
QuestGreeting() : EmoteType(0), EmoteDelay(0) { }
QuestGreeting(uint16 emoteType, uint32 emoteDelay, std::string text)
: EmoteType(emoteType), EmoteDelay(emoteDelay), Text(std::move(text)) { }
};
struct QuestGreetingLocale
{
std::vector<std::string> Greeting;
};
typedef std::unordered_map<uint32, QuestGreetingLocale> QuestGreetingLocaleContainer;
struct GossipMenuItems
{
uint32 MenuID;
@@ -666,7 +661,7 @@ struct QuestPOI
typedef std::vector<QuestPOI> QuestPOIVector;
typedef std::unordered_map<uint32, QuestPOIVector> QuestPOIContainer;
typedef std::array<std::unordered_map<uint32, QuestGreeting>, 2> QuestGreetingContainer;
typedef std::map<std::pair<uint32, uint8>, QuestGreeting> QuestGreetingContainer;
typedef std::unordered_map<uint32, VendorItemData> CacheVendorItemContainer;
typedef std::unordered_map<uint32, TrainerSpellData> CacheTrainerSpellContainer;
@@ -1013,6 +1008,8 @@ public:
void ValidateSpellScripts();
void InitializeSpellInfoPrecomputedData();
bool LoadModuleStrings();
bool LoadModuleStringsLocale();
bool LoadAcoreStrings();
void LoadBroadcastTexts();
void LoadBroadcastTextLocales();
@@ -1268,26 +1265,6 @@ public:
if (itr == _pointOfInterestLocaleStore.end()) return nullptr;
return &itr->second;
}
[[nodiscard]] QuestGreetingLocale const* GetQuestGreetingLocale(TypeID type, uint32 id) const
{
uint32 typeIndex;
if (type == TYPEID_UNIT)
{
typeIndex = 0;
}
else if (type == TYPEID_GAMEOBJECT)
{
typeIndex = 1;
}
else
{
return nullptr;
}
QuestGreetingLocaleContainer::const_iterator itr = _questGreetingLocaleStore.find(MAKE_PAIR32(typeIndex, id));
if (itr == _questGreetingLocaleStore.end()) return nullptr;
return &itr->second;
}
[[nodiscard]] QuestOfferRewardLocale const* GetQuestOfferRewardLocale(uint32 entry) const
{
auto itr = _questOfferRewardLocaleStore.find(entry);
@@ -1306,11 +1283,22 @@ public:
if (itr == _npcTextLocaleStore.end()) return nullptr;
return &itr->second;
}
QuestGreeting const* GetQuestGreeting(TypeID type, uint32 id) const;
[[nodiscard]] QuestGreeting const* GetQuestGreeting(TypeID type, uint32 id) const;
GameObjectData& NewGOData(ObjectGuid::LowType guid) { return _gameObjectDataStore[guid]; }
void DeleteGOData(ObjectGuid::LowType guid);
[[nodiscard]] ModuleString const* GetModuleString(std::string module, uint32 id) const
{
std::pair<std::string, uint32> pairKey = std::make_pair(module, id);
ModuleStringContainer::const_iterator itr = _moduleStringStore.find(pairKey);
if (itr == _moduleStringStore.end())
return nullptr;
return &itr->second;
}
[[nodiscard]] std::string const* GetModuleString(std::string module, uint32 id, LocaleConstant locale) const;
[[nodiscard]] AcoreString const* GetAcoreString(uint32 entry) const
{
AcoreStringContainer::const_iterator itr = _acoreStringStore.find(entry);
@@ -1599,10 +1587,10 @@ private:
QuestRequestItemsLocaleContainer _questRequestItemsLocaleStore;
NpcTextLocaleContainer _npcTextLocaleStore;
PageTextLocaleContainer _pageTextLocaleStore;
ModuleStringContainer _moduleStringStore;
AcoreStringContainer _acoreStringStore;
GossipMenuItemsLocaleContainer _gossipMenuItemsLocaleStore;
PointOfInterestLocaleContainer _pointOfInterestLocaleStore;
QuestGreetingLocaleContainer _questGreetingLocaleStore;
CacheVendorItemContainer _cacheVendorItemStore;
CacheTrainerSpellContainer _cacheTrainerSpellStore;
+1
View File
@@ -16,6 +16,7 @@
*/
#include "Common.h"
#include "CharmInfo.h"
#include "CreatureAI.h"
#include "DisableMgr.h"
#include "GameTime.h"
+5
View File
@@ -820,6 +820,11 @@ char const* WorldSession::GetAcoreString(uint32 entry) const
return sObjectMgr->GetAcoreString(entry, GetSessionDbLocaleIndex());
}
std::string const* WorldSession::GetModuleString(std::string module, uint32 id) const
{
return sObjectMgr->GetModuleString(module, id, GetSessionDbLocaleIndex());
}
void WorldSession::Handle_NULL(WorldPacket& null)
{
LOG_ERROR("network.opcode", "Received unhandled opcode {} from {}",
+1
View File
@@ -517,6 +517,7 @@ public:
LocaleConstant GetSessionDbcLocale() const { return /*_isBot? LOCALE_enUS : */m_sessionDbcLocale; }
LocaleConstant GetSessionDbLocaleIndex() const { return /*_isBot? LOCALE_enUS : */m_sessionDbLocaleIndex; }
char const* GetAcoreString(uint32 entry) const;
std::string const* GetModuleString(std::string module, uint32 id) const;
uint32 GetLatency() const { return m_latency; }
void SetLatency(uint32 latency) { m_latency = latency; }
@@ -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"
+26 -3
View File
@@ -20,6 +20,7 @@
#include "BattlefieldMgr.h"
#include "Battleground.h"
#include "BattlegroundIC.h"
#include "CharmInfo.h"
#include "CellImpl.h"
#include "Common.h"
#include "ConditionMgr.h"
@@ -3738,6 +3739,10 @@ void Spell::cancel(bool bySelf)
if (Unit* unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID))
unit->RemoveOwnedAura(m_spellInfo->Id, m_originalCasterGUID, 0, AURA_REMOVE_BY_CANCEL);
if (m_caster->GetTypeId() == TYPEID_PLAYER)
if (m_spellInfo->HasAttribute(SPELL_ATTR0_COOLDOWN_ON_EVENT))
m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
SendChannelUpdate(0);
SendInterrupted(SPELL_FAILED_INTERRUPTED);
}
@@ -4104,6 +4109,9 @@ void Spell::handle_immediate()
if (m_spellInfo->IsChanneled())
{
int32 duration = m_spellInfo->GetDuration();
if (HasTriggeredCastFlag(TRIGGERED_IGNORE_EFFECTS))
duration = -1;
if (duration > 0)
{
// First mod_duration then haste - see Missile Barrage
@@ -4370,8 +4378,12 @@ void Spell::SendSpellCooldown()
return;
}
// have infinity cooldown but set at aura apply // do not set cooldown for triggered spells (needed by reincarnation)
if (m_spellInfo->IsCooldownStartedOnEvent() || m_spellInfo->IsPassive() || (HasTriggeredCastFlag(TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD) && !m_CastItem))
// have infinity cooldown but set at aura apply
// do not set cooldown for triggered spells (needed by reincarnation)
if (m_spellInfo->IsCooldownStartedOnEvent()
|| m_spellInfo->IsPassive()
|| (HasTriggeredCastFlag(TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD) && !m_CastItem)
|| HasTriggeredCastFlag(TRIGGERED_IGNORE_EFFECTS))
return;
_player->AddSpellAndCategoryCooldowns(m_spellInfo, m_CastItem ? m_CastItem->GetEntry() : 0, this);
@@ -5600,6 +5612,9 @@ void Spell::HandleThreatSpells()
void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode)
{
if (HasTriggeredCastFlag(TRIGGERED_IGNORE_EFFECTS))
return;
effectHandleMode = mode;
unitTarget = pUnitTarget;
itemTarget = pItemTarget;
@@ -6016,6 +6031,11 @@ SpellCastResult Spell::CheckCast(bool strict)
return castResult;
}
if (HasTriggeredCastFlag(TRIGGERED_IGNORE_EFFECTS))
{
return SPELL_CAST_OK;
}
// xinef: do not skip triggered spells if they posses prevention type (eg. Bladestorm vs Hand of Protection)
if (!HasTriggeredCastFlag(TRIGGERED_IGNORE_CASTER_AURAS) || (m_spellInfo->PreventionType > SPELL_PREVENTION_TYPE_NONE && m_triggeredByAuraSpell && m_triggeredByAuraSpell.spellInfo->IsPositive()))
{
@@ -6453,7 +6473,7 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_BAD_TARGETS;
Player* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetTarget());
if (!target || m_caster->ToPlayer() == target || (!target->IsInSameRaidWith(m_caster->ToPlayer()) && m_spellInfo->Id != 48955)) // refer-a-friend spell
if (!target || (!target->IsInSameRaidWith(m_caster->ToPlayer()) && m_spellInfo->Id != 48955)) // refer-a-friend spell
return SPELL_FAILED_BAD_TARGETS;
// Xinef: Implement summon pending error
@@ -8056,6 +8076,9 @@ bool Spell::IsAutoActionResetSpell() const
bool Spell::IsNeedSendToClient(bool go) const
{
if (HasTriggeredCastFlag(TRIGGERED_IGNORE_EFFECTS))
return false;
return m_spellInfo->SpellVisual[0] || m_spellInfo->SpellVisual[1] || m_spellInfo->IsChanneled() ||
m_spellInfo->Speed > 0.0f || (!m_triggeredByAuraSpell && !IsTriggered()) ||
(go && m_triggeredByAuraSpell && m_triggeredByAuraSpell.spellInfo->IsChanneled());
+1
View File
@@ -148,6 +148,7 @@ enum TriggerCastFlags
TRIGGERED_FULL_MASK = 0x0007FFFF, //! Used when doing CastSpell with triggered == true
TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT = 0x00080000, //! Will ignore equipped item requirements
TRIGGERED_NO_PERIODIC_RESET = 0x00100000, //! Periodic aura tick wont be reset on override
TRIGGERED_IGNORE_EFFECTS = 0x00200000, //! Ignore spell effects - used for ritual portals
TRIGGERED_FULL_DEBUG_MASK = 0xFFFFFFFF
};
-3
View File
@@ -5380,9 +5380,6 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
}
Map* cMap = m_caster->GetMap();
// if gameobject is summoning object, it should be spawned right on caster's position
if (goinfo->type == GAMEOBJECT_TYPE_SUMMONING_RITUAL)
m_caster->GetPosition(fx, fy, fz);
GameObject* pGameObj = sObjectMgr->IsGameObjectStaticTransport(name_id) ? new StaticTransport() : new GameObject();
+3
View File
@@ -500,6 +500,9 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const
break;
}
if ((sSpellMgr->GetSpellInfo(_spellInfo->Effects[_effIndex].TriggerSpell) && sSpellMgr->GetSpellInfo(_spellInfo->Effects[_effIndex].TriggerSpell)->HasAttribute(SPELL_ATTR0_SCALES_WITH_CREATURE_LEVEL)) && _spellInfo->HasAttribute(SPELL_ATTR0_SCALES_WITH_CREATURE_LEVEL))
canEffectScale = false;
if (canEffectScale)
{
CreatureTemplate const* cInfo = caster->ToCreature()->GetCreatureTemplate();
+1
View File
@@ -139,6 +139,7 @@ enum WorldBoolConfigs
CONFIG_AUTOBROADCAST,
CONFIG_ALLOW_TICKETS,
CONFIG_DELETE_CHARACTER_TICKET_TRACE,
CONFIG_LFG_CAST_DESERTER,
CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES,
CONFIG_PRESERVE_CUSTOM_CHANNELS,
CONFIG_PDUMP_NO_PATHS,
+9 -2
View File
@@ -1363,7 +1363,9 @@ void World::LoadConfigSettings(bool reload)
_int_configs[CONFIG_WARDEN_CLIENT_RESPONSE_DELAY] = sConfigMgr->GetOption<int32>("Warden.ClientResponseDelay", 600);
// Dungeon finder
_int_configs[CONFIG_LFG_OPTIONSMASK] = sConfigMgr->GetOption<int32>("DungeonFinder.OptionsMask", 5);
_int_configs[CONFIG_LFG_OPTIONSMASK] = sConfigMgr->GetOption<int32>("DungeonFinder.OptionsMask", 5);
_bool_configs[CONFIG_LFG_CAST_DESERTER] = sConfigMgr->GetOption<int32>("DungeonFinder.CastDeserter", true);
// DBC_ItemAttributes
_bool_configs[CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES] = sConfigMgr->GetOption<bool>("DBC.EnforceItemAttributes", true);
@@ -1543,6 +1545,11 @@ void World::SetInitialWorldSettings()
if (!sObjectMgr->LoadAcoreStrings())
exit(1); // Error message displayed in function already
LOG_INFO("server.loading", "Loading Module Strings...");
sObjectMgr->LoadModuleStrings();
LOG_INFO("server.loading", "Loading Module Strings Locale...");
sObjectMgr->LoadModuleStringsLocale();
///- Update the realm entry in the database with the realm type from the config file
//No SQL injection as values are treated as integers
@@ -1789,7 +1796,7 @@ void World::SetInitialWorldSettings()
LOG_INFO("server.loading", "Loading Quest Greetings...");
sObjectMgr->LoadQuestGreetings(); // must be loaded after creature_template, gameobject_template tables
LOG_INFO("server.loading", "Loading Quest Greeting Locales...");
sObjectMgr->LoadQuestGreetingsLocales(); // must be loaded after creature_template, gameobject_template tables
sObjectMgr->LoadQuestGreetingsLocales(); // must be loaded after creature_template, gameobject_template tables, quest_greeting
LOG_INFO("server.loading", "Loading Quest Money Rewards...");
sObjectMgr->LoadQuestMoneyRewards();