aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Player/Player.cpp6
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp22
-rw-r--r--src/server/game/Entities/Unit/Unit.h1
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp103
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h1
5 files changed, 84 insertions, 49 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 24d2fd3f033..34bd02f261a 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -5715,7 +5715,11 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
LearnSkillRewardedSpells(id, newVal);
// if skill value is going up, update enchantments after setting the new value
if (newVal > currVal)
+ {
UpdateSkillEnchantments(id, currVal, newVal);
+ if (id == SKILL_RIDING)
+ UpdateMountCapability();
+ }
UpdateCriteria(CriteriaType::SkillRaised, id);
UpdateCriteria(CriteriaType::AchieveSkillStep, id);
@@ -7220,6 +7224,8 @@ void Player::UpdateArea(uint32 newArea)
PushQuests();
UpdateCriteria(CriteriaType::EnterTopLevelArea, newArea);
+
+ UpdateMountCapability();
}
void Player::UpdateZone(uint32 newZone, uint32 newArea)
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index e01a53f65db..ef3e30948f1 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -3043,7 +3043,7 @@ void Unit::SetInWater(bool inWater)
void Unit::ProcessTerrainStatusUpdate(ZLiquidStatus status, Optional<LiquidData> const& liquidData)
{
- if (IsFlying() || (!IsControlledByPlayer()))
+ if (!IsControlledByPlayer())
return;
SetInWater(status & MAP_LIQUID_STATUS_SWIMMING);
@@ -3060,6 +3060,9 @@ void Unit::ProcessTerrainStatusUpdate(ZLiquidStatus status, Optional<LiquidData>
if (curLiquid && curLiquid->SpellID && (!player || !player->IsGameMaster()))
CastSpell(this, curLiquid->SpellID, true);
_lastLiquid = curLiquid;
+
+ // mount capability depends on liquid state change
+ UpdateMountCapability();
}
}
@@ -7623,7 +7626,8 @@ MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const
if (!(mountCapability->Flags & MOUNT_CAPABILITY_FLAG_GROUND))
continue;
}
- else if (!(mountCapability->Flags & MOUNT_CAPABILITY_FLAG_UNDERWATER))
+ // player is on water surface
+ else if (!(mountCapability->Flags & MOUNT_CAPABILITY_FLAG_FLOAT))
continue;
}
else if (isInWater)
@@ -7660,6 +7664,20 @@ MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const
return nullptr;
}
+void Unit::UpdateMountCapability()
+{
+ AuraEffectList mounts = GetAuraEffectsByType(SPELL_AURA_MOUNTED);
+ for (AuraEffect* aurEff : mounts)
+ {
+ aurEff->RecalculateAmount();
+ if (!aurEff->GetAmount())
+ aurEff->GetBase()->Remove();
+ else if (MountCapabilityEntry const* capability = sMountCapabilityStore.LookupEntry(aurEff->GetAmount())) // aura may get removed by interrupt flag, reapply
+ if (!HasAura(capability->ModSpellAuraID))
+ CastSpell(this, capability->ModSpellAuraID, aurEff);
+ }
+}
+
bool Unit::IsServiceProvider() const
{
return HasNpcFlag(NPCFlags(
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 874a69da264..b05419ead5f 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -993,6 +993,7 @@ class TC_GAME_API Unit : public WorldObject
void Mount(uint32 mount, uint32 vehicleId = 0, uint32 creatureEntry = 0);
void Dismount();
MountCapabilityEntry const* GetMountCapability(uint32 mountType) const;
+ void UpdateMountCapability();
void SendDurabilityLoss(Player* receiver, uint32 percent);
void PlayOneShotAnimKitId(uint16 animKitId);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index a9bfb2cdb82..63a848abad7 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -404,7 +404,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //333 SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_TRIGGERED implemented in Unit::GetCastSpellInfo
&AuraEffect::HandleNoImmediateEffect, //334 SPELL_AURA_MOD_AUTOATTACK_CRIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
&AuraEffect::HandleNULL, //335 SPELL_AURA_335
- &AuraEffect::HandleNULL, //336 SPELL_AURA_MOUNT_RESTRICTIONS implemented in Unit::GetMountCapability
+ &AuraEffect::HandleMountRestrictions, //336 SPELL_AURA_MOUNT_RESTRICTIONS implemented in Unit::GetMountCapability
&AuraEffect::HandleNoImmediateEffect, //337 SPELL_AURA_MOD_VENDOR_ITEMS_PRICES
&AuraEffect::HandleNoImmediateEffect, //338 SPELL_AURA_MOD_DURABILITY_LOSS
&AuraEffect::HandleNoImmediateEffect, //339 SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER implemented in Unit::GetUnitCriticalChance and Unit::GetUnitSpellCriticalChance
@@ -653,10 +653,7 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
mountType = mountEntry->MountTypeID;
if (MountCapabilityEntry const* mountCapability = GetBase()->GetUnitOwner()->GetMountCapability(mountType))
- {
amount = mountCapability->ID;
- m_canBeRecalculated = false;
- }
break;
}
case SPELL_AURA_SHOW_CONFIRMATION_PROMPT_WITH_DIFFICULTY:
@@ -2489,84 +2486,88 @@ void AuraEffect::HandleAuraAllowTalentSwapping(AuraApplication const* aurApp, ui
void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bool apply) const
{
- if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
+ if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK))
return;
Unit* target = aurApp->GetTarget();
if (apply)
{
- uint32 creatureEntry = GetMiscValue();
- uint32 displayId = 0;
- uint32 vehicleId = 0;
-
- if (MountEntry const* mountEntry = sDB2Manager.GetMount(GetId()))
+ if (mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)
{
- if (DB2Manager::MountXDisplayContainer const* mountDisplays = sDB2Manager.GetMountDisplays(mountEntry->ID))
+ uint32 creatureEntry = GetMiscValue();
+ uint32 displayId = 0;
+ uint32 vehicleId = 0;
+
+ if (MountEntry const* mountEntry = sDB2Manager.GetMount(GetId()))
{
- if (mountEntry->IsSelfMount())
+ if (DB2Manager::MountXDisplayContainer const* mountDisplays = sDB2Manager.GetMountDisplays(mountEntry->ID))
{
- displayId = DISPLAYID_HIDDEN_MOUNT;
- }
- else
- {
- DB2Manager::MountXDisplayContainer usableDisplays;
- std::copy_if(mountDisplays->begin(), mountDisplays->end(), std::back_inserter(usableDisplays), [target](MountXDisplayEntry const* mountDisplay)
+ if (mountEntry->IsSelfMount())
+ {
+ displayId = DISPLAYID_HIDDEN_MOUNT;
+ }
+ else
{
- if (Player* playerTarget = target->ToPlayer())
- if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(mountDisplay->PlayerConditionID))
- return sConditionMgr->IsPlayerMeetingCondition(playerTarget, playerCondition);
+ DB2Manager::MountXDisplayContainer usableDisplays;
+ std::copy_if(mountDisplays->begin(), mountDisplays->end(), std::back_inserter(usableDisplays), [target](MountXDisplayEntry const* mountDisplay)
+ {
+ if (Player* playerTarget = target->ToPlayer())
+ if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(mountDisplay->PlayerConditionID))
+ return sConditionMgr->IsPlayerMeetingCondition(playerTarget, playerCondition);
- return true;
- });
+ return true;
+ });
- if (!usableDisplays.empty())
- displayId = Trinity::Containers::SelectRandomContainerElement(usableDisplays)->CreatureDisplayInfoID;
+ if (!usableDisplays.empty())
+ displayId = Trinity::Containers::SelectRandomContainerElement(usableDisplays)->CreatureDisplayInfoID;
+ }
}
+ // TODO: CREATE TABLE mount_vehicle (mountId, vehicleCreatureId) for future mounts that are vehicles (new mounts no longer have proper data in MiscValue)
+ //if (MountVehicle const* mountVehicle = sObjectMgr->GetMountVehicle(mountEntry->Id))
+ // creatureEntry = mountVehicle->VehicleCreatureId;
}
- // TODO: CREATE TABLE mount_vehicle (mountId, vehicleCreatureId) for future mounts that are vehicles (new mounts no longer have proper data in MiscValue)
- //if (MountVehicle const* mountVehicle = sObjectMgr->GetMountVehicle(mountEntry->Id))
- // creatureEntry = mountVehicle->VehicleCreatureId;
- }
- if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creatureEntry))
- {
- vehicleId = creatureInfo->VehicleId;
-
- if (!displayId)
+ if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creatureEntry))
{
- CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo);
- sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo);
- displayId = model.CreatureDisplayID;
+ vehicleId = creatureInfo->VehicleId;
+
+ if (!displayId)
+ {
+ CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo);
+ sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo);
+ displayId = model.CreatureDisplayID;
+ }
+
+ //some spell has one aura of mount and one of vehicle
+ for (SpellEffectInfo const& effect : GetSpellInfo()->GetEffects())
+ if (effect.IsEffect(SPELL_EFFECT_SUMMON) && effect.MiscValue == GetMiscValue())
+ displayId = 0;
}
- //some spell has one aura of mount and one of vehicle
- for (SpellEffectInfo const& effect : GetSpellInfo()->GetEffects())
- if (effect.IsEffect(SPELL_EFFECT_SUMMON) && effect.MiscValue == GetMiscValue())
- displayId = 0;
+ target->Mount(displayId, vehicleId, creatureEntry);
}
- target->Mount(displayId, vehicleId, creatureEntry);
-
// cast speed aura
- if (mode & AURA_EFFECT_HANDLE_REAL)
+ if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)
if (MountCapabilityEntry const* mountCapability = sMountCapabilityStore.LookupEntry(GetAmount()))
target->CastSpell(target, mountCapability->ModSpellAuraID, this);
}
else
{
- target->Dismount();
+ if (mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)
+ target->Dismount();
+
//some mounts like Headless Horseman's Mount or broom stick are skill based spell
// need to remove ALL arura related to mounts, this will stop client crash with broom stick
// and never endless flying after using Headless Horseman's Mount
if (mode & AURA_EFFECT_HANDLE_REAL)
- {
target->RemoveAurasByType(SPELL_AURA_MOUNTED);
+ if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)
// remove speed aura
if (MountCapabilityEntry const* mountCapability = sMountCapabilityStore.LookupEntry(GetAmount()))
target->RemoveAurasDueToSpell(mountCapability->ModSpellAuraID, target->GetGUID());
- }
}
}
@@ -6008,6 +6009,14 @@ void AuraEffect::HandleStoreTeleportReturnPoint(AuraApplication const* aurApp, u
playerTarget->RemoveStoredAuraTeleportLocation(GetSpellInfo()->Id);
}
+void AuraEffect::HandleMountRestrictions(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
+{
+ if (!(mode & AURA_EFFECT_HANDLE_REAL))
+ return;
+
+ aurApp->GetTarget()->UpdateMountCapability();
+}
+
void AuraEffect::HandleCosmeticMounted(AuraApplication const* aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index 7f62550a250..ef071b9e373 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -321,6 +321,7 @@ class TC_GAME_API AuraEffect
void HandleTriggerSpellOnPowerAmount(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleTriggerSpellOnPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleStoreTeleportReturnPoint(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleMountRestrictions(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleCosmeticMounted(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleSuppressItemPassiveEffectBySpellLabel(AuraApplication const* aurApp, uint8 mode, bool apply) const;