Fix movement on ship

This commit is contained in:
Yunfan Li
2024-04-18 20:47:41 +08:00
parent e003ce99f0
commit 6dc6667920
5 changed files with 104 additions and 16 deletions

View File

@@ -844,7 +844,8 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet)
// vcos, vsin, horizontalSpeed, verticalSpeed, x, y, z, bot->GetRelativeAngle(vcos, vsin), bot->GetOrientation()); // vcos, vsin, horizontalSpeed, verticalSpeed, x, y, z, bot->GetRelativeAngle(vcos, vsin), bot->GetOrientation());
// bot->Say(speak, LANG_UNIVERSAL); // bot->Say(speak, LANG_UNIVERSAL);
// bot->GetClosePoint(x, y, z, bot->GetObjectSize(), dist, bot->GetAngle(vcos, vsin)); // bot->GetClosePoint(x, y, z, bot->GetObjectSize(), dist, bot->GetAngle(vcos, vsin));
bot->GetMotionMaster()->MoveJump(x, y, z, horizontalSpeed, verticalSpeed, 0, bot->GetSelectedUnit()); Unit* currentTarget = GetAiObjectContext()->GetValue<Unit*>("current target")->Get();
bot->GetMotionMaster()->MoveJump(x, y, z, horizontalSpeed, verticalSpeed, 0, currentTarget);
// bot->AddUnitMovementFlag(MOVEMENTFLAG_FALLING); // bot->AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
// bot->AddUnitMovementFlag(MOVEMENTFLAG_FORWARD); // bot->AddUnitMovementFlag(MOVEMENTFLAG_FORWARD);
// bot->m_movementInfo.AddMovementFlag(MOVEMENTFLAG_PENDING_STOP); // bot->m_movementInfo.AddMovementFlag(MOVEMENTFLAG_PENDING_STOP);

View File

