From b2af17eb4a01c518f3913293c4dfee7d2f142db9 Mon Sep 17 00:00:00 2001 From: NoName <322016+Faq@users.noreply.github.com> Date: Sun, 29 Mar 2020 16:23:47 +0200 Subject: [PATCH] Core/Spell: Proper SPELL_EFFECT_PULL_TOWARDS_DEST implementation for players * Core/Spell: SPELL_EFFECT_PULL_TOWARDS correction --- src/server/game/Entities/Object/Position.h | 7 +--- src/server/game/Entities/Unit/Unit.cpp | 9 +++-- src/server/game/Entities/Unit/Unit.h | 2 +- src/server/game/Spells/Spell.h | 1 + src/server/game/Spells/SpellEffects.cpp | 46 +++++++++++++++------- 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h index a2deed80ad2..5d8d8cd04e0 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -189,11 +189,8 @@ public: return GetAngle(pos.m_positionX, pos.m_positionY); } float GetAngle(float x, float y) const; - float GetRelativeAngle(Position const* pos) const - { - return GetAngle(pos) - m_orientation; - } - + float GetRelativeAngle(Position const* pos) const { return GetAngle(pos) - m_orientation; } + float GetRelativeAngle(Position const& pos) const { return GetAngle(pos) - m_orientation; } float GetRelativeAngle(float x, float y) const { return GetAngle(x, y) - m_orientation; } void GetSinCos(float x, float y, float &vsin, float &vcos) const; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index b4c4d431f89..a2dd3c07cb2 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -13274,15 +13274,18 @@ uint32 Unit::GetModelForTotem(PlayerTotemType totemType) return 0; } -void Unit::JumpTo(float speedXY, float speedZ, bool forward) +void Unit::JumpTo(float speedXY, float speedZ, bool forward, Optional dest) { float angle = forward ? 0 : float(M_PI); + if (dest) + angle += GetRelativeAngle(*dest); + if (GetTypeId() == TYPEID_UNIT) GetMotionMaster()->MoveJumpTo(angle, speedXY, speedZ); else { - float vcos = std::cos(angle+GetOrientation()); - float vsin = std::sin(angle+GetOrientation()); + float vcos = std::cos(angle + GetOrientation()); + float vsin = std::sin(angle + GetOrientation()); SendMoveKnockBack(ToPlayer(), speedXY, -speedZ, vcos, vsin); } } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 497e9df3015..276d2778b03 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1323,7 +1323,7 @@ class TC_GAME_API Unit : public WorldObject void SendMoveKnockBack(Player* player, float speedXY, float speedZ, float vcos, float vsin); void KnockbackFrom(float x, float y, float speedXY, float speedZ); - void JumpTo(float speedXY, float speedZ, bool forward = true); + void JumpTo(float speedXY, float speedZ, bool forward = true, Optional dest = {}); void JumpTo(WorldObject* obj, float speedZ, bool withOrientation = false); void MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath = false, bool forceDestination = false); diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 578a6328abb..deca66d42ee 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -352,6 +352,7 @@ class TC_GAME_API Spell void EffectSummonCritter(SpellEffIndex effIndex); void EffectKnockBack(SpellEffIndex effIndex); void EffectPullTowards(SpellEffIndex effIndex); + void EffectPullTowardsDest(SpellEffIndex effIndex); void EffectDispelMechanic(SpellEffIndex effIndex); void EffectResurrectPet(SpellEffIndex effIndex); void EffectDestroyAllTotems(SpellEffIndex effIndex); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index cdecd9e355c..138be9b16f2 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -213,7 +213,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectTriggerSpell, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER &Spell::EffectKnockBack, //144 SPELL_EFFECT_KNOCK_BACK_DEST - &Spell::EffectPullTowards, //145 SPELL_EFFECT_PULL_TOWARDS_DEST Black Hole Effect + &Spell::EffectPullTowardsDest, //145 SPELL_EFFECT_PULL_TOWARDS_DEST Black Hole Effect &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail &Spell::EffectTriggerMissileSpell, //148 SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE @@ -4553,22 +4553,40 @@ void Spell::EffectPullTowards(SpellEffIndex effIndex) if (!unitTarget) return; - Position pos; - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_PULL_TOWARDS_DEST) + Position pos = m_caster->GetFirstCollisionPosition(m_caster->GetCombatReach(), m_caster->GetRelativeAngle(unitTarget)); + + // This is a blizzlike mistake: this should be 2D distance according to projectile motion formulas, but Blizzard erroneously used 3D distance. + float distXY = unitTarget->GetExactDist(pos); + float distZ = pos.GetPositionZ() - unitTarget->GetPositionZ(); + float speedXY = m_spellInfo->Effects[effIndex].MiscValue ? m_spellInfo->Effects[effIndex].MiscValue / 10.0f : 30.0f; + float speedZ = (2 * speedXY * speedXY * distZ + Movement::gravity * distXY * distXY) / (2 * speedXY * distXY); + + unitTarget->JumpTo(speedXY, speedZ, true, pos); +} + +void Spell::EffectPullTowardsDest(SpellEffIndex effIndex) +{ + if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) + return; + + if (!unitTarget) + return; + + if (!m_targets.HasDst()) { - if (m_targets.HasDst()) - pos.Relocate(*destTarget); - else - return; - } - else //if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_PULL_TOWARDS) - { - pos.Relocate(m_caster); + TC_LOG_ERROR("spells", "Spell %u with SPELL_EFFECT_PULL_TOWARDS_DEST has no dest target", m_spellInfo->Id); + return; } - float speedXY, speedZ; - CalculateJumpSpeeds(effIndex, m_caster->GetExactDist2d(pos), speedXY, speedZ); - unitTarget->GetMotionMaster()->MoveJump(pos, speedXY, speedZ); + Position const* pos = m_targets.GetDstPos(); + // This is a blizzlike mistake: this should be 2D distance according to projectile motion formulas, but Blizzard erroneously used 3D distance + float distXY = unitTarget->GetExactDist(pos); + float distZ = pos->GetPositionZ() - unitTarget->GetPositionZ(); + + float speedXY = m_spellInfo->Effects[effIndex].MiscValue / 10.0f; + float speedZ = (2 * speedXY * speedXY * distZ + Movement::gravity * distXY * distXY) / (2 * speedXY * distXY); + + unitTarget->JumpTo(speedXY, speedZ, true, *pos); } void Spell::EffectDispelMechanic(SpellEffIndex effIndex)