dragonriding

This commit is contained in:
luis
2026-03-17 23:50:52 -03:00
parent 01cf332cfa
commit 5241086f27
8 changed files with 243 additions and 25 deletions
+11 -6
View File
@@ -32744,15 +32744,20 @@ void Player::InitAdvFlying()
SendAdvFlyingSpeed(SMSG_MOVE_SET_ADV_FLYING_LAUNCH_SPEED_COEFFICIENT, ADV_FLYING_LAUNCH_SPEED_COEFFICIENT);
}
void Player::SendAdvFlyingSpeed(OpcodeServer opcode, AdvFlyingRateTypeSingle speedType, AdvFlyingRateTypeSingle maxSpeedType /*= AdvFlyingRateType(0)*/) //[FIX][2024-07-14] Renamed member to avoid C++ type
void Player::SendAdvFlyingSpeed(OpcodeServer opcode, AdvFlyingRateTypeSingle speedType, std::optional<AdvFlyingRateTypeSingle> maxSpeedType)
{
if (maxSpeedType != AdvFlyingRateTypeSingle(0))
SendDirectMessage(WorldPackets::Movement::SetAdvFlyingMinMaxSpeeds(opcode, m_movementCounter++, GetAdvFlyingSpeed(speedType), GetAdvFlyingSpeed(maxSpeedType)).Write());
//else
// SendDirectMessage(WorldPackets::Movement::SetAdvFlyingSpeed(opcode, m_movementCounter++, GetAdvFlyingSpeed(speedType)).Write());
if (maxSpeedType.has_value() && maxSpeedType.value() != AdvFlyingRateTypeSingle(0))
SendDirectMessage(WorldPackets::Movement::SetAdvFlyingMinMaxSpeeds(opcode, m_movementCounter++, GetAdvFlyingSpeed(speedType), GetAdvFlyingSpeed(maxSpeedType.value())).Write());
else
{
WorldPackets::Movement::SetAdvFlyingSpeed packet(opcode);
packet.MoverGUID = GetGUID();
packet.SequenceIndex = m_movementCounter++;
packet.Speed = GetAdvFlyingSpeed(speedType);
SendDirectMessage(packet.Write());
}
}
void Player::UpdateDynamicFlight(bool apply)
{
if (apply)
+1 -1
View File
@@ -2042,7 +2042,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void AddMoveImpulse(Position direction);
//WowCommunity
void InitAdvFlying();
void SendAdvFlyingSpeed(OpcodeServer opcode, AdvFlyingRateTypeSingle speedType, AdvFlyingRateTypeSingle maxSpeedType = AdvFlyingRateTypeSingle(0)); // [FIX][2024-07-14] Renamed member to avoid C++ type.
void SendAdvFlyingSpeed(OpcodeServer opcode, AdvFlyingRateTypeSingle speedType, std::optional<AdvFlyingRateTypeSingle> maxSpeedType = {});
void UpdateDynamicFlight(bool apply = false);
bool IsInAlliance() const { return m_team == ALLIANCE; }
bool IsInHorde() const { return m_team == HORDE; }
+6
View File
@@ -14648,3 +14648,9 @@ float Unit::GetAdvFlyingVelocity() const
return std::sqrt(advFlying->forwardVelocity * advFlying->forwardVelocity + advFlying->upVelocity * advFlying->upVelocity);
}
bool Unit::IsInAir() const
{
float ground = GetFloorZ();
return (G3D::fuzzyGt(GetPositionZ(), ground + GetHoverOffset() + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(GetPositionZ(), ground - GROUND_HEIGHT_TOLERANCE)); // Can be underground too, prevent the falling
}
+1
View File
@@ -1096,6 +1096,7 @@ class TC_GAME_API Unit : public WorldObject
bool isTargetableForAttack(bool checkFakeDeath = true) const;
bool IsInWater() const;
bool IsInAir() const;
bool IsUnderWater() const;
bool IsOnOceanFloor() const;
bool isInAccessiblePlaceFor(Creature const* c) const;
@@ -22,19 +22,6 @@ void PerksProgramRequestPurchase::Read()
_worldPacket >> VendorItemID;
}
void PerksProgramRequestCartCheckout::Read()
{
uint32 count = _worldPacket.ReadBits(5);
VendorItemIDs.resize(count);
for (uint32 i = 0; i < count; ++i)
_worldPacket >> VendorItemIDs[i];
}
void PerksProgramGetRecentPurchases::Read()
{
// This packet doesn't contain any data, it's just a request
}
void PerksProgramSetFrozenVendorItem::Read()
{
_worldPacket >> VendorItemID;
@@ -2983,13 +2983,19 @@ void AuraEffect::HandleAuraCanTurnWhileFalling(AuraApplication const* aurApp, ui
void AuraEffect::HandleModAdvFlying(AuraApplication const* aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit* target = aurApp->GetTarget();
target->SetCanDoubleJump(apply || target->HasAura(SPELL_DH_DOUBLE_JUMP));
target->SetCanFly(apply);
target->SetCanAdvFly(apply);
Player* player = aurApp->GetTarget()->ToPlayer();
if (!player)
return;
player->SetCanDoubleJump(apply || player->HasAura(SPELL_DH_DOUBLE_JUMP));
player->SetCanFly(apply);
player->SetCanAdvFly(apply);
if (apply)
player->InitAdvFlying();
}
void AuraEffect::HandleIgnoreMovementForces(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -6702,6 +6708,36 @@ void AuraEffect::HandleAuraActAsControlZone(AuraApplication const* aurApp, uint8
controlZone->SetSpellId(GetSpellInfo()->Id);
}
void AuraEffect::HandleAdvFlyModSpeed(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Player* player = aurApp->GetTarget()->ToPlayer();
if (!player)
return;
player->CalculateAdvFlyingSpeeds();
static std::unordered_map<AuraType, std::tuple<OpcodeServer, AdvFlyingRateTypeSingle, std::optional<AdvFlyingRateTypeSingle>>> advFlyMap;
if (advFlyMap.empty())
{
using TupleType = std::tuple<OpcodeServer, AdvFlyingRateTypeSingle, std::optional<AdvFlyingRateTypeSingle>>;
advFlyMap[SPELL_AURA_MOD_ADV_FLYING_LIFT_COEF] = TupleType{ SMSG_MOVE_SET_ADV_FLYING_LIFT_COEFFICIENT, AdvFlyingRateTypeSingle(ADV_FLYING_LIFT_COEFFICIENT), std::optional<AdvFlyingRateTypeSingle>(std::nullopt) };
advFlyMap[SPELL_AURA_MOD_ADV_FLYING_MAX_VEL] = TupleType{ SMSG_MOVE_SET_ADV_FLYING_MAX_VEL, AdvFlyingRateTypeSingle(ADV_FLYING_MAX_VEL), std::optional<AdvFlyingRateTypeSingle>(std::nullopt) };
advFlyMap[SPELL_AURA_MOD_ADV_FLYING_AIR_FRICTION] = TupleType{ SMSG_MOVE_SET_ADV_FLYING_AIR_FRICTION, AdvFlyingRateTypeSingle(ADV_FLYING_AIR_FRICTION), std::optional<AdvFlyingRateTypeSingle>(std::nullopt) };
advFlyMap[SPELL_AURA_MOD_ADV_FLYING_ADD_IMPULSE_MAX_SPEED] = TupleType{ SMSG_MOVE_SET_ADV_FLYING_ADD_IMPULSE_MAX_SPEED, AdvFlyingRateTypeSingle(ADV_FLYING_ADD_IMPULSE_MAX_SPEED), std::optional<AdvFlyingRateTypeSingle>(std::nullopt) };
advFlyMap[SPELL_AURA_MOD_ADV_FLYING_BANKING_RATE] = TupleType{ SMSG_MOVE_SET_ADV_FLYING_PITCHING_RATE_DOWN, AdvFlyingRateTypeSingle(ADV_FLYING_BANKING_RATE), std::optional<AdvFlyingRateTypeSingle>(AdvFlyingRateTypeSingle(ADV_FLYING_PITCHING_RATE_DOWN)) };
advFlyMap[SPELL_AURA_MOD_ADV_FLYING_PITCHING_RATE_DOWN] = TupleType{ SMSG_MOVE_SET_ADV_FLYING_PITCHING_RATE_UP, AdvFlyingRateTypeSingle(ADV_FLYING_PITCHING_RATE_UP), std::optional<AdvFlyingRateTypeSingle>(AdvFlyingRateTypeSingle(ADV_FLYING_PITCHING_RATE_UP)) };
advFlyMap[SPELL_AURA_MOD_ADV_FLYING_PITCHING_RATE_UP] = TupleType{ SMSG_MOVE_SET_ADV_FLYING_OVER_MAX_DECELERATION, AdvFlyingRateTypeSingle(ADV_FLYING_OVER_MAX_DECELERATION), std::optional<AdvFlyingRateTypeSingle>(std::nullopt) };
advFlyMap[SPELL_AURA_MOD_ADV_FLYING_OVER_MAX_DECELERATION] = TupleType{ SMSG_MOVE_SET_ADV_FLYING_BANKING_RATE, AdvFlyingRateTypeSingle(ADV_FLYING_BANKING_RATE), std::optional<AdvFlyingRateTypeSingle>(AdvFlyingRateTypeSingle(ADV_FLYING_BANKING_RATE)) };
}
auto [opcode, speedType, speedTypeMax] = advFlyMap[GetSpellEffectInfo().ApplyAuraName];
player->SendAdvFlyingSpeed(opcode, speedType, speedTypeMax);
}
template TC_GAME_API void AuraEffect::GetTargetList(std::list<Unit*>&) const;
template TC_GAME_API void AuraEffect::GetTargetList(std::deque<Unit*>&) const;
template TC_GAME_API void AuraEffect::GetTargetList(std::vector<Unit*>&) const;
@@ -371,6 +371,7 @@ class TC_GAME_API AuraEffect
void HandleAuraPvpTalents(AuraApplication const* auraApp, uint8 mode, bool apply) const;
void HandleAuraActAsControlZone(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAdvFlyModSpeed(AuraApplication const* aurApp, uint8 mode, bool) const;
};
namespace Trinity
@@ -27,6 +27,8 @@
#include "SpellScript.h"
#include "Unit.h"
const float THRILL_OF_THE_SKIES_MIN_VELOCITY = 40.f;
enum DragonridingSpells
{
SPELL_DRAGONRIDING_SURGE_FORWARD = 372608,
@@ -40,6 +42,12 @@ enum DragonridingSpells
SPELL_SWITCH_FLIGHT_STYLE = 436854,
SPELL_VIGOR = 372773,
SPELL_LIFT_OFF_3 = 386451,
SPELL_THRILL_OF_THE_SKIES = 377234,
SPELL_THRILL_OF_THE_SKIES_2 = 383366,
SPELL_EVOKER_SOAR_RACIAL = 369536,
SPELL_ENERGY_WIDGET = 423624,
SPELL_VIGOR_CACHE = 433547,
SPELL_DRAGONRIDER_ENERGIZE = 372606,
};
// Spell 436854 - Switch Flight Style
@@ -250,6 +258,177 @@ class spell_dragonriding_launch_boost_aura : public AuraScript
}
};
// 406095 - Dynamic Flight
class spell_dragonriding : public AuraScript
{
void OnPeriodic(AuraEffect const* /*aurEff*/)
{
float advFlyingVelocity = GetTarget()->GetAdvFlyingVelocity();
bool advFylingEnabled = GetTarget()->HasAuraType(SPELL_AURA_ADV_FLYING);
float ground = GetTarget()->GetFloorZ();
bool isInAir = (G3D::fuzzyGt(GetTarget()->GetPositionZ(), ground + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(GetTarget()->GetPositionZ(), ground - GROUND_HEIGHT_TOLERANCE));
if (isInAir && advFlyingVelocity && advFylingEnabled)
{
if (advFlyingVelocity > THRILL_OF_THE_SKIES_MIN_VELOCITY)
{
if (!GetTarget()->HasAura(SPELL_THRILL_OF_THE_SKIES))
GetTarget()->CastSpell(GetTarget(), SPELL_THRILL_OF_THE_SKIES, TRIGGERED_FULL_MASK);
GetTarget()->CastSpell(GetTarget(), SPELL_THRILL_OF_THE_SKIES_2, TRIGGERED_FULL_MASK);
}
else
GetTarget()->RemoveAurasDueToSpell(SPELL_THRILL_OF_THE_SKIES);
GetTarget()->RemoveAurasDueToSpell(SPELL_THRILL_OF_THE_SKIES_2);
}
else
{
GetTarget()->RemoveAurasDueToSpell(SPELL_THRILL_OF_THE_SKIES);
GetTarget()->RemoveAurasDueToSpell(SPELL_THRILL_OF_THE_SKIES_2);
}
if (advFlyingVelocity <= 8.5f)
{
// TODO ORNIXX
}
// Soar Evoker
if (!isInAir && GetCaster()->HasAura(SPELL_EVOKER_SOAR_RACIAL))
GetCaster()->RemoveAura(SPELL_EVOKER_SOAR_RACIAL);
}
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
caster->AddAura(SPELL_DRAGONRIDER_ENERGY, caster);
GetTarget()->CastSpell(GetTarget(), SPELL_ENERGY_WIDGET, true);
GetTarget()->SetPower(POWER_ALTERNATE_MOUNT, GetTarget()->GetPower(POWER_ALTERNATE_MOUNT), true);
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
{
caster->RemoveAura(SPELL_DRAGONRIDER_ENERGY);
caster->RemoveAura(SPELL_VIGOR_CACHE);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_dragonriding::OnPeriodic, EFFECT_2, SPELL_AURA_PERIODIC_DUMMY);
OnEffectApply += AuraEffectApplyFn(spell_dragonriding::OnApply, EFFECT_2, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_dragonriding::OnRemove, EFFECT_2, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 372771 - Dragonrider Energy
class spell_dragonrider_energy : public AuraScript
{
void OnPeriodic(AuraEffect* /*aurEff*/)
{
Unit* caster = GetCaster();
if (!caster)
return;
caster->ToPlayer()->AddAura(433547, caster);
int newMaxPower = 3;
if (caster->HasAura(377920) && !caster->HasAura(377921) && !caster->HasAura(377922))
{
newMaxPower = 4;
}
else if (caster->HasAura(377921) && caster->HasAura(377920) && !caster->HasAura(377922))
{
newMaxPower = 5;
}
else if (caster->HasAura(377922) && caster->HasAura(377921) && caster->HasAura(377920))
{
newMaxPower = 6;
}
caster->SetMaxPower(POWER_ALTERNATE_MOUNT, newMaxPower);
}
void Register() override
{
OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_dragonrider_energy::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
}
};
// 372773 - Dragonrider Energy
class spell_af_energy : public AuraScript
{
void OnPeriodic(AuraEffect* /*aurEff*/)
{
if (Unit* caster = GetCaster())
{
if (ShouldRegenEnergy(caster))
{
if (AuraEffect* subAmountAurEff = caster->GetAuraEffect(SPELL_VIGOR_CACHE, EFFECT_1))
{
int32 baseRegen = 20; // Todo : Calculate this based on talents & if we are thrilled/grounded
int32 newAmount = subAmountAurEff->GetAmount() + baseRegen;
if (newAmount >= 100)
{
newAmount -= 100;
caster->CastSpell(caster, SPELL_DRAGONRIDER_ENERGIZE, TRIGGERED_FULL_MASK);
if (AuraEffect* amountAurEff = caster->GetAuraEffect(SPELL_VIGOR_CACHE, EFFECT_0))
amountAurEff->SetAmount(caster->GetPower(POWER_ALTERNATE_MOUNT));
}
subAmountAurEff->SetAmount(newAmount);
subAmountAurEff->GetBase()->SetNeedClientUpdateForTargets();
}
}
}
}
bool ShouldRegenEnergy(Unit const* caster) const
{
if (caster->GetPower(POWER_ALTERNATE_MOUNT) == caster->GetMaxPower(POWER_ALTERNATE_MOUNT))
return false;
FlightCapabilityEntry const* flightCapabilityEntry = sFlightCapabilityStore.LookupEntry(caster->GetFlightCapabilityID());
if (!flightCapabilityEntry)
return false;
float velocityRegenThreshold = flightCapabilityEntry->MaxVel * flightCapabilityEntry->VigorRegenMaxVelCoefficient;
if (caster->GetAdvFlyingVelocity() >= velocityRegenThreshold)
return true;
return !caster->IsInAir() || caster->IsInWater();
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->RemoveAurasDueToSpell(SPELL_VIGOR_CACHE);
}
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
if (!target->HasAura(SPELL_VIGOR_CACHE))
{
CastSpellExtraArgs extraArgs(TRIGGERED_FULL_MASK);
extraArgs.AddSpellMod(SPELLVALUE_BASE_POINT0, target->GetPower(POWER_ALTERNATE_MOUNT));
target->CastSpell(target, SPELL_VIGOR_CACHE, extraArgs);
}
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_af_energy::OnApply, EFFECT_0, SPELL_AURA_ENABLE_ALT_POWER, AURA_EFFECT_HANDLE_REAL);
OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_af_energy::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
OnEffectRemove += AuraEffectRemoveFn(spell_af_energy::OnRemove, EFFECT_0, SPELL_AURA_ENABLE_ALT_POWER, AURA_EFFECT_HANDLE_REAL);
}
};
void AddSC_dragonriding_spell_scripts()
{
RegisterSpellScript(spell_switch_flight);
@@ -257,4 +436,7 @@ void AddSC_dragonriding_spell_scripts()
RegisterSpellAndAuraScriptPair(spell_dragonriding_launch_boost, spell_dragonriding_launch_boost_aura);
RegisterSpellScript(spell_dragonriding_surge_forward);
RegisterSpellScript(spell_dragonriding_skyward_ascent);
RegisterSpellScript(spell_dragonriding);
RegisterSpellScript(spell_dragonrider_energy);
RegisterSpellScript(spell_af_energy);
}