fix(Core/Spells): Implement spell_jump_distance (#25023)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Andrew
2026-03-10 22:09:26 -03:00
committed by GitHub
parent 6ffe41dd59
commit 46b48cdfa0
7 changed files with 57 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
--
CREATE TABLE IF NOT EXISTS `spell_jump_distance` (
`ID` int unsigned NOT NULL COMMENT 'spell id',
`JumpDistance` float NOT NULL DEFAULT '0' COMMENT 'max hop distance in yards',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Per-spell chain jump distance override';
DELETE FROM `spell_jump_distance` WHERE `ID` IN (62131, 64390);
INSERT INTO `spell_jump_distance` (`ID`, `JumpDistance`) VALUES
(62131, 5.0),
(64390, 5.0);

View File

@@ -2126,6 +2126,10 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
break;
}
// per-spell override from spell_jump_distance table
if (m_spellInfo->JumpDistance > 0.0f)
jumpRadius = m_spellInfo->JumpDistance;
// chain lightning/heal spells and similar - allow to jump at larger distance and go out of los
bool isBouncingFar = (m_spellInfo->HasAttribute(SPELL_ATTR4_BOUNCY_CHAIN_MISSILES)
|| m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE

View File

@@ -861,6 +861,7 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry)
_isSpellValid = true;
_isCritCapable = false;
_requireCooldownInfo = false;
JumpDistance = 0.0f;
}
SpellInfo::~SpellInfo()

View File

@@ -401,6 +401,7 @@ public:
bool _isSpellValid;
bool _isCritCapable;
bool _requireCooldownInfo;
float JumpDistance;
SpellInfo(SpellEntry const* spellEntry);
~SpellInfo();

View File

@@ -2957,6 +2957,42 @@ void SpellMgr::LoadSpellSpecificAndAuraState()
LOG_INFO("server.loading", " ");
}
void SpellMgr::LoadSpellJumpDistances()
{
uint32 oldMSTime = getMSTime();
QueryResult result = WorldDatabase.Query("SELECT ID, JumpDistance FROM spell_jump_distance");
if (!result)
{
LOG_WARN("server.loading", ">> Loaded 0 spell jump distances. DB table `spell_jump_distance` is empty.");
LOG_INFO("server.loading", " ");
return;
}
uint32 count = 0;
do
{
Field const* fields = result->Fetch();
uint32 const spellId = fields[0].Get<uint32>();
float const jumpDistance = fields[1].Get<float>();
SpellInfo* spellInfo = _GetSpellInfo(spellId);
if (!spellInfo)
{
LOG_ERROR("sql.sql", "Table `spell_jump_distance` has wrong spell (spell_id: {}), ignored.", spellId);
continue;
}
spellInfo->JumpDistance = jumpDistance;
++count;
} while (result->NextRow());
LOG_INFO("server.loading", ">> Loaded {} spell jump distances in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
}
void SpellMgr::LoadSpellInfoCustomAttributes()
{
uint32 const oldMSTime = getMSTime();

View File

@@ -778,6 +778,7 @@ public:
void LoadSpellInfoCustomAttributes();
void LoadSpellInfoCorrections();
void LoadSpellSpecificAndAuraState();
void LoadSpellJumpDistances();
private:
SpellDifficultySearcherMap mSpellDifficultySearcherMap;

View File

@@ -433,6 +433,9 @@ void World::SetInitialWorldSettings()
LOG_INFO("server.loading", "Loading SpellInfo Custom Attributes...");
sSpellMgr->LoadSpellInfoCustomAttributes();
LOG_INFO("server.loading", "Loading Spell Jump Distances...");
sSpellMgr->LoadSpellJumpDistances();
LOG_INFO("server.loading", "Loading Player Totem models...");
sObjectMgr->LoadPlayerTotemModels();