diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 50675564..878888e1 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -721,6 +721,7 @@ void PlayerbotAI::HandleTeleportAck() bot->GetSession()->HandleMoveWorldportAck(); } // SetNextCheckDelay(urand(2000, 5000)); + SetNextCheckDelay(urand(500, 1500)); // short delay to break bursts without hindering gameplay if (sPlayerbotAIConfig->applyInstanceStrategies) ApplyInstanceStrategies(bot->GetMapId(), true); EvaluateHealerDpsStrategy(); diff --git a/src/Playerbots.h b/src/Playerbots.h index 5b82771b..3ed03f23 100644 --- a/src/Playerbots.h +++ b/src/Playerbots.h @@ -49,4 +49,46 @@ int strcmpi(char const* s1, char const* s2); #define GAI_VALUE(type, name) sSharedValueContext->getGlobalValue(name)->Get() #define GAI_VALUE2(type, name, param) sSharedValueContext->getGlobalValue(name, param)->Get() +// ---- Safe teleport wrappers (module-only) ---- +#include "Map.h" +#include +#include "TravelMgr.h" + +inline bool TeleportToSafe(Player* p, uint32 mapId, float x, float y, float z, float o) +{ + if (!p) return false; + + // If the height is invalid (-200000) or not finite, attempt ONE correction on the same map. + if (z <= -199000.0f || !std::isfinite(z)) + { + if (p->GetMapId() == mapId && p->GetMap()) + { + float hz = p->GetMap()->GetHeight(p->GetPhaseMask(), x, y, p->GetPositionZ(), true); + if (hz > -199000.0f && std::isfinite(hz)) + z = hz; + else + return false; // still invalid -> cancel the TP + } + else + { + return false; // different map: do not "guess" the height here + } + } + return p->TeleportTo(mapId, x, y, z, o); +} + +inline bool TeleportToSafe(Player* p, Position const& pos) +{ + // Position doesn't have mapId: we keep actual bot map + return TeleportToSafe(p, p->GetMapId(), + pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), + pos.GetOrientation()); +} + +inline bool TeleportToSafe(Player* p, WorldPosition pos) +{ + return TeleportToSafe(p, pos.getMapId(), pos.getX(), pos.getY(), pos.getZ(), pos.getO()); +} +// ---- /Safe teleport wrappers ---- + #endif diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index def80972..4f1cd1bb 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -1772,7 +1772,8 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); if (botAI) botAI->Reset(true); - bot->TeleportTo(loc.GetMapId(), x, y, z, 0); + //bot->TeleportTo(loc.GetMapId(), x, y, z, 0); + TeleportToSafe(bot, loc.GetMapId(), x, y, z, 0); // [Fix] Avoid silly teleports bot->SendMovementFlagUpdate(); if (pmo) @@ -3047,7 +3048,8 @@ void RandomPlayerbotMgr::OnPlayerLogin(Player* player) } while (true); } - player->TeleportTo(botPos); + // player->TeleportTo(botPos); + TeleportToSafe(player, botPos); // [Fix] Avoid silly teleports // player->Relocate(botPos.getX(), botPos.getY(), botPos.getZ(), botPos.getO()); } diff --git a/src/strategy/actions/BattleGroundJoinAction.cpp b/src/strategy/actions/BattleGroundJoinAction.cpp index 09523fd2..1e9d9598 100644 --- a/src/strategy/actions/BattleGroundJoinAction.cpp +++ b/src/strategy/actions/BattleGroundJoinAction.cpp @@ -176,7 +176,8 @@ bool BGJoinAction::gatherArenaTeam(ArenaType type) continue; memberBotAI->Reset(); - member->TeleportTo(bot->GetMapId(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), 0); + // member->TeleportTo(bot->GetMapId(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), 0); + TeleportToSafe(member, bot->GetMapId(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), 0); LOG_INFO("playerbots", "Bot {} <{}>: Member of <{}>", member->GetGUID().ToString().c_str(), member->GetName().c_str(), arenateam->GetName().c_str()); diff --git a/src/strategy/actions/BattleGroundTactics.cpp b/src/strategy/actions/BattleGroundTactics.cpp index fab932f7..0dfcd823 100644 --- a/src/strategy/actions/BattleGroundTactics.cpp +++ b/src/strategy/actions/BattleGroundTactics.cpp @@ -4289,9 +4289,11 @@ bool ArenaTactics::moveToCenter(Battleground* bg) { // they like to hang around at the tip of the pipes doing nothing, so we just teleport them down if (bot->GetDistance(1333.07f, 817.18f, 13.35f) < 4) - bot->TeleportTo(bg->GetMapId(), 1330.96f, 816.75f, 3.2f, bot->GetOrientation()); + // bot->TeleportTo(bg->GetMapId(), 1330.96f, 816.75f, 3.2f, bot->GetOrientation()); + TeleportToSafe(bot, bg->GetMapId(), 1330.96f, 816.75f, 3.2f, bot->GetOrientation()); // [Fix] Avaid silly teleport if (bot->GetDistance(1250.13f, 764.79f, 13.34f) < 4) - bot->TeleportTo(bg->GetMapId(), 1252.19f, 765.41f, 3.2f, bot->GetOrientation()); + // bot->TeleportTo(bg->GetMapId(), 1252.19f, 765.41f, 3.2f, bot->GetOrientation()); + TeleportToSafe(bot, bg->GetMapId(), 1252.19f, 765.41f, 3.2f, bot->GetOrientation()); // [Fix] Avaid silly teleport } break; case BATTLEGROUND_RV: diff --git a/src/strategy/actions/ReleaseSpiritAction.cpp b/src/strategy/actions/ReleaseSpiritAction.cpp index cff34f8d..12228603 100644 --- a/src/strategy/actions/ReleaseSpiritAction.cpp +++ b/src/strategy/actions/ReleaseSpiritAction.cpp @@ -147,7 +147,8 @@ bool AutoReleaseSpiritAction::HandleBattlegroundSpiritHealer() // and in IOC it's not within clicking range when they res in own base // Teleport to nearest friendly Spirit Healer when not currently in range of one. - bot->TeleportTo(bot->GetMapId(), spiritHealer->GetPositionX(), spiritHealer->GetPositionY(), spiritHealer->GetPositionZ(), 0.f); + // bot->TeleportTo(bot->GetMapId(), spiritHealer->GetPositionX(), spiritHealer->GetPositionY(), spiritHealer->GetPositionZ(), 0.f); + TeleportToSafe(bot, bot->GetMapId(), spiritHealer->GetPositionX(), spiritHealer->GetPositionY(), spiritHealer->GetPositionZ(), 0.f); // [Fix] Avoid silly teleport RESET_AI_VALUE(bool, "combat::self target"); RESET_AI_VALUE(WorldPosition, "current position"); } @@ -244,7 +245,8 @@ int64 RepopAction::CalculateDeadTime() const void RepopAction::PerformGraveyardTeleport(const GraveyardStruct* graveyard) const { - bot->TeleportTo(graveyard->Map, graveyard->x, graveyard->y, graveyard->z, 0.f); + // bot->TeleportTo(graveyard->Map, graveyard->x, graveyard->y, graveyard->z, 0.f); + TeleportToSafe(bot, graveyard->Map, graveyard->x, graveyard->y, graveyard->z, 0.f); // [Fix] Avoid Silly teleport RESET_AI_VALUE(bool, "combat::self target"); RESET_AI_VALUE(WorldPosition, "current position"); } diff --git a/src/strategy/actions/ReviveFromCorpseAction.cpp b/src/strategy/actions/ReviveFromCorpseAction.cpp index 960f438f..f55904cb 100644 --- a/src/strategy/actions/ReviveFromCorpseAction.cpp +++ b/src/strategy/actions/ReviveFromCorpseAction.cpp @@ -169,7 +169,8 @@ bool FindCorpseAction::Execute(Event event) if (deadTime > delay) { bot->GetMotionMaster()->Clear(); - bot->TeleportTo(moveToPos.getMapId(), moveToPos.getX(), moveToPos.getY(), moveToPos.getZ(), 0); + // bot->TeleportTo(moveToPos.getMapId(), moveToPos.getX(), moveToPos.getY(), moveToPos.getZ(), 0); + TeleportToSafe(bot, moveToPos.getMapId(), moveToPos.getX(), moveToPos.getY(), moveToPos.getZ(), 0); // [fix] Avoid Silly Teleport } moved = true; @@ -350,7 +351,8 @@ bool SpiritHealerAction::Execute(Event event) // if (!botAI->HasActivePlayerMaster()) // { context->GetValue("death count")->Set(dCount + 1); - return bot->TeleportTo(ClosestGrave->Map, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, 0.f); + // return bot->TeleportTo(ClosestGrave->Map, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, 0.f); + return TeleportToSafe(bot, ClosestGrave->Map, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, 0.f); // [Fix] Avoid Silly teleport // } // LOG_INFO("playerbots", "Bot {} {}:{} <{}> can't find a spirit healer", bot->GetGUID().ToString().c_str(), diff --git a/src/strategy/raids/icecrown/RaidIccActions.cpp b/src/strategy/raids/icecrown/RaidIccActions.cpp index eaad5d2f..0d135b59 100644 --- a/src/strategy/raids/icecrown/RaidIccActions.cpp +++ b/src/strategy/raids/icecrown/RaidIccActions.cpp @@ -957,7 +957,8 @@ bool IccGunshipTeleportHordeAction::Execute(Event event) bool IccGunshipTeleportHordeAction::TeleportTo(const Position& position) { - return bot->TeleportTo(bot->GetMapId(), position.GetPositionX(), position.GetPositionY(), position.GetPositionZ(), + // return bot->TeleportTo(bot->GetMapId(), position.GetPositionX(), position.GetPositionY(), position.GetPositionZ(), + return TeleportToSafe(bot, bot->GetMapId(), position.GetPositionX(), position.GetPositionY(), position.GetPositionZ(),// [Fix]Avoid silly teleport bot->GetOrientation()); } diff --git a/src/strategy/raids/ulduar/RaidUlduarActions.cpp b/src/strategy/raids/ulduar/RaidUlduarActions.cpp index 3d180820..8517a0bf 100644 --- a/src/strategy/raids/ulduar/RaidUlduarActions.cpp +++ b/src/strategy/raids/ulduar/RaidUlduarActions.cpp @@ -1357,10 +1357,14 @@ bool KologarnMarkDpsTargetAction::Execute(Event event) bool KologarnFallFromFloorAction::Execute(Event event) { - return bot->TeleportTo(bot->GetMapId(), ULDUAR_KOLOGARN_RESTORE_POSITION.GetPositionX(), + /*return bot->TeleportTo(bot->GetMapId(), ULDUAR_KOLOGARN_RESTORE_POSITION.GetPositionX(), ULDUAR_KOLOGARN_RESTORE_POSITION.GetPositionY(), ULDUAR_KOLOGARN_RESTORE_POSITION.GetPositionZ(), - ULDUAR_KOLOGARN_RESTORE_POSITION.GetOrientation()); + ULDUAR_KOLOGARN_RESTORE_POSITION.GetOrientation());*/ + return TeleportToSafe(bot, bot->GetMapId(), ULDUAR_KOLOGARN_RESTORE_POSITION.GetPositionX(), // [Fix] Avoid silly teleport + ULDUAR_KOLOGARN_RESTORE_POSITION.GetPositionY(), + ULDUAR_KOLOGARN_RESTORE_POSITION.GetPositionZ(), + ULDUAR_KOLOGARN_RESTORE_POSITION.GetOrientation()); } bool KologarnFallFromFloorAction::isUseful() @@ -1407,14 +1411,18 @@ bool KologarnEyebeamAction::Execute(Event event) KologarnEyebeamTrigger kologarnEyebeamTrigger(botAI); if (runToLeftSide) { - teleportedToPoint = bot->TeleportTo(bot->GetMapId(), ULDUAR_KOLOGARN_EYEBEAM_LEFT_POSITION.GetPositionX(), + // teleportedToPoint = bot->TeleportTo(bot->GetMapId(), ULDUAR_KOLOGARN_EYEBEAM_LEFT_POSITION.GetPositionX(), + teleportedToPoint = TeleportToSafe(bot, bot->GetMapId(), + ULDUAR_KOLOGARN_EYEBEAM_LEFT_POSITION.GetPositionX(), ULDUAR_KOLOGARN_EYEBEAM_LEFT_POSITION.GetPositionY(), ULDUAR_KOLOGARN_EYEBEAM_LEFT_POSITION.GetPositionZ(), ULDUAR_KOLOGARN_EYEBEAM_LEFT_POSITION.GetOrientation()); } else { - teleportedToPoint = bot->TeleportTo(bot->GetMapId(), ULDUAR_KOLOGARN_EYEBEAM_RIGHT_POSITION.GetPositionX(), + // teleportedToPoint = bot->TeleportTo(bot->GetMapId(), ULDUAR_KOLOGARN_EYEBEAM_RIGHT_POSITION.GetPositionX(), + teleportedToPoint = TeleportToSafe(bot, bot->GetMapId(), + ULDUAR_KOLOGARN_EYEBEAM_RIGHT_POSITION.GetPositionX(), ULDUAR_KOLOGARN_EYEBEAM_RIGHT_POSITION.GetPositionY(), ULDUAR_KOLOGARN_EYEBEAM_RIGHT_POSITION.GetPositionZ(), ULDUAR_KOLOGARN_EYEBEAM_RIGHT_POSITION.GetOrientation()); diff --git a/src/strategy/raids/vaultofarchavon/RaidVoAActions.cpp b/src/strategy/raids/vaultofarchavon/RaidVoAActions.cpp index 05d6328e..b41c670f 100644 --- a/src/strategy/raids/vaultofarchavon/RaidVoAActions.cpp +++ b/src/strategy/raids/vaultofarchavon/RaidVoAActions.cpp @@ -175,9 +175,13 @@ bool EmalonOverchargeAction::isUseful() bool EmalonFallFromFloorAction::Execute(Event event) { - return bot->TeleportTo(bot->GetMapId(), VOA_EMALON_RESTORE_POSITION.GetPositionX(), + /*return bot->TeleportTo(bot->GetMapId(), VOA_EMALON_RESTORE_POSITION.GetPositionX(), VOA_EMALON_RESTORE_POSITION.GetPositionY(), VOA_EMALON_RESTORE_POSITION.GetPositionZ(), - VOA_EMALON_RESTORE_POSITION.GetOrientation()); + VOA_EMALON_RESTORE_POSITION.GetOrientation());*/ + return TeleportToSafe(bot, bot->GetMapId(), VOA_EMALON_RESTORE_POSITION.GetPositionX(), //[Fix] Avoid Silly Teleport + VOA_EMALON_RESTORE_POSITION.GetPositionY(), + VOA_EMALON_RESTORE_POSITION.GetPositionZ(), + VOA_EMALON_RESTORE_POSITION.GetOrientation()); } bool EmalonFallFromFloorAction::isUseful() diff --git a/src/strategy/rpg/NewRpgBaseAction.cpp b/src/strategy/rpg/NewRpgBaseAction.cpp index 5e71c5c5..9b0ab2a1 100644 --- a/src/strategy/rpg/NewRpgBaseAction.cpp +++ b/src/strategy/rpg/NewRpgBaseAction.cpp @@ -67,7 +67,8 @@ bool NewRpgBaseAction::MoveFarTo(WorldPosition dest) bot->GetName(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId(), dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), dest.getMapId(), bot->GetZoneId(), zone_name); - return bot->TeleportTo(dest); + // return bot->TeleportTo(dest); + return TeleportToSafe(bot, dest); //[Fix] Avoid Silly teleport } float dis = bot->GetExactDist(dest);