mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Bots fly/follow (movePoint core refactor), water walking fixes (#1825)
Closer the original solution, i dont wanna drift to much away without really good reason. At this point i still see NPC and bots moving through the levels or even falling out the levels here and there. I verified whether the MovePoint signature changes and related params itself in playerbots has anything todo with it, even when params are hardcoded the behavior remains. It could be deeper problem, but for now it seems core problem. Therefore i dont wanna change to much until the dust has settled a bit in core itself. I havent implemented moveTakeOff or moveLand which are basically responsible for the transitions phases between ground and air visa versa. I have version where i use takeOff for the animation, which means moving vertical. For now i am gonna leave for what it is. PS: also includes additional movement fix for AreaTriggerAction which we missed first time after the core update on movements. @Wishmaster117 Been testing and trying a lot in the background on find solutions and causes. The general solutions remains removed some tweaks, altered code here and there. With the general idea to keep closer to the original code for now at least. Testing: - Class abilities: Slow fall (priest), Flight Form (druid) : Green - BG: Green - Swimming and walking shallow waters: Green - Takeoff and land when following master: Green - Boat and zeppelins: Green - Flymount and ground walking: Green - Water Walking (shaman), Path of Frost (DK): Green - Water Walking (shaman), Path of Frost (DK) transisions; flying, swimming, water walking: Green Skipping pets when group water walking, path of frost, once core pathing changes has settled more i will add it. Which is easy but i dont wanna add more edge cases and code branches for now.
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
|
||||
#include "Corpse.h"
|
||||
#include "Event.h"
|
||||
#include "FleeManager.h"
|
||||
#include "G3D/Vector3.h"
|
||||
@@ -41,7 +42,6 @@
|
||||
#include "Unit.h"
|
||||
#include "Vehicle.h"
|
||||
#include "WaypointMovementGenerator.h"
|
||||
#include "Corpse.h"
|
||||
|
||||
MovementAction::MovementAction(PlayerbotAI* botAI, std::string const name) : Action(botAI, name)
|
||||
{
|
||||
@@ -192,14 +192,15 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool generatePath = !bot->IsFlying() && !bot->isSwimming();
|
||||
bool disableMoveSplinePath = sPlayerbotAIConfig->disableMoveSplinePath >= 2 ||
|
||||
(sPlayerbotAIConfig->disableMoveSplinePath == 1 && bot->InBattleground());
|
||||
bool disableMoveSplinePath =
|
||||
sPlayerbotAIConfig->disableMoveSplinePath >= 2 ||
|
||||
(sPlayerbotAIConfig->disableMoveSplinePath == 1 && bot->InBattleground());
|
||||
if (Vehicle* vehicle = bot->GetVehicle())
|
||||
{
|
||||
VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(bot);
|
||||
Unit* vehicleBase = vehicle->GetBase();
|
||||
// If the mover (vehicle) can fly, we DO NOT want an mmaps path (2D ground) => disable pathfinding
|
||||
generatePath = !vehicleBase || !vehicleBase->CanFly();
|
||||
if (!vehicleBase || !seat || !seat->CanControl()) // is passenger and cant move anyway
|
||||
return false;
|
||||
@@ -207,22 +208,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
||||
float distance = vehicleBase->GetExactDist(x, y, z); // use vehicle distance, not bot
|
||||
if (distance > 0.01f)
|
||||
{
|
||||
MotionMaster& mm = *vehicleBase->GetMotionMaster(); // need to move vehicle, not bot
|
||||
// Disable ground pathing if the bot/master/vehicle are flying
|
||||
auto isFlying = [](Unit* u){ return u && (u->HasUnitMovementFlag(MOVEMENTFLAG_FLYING) || u->IsInFlight()); };
|
||||
bool allowPathVeh = generatePath;
|
||||
Unit* masterVeh = botAI ? botAI->GetMaster() : nullptr;
|
||||
if (isFlying(vehicleBase) || isFlying(bot) || isFlying(masterVeh))
|
||||
allowPathVeh = false;
|
||||
mm.Clear();
|
||||
if (!backwards)
|
||||
{
|
||||
mm.MovePoint(0, x, y, z, FORCED_MOVEMENT_NONE, 0.0f, 0.0f, allowPathVeh);
|
||||
}
|
||||
else
|
||||
{
|
||||
mm.MovePointBackwards(0, x, y, z, allowPathVeh);
|
||||
}
|
||||
DoMovePoint(vehicleBase, x, y, z, generatePath, backwards);
|
||||
float speed = backwards ? vehicleBase->GetSpeed(MOVE_RUN_BACK) : vehicleBase->GetSpeed(MOVE_RUN);
|
||||
float delay = 1000.0f * (distance / speed);
|
||||
if (lessDelay)
|
||||
@@ -248,23 +234,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
||||
// bot->CastStop();
|
||||
// botAI->InterruptSpell();
|
||||
// }
|
||||
|
||||
MotionMaster& mm = *bot->GetMotionMaster();
|
||||
// No ground pathfinding if the bot/master are flying => allow true 3D (Z) movement
|
||||
auto isFlying = [](Unit* u){ return u && (u->HasUnitMovementFlag(MOVEMENTFLAG_FLYING) || u->IsInFlight()); };
|
||||
bool allowPath = generatePath;
|
||||
Unit* master = botAI ? botAI->GetMaster() : nullptr;
|
||||
if (isFlying(bot) || isFlying(master))
|
||||
allowPath = false;
|
||||
mm.Clear();
|
||||
if (!backwards)
|
||||
{
|
||||
mm.MovePoint(0, x, y, z, FORCED_MOVEMENT_NONE, 0.0f, 0.0f, allowPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
mm.MovePointBackwards(0, x, y, z, allowPath);
|
||||
}
|
||||
DoMovePoint(bot, x, y, z, generatePath, backwards);
|
||||
float delay = 1000.0f * MoveDelay(distance, backwards);
|
||||
if (lessDelay)
|
||||
{
|
||||
@@ -282,9 +252,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
||||
Movement::PointsArray path =
|
||||
SearchForBestPath(x, y, z, modifiedZ, sPlayerbotAIConfig->maxMovementSearchTime, normal_only);
|
||||
if (modifiedZ == INVALID_HEIGHT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
float distance = bot->GetExactDist(x, y, modifiedZ);
|
||||
if (distance > 0.01f)
|
||||
{
|
||||
@@ -296,24 +264,8 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
||||
// bot->CastStop();
|
||||
// botAI->InterruptSpell();
|
||||
// }
|
||||
|
||||
MotionMaster& mm = *bot->GetMotionMaster();
|
||||
G3D::Vector3 endP = path.back();
|
||||
// No ground pathfinding if the bot/master are flying => allow true 3D (Z) movement
|
||||
auto isFlying = [](Unit* u){ return u && (u->HasUnitMovementFlag(MOVEMENTFLAG_FLYING) || u->IsInFlight()); };
|
||||
bool allowPath = generatePath;
|
||||
Unit* master = botAI ? botAI->GetMaster() : nullptr;
|
||||
if (isFlying(bot) || isFlying(master))
|
||||
allowPath = false;
|
||||
mm.Clear();
|
||||
if (!backwards)
|
||||
{
|
||||
mm.MovePoint(0, x, y, z, FORCED_MOVEMENT_NONE, 0.0f, 0.0f, allowPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
mm.MovePointBackwards(0, x, y, z, allowPath);
|
||||
}
|
||||
DoMovePoint(bot, x, y, z, generatePath, backwards);
|
||||
float delay = 1000.0f * MoveDelay(distance, backwards);
|
||||
if (lessDelay)
|
||||
{
|
||||
@@ -581,9 +533,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
||||
// bool goTaxi = bot->ActivateTaxiPathTo({ tEntry->from, tEntry->to }, unit, 1);
|
||||
|
||||
// if (botAI->HasCheat(BotCheatMask::gold))
|
||||
// {
|
||||
// bot->SetMoney(botMoney);
|
||||
// }
|
||||
// LOG_DEBUG("playerbots", "goTaxi");
|
||||
// return goTaxi;
|
||||
// }
|
||||
@@ -874,7 +824,7 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance)
|
||||
|
||||
float deltaAngle = Position::NormalizeOrientation(targetOrientation - target->GetAngle(bot));
|
||||
if (deltaAngle > M_PI)
|
||||
deltaAngle -= 2.0f * M_PI; // -PI..PI
|
||||
deltaAngle -= 2.0f * M_PI; // -PI..PI
|
||||
// if target is moving forward and moving far away, predict the position
|
||||
bool behind = fabs(deltaAngle) > M_PI_2;
|
||||
if (target->HasUnitMovementFlag(MOVEMENTFLAG_FORWARD) && behind)
|
||||
@@ -882,8 +832,8 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance)
|
||||
float predictDis = std::min(3.0f, target->GetObjectSize() * 2);
|
||||
tx += cos(target->GetOrientation()) * predictDis;
|
||||
ty += sin(target->GetOrientation()) * predictDis;
|
||||
if (!target->GetMap()->CheckCollisionAndGetValidCoords(target, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),
|
||||
tx, ty, tz))
|
||||
if (!target->GetMap()->CheckCollisionAndGetValidCoords(target, target->GetPositionX(), target->GetPositionY(),
|
||||
target->GetPositionZ(), tx, ty, tz))
|
||||
{
|
||||
tx = target->GetPositionX();
|
||||
ty = target->GetPositionY();
|
||||
@@ -1001,9 +951,8 @@ bool MovementAction::IsMovingAllowed()
|
||||
return false;
|
||||
|
||||
if (bot->isFrozen() || bot->IsPolymorphed() || (bot->isDead() && !bot->HasPlayerFlag(PLAYER_FLAGS_GHOST)) ||
|
||||
bot->IsBeingTeleported() || bot->HasRootAura() || bot->HasSpiritOfRedemptionAura() ||
|
||||
bot->HasConfuseAura() || bot->IsCharmed() || bot->HasStunAura() ||
|
||||
bot->IsInFlight() || bot->HasUnitState(UNIT_STATE_LOST_CONTROL))
|
||||
bot->IsBeingTeleported() || bot->HasRootAura() || bot->HasSpiritOfRedemptionAura() || bot->HasConfuseAura() ||
|
||||
bot->IsCharmed() || bot->HasStunAura() || bot->IsInFlight() || bot->HasUnitState(UNIT_STATE_LOST_CONTROL))
|
||||
return false;
|
||||
|
||||
if (bot->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) != NULL_MOTION_TYPE)
|
||||
@@ -1022,64 +971,59 @@ bool MovementAction::Follow(Unit* target, float distance) { return Follow(target
|
||||
|
||||
void MovementAction::UpdateMovementState()
|
||||
{
|
||||
int8 botInLiquidState = bot->GetLiquidData().Status;
|
||||
// state flags
|
||||
const float gLvlZ = bot->GetMapWaterOrGroundLevel(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ());
|
||||
const bool onGround = bot->GetPositionZ() < gLvlZ + 1.f;
|
||||
const bool wantsToFly = bot->HasIncreaseMountedFlightSpeedAura() || bot->HasFlyAura();
|
||||
const auto master = botAI ? botAI->GetMaster() : nullptr; // real or not
|
||||
const bool masterIsFlying = master && master->HasUnitMovementFlag(MOVEMENTFLAG_FLYING);
|
||||
const bool isFlying = bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING);
|
||||
const auto liquidState = bot->GetLiquidData().Status; // default LIQUID_MAP_NO_WATER
|
||||
const bool isWaterArea = liquidState != LIQUID_MAP_NO_WATER;
|
||||
const bool isUnderWater = liquidState == LIQUID_MAP_UNDER_WATER;
|
||||
const bool isInWater = liquidState == LIQUID_MAP_IN_WATER;
|
||||
const bool isWaterWalking = bot->HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
|
||||
const bool isSwimming = bot->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
|
||||
const bool wantsToWaterWalk = bot->HasWaterWalkAura();
|
||||
const bool wantsToSwim = isInWater || isUnderWater;
|
||||
|
||||
if (botInLiquidState == LIQUID_MAP_IN_WATER || botInLiquidState == LIQUID_MAP_UNDER_WATER)
|
||||
// handle water state
|
||||
if (isWaterArea)
|
||||
{
|
||||
bot->SetSwim(true);
|
||||
// water walking
|
||||
if (wantsToWaterWalk && !isWaterWalking && !isUnderWater && !isFlying)
|
||||
{
|
||||
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
|
||||
bot->AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
|
||||
bot->SendMovementFlagUpdate();
|
||||
}
|
||||
// swimming
|
||||
else if (wantsToSwim && !isSwimming && !wantsToWaterWalk && !isFlying)
|
||||
{
|
||||
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
|
||||
bot->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
|
||||
bot->SendMovementFlagUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bot->SetSwim(false);
|
||||
// reset flags, if not will inherit incorrect walk speed here and there
|
||||
// when transistions between land and water.
|
||||
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
|
||||
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
|
||||
bot->SendMovementFlagUpdate();
|
||||
}
|
||||
|
||||
bool onGround = bot->GetPositionZ() <
|
||||
bot->GetMapWaterOrGroundLevel(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()) + 1.0f;
|
||||
|
||||
// Keep bot->SendMovementFlagUpdate() withing the if statements to not intefere with bot behavior on ground/(shallow) waters
|
||||
|
||||
bool hasFlightAura = bot->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || bot->HasAuraType(SPELL_AURA_FLY);
|
||||
if (hasFlightAura)
|
||||
// handle flying state
|
||||
if (wantsToFly && !isFlying && masterIsFlying)
|
||||
{
|
||||
bool changed = false;
|
||||
if (!bot->HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY))
|
||||
{
|
||||
bot->AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
|
||||
changed = true;
|
||||
}
|
||||
if (!bot->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY))
|
||||
{
|
||||
bot->AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
|
||||
changed = true;
|
||||
}
|
||||
if (!bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING))
|
||||
{
|
||||
bot->AddUnitMovementFlag(MOVEMENTFLAG_FLYING);
|
||||
changed = true;
|
||||
}
|
||||
if (changed)
|
||||
bot->SendMovementFlagUpdate();
|
||||
bot->AddUnitMovementFlag(MOVEMENTFLAG_FLYING);
|
||||
bot->SendMovementFlagUpdate();
|
||||
}
|
||||
else if (!hasFlightAura)
|
||||
else if ((!wantsToFly || onGround) && isFlying)
|
||||
{
|
||||
bool changed = false;
|
||||
if (bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING))
|
||||
{
|
||||
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING);
|
||||
changed = true;
|
||||
}
|
||||
if (bot->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY))
|
||||
{
|
||||
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
|
||||
changed = true;
|
||||
}
|
||||
if (bot->HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY))
|
||||
{
|
||||
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
|
||||
changed = true;
|
||||
}
|
||||
if (changed)
|
||||
bot->SendMovementFlagUpdate();
|
||||
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING);
|
||||
bot->SendMovementFlagUpdate();
|
||||
}
|
||||
|
||||
// See if the bot is currently slowed, rooted, or otherwise unable to move
|
||||
@@ -1180,6 +1124,13 @@ bool MovementAction::Follow(Unit* target, float distance, float angle)
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
if (!bot->InBattleground() && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target),
|
||||
sPlayerbotAIConfig->followDistance))
|
||||
{
|
||||
// botAI->TellError("No need to follow");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if (!bot->InBattleground()
|
||||
&& sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target->GetPositionX(),
|
||||
@@ -1297,17 +1248,21 @@ bool MovementAction::Follow(Unit* target, float distance, float angle)
|
||||
return MoveTo(target, sPlayerbotAIConfig->followDistance);
|
||||
}
|
||||
|
||||
if (sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target),
|
||||
sPlayerbotAIConfig->followDistance))
|
||||
{
|
||||
// botAI->TellError("No need to follow");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target->IsFriendlyTo(bot) && bot->IsMounted() && AI_VALUE(GuidVector, "all targets").empty())
|
||||
distance += angle;
|
||||
|
||||
// Do not cancel follow if the 2D distance is short but the Z still differs (e.g., master above).
|
||||
float dz1 = fabs(bot->GetPositionZ() - target->GetPositionZ());
|
||||
if (!bot->InBattleground()
|
||||
&& sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target), sPlayerbotAIConfig->followDistance)
|
||||
&& dz1 < sPlayerbotAIConfig->contactDistance)
|
||||
if (!bot->InBattleground() && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target),
|
||||
sPlayerbotAIConfig->followDistance))
|
||||
{
|
||||
// botAI->TellError("No need to follow");
|
||||
return false; // truly in range (2D and Z) => no need to move
|
||||
return false;
|
||||
}
|
||||
|
||||
bot->HandleEmoteCommand(0);
|
||||
@@ -1388,7 +1343,7 @@ float MovementAction::MoveDelay(float distance, bool backwards)
|
||||
}
|
||||
else
|
||||
{
|
||||
speed = backwards ? bot->GetSpeed(MOVE_RUN_BACK) :bot->GetSpeed(MOVE_RUN);
|
||||
speed = backwards ? bot->GetSpeed(MOVE_RUN_BACK) : bot->GetSpeed(MOVE_RUN);
|
||||
}
|
||||
float delay = distance / speed;
|
||||
return delay;
|
||||
@@ -1418,8 +1373,7 @@ void MovementAction::SetNextMovementDelay(float delayMillis)
|
||||
{
|
||||
AI_VALUE(LastMovement&, "last movement")
|
||||
.Set(bot->GetMapId(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetOrientation(),
|
||||
delayMillis,
|
||||
MovementPriority::MOVEMENT_FORCED);
|
||||
delayMillis, MovementPriority::MOVEMENT_FORCED);
|
||||
}
|
||||
|
||||
bool MovementAction::Flee(Unit* target)
|
||||
@@ -1633,7 +1587,8 @@ bool MovementAction::MoveAway(Unit* target, float distance, bool backwards)
|
||||
dz = bot->GetPositionZ();
|
||||
exact = false;
|
||||
}
|
||||
if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true, exact, MovementPriority::MOVEMENT_COMBAT, false, backwards))
|
||||
if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true, exact, MovementPriority::MOVEMENT_COMBAT, false,
|
||||
backwards))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -1655,7 +1610,8 @@ bool MovementAction::MoveAway(Unit* target, float distance, bool backwards)
|
||||
dz = bot->GetPositionZ();
|
||||
exact = false;
|
||||
}
|
||||
if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true, exact, MovementPriority::MOVEMENT_COMBAT, false, backwards))
|
||||
if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true, exact, MovementPriority::MOVEMENT_COMBAT, false,
|
||||
backwards))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -1704,7 +1660,7 @@ bool MovementAction::Move(float angle, float distance)
|
||||
float x = bot->GetPositionX() + cos(angle) * distance;
|
||||
float y = bot->GetPositionY() + sin(angle) * distance;
|
||||
|
||||
//TODO do we need GetMapWaterOrGroundLevel() if we're using CheckCollisionAndGetValidCoords() ?
|
||||
// TODO do we need GetMapWaterOrGroundLevel() if we're using CheckCollisionAndGetValidCoords() ?
|
||||
float z = bot->GetMapWaterOrGroundLevel(x, y, bot->GetPositionZ());
|
||||
if (z == -100000.0f || z == -200000.0f)
|
||||
z = bot->GetPositionZ();
|
||||
@@ -1758,9 +1714,7 @@ bool MovementAction::MoveInside(uint32 mapId, float x, float y, float z, float d
|
||||
// min_length = gen.getPathLength();
|
||||
// current_z = modified_z;
|
||||
// if (abs(current_z - z) < 0.5f)
|
||||
// {
|
||||
// return current_z;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// for (delta = range / 2 + step; delta <= range; delta += 2) {
|
||||
@@ -1857,6 +1811,59 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y,
|
||||
return result;
|
||||
}
|
||||
|
||||
void MovementAction::DoMovePoint(Unit* unit, float x, float y, float z, bool generatePath, bool backwards)
|
||||
{
|
||||
if (!unit)
|
||||
return;
|
||||
|
||||
MotionMaster* mm = unit->GetMotionMaster();
|
||||
if (!mm)
|
||||
return;
|
||||
|
||||
// enable flying
|
||||
if (unit->HasUnitMovementFlag(MOVEMENTFLAG_FLYING))
|
||||
{
|
||||
unit->AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
|
||||
unit->AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
|
||||
}
|
||||
else
|
||||
{
|
||||
unit->RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
|
||||
unit->RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
|
||||
}
|
||||
|
||||
// enable water walking
|
||||
if (unit->HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING))
|
||||
{
|
||||
float gLvlZ = unit->GetMapWaterOrGroundLevel(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ());
|
||||
unit->UpdatePosition(unit->GetPositionX(), unit->GetPositionY(), gLvlZ, false);
|
||||
// z = gLvlZ; do not overwrite Z axex, otherwise you wont be able to steer the bots into swimming when water
|
||||
// walking.
|
||||
}
|
||||
|
||||
mm->Clear();
|
||||
if (backwards)
|
||||
{
|
||||
mm->MovePointBackwards(
|
||||
/*id*/ 0,
|
||||
/*coords*/ x, y, z,
|
||||
/*generatePath*/ generatePath,
|
||||
/*forceDestination*/ false);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
mm->MovePoint(
|
||||
/*id*/ 0,
|
||||
/*coords*/ x, y, z,
|
||||
/*forcedMovement*/ FORCED_MOVEMENT_NONE,
|
||||
/*speed*/ 0.f,
|
||||
/*orientation*/ 0.f,
|
||||
/*generatePath*/ generatePath, // true => terrain path (2d mmap); false => straight spline (3d vmap)
|
||||
/*forceDestination*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
bool FleeAction::Execute(Event event)
|
||||
{
|
||||
return MoveAway(AI_VALUE(Unit*, "current target"), sPlayerbotAIConfig->fleeDistance, true);
|
||||
@@ -1937,7 +1944,8 @@ bool AvoidAoeAction::AvoidAuraWithDynamicObj()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(spellInfo->Id) != sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end())
|
||||
if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(spellInfo->Id) !=
|
||||
sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end())
|
||||
return false;
|
||||
|
||||
DynamicObject* dynOwner = aura->GetDynobjOwner();
|
||||
@@ -2002,7 +2010,8 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(spellId) != sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end())
|
||||
if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(spellId) !=
|
||||
sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end())
|
||||
continue;
|
||||
|
||||
const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId);
|
||||
@@ -2028,7 +2037,8 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage()
|
||||
lastTellTimer = time(NULL);
|
||||
lastMoveTimer = getMSTime();
|
||||
std::ostringstream out;
|
||||
out << "I'm avoiding " << name.str() << " (" << spellInfo->Id << ")" << " Radius " << radius << " - [Trap]";
|
||||
out << "I'm avoiding " << name.str() << " (" << spellInfo->Id << ")" << " Radius " << radius
|
||||
<< " - [Trap]";
|
||||
bot->Say(out.str(), LANG_UNIVERSAL);
|
||||
}
|
||||
return true;
|
||||
@@ -2071,7 +2081,8 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura()
|
||||
sSpellMgr->GetSpellInfo(spellInfo->Effects[aurEff->GetEffIndex()].TriggerSpell);
|
||||
if (!triggerSpellInfo)
|
||||
continue;
|
||||
if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(triggerSpellInfo->Id) != sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end())
|
||||
if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(triggerSpellInfo->Id) !=
|
||||
sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end())
|
||||
return false;
|
||||
for (int j = 0; j < MAX_SPELL_EFFECTS; j++)
|
||||
{
|
||||
@@ -2093,7 +2104,8 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura()
|
||||
lastTellTimer = time(NULL);
|
||||
lastMoveTimer = getMSTime();
|
||||
std::ostringstream out;
|
||||
out << "I'm avoiding " << name.str() << " (" << triggerSpellInfo->Id << ")" << " Radius " << radius << " - [Unit Trigger]";
|
||||
out << "I'm avoiding " << name.str() << " (" << triggerSpellInfo->Id << ")"
|
||||
<< " Radius " << radius << " - [Unit Trigger]";
|
||||
bot->Say(out.str(), LANG_UNIVERSAL);
|
||||
}
|
||||
}
|
||||
@@ -2112,7 +2124,8 @@ Position MovementAction::BestPositionForMeleeToFlee(Position pos, float radius)
|
||||
if (currentTarget)
|
||||
{
|
||||
// Normally, move to left or right is the best position
|
||||
bool isTanking = (!currentTarget->isFrozen() && !currentTarget->HasRootAura()) && (currentTarget->GetVictim() == bot);
|
||||
bool isTanking = (!currentTarget->isFrozen()
|
||||
&& !currentTarget->HasRootAura()) && (currentTarget->GetVictim() == bot);
|
||||
float angle = bot->GetAngle(currentTarget);
|
||||
float angleLeft = angle + (float)M_PI / 2;
|
||||
float angleRight = angle - (float)M_PI / 2;
|
||||
@@ -2327,8 +2340,7 @@ bool CombatFormationMoveAction::isUseful()
|
||||
bool CombatFormationMoveAction::Execute(Event event)
|
||||
{
|
||||
float dis = AI_VALUE(float, "disperse distance");
|
||||
if (dis <= 0.0f ||
|
||||
(!bot->IsInCombat() && botAI->HasStrategy("stay", BotState::BOT_STATE_NON_COMBAT)) ||
|
||||
if (dis <= 0.0f || (!bot->IsInCombat() && botAI->HasStrategy("stay", BotState::BOT_STATE_NON_COMBAT)) ||
|
||||
(bot->IsInCombat() && botAI->HasStrategy("stay", BotState::BOT_STATE_COMBAT)))
|
||||
return false;
|
||||
Player* playerToLeave = NearestGroupMember(dis);
|
||||
@@ -2478,7 +2490,7 @@ bool TankFaceAction::Execute(Event event)
|
||||
|
||||
float deltaAngle = Position::NormalizeOrientation(averageAngle - target->GetAngle(bot));
|
||||
if (deltaAngle > M_PI)
|
||||
deltaAngle -= 2.0f * M_PI; // -PI..PI
|
||||
deltaAngle -= 2.0f * M_PI; // -PI..PI
|
||||
|
||||
float tolerable = M_PI_2;
|
||||
|
||||
@@ -2489,12 +2501,13 @@ bool TankFaceAction::Execute(Event event)
|
||||
float goodAngle2 = Position::NormalizeOrientation(averageAngle - M_PI * 3 / 5);
|
||||
|
||||
// if dist < bot->GetMeleeRange(target) / 2, target will move backward
|
||||
float dist = std::max(bot->GetExactDist(target), bot->GetMeleeRange(target) / 2) - bot->GetCombatReach() - target->GetCombatReach();
|
||||
float dist = std::max(bot->GetExactDist(target), bot->GetMeleeRange(target) / 2) - bot->GetCombatReach() -
|
||||
target->GetCombatReach();
|
||||
std::vector<Position> availablePos;
|
||||
float x, y, z;
|
||||
target->GetNearPoint(bot, x, y, z, 0.0f, dist, goodAngle1);
|
||||
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||
x, y, z))
|
||||
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||
bot->GetPositionZ(), x, y, z))
|
||||
{
|
||||
/// @todo: movement control now is a mess, prepare to rewrite
|
||||
std::list<FleeInfo>& infoList = AI_VALUE(std::list<FleeInfo>&, "recently flee info");
|
||||
@@ -2506,8 +2519,8 @@ bool TankFaceAction::Execute(Event event)
|
||||
}
|
||||
}
|
||||
target->GetNearPoint(bot, x, y, z, 0.0f, dist, goodAngle2);
|
||||
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||
x, y, z))
|
||||
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||
bot->GetPositionZ(), x, y, z))
|
||||
{
|
||||
std::list<FleeInfo>& infoList = AI_VALUE(std::list<FleeInfo>&, "recently flee info");
|
||||
Position pos(x, y, z);
|
||||
@@ -2520,13 +2533,15 @@ bool TankFaceAction::Execute(Event event)
|
||||
if (availablePos.empty())
|
||||
return false;
|
||||
Position nearest = GetNearestPosition(availablePos);
|
||||
return MoveTo(bot->GetMapId(), nearest.GetPositionX(), nearest.GetPositionY(), nearest.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT);
|
||||
return MoveTo(bot->GetMapId(), nearest.GetPositionX(), nearest.GetPositionY(), nearest.GetPositionZ(), false, false,
|
||||
false, true, MovementPriority::MOVEMENT_COMBAT);
|
||||
}
|
||||
|
||||
bool RearFlankAction::isUseful()
|
||||
{
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
if (!target) { return false; }
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
// Need to double the front angle check to account for mirrored angle.
|
||||
bool inFront = target->HasInArc(2.f * minAngle, bot);
|
||||
@@ -2540,7 +2555,8 @@ bool RearFlankAction::isUseful()
|
||||
bool RearFlankAction::Execute(Event event)
|
||||
{
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
if (!target) { return false; }
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
float angle = frand(minAngle, maxAngle);
|
||||
float baseDistance = bot->GetMeleeRange(target) * 0.5f;
|
||||
@@ -2559,8 +2575,8 @@ bool RearFlankAction::Execute(Event event)
|
||||
destination = &rightFlank;
|
||||
}
|
||||
|
||||
return MoveTo(bot->GetMapId(), destination->GetPositionX(), destination->GetPositionY(), destination->GetPositionZ(),
|
||||
false, false, false, true, MovementPriority::MOVEMENT_COMBAT);
|
||||
return MoveTo(bot->GetMapId(), destination->GetPositionX(), destination->GetPositionY(),
|
||||
destination->GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT);
|
||||
}
|
||||
|
||||
bool DisperseSetAction::Execute(Event event)
|
||||
@@ -2688,9 +2704,8 @@ bool SetFacingTargetAction::isUseful() { return !AI_VALUE2(bool, "facing", "curr
|
||||
bool SetFacingTargetAction::isPossible()
|
||||
{
|
||||
if (bot->isFrozen() || bot->IsPolymorphed() || (bot->isDead() && !bot->HasPlayerFlag(PLAYER_FLAGS_GHOST)) ||
|
||||
bot->IsBeingTeleported() || bot->HasConfuseAura() || bot->IsCharmed() ||
|
||||
bot->HasStunAura() || bot->IsInFlight() ||
|
||||
bot->HasUnitState(UNIT_STATE_LOST_CONTROL))
|
||||
bot->IsBeingTeleported() || bot->HasConfuseAura() || bot->IsCharmed() || bot->HasStunAura() ||
|
||||
bot->IsInFlight() || bot->HasUnitState(UNIT_STATE_LOST_CONTROL))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -2710,7 +2725,7 @@ bool SetBehindTargetAction::Execute(Event event)
|
||||
|
||||
float deltaAngle = Position::NormalizeOrientation(target->GetOrientation() - target->GetAngle(bot));
|
||||
if (deltaAngle > M_PI)
|
||||
deltaAngle -= 2.0f * M_PI; // -PI..PI
|
||||
deltaAngle -= 2.0f * M_PI; // -PI..PI
|
||||
|
||||
float tolerable = M_PI_2;
|
||||
|
||||
@@ -2720,12 +2735,13 @@ bool SetBehindTargetAction::Execute(Event event)
|
||||
float goodAngle1 = Position::NormalizeOrientation(target->GetOrientation() + M_PI * 3 / 5);
|
||||
float goodAngle2 = Position::NormalizeOrientation(target->GetOrientation() - M_PI * 3 / 5);
|
||||
|
||||
float dist = std::max(bot->GetExactDist(target), bot->GetMeleeRange(target) / 2) - bot->GetCombatReach() - target->GetCombatReach();
|
||||
float dist = std::max(bot->GetExactDist(target), bot->GetMeleeRange(target) / 2) - bot->GetCombatReach() -
|
||||
target->GetCombatReach();
|
||||
std::vector<Position> availablePos;
|
||||
float x, y, z;
|
||||
target->GetNearPoint(bot, x, y, z, 0.0f, dist, goodAngle1);
|
||||
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||
x, y, z))
|
||||
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||
bot->GetPositionZ(), x, y, z))
|
||||
{
|
||||
/// @todo: movement control now is a mess, prepare to rewrite
|
||||
std::list<FleeInfo>& infoList = AI_VALUE(std::list<FleeInfo>&, "recently flee info");
|
||||
@@ -2737,8 +2753,8 @@ bool SetBehindTargetAction::Execute(Event event)
|
||||
}
|
||||
}
|
||||
target->GetNearPoint(bot, x, y, z, 0.0f, dist, goodAngle2);
|
||||
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||
x, y, z))
|
||||
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||
bot->GetPositionZ(), x, y, z))
|
||||
{
|
||||
std::list<FleeInfo>& infoList = AI_VALUE(std::list<FleeInfo>&, "recently flee info");
|
||||
Position pos(x, y, z);
|
||||
@@ -2751,7 +2767,8 @@ bool SetBehindTargetAction::Execute(Event event)
|
||||
if (availablePos.empty())
|
||||
return false;
|
||||
Position nearest = GetNearestPosition(availablePos);
|
||||
return MoveTo(bot->GetMapId(), nearest.GetPositionX(), nearest.GetPositionY(), nearest.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT);
|
||||
return MoveTo(bot->GetMapId(), nearest.GetPositionX(), nearest.GetPositionY(), nearest.GetPositionZ(), false, false,
|
||||
false, true, MovementPriority::MOVEMENT_COMBAT);
|
||||
}
|
||||
|
||||
bool MoveOutOfCollisionAction::Execute(Event event)
|
||||
@@ -2822,7 +2839,7 @@ bool MoveFromGroupAction::Execute(Event event)
|
||||
{
|
||||
float distance = atoi(event.getParam().c_str());
|
||||
if (!distance)
|
||||
distance = 20.0f; // flee distance from config is too small for this
|
||||
distance = 20.0f; // flee distance from config is too small for this
|
||||
return MoveFromGroup(distance);
|
||||
}
|
||||
|
||||
@@ -2905,10 +2922,7 @@ bool MoveAwayFromCreatureAction::Execute(Event event)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MoveAwayFromCreatureAction::isPossible()
|
||||
{
|
||||
return bot->CanFreeMove();
|
||||
}
|
||||
bool MoveAwayFromCreatureAction::isPossible() { return bot->CanFreeMove(); }
|
||||
|
||||
bool MoveAwayFromPlayerWithDebuffAction::Execute(Event event)
|
||||
{
|
||||
@@ -2995,7 +3009,4 @@ bool MoveAwayFromPlayerWithDebuffAction::Execute(Event event)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MoveAwayFromPlayerWithDebuffAction::isPossible()
|
||||
{
|
||||
return bot->CanFreeMove();
|
||||
}
|
||||
bool MoveAwayFromPlayerWithDebuffAction::isPossible() { return bot->CanFreeMove(); }
|
||||
|
||||
Reference in New Issue
Block a user