fix(DB/SpellCone): implement spell_cone table and radius calculation (#26024)
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
--
|
||||||
|
DROP TABLE IF EXISTS `spell_cone`;
|
||||||
|
CREATE TABLE `spell_cone` (
|
||||||
|
`ID` INT UNSIGNED NOT NULL COMMENT 'Spell ID',
|
||||||
|
`ConeDegrees` SMALLINT NOT NULL DEFAULT '60' COMMENT 'Cone angle in degrees',
|
||||||
|
PRIMARY KEY (`ID`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
--
|
||||||
|
DELETE FROM `spell_cone` WHERE `ID` > 0;
|
||||||
|
INSERT INTO `spell_cone` VALUES
|
||||||
|
(5708, 90),
|
||||||
|
(8374, 90),
|
||||||
|
-- (9457, 90), -- Tharnariun's Heal
|
||||||
|
(11019, 90),
|
||||||
|
(12882, 90),
|
||||||
|
(12887, 90),
|
||||||
|
-- (15529, 359), -- Gout of Flame
|
||||||
|
(15847, -120),
|
||||||
|
(16094, 90),
|
||||||
|
(16099, 90),
|
||||||
|
(16169, 90),
|
||||||
|
(16340, 90),
|
||||||
|
(16350, 90),
|
||||||
|
(16359, 90),
|
||||||
|
(16390, 90),
|
||||||
|
(16396, 120),
|
||||||
|
(18144, 90),
|
||||||
|
(18435, 120),
|
||||||
|
(18500, 120),
|
||||||
|
(19630, 120),
|
||||||
|
(19641, 120),
|
||||||
|
(19813, 180),
|
||||||
|
(20667, 90),
|
||||||
|
(20712, 120),
|
||||||
|
(20716, 90),
|
||||||
|
(20717, 90),
|
||||||
|
(21071, 120),
|
||||||
|
(21099, 120),
|
||||||
|
(21189, 90),
|
||||||
|
(21333, 180),
|
||||||
|
(22479, 90),
|
||||||
|
(22539, 120),
|
||||||
|
(22558, 90),
|
||||||
|
(22559, 90),
|
||||||
|
(22560, 90),
|
||||||
|
(22561, 90),
|
||||||
|
-- (22600, 120), -- Force Reactive Disk
|
||||||
|
(22642, 90),
|
||||||
|
-- (22682, 120), -- Shadow Flame
|
||||||
|
(22833, 120),
|
||||||
|
(22945, 120),
|
||||||
|
-- (22993, 120), -- Shadow Flame
|
||||||
|
-- (23187, 120), -- Frost Burn
|
||||||
|
-- (23189, 120), -- Frost Burn
|
||||||
|
-- (23308, 120), -- Incinerate
|
||||||
|
-- (23309, 120), -- Incinerate
|
||||||
|
-- (23310, 120), -- Time Lapse
|
||||||
|
-- (23311, 120), -- Time Lapse
|
||||||
|
-- (23312, 120), -- Time Lapse
|
||||||
|
-- (23313, 120), -- Corrosive Acid
|
||||||
|
-- (23314, 120), -- Corrosive Acid
|
||||||
|
-- (23315, 120), -- Ignite Flesh
|
||||||
|
-- (23316, 120), -- Ignite Flesh
|
||||||
|
(23339, 120),
|
||||||
|
(23364, -120),
|
||||||
|
(23461, 120),
|
||||||
|
(23618, 90),
|
||||||
|
(23919, 120),
|
||||||
|
(24192, 120),
|
||||||
|
(24682, 120),
|
||||||
|
(24818, 120),
|
||||||
|
(24821, 45),
|
||||||
|
(24822, 135),
|
||||||
|
(24823, 90),
|
||||||
|
(24835, 180),
|
||||||
|
(24836, 225),
|
||||||
|
(24837, 270),
|
||||||
|
(24838, 315),
|
||||||
|
(24839, 120),
|
||||||
|
(24933, 7),
|
||||||
|
-- (25024, 45), -- Drop Mine
|
||||||
|
-- (25026, 45), Activate MG Turret
|
||||||
|
-- (25027, 30), -- Flamethrower
|
||||||
|
(25029, 30), -- Flamethrower
|
||||||
|
(25030, 90), -- Shoot Rocket
|
||||||
|
-- (25031, 45), -- Shoot Missile
|
||||||
|
-- (25032, 10), -- Machine Gun
|
||||||
|
-- (25060, 90), -- Updraft
|
||||||
|
(25145, 90),
|
||||||
|
(25149, 90),
|
||||||
|
(25150, 90),
|
||||||
|
(25322, 90),
|
||||||
|
(25653, -120),
|
||||||
|
(25993, 120),
|
||||||
|
(26025, 180), -- Impale used by 15233 Vekniss Guardian; Knockback AoE, Bleed Cone
|
||||||
|
-- (26027, 180), -- Knockback
|
||||||
|
(26029, 5), -- Dark Glare
|
||||||
|
-- (27766, 90), -- Cannon
|
||||||
|
(27807, 90),
|
||||||
|
(28127, 90),
|
||||||
|
(28157, 45),
|
||||||
|
(28168, 120),
|
||||||
|
(28405, 180),
|
||||||
|
(28438, 180),
|
||||||
|
(28459, 90),
|
||||||
|
-- (28460, 90), -- Wail of Souls
|
||||||
|
-- (28469, 360), -- Ghost Vision
|
||||||
|
(28741, 120),
|
||||||
|
(28783, 30),
|
||||||
|
-- (29998, 180), -- Decrepit Fever
|
||||||
|
(30043, 90),
|
||||||
|
(30056, 180),
|
||||||
|
(30732, 180);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
--
|
||||||
|
-- 25029 Flamethrower TARGET_UNIT_CONE_ENTRY
|
||||||
|
-- 25030 Shoot Rocket TARGET_UNIT_CONE_ENTRY
|
||||||
|
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceEntry` IN (25029, 25030)) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 31) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 3) AND (`ConditionValue2` = 15328) AND (`ConditionValue3` = 0);
|
||||||
|
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||||
|
(13, 5, 25029, 0, 0, 31, 0, 3, 15328, 0, 0, 0, 0, '', 'target must be \'Steam Stonk\''),
|
||||||
|
(13, 1, 25030, 0, 0, 31, 0, 3, 15328, 0, 0, 0, 0, '', 'target must be \'Steam Stonk\'');
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "WorldPacket.h"
|
#include "WorldPacket.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <G3D/g3dmath.h>
|
||||||
|
|
||||||
/// @todo: this import is not necessary for compilation and marked as unused by the IDE
|
/// @todo: this import is not necessary for compilation and marked as unused by the IDE
|
||||||
// however, for some reasons removing it would cause a damn linking issue
|
// however, for some reasons removing it would cause a damn linking issue
|
||||||
@@ -1225,9 +1226,28 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
|
|||||||
SpellTargetObjectTypes objectType = targetType.GetObjectType();
|
SpellTargetObjectTypes objectType = targetType.GetObjectType();
|
||||||
SpellTargetCheckTypes selectionType = targetType.GetCheckType();
|
SpellTargetCheckTypes selectionType = targetType.GetCheckType();
|
||||||
ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
|
ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
|
||||||
float coneAngle = M_PI / 2;
|
float coneAngle = G3D::toRadians(60.0f);
|
||||||
float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
|
if (SpellCone const* sc = sSpellMgr->GetSpellCone(m_spellInfo->Id))
|
||||||
|
coneAngle = G3D::toRadians(static_cast<float>(sc->cone_degrees));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (targetType.GetTarget())
|
||||||
|
{
|
||||||
|
case TARGET_UNIT_CONE_ENEMY_24:
|
||||||
|
coneAngle = G3D::toRadians(24.0f);
|
||||||
|
break;
|
||||||
|
case TARGET_UNIT_CONE_ENEMY_54:
|
||||||
|
coneAngle = G3D::toRadians(54.0f);
|
||||||
|
break;
|
||||||
|
case TARGET_UNIT_CONE_ENEMY_104:
|
||||||
|
coneAngle = G3D::toRadians(104.0f);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
|
||||||
if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList))
|
if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList))
|
||||||
{
|
{
|
||||||
Acore::WorldObjectSpellConeTargetCheck check(coneAngle, radius, m_caster, m_spellInfo, selectionType, condList);
|
Acore::WorldObjectSpellConeTargetCheck check(coneAngle, radius, m_caster, m_spellInfo, selectionType, condList);
|
||||||
|
|||||||
@@ -5207,6 +5207,13 @@ void SpellMgr::LoadSpellInfoCorrections()
|
|||||||
spellInfo->Effects[EFFECT_0].BasePoints = 1;
|
spellInfo->Effects[EFFECT_0].BasePoints = 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 26025 Impale
|
||||||
|
ApplySpellFix({ 26025 }, [](SpellInfo* spellInfo)
|
||||||
|
{
|
||||||
|
spellInfo->Effects[EFFECT_1].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CONE_ENEMY_54);
|
||||||
|
spellInfo->Effects[EFFECT_1].TargetB = SpellImplicitTargetInfo(0);
|
||||||
|
});
|
||||||
|
|
||||||
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
||||||
{
|
{
|
||||||
SpellInfo* spellInfo = mSpellInfoMap[i];
|
SpellInfo* spellInfo = mSpellInfoMap[i];
|
||||||
|
|||||||
@@ -695,6 +695,16 @@ SpellTargetPosition const* SpellMgr::GetSpellTargetPosition(uint32 spell_id, Spe
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpellCone const* SpellMgr::GetSpellCone(uint32 spell_id) const
|
||||||
|
{
|
||||||
|
spell_id = GetFirstSpellInChain(spell_id);
|
||||||
|
auto itr = mSpellCones.find(spell_id);
|
||||||
|
if (itr != mSpellCones.end())
|
||||||
|
return &itr->second;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
SpellSpellGroupMapBounds SpellMgr::GetSpellSpellGroupMapBounds(uint32 spell_id) const
|
SpellSpellGroupMapBounds SpellMgr::GetSpellSpellGroupMapBounds(uint32 spell_id) const
|
||||||
{
|
{
|
||||||
spell_id = GetFirstSpellInChain(spell_id);
|
spell_id = GetFirstSpellInChain(spell_id);
|
||||||
@@ -1580,6 +1590,93 @@ void SpellMgr::LoadSpellTargetPositions()
|
|||||||
LOG_INFO("server.loading", " ");
|
LOG_INFO("server.loading", " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpellMgr::LoadSpellCones()
|
||||||
|
{
|
||||||
|
uint32 oldMSTime = getMSTime();
|
||||||
|
|
||||||
|
mSpellCones.clear(); // need for reload case
|
||||||
|
|
||||||
|
// 0 1
|
||||||
|
QueryResult result = WorldDatabase.Query("SELECT ID, ConeDegrees FROM spell_cone");
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
LOG_WARN("server.loading", ">> Loaded 0 spell cone definitions. DB table `spell_cone` is empty.");
|
||||||
|
LOG_INFO("server.loading", " ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 count = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Field* fields = result->Fetch();
|
||||||
|
|
||||||
|
uint32 spellId = fields[0].Get<uint32>();
|
||||||
|
int16 coneDeg = fields[1].Get<int16>();
|
||||||
|
|
||||||
|
SpellInfo const* spellInfo = GetSpellInfo(spellId);
|
||||||
|
if (!spellInfo)
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "Spell (ID:{}) listed in `spell_cone` does not exist.", spellId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coneDeg < -360 || coneDeg > 360)
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "Spell (Id: {}) cone degrees {} out of range (-360..360).", spellId, coneDeg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 firstRankId = GetFirstSpellInChain(spellId);
|
||||||
|
SpellInfo const* firstSpellInfo = GetSpellInfo(firstRankId);
|
||||||
|
|
||||||
|
SpellInfo const* checkInfo = firstSpellInfo ? firstSpellInfo : spellInfo;
|
||||||
|
|
||||||
|
bool hasCone = false;
|
||||||
|
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||||
|
{
|
||||||
|
if (checkInfo->Effects[i].TargetA.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE ||
|
||||||
|
checkInfo->Effects[i].TargetB.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE)
|
||||||
|
{
|
||||||
|
hasCone = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasCone)
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "Spell (ID:{}) listed in `spell_cone` does not have a cone implicit target.", spellId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstRankId != spellId)
|
||||||
|
LOG_INFO("server.loading", "Spell (ID:{}) listed in `spell_cone` is not first rank; mapping to first rank {}.", spellId, firstRankId);
|
||||||
|
|
||||||
|
SpellCone sc{};
|
||||||
|
sc.cone_degrees = coneDeg;
|
||||||
|
|
||||||
|
// Avoid overwriting an existing first-rank entry with conflicting values
|
||||||
|
auto itr = mSpellCones.find(firstRankId);
|
||||||
|
if (itr != mSpellCones.end())
|
||||||
|
{
|
||||||
|
if (itr->second.cone_degrees != sc.cone_degrees)
|
||||||
|
LOG_ERROR("sql.sql",
|
||||||
|
"Conflicting `spell_cone` entries for first-rank spell ID {}: {} vs {}. Keeping first value.",
|
||||||
|
firstRankId,
|
||||||
|
itr->second.cone_degrees,
|
||||||
|
sc.cone_degrees);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mSpellCones[firstRankId] = sc;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
} while (result->NextRow());
|
||||||
|
|
||||||
|
LOG_INFO("server.loading", ">> Loaded {} Spell Cone definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||||
|
LOG_INFO("server.loading", " ");
|
||||||
|
}
|
||||||
|
|
||||||
void SpellMgr::LoadSpellGroups()
|
void SpellMgr::LoadSpellGroups()
|
||||||
{
|
{
|
||||||
uint32 oldMSTime = getMSTime();
|
uint32 oldMSTime = getMSTime();
|
||||||
|
|||||||
@@ -393,6 +393,13 @@ struct SpellTargetPosition
|
|||||||
|
|
||||||
typedef std::map<std::pair<uint32 /*spell_id*/, SpellEffIndex /*effIndex*/>, SpellTargetPosition> SpellTargetPositionMap;
|
typedef std::map<std::pair<uint32 /*spell_id*/, SpellEffIndex /*effIndex*/>, SpellTargetPosition> SpellTargetPositionMap;
|
||||||
|
|
||||||
|
struct SpellCone
|
||||||
|
{
|
||||||
|
int16_t cone_degrees;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<uint32 /*spell_id*/, SpellCone> SpellConeMap;
|
||||||
|
|
||||||
// Enum with EffectRadiusIndex and their actual radius
|
// Enum with EffectRadiusIndex and their actual radius
|
||||||
enum EffectRadiusIndex
|
enum EffectRadiusIndex
|
||||||
{
|
{
|
||||||
@@ -683,6 +690,7 @@ public:
|
|||||||
|
|
||||||
// Spell target coordinates
|
// Spell target coordinates
|
||||||
[[nodiscard]] SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id, SpellEffIndex effIndex) const;
|
[[nodiscard]] SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id, SpellEffIndex effIndex) const;
|
||||||
|
[[nodiscard]] SpellCone const* GetSpellCone(uint32 spell_id) const;
|
||||||
|
|
||||||
// Spell Groups table
|
// Spell Groups table
|
||||||
SpellSpellGroupMapBounds GetSpellSpellGroupMapBounds(uint32 spell_id) const;
|
SpellSpellGroupMapBounds GetSpellSpellGroupMapBounds(uint32 spell_id) const;
|
||||||
@@ -775,6 +783,7 @@ public:
|
|||||||
void LoadSpellRequired();
|
void LoadSpellRequired();
|
||||||
void LoadSpellLearnSkills();
|
void LoadSpellLearnSkills();
|
||||||
void LoadSpellTargetPositions();
|
void LoadSpellTargetPositions();
|
||||||
|
void LoadSpellCones();
|
||||||
void LoadSpellGroups();
|
void LoadSpellGroups();
|
||||||
void LoadSpellGroupStackRules();
|
void LoadSpellGroupStackRules();
|
||||||
void LoadSpellProcs();
|
void LoadSpellProcs();
|
||||||
@@ -807,6 +816,7 @@ private:
|
|||||||
SpellRequiredMap mSpellReq;
|
SpellRequiredMap mSpellReq;
|
||||||
SpellLearnSkillMap mSpellLearnSkills;
|
SpellLearnSkillMap mSpellLearnSkills;
|
||||||
SpellTargetPositionMap mSpellTargetPositions;
|
SpellTargetPositionMap mSpellTargetPositions;
|
||||||
|
SpellConeMap mSpellCones;
|
||||||
SpellSpellGroupMap mSpellSpellGroup;
|
SpellSpellGroupMap mSpellSpellGroup;
|
||||||
SpellGroupSpellMap mSpellGroupSpell;
|
SpellGroupSpellMap mSpellGroupSpell;
|
||||||
SpellGroupStackMap mSpellGroupStack;
|
SpellGroupStackMap mSpellGroupStack;
|
||||||
|
|||||||
@@ -682,6 +682,9 @@ void World::SetInitialWorldSettings()
|
|||||||
LOG_INFO("server.loading", "Loading Spell Target Coordinates...");
|
LOG_INFO("server.loading", "Loading Spell Target Coordinates...");
|
||||||
sSpellMgr->LoadSpellTargetPositions();
|
sSpellMgr->LoadSpellTargetPositions();
|
||||||
|
|
||||||
|
LOG_INFO("server.loading", "Loading Spell Cone definitions...");
|
||||||
|
sSpellMgr->LoadSpellCones();
|
||||||
|
|
||||||
LOG_INFO("server.loading", "Loading Enchant Custom Attributes...");
|
LOG_INFO("server.loading", "Loading Enchant Custom Attributes...");
|
||||||
sSpellMgr->LoadEnchantCustomAttr();
|
sSpellMgr->LoadEnchantCustomAttr();
|
||||||
|
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ public:
|
|||||||
{ "spell_proc", HandleReloadSpellProcsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_PROC, Console::Yes },
|
{ "spell_proc", HandleReloadSpellProcsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_PROC, Console::Yes },
|
||||||
{ "spell_scripts", HandleReloadSpellScriptsCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes },
|
{ "spell_scripts", HandleReloadSpellScriptsCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes },
|
||||||
{ "spell_target_position", HandleReloadSpellTargetPositionCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_TARGET_POSITION, Console::Yes },
|
{ "spell_target_position", HandleReloadSpellTargetPositionCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_TARGET_POSITION, Console::Yes },
|
||||||
|
{ "spell_cone", HandleReloadSpellConeCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_TARGET_POSITION, Console::Yes },
|
||||||
{ "spell_threats", HandleReloadSpellThreatsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_THREATS, Console::Yes },
|
{ "spell_threats", HandleReloadSpellThreatsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_THREATS, Console::Yes },
|
||||||
{ "spell_group_stack_rules", HandleReloadSpellGroupStackRulesCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP_STACK_RULES, Console::Yes },
|
{ "spell_group_stack_rules", HandleReloadSpellGroupStackRulesCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP_STACK_RULES, Console::Yes },
|
||||||
{ "player_loot_template", HandleReloadLootTemplatesPlayerCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes },
|
{ "player_loot_template", HandleReloadLootTemplatesPlayerCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes },
|
||||||
@@ -936,6 +937,14 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool HandleReloadSpellConeCommand(ChatHandler* handler)
|
||||||
|
{
|
||||||
|
LOG_INFO("server.loading", "Reloading Spell cone definitions...");
|
||||||
|
sSpellMgr->LoadSpellCones();
|
||||||
|
handler->SendGlobalGMSysMessage("DB table `spell_cone` reloaded.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool HandleReloadSpellThreatsCommand(ChatHandler* handler)
|
static bool HandleReloadSpellThreatsCommand(ChatHandler* handler)
|
||||||
{
|
{
|
||||||
LOG_INFO("server.loading", "Reloading Aggro Spells Definitions...");
|
LOG_INFO("server.loading", "Reloading Aggro Spells Definitions...");
|
||||||
|
|||||||
Reference in New Issue
Block a user