diff options
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 22 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 1 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 103 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.h | 1 |
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; |
