From 6dc666792091967dd4e0c563f5970f92813b92e7 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 18 Apr 2024 20:47:41 +0800 Subject: [PATCH] Fix movement on ship --- src/PlayerbotAI.cpp | 3 +- src/strategy/actions/MovementActions.cpp | 101 +++++++++++++++++++++-- src/strategy/actions/MovementActions.h | 1 + src/strategy/values/Arrow.cpp | 2 +- src/strategy/values/Formations.cpp | 13 +-- 5 files changed, 104 insertions(+), 16 deletions(-) diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 4ca16af7..e2678854 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -844,7 +844,8 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet) // vcos, vsin, horizontalSpeed, verticalSpeed, x, y, z, bot->GetRelativeAngle(vcos, vsin), bot->GetOrientation()); // bot->Say(speak, LANG_UNIVERSAL); // 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("current target")->Get(); + bot->GetMotionMaster()->MoveJump(x, y, z, horizontalSpeed, verticalSpeed, 0, currentTarget); // bot->AddUnitMovementFlag(MOVEMENTFLAG_FALLING); // bot->AddUnitMovementFlag(MOVEMENTFLAG_FORWARD); // bot->m_movementInfo.AddMovementFlag(MOVEMENTFLAG_PENDING_STOP); diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index cd5ff65f..880ed74a 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -14,6 +14,8 @@ #include "PlayerbotAIConfig.h" #include "Random.h" #include "SharedDefines.h" +#include "SpellAuraEffects.h" +#include "SpellAuraEffects.h" #include "SpellInfo.h" #include "TargetedMovementGenerator.h" #include "Event.h" @@ -177,7 +179,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, } } else { 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) { return false; } @@ -1409,23 +1411,25 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y, { bool found = false; modified_z = INVALID_HEIGHT; - float tempZ = bot->GetMapWaterOrGroundLevel(x, y, z); + float tempZ = bot->GetMapHeight(x, y, z); PathGenerator gen(bot); gen.CalculatePath(x, y, tempZ); Movement::PointsArray result = gen.GetPath(); + modified_z = tempZ; float min_length = gen.getPathLength(); if (gen.GetPathType() == PATHFIND_NORMAL && abs(tempZ - z) < 0.5f) { - modified_z = tempZ; return result; } // Start searching if (gen.GetPathType() == PATHFIND_NORMAL) { found = true; - modified_z = tempZ; } int count = 1; 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); gen.CalculatePath(x, y, tempZ); 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) { - tempZ = bot->GetMapWaterOrGroundLevel(x, y, z + delta); + tempZ = bot->GetMapHeight(x, y, z + delta); + if (tempZ == INVALID_HEIGHT) { + continue; + } PathGenerator gen(bot); gen.CalculatePath(x, y, tempZ); 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) { + modified_z = INVALID_HEIGHT; return Movement::PointsArray{}; } if (!found && !normal_only) { @@ -1488,7 +1496,8 @@ bool FleeWithPetAction::Execute(Event event) bool AvoidAoeAction::isUseful() { 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) @@ -1502,6 +1511,9 @@ bool AvoidAoeAction::Execute(Event event) return true; } // Case #3: Trigger npc (e.g. Lesser shadow fissure) + if (AvoidUnitWithDamageAura()) { + return true; + } return false; } @@ -1575,7 +1587,7 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage() // } // } if (bot->GetDistance(go) > radius) { - return false; + continue; } std::ostringstream name; name << "[" << spellInfo->SpellName[0] << "] (object)"; @@ -1587,6 +1599,79 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage() 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) { Unit* currentTarget = AI_VALUE(Unit*, "current target"); diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index 4596aeb3..befb1b43 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -77,6 +77,7 @@ class AvoidAoeAction : public MovementAction protected: bool AvoidAuraWithDynamicObj(); bool AvoidGameObjectWithDamage(); + bool AvoidUnitWithDamageAura(); bool FleePostion(Position pos, float radius, std::string name); }; diff --git a/src/strategy/values/Arrow.cpp b/src/strategy/values/Arrow.cpp index ac65b7ff..3c3daf28 100644 --- a/src/strategy/values/Arrow.cpp +++ b/src/strategy/values/Arrow.cpp @@ -45,7 +45,7 @@ WorldLocation ArrowFormation::GetLocationInternal() float y = master->GetPositionY() - masterUnit->GetY() + botUnit->GetY(); 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) return Formation::NullLocation; // master->UpdateGroundPositionZ(x, y, z); diff --git a/src/strategy/values/Formations.cpp b/src/strategy/values/Formations.cpp index ba320917..eee6dcf7 100644 --- a/src/strategy/values/Formations.cpp +++ b/src/strategy/values/Formations.cpp @@ -88,7 +88,8 @@ class NearFormation : public MoveAheadFormation float x = master->GetPositionX() + cos(angle) * range; float y = master->GetPositionY() + sin(angle) * range; 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) return Formation::NullLocation; @@ -126,7 +127,7 @@ class ChaosFormation : public MoveAheadFormation float x = master->GetPositionX() + cos(angle) * range + dx; float y = master->GetPositionY() + sin(angle) * range + dy; 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) return Formation::NullLocation; @@ -183,7 +184,7 @@ class CircleFormation : public MoveFormation float x = target->GetPositionX() + cos(angle) * range; float y = target->GetPositionY() + sin(angle) * range; 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) return Formation::NullLocation; @@ -327,7 +328,7 @@ class FarFormation : public FollowFormation float y = master->GetPositionY() + sin(angle) * range + sin(followAngle) * followRange; 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) { float minDist = 0, minX = 0, minY = 0; @@ -336,7 +337,7 @@ class FarFormation : public FollowFormation x = master->GetPositionX() + cos(angle) * range + cos(followAngle) * followRange; y = master->GetPositionY() + sin(angle) * range + sin(followAngle) * followRange; 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)) { minDist = dist; @@ -613,7 +614,7 @@ WorldLocation MoveFormation::MoveSingleLine(std::vector line, float dif float lx = x + cos(angle) * radius; float ly = y + sin(angle) * radius; 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) return Formation::NullLocation;