@@ -14,6 +14,8 @@
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "Random.h" #include "Random.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include "SpellAuraEffects.h"
#include "SpellAuraEffects.h"
#include "SpellInfo.h" #include "SpellInfo.h"
#include "TargetedMovementGenerator.h" #include "TargetedMovementGenerator.h"
#include "Event.h" #include "Event.h"
@@ -177,7 +179,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
} }
} else { } else {
float modifiedZ; float modifiedZ;
Movement::PointsArray path = SearchForBestPath(x, y, z, modifiedZ, sPlayerbotAIConfig->maxMovementSearchTime); Movement::PointsArray path = SearchForBestPath(x, y, z, modifiedZ, sPlayerbotAIConfig->maxMovementSearchTime, normal_only);
if (modifiedZ == INVALID_HEIGHT) { if (modifiedZ == INVALID_HEIGHT) {
return false; return false;
} }
@@ -1409,23 +1411,25 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y,
{ {
bool found = false; bool found = false;
modified_z = INVALID_HEIGHT; modified_z = INVALID_HEIGHT;
float tempZ = bot->GetMapWaterOrGroundLevel(x, y, z); float tempZ = bot->GetMapHeight(x, y, z);
PathGenerator gen(bot); PathGenerator gen(bot);
gen.CalculatePath(x, y, tempZ); gen.CalculatePath(x, y, tempZ);
Movement::PointsArray result = gen.GetPath(); Movement::PointsArray result = gen.GetPath();
modified_z = tempZ;
float min_length = gen.getPathLength(); float min_length = gen.getPathLength();
if (gen.GetPathType() == PATHFIND_NORMAL && abs(tempZ - z) < 0.5f) { if (gen.GetPathType() == PATHFIND_NORMAL && abs(tempZ - z) < 0.5f) {
modified_z = tempZ;
return result; return result;
} }
// Start searching // Start searching
if (gen.GetPathType() == PATHFIND_NORMAL) { if (gen.GetPathType() == PATHFIND_NORMAL) {
found = true; found = true;
modified_z = tempZ;
} }
int count = 1; int count = 1;
for (float delta = step; count < maxSearchCount / 2 + 1; count++, delta += step) { for (float delta = step; count < maxSearchCount / 2 + 1; count++, delta += step) {
tempZ = bot->GetMapWaterOrGroundLevel(x, y, z + delta); tempZ = bot->GetMapHeight(x, y, z + delta);
if (tempZ == INVALID_HEIGHT) {
continue;
}
PathGenerator gen(bot); PathGenerator gen(bot);
gen.CalculatePath(x, y, tempZ); gen.CalculatePath(x, y, tempZ);
if (gen.GetPathType() == PATHFIND_NORMAL && gen.getPathLength() < min_length) { if (gen.GetPathType() == PATHFIND_NORMAL && gen.getPathLength() < min_length) {
@@ -1436,7 +1440,10 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y,
} }
} }
for (float delta = -step; count < maxSearchCount; count++, delta -= step) { for (float delta = -step; count < maxSearchCount; count++, delta -= step) {
tempZ = bot->GetMapWaterOrGroundLevel(x, y, z + delta); tempZ = bot->GetMapHeight(x, y, z + delta);
if (tempZ == INVALID_HEIGHT) {
continue;
}
PathGenerator gen(bot); PathGenerator gen(bot);
gen.CalculatePath(x, y, tempZ); gen.CalculatePath(x, y, tempZ);
if (gen.GetPathType() == PATHFIND_NORMAL && gen.getPathLength() < min_length) { if (gen.GetPathType() == PATHFIND_NORMAL && gen.getPathLength() < min_length) {
@@ -1447,6 +1454,7 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y,
} }
} }
if (!found && normal_only) { if (!found && normal_only) {
modified_z = INVALID_HEIGHT;
return Movement::PointsArray{}; return Movement::PointsArray{};
} }
if (!found && !normal_only) { if (!found && !normal_only) {
@@ -1488,7 +1496,8 @@ bool FleeWithPetAction::Execute(Event event)
bool AvoidAoeAction::isUseful() bool AvoidAoeAction::isUseful()
{ {
GuidVector traps = AI_VALUE(GuidVector, "nearest trap with damage"); GuidVector traps = AI_VALUE(GuidVector, "nearest trap with damage");
return AI_VALUE(Aura*, "area debuff") || !traps.empty(); GuidVector triggers = AI_VALUE(GuidVector, "possible triggers");
return AI_VALUE(Aura*, "area debuff") || !traps.empty() || !triggers.empty();
} }
bool AvoidAoeAction::Execute(Event event) bool AvoidAoeAction::Execute(Event event)
@@ -1502,6 +1511,9 @@ bool AvoidAoeAction::Execute(Event event)
return true; return true;
} }
// Case #3: Trigger npc (e.g. Lesser shadow fissure) // Case #3: Trigger npc (e.g. Lesser shadow fissure)
if (AvoidUnitWithDamageAura()) {
return true;
}
return false; return false;
} }
@@ -1575,7 +1587,7 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage()
// } // }
// } // }
if (bot->GetDistance(go) > radius) { if (bot->GetDistance(go) > radius) {
return false; continue;
} }
std::ostringstream name; std::ostringstream name;
name << "[" << spellInfo->SpellName[0] << "] (object)"; name << "[" << spellInfo->SpellName[0] << "] (object)";
@@ -1587,6 +1599,79 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage()
return false; return false;
} }
bool AvoidAoeAction::AvoidUnitWithDamageAura()
{
GuidVector traps = AI_VALUE(GuidVector, "possible triggers");
if (traps.empty()) {
return false;
}
for (ObjectGuid &guid : traps) {
Unit* unit = botAI->GetUnit(guid);
if (!unit || !unit->IsInWorld()) {
continue;
}
if (!unit->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE)) {
return false;
}
Unit::AuraEffectList const& auras = unit->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL);
for (auto i = auras.begin(); i != auras.end(); ++i)
{
AuraEffect* aurEff = *i;
const SpellInfo* spellInfo = aurEff->GetSpellInfo();
if (!spellInfo)
continue;
const SpellInfo* triggerSpellInfo = sSpellMgr->GetSpellInfo(spellInfo->Effects[aurEff->GetEffIndex()].TriggerSpell);
if (!triggerSpellInfo)
continue;
for (int j = 0; j < MAX_SPELL_EFFECTS; j++) {
if (triggerSpellInfo->Effects[j].Effect == SPELL_EFFECT_SCHOOL_DAMAGE) {
float radius = triggerSpellInfo->Effects[j].CalcRadius();
if (bot->GetDistance(unit) > radius) {
break;
}
std::ostringstream name;
name << "[" << triggerSpellInfo->SpellName[0] << "] (unit)";
if (FleePostion(unit->GetPosition(), radius, name.str())) {
return true;
}
}
}
}
// Unit::AuraApplicationMap& map = unit->GetAppliedAuras();
// for (Unit::AuraApplicationMap::iterator i = map.begin(); i != map.end(); ++i)
// {
// Aura *aura = i->second->GetBase();
// if (!aura)
// continue;
// const SpellInfo* spellInfo = aura->GetSpellInfo();
// if (!spellInfo)
// continue;
// for (int i = 0; i < MAX_SPELL_EFFECTS; i++) {
// if (spellInfo->Effects[i].Effect == SPELL_EFFECT_APPLY_AURA &&
// spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_PERIODIC_TRIGGER_SPELL) {
// const SpellInfo* triggerSpellInfo = sSpellMgr->GetSpellInfo(spellInfo->Effects[i].TriggerSpell);
// if (!triggerSpellInfo)
// continue;
// for (int j = 0; j < MAX_SPELL_EFFECTS; j++) {
// if (triggerSpellInfo->Effects[j].Effect == SPELL_EFFECT_SCHOOL_DAMAGE) {
// float radius = triggerSpellInfo->Effects[j].CalcRadius();
// if (bot->GetDistance(unit) > radius) {
// break;
// }
// std::ostringstream name;
// name << "[" << triggerSpellInfo->SpellName[0] << "] (unit)";
// if (FleePostion(unit->GetPosition(), radius, name.str())) {
// return true;
// }
// }
// }
// }
// }
// }
}
return false;
}
bool AvoidAoeAction::FleePostion(Position pos, float radius, std::string name) bool AvoidAoeAction::FleePostion(Position pos, float radius, std::string name)
{ {
Unit* currentTarget = AI_VALUE(Unit*, "current target"); Unit* currentTarget = AI_VALUE(Unit*, "current target");

View File

@@ -77,6 +77,7 @@ class AvoidAoeAction : public MovementAction
protected: protected:
bool AvoidAuraWithDynamicObj(); bool AvoidAuraWithDynamicObj();
bool AvoidGameObjectWithDamage(); bool AvoidGameObjectWithDamage();
bool AvoidUnitWithDamageAura();
bool FleePostion(Position pos, float radius, std::string name); bool FleePostion(Position pos, float radius, std::string name);
}; };

