Core/Spells: Fixed Charge

* Implemented Glyph of Blazing Charge
* Implemented a way to compute spline position at any given point in time
* Removed incorrect ProgressCurveId handling, it needs to apply to entire spline duration not to each segment separately

Closes #19217
This commit is contained in:
Shauren
2017-03-18 20:14:26 +01:00
parent 850390c963
commit 51207376b7
4 changed files with 165 additions and 40 deletions

View File

@@ -0,0 +1,5 @@
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_warr_charge_effect','spell_warr_charge_drop_fire_periodic');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(198337, 'spell_warr_charge_effect'),
(218104, 'spell_warr_charge_effect'),
(126661, 'spell_warr_charge_drop_fire_periodic');

View File

@@ -25,30 +25,25 @@
namespace Movement{
Location MoveSpline::ComputePosition() const
Location MoveSpline::computePosition(int32 time_point, int32 point_index) const
{
ASSERT(Initialized());
float u = 1.0f;
float u2 = 1.0f;
int32 seg_time = spline.length(point_Idx, point_Idx+1);
int32 seg_time = spline.length(point_index, point_index + 1);
if (seg_time > 0)
{
u = (time_passed - spline.length(point_Idx)) / (float)seg_time;
u2 = u;
if (spell_effect_extra && spell_effect_extra->ProgressCurveId)
u = sDB2Manager.GetCurveValueAt(spell_effect_extra->ProgressCurveId, u);
}
u = (time_point - spline.length(point_index)) / (float)seg_time;
Location c;
c.orientation = initialOrientation;
spline.evaluate_percent(point_Idx, u, c);
spline.evaluate_percent(point_index, u, c);
if (splineflags.animation)
;// MoveSplineFlag::Animation disables falling or parabolic movement
else if (splineflags.parabolic)
computeParabolicElevation(c.z, u2 /*progress without curve modifer is expected here*/);
computeParabolicElevation(time_point, c.z);
else if (splineflags.falling)
computeFallElevation(c.z);
computeFallElevation(time_point, c.z);
if (splineflags.done && facing.type != MONSTER_MOVE_NORMAL)
{
@@ -73,14 +68,38 @@ Location MoveSpline::ComputePosition() const
return c;
}
void MoveSpline::computeParabolicElevation(float& el, float u) const
Location MoveSpline::ComputePosition() const
{
if (time_passed > effect_start_time)
return computePosition(time_passed, point_Idx);
}
Location MoveSpline::ComputePosition(int32 time_offset) const
{
int32 time_point = time_passed + time_offset;
if (time_point >= Duration())
return computePosition(Duration(), spline.last() - 1);
if (time_point <= 0)
return computePosition(0, spline.first());
// find point_index where spline.length(point_index) < time_point < spline.length(point_index + 1)
int32 point_index = point_Idx;
while (time_point >= spline.length(point_index + 1))
++point_index;
while (time_point < spline.length(point_index))
--point_index;
return computePosition(time_point, point_index);
}
void MoveSpline::computeParabolicElevation(int32 time_point, float& el) const
{
if (time_point > effect_start_time)
{
float t_passedf = MSToSec(time_passed - effect_start_time);
float t_passedf = MSToSec(time_point - effect_start_time);
float t_durationf = MSToSec(Duration() - effect_start_time); //client use not modified duration here
if (spell_effect_extra && spell_effect_extra->ParabolicCurveId)
t_passedf *= sDB2Manager.GetCurveValueAt(spell_effect_extra->ParabolicCurveId, u);
t_passedf *= sDB2Manager.GetCurveValueAt(spell_effect_extra->ParabolicCurveId, float(time_point) / Duration());
// -a*x*x + bx + c:
//(dur * v3->z_acceleration * dt)/2 - (v3->z_acceleration * dt * dt)/2 + Z;
@@ -88,9 +107,9 @@ void MoveSpline::computeParabolicElevation(float& el, float u) const
}
}
void MoveSpline::computeFallElevation(float& el) const
void MoveSpline::computeFallElevation(int32 time_point, float& el) const
{
float z_now = spline.getPoint(spline.first()).z - Movement::computeFallElevation(MSToSec(time_passed), false);
float z_now = spline.getPoint(spline.first()).z - Movement::computeFallElevation(MSToSec(time_point), false);
float final_z = FinalDestination().z;
el = std::max(z_now, final_z);
}

View File

@@ -86,8 +86,9 @@ namespace Movement
protected:
MySpline::ControlArray const& getPath() const { return spline.getPoints(); }
void computeParabolicElevation(float& el, float u) const;
void computeFallElevation(float& el) const;
Location computePosition(int32 time_point, int32 point_index) const;
void computeParabolicElevation(int32 time_point, float& el) const;
void computeFallElevation(int32 time_point, float& el) const;
UpdateResult _updateState(int32& ms_time_diff);
int32 next_timestamp() const { return spline.length(point_Idx + 1); }
@@ -125,6 +126,7 @@ namespace Movement
}
Location ComputePosition() const;
Location ComputePosition(int32 time_offset) const;
uint32 GetId() const { return m_Id; }
bool Finalized() const { return splineflags.done; }

View File

@@ -23,17 +23,25 @@
#include "Player.h"
#include "ScriptMgr.h"
#include "MoveSpline.h"
#include "SpellHistory.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "SpellPackets.h"
enum WarriorSpells
{
SPELL_WARRIOR_BLADESTORM_PERIODIC_WHIRLWIND = 50622,
SPELL_WARRIOR_BLOODTHIRST_HEAL = 117313,
SPELL_WARRIOR_CHARGE = 34846,
SPELL_WARRIOR_CHARGE_EFFECT = 218104,
SPELL_WARRIOR_CHARGE_EFFECT_BLAZING_TRAIL = 198337,
SPELL_WARRIOR_CHARGE_PAUSE_RAGE_DECAY = 109128,
SPELL_WARRIOR_CHARGE_ROOT_EFFECT = 105771,
SPELL_WARRIOR_CHARGE_SLOW_EFFECT = 236027,
SPELL_WARRIOR_COLOSSUS_SMASH = 86346,
SPELL_WARRIOR_EXECUTE = 20647,
SPELL_WARRIOR_GLYPH_OF_THE_BLAZING_TRAIL = 123779,
SPELL_WARRIOR_GLYPH_OF_HEROIC_LEAP = 159708,
SPELL_WARRIOR_GLYPH_OF_HEROIC_LEAP_BUFF = 133278,
SPELL_WARRIOR_HEROIC_LEAP_JUMP = 178368,
@@ -66,6 +74,11 @@ enum WarriorSpells
SPELL_WARRIOR_VICTORY_RUSH_HEAL = 118779,
};
enum WarriorMisc
{
SPELL_VISUAL_BLAZING_CHARGE = 26423
};
// 23881 - Bloodthirst
class spell_warr_bloodthirst : public SpellScriptLoader
{
@@ -101,7 +114,7 @@ public:
}
};
/// Updated 4.3.4
// 100 - Charge
class spell_warr_charge : public SpellScriptLoader
{
public:
@@ -113,27 +126,25 @@ class spell_warr_charge : public SpellScriptLoader
bool Validate(SpellInfo const* /*spellInfo*/) override
{
if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_TALENT) ||
!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_BUFF) ||
!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_CHARGE))
return false;
return true;
return ValidateSpellInfo
({
SPELL_WARRIOR_CHARGE_EFFECT,
SPELL_WARRIOR_CHARGE_EFFECT_BLAZING_TRAIL
});
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
int32 chargeBasePoints0 = GetEffectValue();
Unit* caster = GetCaster();
caster->CastCustomSpell(caster, SPELL_WARRIOR_CHARGE, &chargeBasePoints0, NULL, NULL, true);
uint32 spellId = SPELL_WARRIOR_CHARGE_EFFECT;
if (GetCaster()->HasAura(SPELL_WARRIOR_GLYPH_OF_THE_BLAZING_TRAIL))
spellId = SPELL_WARRIOR_CHARGE_EFFECT_BLAZING_TRAIL;
// Juggernaut crit bonus
if (caster->HasAura(SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_TALENT))
caster->CastSpell(caster, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_BUFF, true);
GetCaster()->CastSpell(GetHitUnit(), spellId, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_warr_charge_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY);
OnEffectHitTarget += SpellEffectFn(spell_warr_charge_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
@@ -143,6 +154,92 @@ class spell_warr_charge : public SpellScriptLoader
}
};
// 126661 - Warrior Charge Drop Fire Periodic
class spell_warr_charge_drop_fire_periodic : public SpellScriptLoader
{
public:
spell_warr_charge_drop_fire_periodic() : SpellScriptLoader("spell_warr_charge_drop_fire_periodic") { }
class spell_warr_charge_drop_fire_periodic_AuraScript : public AuraScript
{
PrepareAuraScript(spell_warr_charge_drop_fire_periodic_AuraScript);
void DropFireVisual(AuraEffect const* aurEff)
{
PreventDefaultAction();
if (GetTarget()->IsSplineEnabled())
{
for (uint32 i = 0; i < 5; ++i)
{
int32 timeOffset = 6 * i * aurEff->GetPeriod() / 25;
WorldPackets::Spells::PlaySpellVisual playSpellVisual;
playSpellVisual.Source = GetTarget()->GetGUID();
playSpellVisual.TargetPostion = static_cast<G3D::Vector3>(GetTarget()->movespline->ComputePosition(timeOffset)); // slices
playSpellVisual.SpellVisualID = SPELL_VISUAL_BLAZING_CHARGE;
playSpellVisual.TravelSpeed = 1.0f;
playSpellVisual.MissReason = 0;
playSpellVisual.ReflectStatus = 0;
playSpellVisual.Orientation = 0.0f;
playSpellVisual.SpeedAsTime = true;
GetTarget()->SendMessageToSet(playSpellVisual.Write(), true);
}
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_warr_charge_drop_fire_periodic_AuraScript::DropFireVisual, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_warr_charge_drop_fire_periodic_AuraScript();
}
};
// 198337 - Charge Effect (dropping Blazing Trail)
// 218104 - Charge Effect
class spell_warr_charge_effect : public SpellScriptLoader
{
public:
spell_warr_charge_effect() : SpellScriptLoader("spell_warr_charge_effect") { }
class spell_warr_charge_effect_SpellScript : public SpellScript
{
PrepareSpellScript(spell_warr_charge_effect_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_WARRIOR_CHARGE_PAUSE_RAGE_DECAY,
SPELL_WARRIOR_CHARGE_ROOT_EFFECT,
SPELL_WARRIOR_CHARGE_SLOW_EFFECT
});
}
void HandleCharge(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
caster->CastCustomSpell(SPELL_WARRIOR_CHARGE_PAUSE_RAGE_DECAY, SPELLVALUE_BASE_POINT0, 0, caster, true);
caster->CastSpell(target, SPELL_WARRIOR_CHARGE_ROOT_EFFECT, true);
caster->CastSpell(target, SPELL_WARRIOR_CHARGE_SLOW_EFFECT, true);
}
void Register() override
{
OnEffectLaunchTarget += SpellEffectFn(spell_warr_charge_effect_SpellScript::HandleCharge, EFFECT_0, SPELL_EFFECT_CHARGE);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_warr_charge_effect_SpellScript();
}
};
/// Updated 4.3.4
class spell_warr_concussion_blow : public SpellScriptLoader
{
@@ -444,7 +541,7 @@ class spell_warr_last_stand : public SpellScriptLoader
{
Unit* caster = GetCaster();
int32 healthModSpellBasePoints0 = int32(caster->CountPctFromMaxHealth(GetEffectValue()));
caster->CastCustomSpell(caster, SPELL_WARRIOR_LAST_STAND_TRIGGERED, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
caster->CastCustomSpell(caster, SPELL_WARRIOR_LAST_STAND_TRIGGERED, &healthModSpellBasePoints0, nullptr, nullptr, true, nullptr);
}
void Register() override
@@ -524,7 +621,7 @@ class spell_warr_rallying_cry : public SpellScriptLoader
{
int32 basePoints0 = int32(GetHitUnit()->CountPctFromMaxHealth(GetEffectValue()));
GetCaster()->CastCustomSpell(GetHitUnit(), SPELL_WARRIOR_RALLYING_CRY, &basePoints0, NULL, NULL, true);
GetCaster()->CastCustomSpell(GetHitUnit(), SPELL_WARRIOR_RALLYING_CRY, &basePoints0, nullptr, nullptr, true);
}
void Register() override
@@ -603,7 +700,7 @@ class spell_warr_retaliation : public SpellScriptLoader
void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_WARRIOR_RETALIATION_DAMAGE, true, NULL, aurEff);
GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_WARRIOR_RETALIATION_DAMAGE, true, nullptr, aurEff);
}
void Register() override
@@ -725,7 +822,7 @@ class spell_warr_second_wind_proc : public SpellScriptLoader
if (!spellId)
return;
GetTarget()->CastSpell(GetTarget(), spellId, true, NULL, aurEff);
GetTarget()->CastSpell(GetTarget(), spellId, true, nullptr, aurEff);
}
@@ -930,12 +1027,12 @@ class spell_warr_sweeping_strikes : public SpellScriptLoader
if (spellInfo && (spellInfo->Id == SPELL_WARRIOR_BLADESTORM_PERIODIC_WHIRLWIND || (spellInfo->Id == SPELL_WARRIOR_EXECUTE && !_procTarget->HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT))))
{
// If triggered by Execute (while target is not under 20% hp) or Bladestorm deals normalized weapon damage
GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2, true, NULL, aurEff);
GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2, true, nullptr, aurEff);
}
else
{
int32 damage = eventInfo.GetDamageInfo()->GetDamage();
GetTarget()->CastCustomSpell(SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, SPELLVALUE_BASE_POINT0, damage, _procTarget, true, NULL, aurEff);
GetTarget()->CastCustomSpell(SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, SPELLVALUE_BASE_POINT0, damage, _procTarget, true, nullptr, aurEff);
}
}
}
@@ -1057,7 +1154,7 @@ class spell_warr_vigilance : public SpellScriptLoader
bool Load() override
{
_procTarget = NULL;
_procTarget = nullptr;
return true;
}
@@ -1139,6 +1236,8 @@ void AddSC_warrior_spell_scripts()
{
new spell_warr_bloodthirst();
new spell_warr_charge();
new spell_warr_charge_drop_fire_periodic();
new spell_warr_charge_effect();
new spell_warr_concussion_blow();
new spell_warr_execute();
new spell_warr_heroic_leap();