From 18436298f43372edef32587ed1bf6e6f625c200c Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 6 May 2025 19:22:21 +0200 Subject: Core/Spells: Implemented new SpellMisc field, MinDuration that controls minimum spell missile travel time (cherry picked from commit a63d404e7bf2dce3b15ce5f66ac98fe71a41f51c) --- src/server/game/Entities/Object/Object.cpp | 4 ++-- src/server/game/Spells/Spell.cpp | 28 ++++++++++++++-------------- src/server/game/Spells/SpellInfo.cpp | 1 + src/server/game/Spells/SpellInfo.h | 1 + 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index bb0f465671c..50f6d691717 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -3380,9 +3380,9 @@ Unit* WorldObject::GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spel // Set up missile speed based delay float hitDelay = spellInfo->LaunchDelay; if (spellInfo->HasAttribute(SPELL_ATTR9_MISSILE_SPEED_IS_DELAY_IN_SEC)) - hitDelay += spellInfo->Speed; + hitDelay += std::max(spellInfo->Speed, spellInfo->MinDuration); else if (spellInfo->Speed > 0.0f) - hitDelay += std::max(victim->GetDistance(this), 5.0f) / spellInfo->Speed; + hitDelay += std::max(std::max(victim->GetDistance(this), 5.0f) / spellInfo->Speed, spellInfo->MinDuration); uint32 delay = uint32(std::floor(hitDelay * 1000.0f)); // Schedule charge drop diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index b697a8e2a04..c33c6c04f2b 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -826,15 +826,15 @@ uint64 Spell::CalculateDelayMomentForDst(float launchDelay) const { float speed = m_targets.GetSpeedXY(); if (speed > 0.0f) - return uint64(std::floor((m_targets.GetDist2d() / speed + launchDelay) * 1000.0f)); + return uint64(std::floor((std::max(m_targets.GetDist2d() / speed, m_spellInfo->MinDuration) + launchDelay) * 1000.0f)); } else if (m_spellInfo->HasAttribute(SPELL_ATTR9_MISSILE_SPEED_IS_DELAY_IN_SEC)) - return uint64(std::floor((m_spellInfo->Speed + launchDelay) * 1000.0f)); + return uint64(std::floor((std::max(m_spellInfo->Speed, m_spellInfo->MinDuration) + launchDelay) * 1000.0f)); else if (m_spellInfo->Speed > 0.0f) { // We should not subtract caster size from dist calculation (fixes execution time desync with animation on client, eg. Malleable Goo cast by PP) float dist = m_caster->GetExactDist(*m_targets.GetDstPos()); - return uint64(std::floor((dist / m_spellInfo->Speed + launchDelay) * 1000.0f)); + return uint64(std::floor((std::max(dist / m_spellInfo->Speed, m_spellInfo->MinDuration) + launchDelay) * 1000.0f)); } return uint64(std::floor(launchDelay * 1000.0f)); @@ -2425,7 +2425,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= ObjectGuid targetGUID = target->GetGUID(); // Lookup target in already in list - auto ihit = std::find_if(std::begin(m_UniqueTargetInfo), std::end(m_UniqueTargetInfo), [targetGUID](TargetInfo const& target) { return target.TargetGUID == targetGUID; }); + auto ihit = std::ranges::find(m_UniqueTargetInfo, targetGUID, &TargetInfo::TargetGUID); if (ihit != std::end(m_UniqueTargetInfo)) // Found in list { // Immune effects removed from mask @@ -2456,7 +2456,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= WorldObject const* missileSource = m_caster; if (m_spellInfo->HasAttribute(SPELL_ATTR4_BOUNCY_CHAIN_MISSILES)) { - auto previousTargetItr = std::find_if(m_UniqueTargetInfo.rbegin(), m_UniqueTargetInfo.rend(), [effectMask](TargetInfo const& target) + auto previousTargetItr = std::ranges::find_if(m_UniqueTargetInfo.rbegin(), m_UniqueTargetInfo.rend(), [effectMask](TargetInfo const& target) { return (target.EffectMask & effectMask) != 0; }); @@ -2472,13 +2472,13 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= } if (m_spellInfo->HasAttribute(SPELL_ATTR9_MISSILE_SPEED_IS_DELAY_IN_SEC)) - hitDelay += m_spellInfo->Speed; + hitDelay += std::max(m_spellInfo->Speed, m_spellInfo->MinDuration); else if (m_spellInfo->Speed > 0.0f) { // calculate spell incoming interval /// @todo this is a hack float dist = std::max(missileSource->GetDistance(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()), 5.0f); - hitDelay += dist / m_spellInfo->Speed; + hitDelay += std::max(dist / m_spellInfo->Speed, m_spellInfo->MinDuration); } targetInfo.TimeDelay += uint64(std::floor(hitDelay * 1000.0f)); @@ -2523,7 +2523,7 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask) ObjectGuid targetGUID = go->GetGUID(); // Lookup target in already in list - auto ihit = std::find_if(std::begin(m_UniqueGOTargetInfo), std::end(m_UniqueGOTargetInfo), [targetGUID](GOTargetInfo const& target) { return target.TargetGUID == targetGUID; }); + auto ihit = std::ranges::find(m_UniqueGOTargetInfo, targetGUID, &GOTargetInfo::TargetGUID); if (ihit != std::end(m_UniqueGOTargetInfo)) // Found in list { // Add only effect mask @@ -2542,12 +2542,12 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask) { float hitDelay = m_spellInfo->LaunchDelay; if (m_spellInfo->HasAttribute(SPELL_ATTR9_MISSILE_SPEED_IS_DELAY_IN_SEC)) - hitDelay += m_spellInfo->Speed; + hitDelay += std::max(m_spellInfo->Speed, m_spellInfo->MinDuration); else if (m_spellInfo->Speed > 0.0f) { // calculate spell incoming interval float dist = std::max(m_caster->GetDistance(go->GetPositionX(), go->GetPositionY(), go->GetPositionZ()), 5.0f); - hitDelay += dist / m_spellInfo->Speed; + hitDelay += std::max(dist / m_spellInfo->Speed, m_spellInfo->MinDuration); } target.TimeDelay = uint64(std::floor(hitDelay * 1000.0f)); @@ -2574,7 +2574,7 @@ void Spell::AddItemTarget(Item* item, uint32 effectMask) return; // Lookup target in already in list - auto ihit = std::find_if(std::begin(m_UniqueItemInfo), std::end(m_UniqueItemInfo), [item](ItemTargetInfo const& target) { return target.TargetItem == item; }); + auto ihit = std::ranges::find(m_UniqueItemInfo, item, &ItemTargetInfo::TargetItem); if (ihit != std::end(m_UniqueItemInfo)) // Found in list { // Add only effect mask @@ -2604,7 +2604,7 @@ void Spell::AddCorpseTarget(Corpse* corpse, uint32 effectMask) ObjectGuid targetGUID = corpse->GetGUID(); // Lookup target in already in list - auto ihit = std::find_if(std::begin(m_UniqueCorpseTargetInfo), std::end(m_UniqueCorpseTargetInfo), [targetGUID](CorpseTargetInfo const& target) { return target.TargetGUID == targetGUID; }); + auto ihit = std::ranges::find(m_UniqueCorpseTargetInfo, targetGUID, &CorpseTargetInfo::TargetGUID); if (ihit != std::end(m_UniqueCorpseTargetInfo)) // Found in list { // Add only effect mask @@ -2622,12 +2622,12 @@ void Spell::AddCorpseTarget(Corpse* corpse, uint32 effectMask) { float hitDelay = m_spellInfo->LaunchDelay; if (m_spellInfo->HasAttribute(SPELL_ATTR9_MISSILE_SPEED_IS_DELAY_IN_SEC)) - hitDelay += m_spellInfo->Speed; + hitDelay += std::max(m_spellInfo->Speed, m_spellInfo->MinDuration); else if (m_spellInfo->Speed > 0.0f) { // calculate spell incoming interval float dist = std::max(m_caster->GetDistance(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ()), 5.0f); - hitDelay += dist / m_spellInfo->Speed; + hitDelay += std::max(dist / m_spellInfo->Speed, m_spellInfo->MinDuration); } target.TimeDelay = uint64(std::floor(hitDelay * 1000.0f)); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 378c89eee45..5100e50f278 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1226,6 +1226,7 @@ SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, S RangeEntry = sSpellRangeStore.LookupEntry(_misc->RangeIndex); Speed = _misc->Speed; LaunchDelay = _misc->LaunchDelay; + MinDuration = _misc->MinDuration; SchoolMask = _misc->SchoolMask; IconFileDataId = _misc->SpellIconFileDataID; ActiveIconFileDataId = _misc->ActiveIconFileDataID; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 304cdf0c968..8d7cbefc396 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -382,6 +382,7 @@ class TC_GAME_API SpellInfo SpellRangeEntry const* RangeEntry = nullptr; float Speed = 0.0f; float LaunchDelay = 0.0f; + float MinDuration = 0.0f; uint32 StackAmount = 0; std::array Totem = {}; std::array TotemCategory = {}; -- cgit v1.2.3