View File

@@ -45,7 +45,7 @@ WorldLocation ArrowFormation::GetLocationInternal()
float y = master->GetPositionY() - masterUnit->GetY() + botUnit->GetY(); float y = master->GetPositionY() - masterUnit->GetY() + botUnit->GetY();
float z = master->GetPositionZ(); float z = master->GetPositionZ();
float ground = master->GetMap()->GetHeight(x, y, z + 30.0f); float ground = master->GetMapHeight(x, y, z + 30.0f);
if (ground <= INVALID_HEIGHT) if (ground <= INVALID_HEIGHT)
return Formation::NullLocation; return Formation::NullLocation;
// master->UpdateGroundPositionZ(x, y, z); // master->UpdateGroundPositionZ(x, y, z);

View File

@@ -88,7 +88,8 @@ class NearFormation : public MoveAheadFormation
float x = master->GetPositionX() + cos(angle) * range; float x = master->GetPositionX() + cos(angle) * range;
float y = master->GetPositionY() + sin(angle) * range; float y = master->GetPositionY() + sin(angle) * range;
float z = master->GetPositionZ(); float z = master->GetPositionZ();
float ground = master->GetMap()->GetHeight(x, y, z + 30.0f);
float ground = master->GetMapHeight(x, y, z + 30.0f);
if (ground <= INVALID_HEIGHT) if (ground <= INVALID_HEIGHT)
return Formation::NullLocation; return Formation::NullLocation;
@@ -126,7 +127,7 @@ class ChaosFormation : public MoveAheadFormation
float x = master->GetPositionX() + cos(angle) * range + dx; float x = master->GetPositionX() + cos(angle) * range + dx;
float y = master->GetPositionY() + sin(angle) * range + dy; float y = master->GetPositionY() + sin(angle) * range + dy;
float z = master->GetPositionZ(); float z = master->GetPositionZ();
float ground = master->GetMap()->GetHeight(x, y, z + 30.0f); float ground = master->GetMapHeight(x, y, z + 30.0f);
if (ground <= INVALID_HEIGHT) if (ground <= INVALID_HEIGHT)
return Formation::NullLocation; return Formation::NullLocation;
@@ -183,7 +184,7 @@ class CircleFormation : public MoveFormation
float x = target->GetPositionX() + cos(angle) * range; float x = target->GetPositionX() + cos(angle) * range;
float y = target->GetPositionY() + sin(angle) * range; float y = target->GetPositionY() + sin(angle) * range;
float z = target->GetPositionZ(); float z = target->GetPositionZ();
float ground = target->GetMap()->GetHeight(x, y, z + 30.0f); float ground = target->GetMapHeight(x, y, z + 30.0f);
if (ground <= INVALID_HEIGHT) if (ground <= INVALID_HEIGHT)
return Formation::NullLocation; return Formation::NullLocation;
@@ -327,7 +328,7 @@ class FarFormation : public FollowFormation
float y = master->GetPositionY() + sin(angle) * range + sin(followAngle) * followRange; float y = master->GetPositionY() + sin(angle) * range + sin(followAngle) * followRange;
float z = master->GetPositionZ(); float z = master->GetPositionZ();
float ground = master->GetMap()->GetHeight(x, y, z + 30.0f); float ground = master->GetMapHeight(x, y, z + 30.0f);
if (ground <= INVALID_HEIGHT) if (ground <= INVALID_HEIGHT)
{ {
float minDist = 0, minX = 0, minY = 0; float minDist = 0, minX = 0, minY = 0;
@@ -336,7 +337,7 @@ class FarFormation : public FollowFormation
x = master->GetPositionX() + cos(angle) * range + cos(followAngle) * followRange; x = master->GetPositionX() + cos(angle) * range + cos(followAngle) * followRange;
y = master->GetPositionY() + sin(angle) * range + sin(followAngle) * followRange; y = master->GetPositionY() + sin(angle) * range + sin(followAngle) * followRange;
float dist = sServerFacade->GetDistance2d(bot, x, y); float dist = sServerFacade->GetDistance2d(bot, x, y);
float ground = master->GetMap()->GetHeight(x, y, z + 30.0f); float ground = master->GetMapHeight(x, y, z + 30.0f);
if (ground > INVALID_HEIGHT && (!minDist || minDist > dist)) if (ground > INVALID_HEIGHT && (!minDist || minDist > dist))
{ {
minDist = dist; minDist = dist;
@@ -613,7 +614,7 @@ WorldLocation MoveFormation::MoveSingleLine(std::vector<Player*> line, float dif
float lx = x + cos(angle) * radius; float lx = x + cos(angle) * radius;
float ly = y + sin(angle) * radius; float ly = y + sin(angle) * radius;
float lz = cz; float lz = cz;
float ground = bot->GetMap()->GetHeight(lx, ly, lz + 30.0f); float ground = bot->GetMapHeight(lx, ly, lz + 30.0f);
if (ground <= INVALID_HEIGHT) if (ground <= INVALID_HEIGHT)
return Formation::NullLocation; return Formation::NullLocation;