|
17 | 17 | #include "SpellAuraEffects.h" |
18 | 18 |
|
19 | 19 | static constexpr uint32 SPELL_COLD_WEATHER_FLYING = 54197; |
| 20 | +static constexpr float PARACHUTE_LAND_THRESHOLD = 15.0f; |
20 | 21 |
|
21 | 22 | // Define the static map / init bool for caching bot preferred mount data globally |
22 | 23 | std::unordered_map<uint32, PreferredMountCache> CheckMountStateAction::mountCache; |
@@ -61,6 +62,21 @@ MountData CollectMountData(const Player* bot) |
61 | 62 |
|
62 | 63 | bool CheckMountStateAction::Execute(Event /*event*/) |
63 | 64 | { |
| 65 | + // Forced flight dismount: |
| 66 | + // Bots get stale flight movement flags after a forced dismount (e.g: Dalaran) because the post landing dismount cleanup |
| 67 | + // needs MSG_MOVE_FALL_LAND (a client opcode) and client movement packets. The stale flags cause the bot to be stuck with |
| 68 | + // the parachute, or even keep the bot hovering indefinitely and block MMAP routing. |
| 69 | + // Note: Without MSG_MOVE_FALL_LAND, HandleFall doesn't trigger, meaning bots don't get fall damage in forced dismounts anyway, |
| 70 | + // so the parachute usage here is more of an immersion feature. |
| 71 | + if (bot->HasFeatherFallAura()) |
| 72 | + { |
| 73 | + float floorZ = bot->GetMapHeight(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()); |
| 74 | + if (floorZ != INVALID_HEIGHT && floorZ != VMAP_INVALID_HEIGHT_VALUE && |
| 75 | + bot->GetPositionZ() - floorZ <= PARACHUTE_LAND_THRESHOLD) |
| 76 | + bot->RemoveAurasByType(SPELL_AURA_FEATHER_FALL); |
| 77 | + } |
| 78 | + ClearStaleFlightFlags(); |
| 79 | + |
64 | 80 | // Determine if there are no attackers |
65 | 81 | bool noAttackers = !AI_VALUE2(bool, "combat", "self target") || !AI_VALUE(uint8, "attacker count"); |
66 | 82 | bool enemy = AI_VALUE(Unit*, "enemy player target"); |
@@ -204,7 +220,7 @@ bool CheckMountStateAction::Mount() |
204 | 220 | // Get bot mount data |
205 | 221 | MountData mountData = CollectMountData(bot); |
206 | 222 | int32 masterMountType = GetMountType(master); |
207 | | - int32 masterSpeed = CalculateMasterMountSpeed(master, mountData); |
| 223 | + int32 masterSpeed = CalculateMasterMountSpeed(master); |
208 | 224 |
|
209 | 225 | // Try shapeshift |
210 | 226 | if (TryForms(master, masterMountType, masterSpeed)) |
@@ -234,14 +250,17 @@ void CheckMountStateAction::Dismount() |
234 | 250 | WorldPacket emptyPacket; |
235 | 251 | bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket); |
236 | 252 |
|
237 | | - bool const wantsFly = bot->HasIncreaseMountedFlightSpeedAura() || bot->HasFlyAura(); |
238 | | - bool const isWaterWalking = bot->HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); |
239 | | - bool const isFlying = bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING); |
240 | | - bool const hasGravityDisabled = bot->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); |
241 | | - if (!wantsFly && !isWaterWalking && (isFlying || hasGravityDisabled)) |
| 253 | + ClearStaleFlightFlags(); |
| 254 | +} |
| 255 | + |
| 256 | +void CheckMountStateAction::ClearStaleFlightFlags() |
| 257 | +{ |
| 258 | + if (bot->HasIncreaseMountedFlightSpeedAura() || bot->HasFlyAura()) |
| 259 | + return; |
| 260 | + |
| 261 | + if (bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY)) |
242 | 262 | { |
243 | | - bot->RemoveUnitMovementFlag( |
244 | | - MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY); |
| 263 | + bot->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_CAN_FLY); |
245 | 264 | if (!bot->IsRooted()) |
246 | 265 | bot->SendMovementFlagUpdate(); |
247 | 266 | } |
@@ -490,7 +509,7 @@ static bool BotCanUseFlyingMount(Player const* bot) |
490 | 509 | return true; |
491 | 510 | } |
492 | 511 |
|
493 | | -int32 CheckMountStateAction::CalculateMasterMountSpeed(Player* master, const MountData& mountData) const |
| 512 | +int32 CheckMountStateAction::CalculateMasterMountSpeed(Player* master) const |
494 | 513 | { |
495 | 514 | // Check riding skill and level requirements |
496 | 515 | int32 ridingSkill = bot->GetPureSkillValue(SKILL_RIDING); |
|
0 commit comments