spell and solo lfg fix
This commit is contained in:
@@ -462,7 +462,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
|
||||
return LFG_COMPATIBLES_WITH_LESS_PLAYERS;
|
||||
}
|
||||
|
||||
if (check.size() == 1 && numPlayers != MAX_GROUP_SIZE && !hasFollowerDungeon)
|
||||
if (!sLFGMgr->IsSoloLFG() && !forceMinPlayers && check.size() == 1 && numPlayers != MAX_GROUP_SIZE && !hasFollowerDungeon)
|
||||
{
|
||||
TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) single group. Compatibles", GetDetailedMatchRoles(check));
|
||||
LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(check.front());
|
||||
|
||||
@@ -3623,12 +3623,46 @@ void Unit::_ApplyAuraEffect(Aura* aura, uint8 effIndex)
|
||||
aurApp->_HandleEffect(effIndex, true);
|
||||
}
|
||||
|
||||
//WowCommunity
|
||||
|
||||
namespace
|
||||
{
|
||||
// RAII helper: while a Fel Rush style dash bundle is being (un)applied we suppress the
|
||||
// per-effect UpdateSpeed calls so the whole bundle lands in one movement transaction,
|
||||
// then flush once on scope exit (see Unit::EndDeferDashMovementSpeedUpdates).
|
||||
struct DashSpeedUpdateDeferGuard
|
||||
{
|
||||
Unit* UnitPtr;
|
||||
bool Active;
|
||||
|
||||
DashSpeedUpdateDeferGuard(Unit* unit, bool active) : UnitPtr(unit), Active(active)
|
||||
{
|
||||
if (Active)
|
||||
UnitPtr->BeginDeferDashMovementSpeedUpdates();
|
||||
}
|
||||
|
||||
DashSpeedUpdateDeferGuard(DashSpeedUpdateDeferGuard const&) = delete;
|
||||
DashSpeedUpdateDeferGuard& operator=(DashSpeedUpdateDeferGuard const&) = delete;
|
||||
|
||||
~DashSpeedUpdateDeferGuard()
|
||||
{
|
||||
if (Active)
|
||||
UnitPtr->EndDeferDashMovementSpeedUpdates();
|
||||
}
|
||||
};
|
||||
}
|
||||
//WowCommunity
|
||||
|
||||
// handles effects of aura application
|
||||
// should be done after registering aura in lists
|
||||
void Unit::_ApplyAura(AuraApplication* aurApp, uint32 effMask)
|
||||
{
|
||||
Aura* aura = aurApp->GetBase();
|
||||
|
||||
//WowCommunity
|
||||
DashSpeedUpdateDeferGuard deferGuard(this, GetTypeId() == TYPEID_PLAYER && aura->GetSpellInfo()->IsDashMovementBundle());
|
||||
//WowCommunity
|
||||
|
||||
_RemoveNoStackAurasDueToAura(aura, false);
|
||||
|
||||
if (aurApp->GetRemoveMode())
|
||||
@@ -3732,6 +3766,10 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator& i, AuraRemoveMode removeMo
|
||||
aurApp->_Remove();
|
||||
aura->_UnapplyForTarget(this, caster, aurApp);
|
||||
|
||||
//WowCommunity
|
||||
DashSpeedUpdateDeferGuard deferGuard(this, GetTypeId() == TYPEID_PLAYER && aura->GetSpellInfo()->IsDashMovementBundle());
|
||||
//WowCommunity
|
||||
|
||||
// remove effects of the spell - needs to be done after removing aura from lists
|
||||
for (AuraEffect const* aurEff : aura->GetAuraEffects())
|
||||
if (aurApp->HasEffect(aurEff->GetEffIndex()))
|
||||
@@ -9068,6 +9106,33 @@ void Unit::UpdateSpeed(UnitMoveType mtype)
|
||||
speed = min_speed;
|
||||
}
|
||||
|
||||
//WowCommunity
|
||||
// SPELL_AURA_MOD_SPEED_NO_CONTROL: dash abilities push an absolute yards/sec floor through
|
||||
// SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED instead of a percentage speed mod.
|
||||
// Threshold note (UNVERIFIED, inherited from the source branch): Fel Rush is reported to use a
|
||||
// 66 yd/s floor while Monk Roll's aura 191 value (~35) is a cap only, hence only normalization
|
||||
// values at or above 60 yd/s are treated as a forced floor. Needs an in-game/sniff re-check.
|
||||
if (GetMaxPositiveAuraModifier(SPELL_AURA_MOD_SPEED_NO_CONTROL))
|
||||
{
|
||||
if (mtype == MOVE_RUN || mtype == MOVE_RUN_BACK || mtype == MOVE_WALK)
|
||||
{
|
||||
if (float normalization = GetMaxPositiveAuraModifier(SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED))
|
||||
{
|
||||
float constexpr felRushNormalizationYardsPerSec = 60.0f;
|
||||
if (normalization >= felRushNormalizationYardsPerSec)
|
||||
{
|
||||
float baseSpeed = IsControlledByPlayer() ? playerBaseMoveSpeed[mtype] : baseMoveSpeed[mtype];
|
||||
if (baseSpeed > 0.0f)
|
||||
{
|
||||
float forcedRate = normalization / baseSpeed;
|
||||
if (speed < forcedRate)
|
||||
speed = forcedRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//WowCommunity
|
||||
SetSpeedRate(mtype, speed);
|
||||
}
|
||||
|
||||
@@ -15582,3 +15647,91 @@ void Unit::GetAttackableUnitListInRange(std::list<Unit*>& list, float fMaxSearch
|
||||
cell.Visit(p, world_unit_searcher, *GetMap(), *this, fMaxSearchRange);
|
||||
cell.Visit(p, grid_unit_searcher, *GetMap(), *this, fMaxSearchRange);
|
||||
}
|
||||
|
||||
void Unit::BeginDeferDashMovementSpeedUpdates()
|
||||
{
|
||||
++_deferDashMovementSpeedUpdates;
|
||||
_dashMovementSpeedUpdatesFinalized = false;
|
||||
}
|
||||
|
||||
void Unit::EndDeferDashMovementSpeedUpdates()
|
||||
{
|
||||
ASSERT(_deferDashMovementSpeedUpdates > 0);
|
||||
--_deferDashMovementSpeedUpdates;
|
||||
|
||||
if (_deferDashMovementSpeedUpdates == 0)
|
||||
{
|
||||
if (!_dashMovementSpeedUpdatesFinalized)
|
||||
{
|
||||
UpdateSpeed(MOVE_RUN);
|
||||
UpdateSpeed(MOVE_RUN_BACK);
|
||||
UpdateSpeed(MOVE_WALK);
|
||||
UpdateSpeed(MOVE_SWIM);
|
||||
UpdateSpeed(MOVE_FLIGHT);
|
||||
}
|
||||
|
||||
RestoreDeferredDashGravity();
|
||||
_dashMovementSpeedUpdatesFinalized = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::PrepareDashMovementState()
|
||||
{
|
||||
// Matches the client's gravity-disable acknowledgement during a dash: moving Forward with
|
||||
// gravity off and no horizontal fall carry (HasFallDirection false).
|
||||
m_movementInfo.jump.sinAngle = 0.0f;
|
||||
m_movementInfo.jump.cosAngle = 0.0f;
|
||||
m_movementInfo.jump.xyspeed = 0.0f;
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR);
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_FORWARD);
|
||||
}
|
||||
|
||||
void Unit::FinalizeDashMovementSpeedUpdates()
|
||||
{
|
||||
if (_dashMovementSpeedUpdatesFinalized)
|
||||
return;
|
||||
|
||||
_dashMovementSpeedUpdatesFinalized = true;
|
||||
|
||||
PrepareDashMovementState();
|
||||
|
||||
UpdateSpeed(MOVE_RUN);
|
||||
UpdateSpeed(MOVE_RUN_BACK);
|
||||
UpdateSpeed(MOVE_WALK);
|
||||
UpdateSpeed(MOVE_SWIM);
|
||||
UpdateSpeed(MOVE_FLIGHT);
|
||||
}
|
||||
|
||||
void Unit::CleanupDashMovementAfterAuraEnd()
|
||||
{
|
||||
m_movementInfo.jump.Reset();
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR);
|
||||
|
||||
if (Player* playerMover = GetPlayerMovingMe())
|
||||
{
|
||||
WorldPackets::Movement::MoveUpdate moveUpdate;
|
||||
moveUpdate.Status = &m_movementInfo;
|
||||
SendMessageToSet(moveUpdate.Write(), playerMover);
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::DeferDashGravityRestore()
|
||||
{
|
||||
_deferDashGravityRestore = true;
|
||||
}
|
||||
|
||||
void Unit::RestoreDeferredDashGravity()
|
||||
{
|
||||
if (!_deferDashGravityRestore)
|
||||
return;
|
||||
|
||||
_deferDashGravityRestore = false;
|
||||
|
||||
if (HasAuraType(SPELL_AURA_MOD_ROOT_DISABLE_GRAVITY)
|
||||
|| HasAuraType(SPELL_AURA_MOD_STUN_DISABLE_GRAVITY)
|
||||
|| HasAuraType(SPELL_AURA_DISABLE_GRAVITY)
|
||||
|| (IsCreature() && ToCreature()->IsFloating()))
|
||||
return;
|
||||
|
||||
SetDisableGravity(false);
|
||||
}
|
||||
|
||||
@@ -1187,6 +1187,16 @@ class TC_GAME_API Unit : public WorldObject
|
||||
bool SetCanAdvFly(bool enable);
|
||||
bool SetMoveCantSwim(bool cantSwim);
|
||||
void SendSetVehicleRecId(uint32 vehicleId);
|
||||
//WowCommunity
|
||||
void BeginDeferDashMovementSpeedUpdates();
|
||||
void EndDeferDashMovementSpeedUpdates();
|
||||
bool IsDeferringDashMovementSpeedUpdates() const { return _deferDashMovementSpeedUpdates > 0; }
|
||||
void FinalizeDashMovementSpeedUpdates();
|
||||
void PrepareDashMovementState();
|
||||
void CleanupDashMovementAfterAuraEnd();
|
||||
void DeferDashGravityRestore();
|
||||
void RestoreDeferredDashGravity();
|
||||
//WowCommunity
|
||||
|
||||
MovementForces const* GetMovementForces() const { return _movementForces.get(); }
|
||||
void ApplyMovementForce(ObjectGuid id, Position origin, float magnitude, MovementForceType type, Position direction = {}, ObjectGuid transportGuid = ObjectGuid::Empty);
|
||||
@@ -1995,6 +2005,12 @@ class TC_GAME_API Unit : public WorldObject
|
||||
std::array<float, MAX_MOVE_TYPE> m_speed_rate;
|
||||
std::array<float, ADV_FLYING_MAX_SPEED_TYPE> m_advFlyingSpeed;
|
||||
|
||||
//WowCommunity
|
||||
uint32 _deferDashMovementSpeedUpdates = 0;
|
||||
bool _dashMovementSpeedUpdatesFinalized = false;
|
||||
bool _deferDashGravityRestore = false;
|
||||
//WowCommunity
|
||||
|
||||
Unit* m_unitMovedByMe; // only ever set for players, and only for direct client control
|
||||
Player* m_playerMovingMe; // only set for direct client control (possess effects, vehicles and similar)
|
||||
Unit* m_charmer; // Unit that is charming ME
|
||||
|
||||
@@ -457,7 +457,7 @@ enum AuraType : uint32
|
||||
SPELL_AURA_SPELL_OVERRIDE_NAME_GROUP = 370, // picks a random SpellOverrideName id from a group (group id in miscValue)
|
||||
SPELL_AURA_DISABLE_AUTOATTACK = 371,
|
||||
SPELL_AURA_OVERRIDE_MOUNT_FROM_SET = 372, // NYI
|
||||
SPELL_AURA_MOD_SPEED_NO_CONTROL = 373, // NYI
|
||||
SPELL_AURA_MOD_SPEED_NO_CONTROL = 373,
|
||||
SPELL_AURA_MODIFY_FALL_DAMAGE_PCT = 374,
|
||||
SPELL_AURA_HIDE_MODEL_AND_EQUIPEMENT_SLOTS = 375,
|
||||
SPELL_AURA_MOD_CURRENCY_GAIN_FROM_SOURCE = 376, // NYI
|
||||
|
||||
@@ -442,7 +442,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
|
||||
&AuraEffect::HandleNULL, //370 SPELL_AURA_SPELL_OVERRIDE_NAME_GROUP
|
||||
&AuraEffect::HandleNoImmediateEffect, //371 SPELL_AURA_DISABLE_AUTOATTACK implemented in Unit::_UpdateAutoRepeatSpell and Unit::AttackerStateUpdate
|
||||
&AuraEffect::HandleNULL, //372 SPELL_AURA_OVERRIDE_MOUNT_FROM_SET
|
||||
&AuraEffect::HandleNULL, //373 SPELL_AURA_MOD_SPEED_NO_CONTROL
|
||||
&AuraEffect::HandleAuraModSpeedNoControl, //373 SPELL_AURA_MOD_SPEED_NO_CONTROL
|
||||
&AuraEffect::HandleNoImmediateEffect, //374 SPELL_AURA_MODIFY_FALL_DAMAGE_PCT implemented in Player::HandleFall
|
||||
&AuraEffect::HandleNULL, //375 SPELL_AURA_HIDE_MODEL_AND_EQUIPEMENT_SLOTS implemented clientside
|
||||
&AuraEffect::HandleNULL, //376 SPELL_AURA_MOD_CURRENCY_GAIN_FROM_SOURCE
|
||||
@@ -3286,6 +3286,20 @@ static void HandleAuraDisableGravity(Unit* target, bool apply)
|
||||
|| (target->IsCreature() && target->ToCreature()->IsFloating()))
|
||||
return;
|
||||
|
||||
if (target->IsDeferringDashMovementSpeedUpdates())
|
||||
{
|
||||
if (apply)
|
||||
target->FinalizeDashMovementSpeedUpdates();
|
||||
else
|
||||
{
|
||||
// Keep gravity off until the whole dash bundle has been unapplied, otherwise the client
|
||||
// starts falling mid-transaction.
|
||||
target->CleanupDashMovementAfterAuraEnd();
|
||||
target->DeferDashGravityRestore();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (target->SetDisableGravity(apply))
|
||||
if (!apply && !target->IsFlying())
|
||||
target->GetMotionMaster()->MoveFall();
|
||||
@@ -3488,6 +3502,9 @@ void AuraEffect::HandleAuraModIncreaseSpeed(AuraApplication const* aurApp, uint8
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
if (target->IsDeferringDashMovementSpeedUpdates())
|
||||
return;
|
||||
|
||||
target->UpdateSpeed(MOVE_RUN);
|
||||
}
|
||||
|
||||
@@ -3564,11 +3581,31 @@ void AuraEffect::HandleAuraModUseNormalSpeed(AuraApplication const* aurApp, uint
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
if (target->IsDeferringDashMovementSpeedUpdates())
|
||||
return;
|
||||
|
||||
target->UpdateSpeed(MOVE_RUN);
|
||||
target->UpdateSpeed(MOVE_SWIM);
|
||||
target->UpdateSpeed(MOVE_FLIGHT);
|
||||
}
|
||||
|
||||
void AuraEffect::HandleAuraModSpeedNoControl(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
|
||||
{
|
||||
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
|
||||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
if (target->IsDeferringDashMovementSpeedUpdates())
|
||||
return;
|
||||
|
||||
target->UpdateSpeed(MOVE_RUN);
|
||||
target->UpdateSpeed(MOVE_RUN_BACK);
|
||||
target->UpdateSpeed(MOVE_WALK);
|
||||
target->UpdateSpeed(MOVE_SWIM);
|
||||
target->UpdateSpeed(MOVE_FLIGHT);
|
||||
}
|
||||
|
||||
void AuraEffect::HandleAuraModMinimumSpeedRate(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
|
||||
{
|
||||
if (!(mode & AURA_EFFECT_HANDLE_REAL))
|
||||
@@ -3576,6 +3613,9 @@ void AuraEffect::HandleAuraModMinimumSpeedRate(AuraApplication const* aurApp, ui
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
if (target->IsDeferringDashMovementSpeedUpdates())
|
||||
return;
|
||||
|
||||
target->UpdateSpeed(MOVE_RUN);
|
||||
}
|
||||
|
||||
|
||||
@@ -222,6 +222,7 @@ class TC_GAME_API AuraEffect
|
||||
void HandleAuraModIncreaseSwimSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleAuraModDecreaseSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleAuraModUseNormalSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleAuraModSpeedNoControl(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleAuraModMinimumSpeedRate(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleModMovementForceMagnitude(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleAuraModAdvFlyingSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
|
||||
@@ -5158,3 +5158,13 @@ bool SpellInfo::HasLabel(uint32 labelId) const
|
||||
{
|
||||
return Labels.contains(labelId);
|
||||
}
|
||||
|
||||
bool SpellInfo::IsDashMovementBundle() const
|
||||
{
|
||||
// Many spells share HasAura(SPELL_AURA_MOD_SPEED_NO_CONTROL) && HasAura(SPELL_AURA_DISABLE_GRAVITY)
|
||||
// (Evoker Hover, Void Dash, Crane Rush, ...), but FinalizeDashMovementSpeedUpdates and
|
||||
// PrepareDashMovementState model the Fel Rush *air* dash specifically and must not fire on the
|
||||
// others. Keep this an explicit allowlist rather than an aura-shape test.
|
||||
return Id == 197923 // Fel Rush air bundle
|
||||
|| Id == 389659; // Fel Rush air bundle (variant)
|
||||
}
|
||||
|
||||
@@ -454,7 +454,9 @@ public:
|
||||
bool HasAreaAuraEffect() const;
|
||||
bool HasOnlyDamageEffects() const;
|
||||
bool HasTargetType(::Targets target) const;
|
||||
|
||||
//WowCommunity
|
||||
bool IsDashMovementBundle() const;
|
||||
//WowCommunity
|
||||
bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); }
|
||||
bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); }
|
||||
bool HasAttribute(SpellAttr2 attribute) const { return !!(AttributesEx2 & attribute); }
|
||||
|
||||
@@ -5755,6 +5755,25 @@ void SpellMgr::LoadSpellInfoTargetCaps()
|
||||
spellInfo->_LoadSqrtTargetLimit(5, 0, 1226033, EFFECT_0, {}, {});
|
||||
});
|
||||
|
||||
// Fel Rush air dash (197923): the client-side bundle triggers the momentum/dash-end helpers from
|
||||
// effects 8 and 10 while effect 6 points at a dead trigger. UNVERIFIED against a live sniff -
|
||||
// ported from the source branch, re-check the trigger ids if air Fel Rush misbehaves.
|
||||
ApplySpellFix({ 197923 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
ApplySpellEffectFix(spellInfo, EFFECT_6, [](SpellEffectInfo* spellEffectInfo)
|
||||
{
|
||||
spellEffectInfo->TriggerSpell = 0;
|
||||
});
|
||||
ApplySpellEffectFix(spellInfo, EFFECT_8, [](SpellEffectInfo* spellEffectInfo)
|
||||
{
|
||||
spellEffectInfo->TriggerSpell = 199737;
|
||||
});
|
||||
ApplySpellEffectFix(spellInfo, EFFECT_10, [](SpellEffectInfo* spellEffectInfo)
|
||||
{
|
||||
spellEffectInfo->TriggerSpell = 346123;
|
||||
});
|
||||
});
|
||||
|
||||
TC_LOG_INFO("server.loading", ">> Loaded SpellInfo target caps in {} ms", GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
|
||||
@@ -3182,6 +3182,135 @@ class spell_dh_collapsing_star_damage : public SpellScript
|
||||
int32 _apocalypsePct = 0;
|
||||
};
|
||||
|
||||
|
||||
// 195072 - Fel Rush
|
||||
class spell_dh_fel_rush : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DH_FEL_RUSH_GROUND, SPELL_DH_FEL_RUSH_WATER_AIR, SPELL_DH_FEL_RUSH_DMG,
|
||||
SPELL_DH_GLIDE, SPELL_DH_GLIDE_DURATION });
|
||||
}
|
||||
|
||||
SpellCastResult CheckCast()
|
||||
{
|
||||
if (GetCaster()->HasUnitState(UNIT_STATE_ROOT))
|
||||
return SPELL_FAILED_ROOTED;
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
void CastPathDamage() const
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
|
||||
float dashDistance = float(GetEffectInfo(EFFECT_0).CalcValue(caster));
|
||||
if (dashDistance <= 0.0f)
|
||||
return;
|
||||
|
||||
caster->CastSpell(caster->GetFirstCollisionPosition(dashDistance, 0.0f), SPELL_DH_FEL_RUSH_DMG, CastSpellExtraArgsInit{
|
||||
.TriggerFlags = TRIGGERED_FULL_MASK,
|
||||
.TriggeringSpell = GetSpell()
|
||||
});
|
||||
}
|
||||
|
||||
void PrepareDash(Unit* caster) const
|
||||
{
|
||||
caster->RemoveAurasDueToSpell(SPELL_DH_GLIDE);
|
||||
caster->RemoveAurasDueToSpell(SPELL_DH_GLIDE_DURATION);
|
||||
caster->m_movementInfo.inertia.reset();
|
||||
caster->m_movementInfo.advFlying.reset();
|
||||
|
||||
if (Player* player = caster->ToPlayer())
|
||||
{
|
||||
// Mirror of the 250 ms Fel Rush lockout spell_dh_glide starts, in the other direction.
|
||||
player->GetSpellHistory()->StartCooldown(sSpellMgr->AssertSpellInfo(SPELL_DH_GLIDE, GetCastDifficulty()), 0, nullptr, false, 250ms);
|
||||
player->UpdateSpeed(MOVE_FLIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleGroundDash(SpellEffIndex /*effIndex*/) const
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (caster->IsFalling() && !caster->IsInWater())
|
||||
return;
|
||||
|
||||
CastPathDamage();
|
||||
PrepareDash(caster);
|
||||
|
||||
caster->CastSpell(caster, SPELL_DH_FEL_RUSH_GROUND, CastSpellExtraArgsInit{
|
||||
.TriggerFlags = TRIGGERED_FULL_MASK,
|
||||
.TriggeringSpell = GetSpell()
|
||||
});
|
||||
}
|
||||
|
||||
void HandleAirDash(SpellEffIndex /*effIndex*/) const
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster->IsFalling() || caster->IsInWater())
|
||||
return;
|
||||
|
||||
CastPathDamage();
|
||||
PrepareDash(caster);
|
||||
|
||||
caster->CastSpell(caster, SPELL_DH_FEL_RUSH_WATER_AIR, CastSpellExtraArgsInit{
|
||||
.TriggerFlags = TRIGGERED_FULL_MASK,
|
||||
.TriggeringSpell = GetSpell()
|
||||
});
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnCheckCast += SpellCheckCastFn(spell_dh_fel_rush::CheckCast);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_dh_fel_rush::HandleGroundDash, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_dh_fel_rush::HandleAirDash, EFFECT_1, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 197922 - Fel Rush (ground dash bundle)
|
||||
// 197923 - Fel Rush (air / water dash bundle)
|
||||
class spell_dh_fel_rush_aura : public AuraScript
|
||||
{
|
||||
// EFFECT_5 on 197922 is SPELL_AURA_MECHANIC_IMMUNITY with base points 0; the dash is supposed to
|
||||
// shed the mechanic rather than grant immunity to it, so the amount is driven negative.
|
||||
void CalcImmunityAmount(AuraEffect const* /*aurEff*/, SpellEffectValue& amount, bool& /*canBeRecalculated*/) const
|
||||
{
|
||||
amount -= 100.0f;
|
||||
}
|
||||
|
||||
// While the dash owns movement the run-back speed must not be touched - the dash engine batches
|
||||
// the speed updates itself and re-sends them once it is done.
|
||||
void ChangeRunBackSpeed(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (target->IsDeferringDashMovementSpeedUpdates())
|
||||
return;
|
||||
|
||||
target->SetSpeed(MOVE_RUN_BACK, target->GetSpeed(MOVE_RUN));
|
||||
}
|
||||
|
||||
void RestoreRunBackSpeed(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (target->IsDeferringDashMovementSpeedUpdates())
|
||||
return;
|
||||
|
||||
target->UpdateSpeed(MOVE_RUN_BACK);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
// Aura 191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED sits on EFFECT_4 of both bundles, but
|
||||
// SPELL_AURA_MECHANIC_IMMUNITY is EFFECT_5 on 197922 and EFFECT_7 on 197923, so the amount
|
||||
// hook is only valid for the ground bundle. [DB2 12.0.7.68275 SpellEffect]
|
||||
AfterEffectApply += AuraEffectApplyFn(spell_dh_fel_rush_aura::ChangeRunBackSpeed, EFFECT_4, SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED, AURA_EFFECT_HANDLE_REAL);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_dh_fel_rush_aura::RestoreRunBackSpeed, EFFECT_4, SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED, AURA_EFFECT_HANDLE_REAL);
|
||||
|
||||
if (m_scriptSpellId == SPELL_DH_FEL_RUSH_GROUND)
|
||||
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dh_fel_rush_aura::CalcImmunityAmount, EFFECT_5, SPELL_AURA_MECHANIC_IMMUNITY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_demon_hunter_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_dh_army_unto_oneself);
|
||||
@@ -3316,4 +3445,6 @@ void AddSC_demon_hunter_spell_scripts()
|
||||
RegisterSpellScript(spell_dh_void_metamorphosis_devourer);
|
||||
RegisterSpellScript(spell_dh_collapsing_star);
|
||||
RegisterSpellScript(spell_dh_collapsing_star_damage);
|
||||
RegisterSpellScript(spell_dh_fel_rush);
|
||||
RegisterSpellScript(spell_dh_fel_rush_aura);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user