From 6dc666792091967dd4e0c563f5970f92813b92e7 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 18 Apr 2024 20:47:41 +0800 Subject: [PATCH 01/14] 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; From 0629c106ae1da7da384fbe2e36bb59f4983a760d Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 18 Apr 2024 21:07:13 +0800 Subject: [PATCH 02/14] Hunter crash fix --- src/strategy/hunter/HunterActions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategy/hunter/HunterActions.cpp b/src/strategy/hunter/HunterActions.cpp index dbf85fab..f863e861 100644 --- a/src/strategy/hunter/HunterActions.cpp +++ b/src/strategy/hunter/HunterActions.cpp @@ -41,7 +41,7 @@ bool CastAutoShotAction::isUseful() if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true)) return false; - if (bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) && bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_targets.GetUnitTargetGUID() == AI_VALUE(Unit*, "current target")->GetGUID()) { + if (AI_VALUE(Unit*, "current target") && bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) && bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_targets.GetUnitTargetGUID() == AI_VALUE(Unit*, "current target")->GetGUID()) { return false; } return AI_VALUE(uint32, "active spell") != AI_VALUE2(uint32, "spell id", getName()); From 248bf6c0033d57e029d4209e5e75be7a7f2ad5c1 Mon Sep 17 00:00:00 2001 From: Oiuv Date: Tue, 16 Apr 2024 19:22:00 +0800 Subject: [PATCH 03/14] Modify command `s` to prevent the accidental sale of all items --- src/strategy/actions/SellAction.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/strategy/actions/SellAction.cpp b/src/strategy/actions/SellAction.cpp index 2a15d08c..cafe9192 100644 --- a/src/strategy/actions/SellAction.cpp +++ b/src/strategy/actions/SellAction.cpp @@ -74,13 +74,18 @@ bool SellAction::Execute(Event event) return true; } - std::vector items = parseItems(text, ITERATE_ITEMS_IN_BAGS); - for (Item* item : items) + if (text == "all") { - Sell(item); + std::vector items = parseItems(text, ITERATE_ITEMS_IN_BAGS); + for (Item *item : items) + { + Sell(item); + } + return true; } - return true; + botAI->TellError("Usage: s gray/*/vendor/all"); + return false; } void SellAction::Sell(FindItemVisitor* visitor) From 19ffe0227a685a28b247000a4eea12e229655c5d Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 18 Apr 2024 22:41:14 +0800 Subject: [PATCH 04/14] [Avoid aoe] Crash fix and cover more spell --- src/strategy/actions/MovementActions.cpp | 95 +++----------------- src/strategy/actions/TellLosAction.cpp | 1 - src/strategy/values/AoeValues.cpp | 35 +++++--- src/strategy/values/NearestGameObjects.h | 2 +- src/strategy/values/NearestUnitsValue.h | 4 +- src/strategy/values/PossibleTargetsValue.cpp | 28 +++++- src/strategy/values/PossibleTargetsValue.h | 4 +- 7 files changed, 67 insertions(+), 102 deletions(-) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 880ed74a..c6770a16 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -14,8 +14,6 @@ #include "PlayerbotAIConfig.h" #include "Random.h" #include "SharedDefines.h" -#include "SpellAuraEffects.h" -#include "SpellAuraEffects.h" #include "SpellInfo.h" #include "TargetedMovementGenerator.h" #include "Event.h" @@ -1415,13 +1413,13 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y, 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) { + if (gen.GetPathType() & PATHFIND_NORMAL) { found = true; } int count = 1; @@ -1432,7 +1430,7 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y, } PathGenerator gen(bot); gen.CalculatePath(x, y, tempZ); - if (gen.GetPathType() == PATHFIND_NORMAL && gen.getPathLength() < min_length) { + if (gen.GetPathType() & PATHFIND_NORMAL && gen.getPathLength() < min_length) { found = true; min_length = gen.getPathLength(); result = gen.GetPath(); @@ -1446,7 +1444,7 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y, } PathGenerator gen(bot); gen.CalculatePath(x, y, tempZ); - if (gen.GetPathType() == PATHFIND_NORMAL && gen.getPathLength() < min_length) { + if (gen.GetPathType() & PATHFIND_NORMAL && gen.getPathLength() < min_length) { found = true; min_length = gen.getPathLength(); result = gen.GetPath(); @@ -1520,16 +1518,17 @@ bool AvoidAoeAction::Execute(Event event) bool AvoidAoeAction::AvoidAuraWithDynamicObj() { Aura* aura = AI_VALUE(Aura*, "area debuff"); - if (!aura) { + if (!aura || aura->IsRemoved() || aura->IsExpired()) { + return false; + } + // Crash fix: maybe change owner due to check interval + if (aura->GetType() != DYNOBJ_AURA_TYPE) { return false; } const SpellInfo* spellInfo = aura->GetSpellInfo(); if (!spellInfo) { return false; } - if (!bot->HasAura(spellInfo->Id)) { - return false; - } DynamicObject* dynOwner = aura->GetDynobjOwner(); if (!dynOwner || !dynOwner->IsInWorld()) { return false; @@ -1599,84 +1598,12 @@ 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"); std::vector possibleAngles; if (currentTarget) { + // Normally, move to left or right is the best position float angleLeft = bot->GetAngle(currentTarget) + M_PI / 2; float angleRight = bot->GetAngle(currentTarget) - M_PI / 2; possibleAngles.push_back(angleLeft); @@ -1859,4 +1786,4 @@ bool RotateAroundTheCenterPointAction::Execute(Event event) return true; } return false; -} \ No newline at end of file +} diff --git a/src/strategy/actions/TellLosAction.cpp b/src/strategy/actions/TellLosAction.cpp index 234bebcc..8c729cf3 100644 --- a/src/strategy/actions/TellLosAction.cpp +++ b/src/strategy/actions/TellLosAction.cpp @@ -78,7 +78,6 @@ bool TellAuraAction::Execute(Event event) Aura * aura = i->second->GetBase(); if (!aura) continue; - const std::string auraName = aura->GetSpellInfo()->SpellName[0]; sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "Info of Aura - name: " + auraName); AuraObjectType type = aura->GetType(); diff --git a/src/strategy/values/AoeValues.cpp b/src/strategy/values/AoeValues.cpp index 3d93640c..7f355949 100644 --- a/src/strategy/values/AoeValues.cpp +++ b/src/strategy/values/AoeValues.cpp @@ -120,15 +120,13 @@ bool HasAreaDebuffValue::Calculate() Aura* AreaDebuffValue::Calculate() { - Unit::AuraApplicationMap& map = bot->GetAppliedAuras(); - for (Unit::AuraApplicationMap::iterator i = map.begin(); i != map.end(); ++i) - { - Aura *aura = i->second->GetBase(); - if (!aura) - continue; - - AuraObjectType type = aura->GetType(); - // bool is_area = aura->IsArea(); + // Unit::AuraApplicationMap& map = bot->GetAppliedAuras(); + Unit::AuraEffectList const& auras = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE); + for (auto i = auras.begin(); i != auras.end(); ++i) + { + AuraEffect* aurEff = *i; + Aura *aura = aurEff->GetBase(); + AuraObjectType type = aura->GetType(); bool isPositive = aura->GetSpellInfo()->IsPositive(); if (type == DYNOBJ_AURA_TYPE && !isPositive) { DynamicObject* dynOwner = aura->GetDynobjOwner(); @@ -137,6 +135,23 @@ Aura* AreaDebuffValue::Calculate() } return aura; } - } + } + // for (Unit::AuraApplicationMap::iterator i = map.begin(); i != map.end(); ++i) + // { + // Aura *aura = i->second->GetBase(); + // if (!aura) + // continue; + + // AuraObjectType type = aura->GetType(); + // // bool is_area = aura->IsArea(); + // bool isPositive = aura->GetSpellInfo()->IsPositive(); + // if (type == DYNOBJ_AURA_TYPE && !isPositive) { + // DynamicObject* dynOwner = aura->GetDynobjOwner(); + // if (!dynOwner) { + // continue; + // } + // return aura; + // } + // } return nullptr; } \ No newline at end of file diff --git a/src/strategy/values/NearestGameObjects.h b/src/strategy/values/NearestGameObjects.h index d0e7850f..399222cc 100644 --- a/src/strategy/values/NearestGameObjects.h +++ b/src/strategy/values/NearestGameObjects.h @@ -27,7 +27,7 @@ class NearestGameObjects : public ObjectGuidListCalculatedValue class NearestTrapWithDamageValue : public ObjectGuidListCalculatedValue { public: - NearestTrapWithDamageValue(PlayerbotAI* botAI, float range = 10.0f) : + NearestTrapWithDamageValue(PlayerbotAI* botAI, float range = 15.0f) : ObjectGuidListCalculatedValue(botAI, "nearest trap with damage", 1 * 1000), range(range) { } protected: diff --git a/src/strategy/values/NearestUnitsValue.h b/src/strategy/values/NearestUnitsValue.h index 7b262370..6f154e4e 100644 --- a/src/strategy/values/NearestUnitsValue.h +++ b/src/strategy/values/NearestUnitsValue.h @@ -14,8 +14,8 @@ class PlayerbotAI; class NearestUnitsValue : public ObjectGuidListCalculatedValue { public: - NearestUnitsValue(PlayerbotAI* botAI, std::string const name = "nearest units", float range = sPlayerbotAIConfig->sightDistance, bool ignoreLos = false) : - ObjectGuidListCalculatedValue(botAI, name, 1), range(range), ignoreLos(ignoreLos) { } + NearestUnitsValue(PlayerbotAI* botAI, std::string const name = "nearest units", float range = sPlayerbotAIConfig->sightDistance, bool ignoreLos = false, uint32 checkInterval = 1) : + ObjectGuidListCalculatedValue(botAI, name, checkInterval), range(range), ignoreLos(ignoreLos) { } GuidVector Calculate() override; diff --git a/src/strategy/values/PossibleTargetsValue.cpp b/src/strategy/values/PossibleTargetsValue.cpp index 729c0ae0..904cfc01 100644 --- a/src/strategy/values/PossibleTargetsValue.cpp +++ b/src/strategy/values/PossibleTargetsValue.cpp @@ -5,9 +5,14 @@ #include "PossibleTargetsValue.h" #include "AttackersValue.h" #include "CellImpl.h" +#include "DBCStructure.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" #include "Playerbots.h" +#include "SharedDefines.h" +#include "SpellAuraDefines.h" +#include "SpellAuraEffects.h" +#include "SpellMgr.h" #include "Unit.h" void PossibleTargetsValue::FindUnits(std::list& targets) @@ -31,7 +36,26 @@ void PossibleTriggersValue::FindUnits(std::list& targets) bool PossibleTriggersValue::AcceptUnit(Unit* unit) { - return unit->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE) && unit->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - return true; // AttackersValue::IsPossibleTarget(unit, bot, range); + 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) { + return true; + } + } + } + return false; + // return true; // AttackersValue::IsPossibleTarget(unit, bot, range); } diff --git a/src/strategy/values/PossibleTargetsValue.h b/src/strategy/values/PossibleTargetsValue.h index 81cd2bd3..1ffcdd51 100644 --- a/src/strategy/values/PossibleTargetsValue.h +++ b/src/strategy/values/PossibleTargetsValue.h @@ -30,8 +30,8 @@ class AllTargetsValue : public PossibleTargetsValue class PossibleTriggersValue : public NearestUnitsValue { public: - PossibleTriggersValue(PlayerbotAI* botAI, std::string const name = "possible targets", float range = sPlayerbotAIConfig->sightDistance, bool ignoreLos = true): - NearestUnitsValue(botAI, name, range, ignoreLos) { } + PossibleTriggersValue(PlayerbotAI* botAI, std::string const name = "possible triggers", float range = 15.0f, bool ignoreLos = true): + NearestUnitsValue(botAI, name, range, ignoreLos, 1 * 1000) { } protected: void FindUnits(std::list& targets) override; From 7e4449b4fa655a4a6931f15981e55a3a64add3e7 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 18 Apr 2024 22:45:42 +0800 Subject: [PATCH 05/14] [Avoid aoe] Fix avoid unit with damage aura --- src/strategy/actions/MovementActions.cpp | 43 ++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index c6770a16..8fe7d750 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -14,6 +14,7 @@ #include "PlayerbotAIConfig.h" #include "Random.h" #include "SharedDefines.h" +#include "SpellAuraEffects.h" #include "SpellInfo.h" #include "TargetedMovementGenerator.h" #include "Event.h" @@ -1598,6 +1599,48 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage() return false; } +bool AvoidAoeAction::AvoidUnitWithDamageAura() +{ + GuidVector triggers = AI_VALUE(GuidVector, "possible triggers"); + if (triggers.empty()) { + return false; + } + for (ObjectGuid &guid : triggers) { + 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; + } + } + } + } + } + return false; +} + bool AvoidAoeAction::FleePostion(Position pos, float radius, std::string name) { Unit* currentTarget = AI_VALUE(Unit*, "current target"); From 32f787b2aa10d729bb3b3338b46aa954ce25356b Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 19 Apr 2024 12:11:46 +0800 Subject: [PATCH 06/14] [Cast spell] Arc check only forfacing spell --- src/PlayerbotAI.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index e2678854..68b4a3f6 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -2478,9 +2478,8 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) ObjectGuid oldSel = bot->GetSelectedUnit() ? bot->GetSelectedUnit()->GetGUID() : ObjectGuid(); bot->SetSelection(target->GetGUID()); - WorldObject* faceTo = target; - if (!bot->HasInArc(CAST_ANGLE_IN_FRONT, faceTo)) + if (!bot->HasInArc(CAST_ANGLE_IN_FRONT, faceTo) && (spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT)) { sServerFacade->SetFacingTo(bot, faceTo); //failWithDelay = true; From 7af4f3bb95abd0c94a7b43c2c87b5f732c4da75b Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 19 Apr 2024 18:32:15 +0800 Subject: [PATCH 07/14] [Avoid aoe] Area debuff judgement --- src/strategy/values/AoeValues.cpp | 44 +++++++++++-------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/src/strategy/values/AoeValues.cpp b/src/strategy/values/AoeValues.cpp index 7f355949..4675beb7 100644 --- a/src/strategy/values/AoeValues.cpp +++ b/src/strategy/values/AoeValues.cpp @@ -121,37 +121,23 @@ bool HasAreaDebuffValue::Calculate() Aura* AreaDebuffValue::Calculate() { // Unit::AuraApplicationMap& map = bot->GetAppliedAuras(); - Unit::AuraEffectList const& auras = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE); - for (auto i = auras.begin(); i != auras.end(); ++i) - { - AuraEffect* aurEff = *i; - Aura *aura = aurEff->GetBase(); - AuraObjectType type = aura->GetType(); - bool isPositive = aura->GetSpellInfo()->IsPositive(); - if (type == DYNOBJ_AURA_TYPE && !isPositive) { - DynamicObject* dynOwner = aura->GetDynobjOwner(); - if (!dynOwner) { - continue; + Unit::AuraEffectList const& aurasPeriodicDamage = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE); + Unit::AuraEffectList const& aurasPeriodicTriggerSpell = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL); + for (const Unit::AuraEffectList& list : {aurasPeriodicDamage, aurasPeriodicTriggerSpell}) { + for (auto i = list.begin(); i != list.end(); ++i) + { + AuraEffect* aurEff = *i; + Aura *aura = aurEff->GetBase(); + AuraObjectType type = aura->GetType(); + bool isPositive = aura->GetSpellInfo()->IsPositive(); + if (type == DYNOBJ_AURA_TYPE && !isPositive) { + DynamicObject* dynOwner = aura->GetDynobjOwner(); + if (!dynOwner) { + continue; + } + return aura; } - return aura; } } - // for (Unit::AuraApplicationMap::iterator i = map.begin(); i != map.end(); ++i) - // { - // Aura *aura = i->second->GetBase(); - // if (!aura) - // continue; - - // AuraObjectType type = aura->GetType(); - // // bool is_area = aura->IsArea(); - // bool isPositive = aura->GetSpellInfo()->IsPositive(); - // if (type == DYNOBJ_AURA_TYPE && !isPositive) { - // DynamicObject* dynOwner = aura->GetDynobjOwner(); - // if (!dynOwner) { - // continue; - // } - // return aura; - // } - // } return nullptr; } \ No newline at end of file From a94f626106c66f10e4c2a55705e477183c1f6922 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 19 Apr 2024 19:25:50 +0800 Subject: [PATCH 08/14] [Avoid aoe] Enhance spell judge --- src/strategy/values/AoeValues.cpp | 3 +- src/strategy/values/PossibleTargetsValue.cpp | 31 +++++++++++--------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/strategy/values/AoeValues.cpp b/src/strategy/values/AoeValues.cpp index 4675beb7..e6295349 100644 --- a/src/strategy/values/AoeValues.cpp +++ b/src/strategy/values/AoeValues.cpp @@ -123,7 +123,8 @@ Aura* AreaDebuffValue::Calculate() // Unit::AuraApplicationMap& map = bot->GetAppliedAuras(); Unit::AuraEffectList const& aurasPeriodicDamage = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE); Unit::AuraEffectList const& aurasPeriodicTriggerSpell = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL); - for (const Unit::AuraEffectList& list : {aurasPeriodicDamage, aurasPeriodicTriggerSpell}) { + Unit::AuraEffectList const& aurasPeriodicTriggerWithValueSpell = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE); + for (const Unit::AuraEffectList& list : {aurasPeriodicDamage, aurasPeriodicTriggerSpell, aurasPeriodicTriggerWithValueSpell}) { for (auto i = list.begin(); i != list.end(); ++i) { AuraEffect* aurEff = *i; diff --git a/src/strategy/values/PossibleTargetsValue.cpp b/src/strategy/values/PossibleTargetsValue.cpp index 904cfc01..a5365592 100644 --- a/src/strategy/values/PossibleTargetsValue.cpp +++ b/src/strategy/values/PossibleTargetsValue.cpp @@ -39,22 +39,25 @@ bool PossibleTriggersValue::AcceptUnit(Unit* unit) 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) { - return true; + Unit::AuraEffectList const& aurasPeriodicTriggerSpell = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL); + Unit::AuraEffectList const& aurasPeriodicTriggerWithValueSpell = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE); + for (const Unit::AuraEffectList& list : {aurasPeriodicTriggerSpell, aurasPeriodicTriggerWithValueSpell}) { + for (auto i = list.begin(); i != list.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) { + return true; + } } } - } + } return false; // return true; // AttackersValue::IsPossibleTarget(unit, bot, range); } From a4f97839970033397d4f99083544a90da3ecd2de Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sat, 20 Apr 2024 00:22:56 +0800 Subject: [PATCH 09/14] [Avoid aoe] Fix possible triggers --- src/strategy/values/NearestNpcsValue.h | 2 +- src/strategy/values/PossibleTargetsValue.cpp | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/strategy/values/NearestNpcsValue.h b/src/strategy/values/NearestNpcsValue.h index e23fc822..419c5fa4 100644 --- a/src/strategy/values/NearestNpcsValue.h +++ b/src/strategy/values/NearestNpcsValue.h @@ -43,7 +43,7 @@ class NearestTriggersValue : public NearestUnitsValue class NearestTotemsValue : public NearestUnitsValue { public: - NearestTotemsValue(PlayerbotAI* botAI, float range = 30.0f) : NearestUnitsValue(botAI, "nearest npcs", range, true) { } + NearestTotemsValue(PlayerbotAI* botAI, float range = 30.0f) : NearestUnitsValue(botAI, "nearest totems", range, true) { } protected: void FindUnits(std::list& targets) override; diff --git a/src/strategy/values/PossibleTargetsValue.cpp b/src/strategy/values/PossibleTargetsValue.cpp index a5365592..ddef5ccc 100644 --- a/src/strategy/values/PossibleTargetsValue.cpp +++ b/src/strategy/values/PossibleTargetsValue.cpp @@ -39,8 +39,8 @@ bool PossibleTriggersValue::AcceptUnit(Unit* unit) if (!unit->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE)) { return false; } - Unit::AuraEffectList const& aurasPeriodicTriggerSpell = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL); - Unit::AuraEffectList const& aurasPeriodicTriggerWithValueSpell = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE); + Unit::AuraEffectList const& aurasPeriodicTriggerSpell = unit->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL); + Unit::AuraEffectList const& aurasPeriodicTriggerWithValueSpell = unit->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE); for (const Unit::AuraEffectList& list : {aurasPeriodicTriggerSpell, aurasPeriodicTriggerWithValueSpell}) { for (auto i = list.begin(); i != list.end(); ++i) { @@ -59,6 +59,4 @@ bool PossibleTriggersValue::AcceptUnit(Unit* unit) } } return false; - // return true; // AttackersValue::IsPossibleTarget(unit, bot, range); } - From 98ff69473c753d7406eb99a216b09dc2e5b11a85 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sat, 20 Apr 2024 00:30:11 +0800 Subject: [PATCH 10/14] [Avoid aoe] Fix avoid unit --- src/strategy/actions/MovementActions.cpp | 43 +++++++++++++----------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 8fe7d750..66c4f7af 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1613,26 +1613,29 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura() 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::AuraEffectList const& aurasPeriodicTriggerSpell = unit->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL); + Unit::AuraEffectList const& aurasPeriodicTriggerWithValueSpell = unit->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE); + for (const Unit::AuraEffectList& list : {aurasPeriodicTriggerSpell, aurasPeriodicTriggerWithValueSpell}) { + for (auto i = list.begin(); i != list.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; + } } } } From f789f531b3cbf18538a3299d343189fc757a8465 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sat, 20 Apr 2024 13:43:05 +0800 Subject: [PATCH 11/14] [Movement] Fix path finder --- src/strategy/actions/MovementActions.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 66c4f7af..b9bb57fc 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1415,7 +1415,7 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y, gen.CalculatePath(x, y, tempZ); Movement::PointsArray result = gen.GetPath(); 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; } @@ -1431,7 +1431,7 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y, } PathGenerator gen(bot); gen.CalculatePath(x, y, tempZ); - if (gen.GetPathType() & PATHFIND_NORMAL && gen.getPathLength() < min_length) { + if ((gen.GetPathType() & PATHFIND_NORMAL) && gen.getPathLength() < min_length) { found = true; min_length = gen.getPathLength(); result = gen.GetPath(); @@ -1445,7 +1445,7 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y, } PathGenerator gen(bot); gen.CalculatePath(x, y, tempZ); - if (gen.GetPathType() & PATHFIND_NORMAL && gen.getPathLength() < min_length) { + if ((gen.GetPathType() & PATHFIND_NORMAL) && gen.getPathLength() < min_length) { found = true; min_length = gen.getPathLength(); result = gen.GetPath(); From 10166048d7475d903766dca6980fc093f4c224d7 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sat, 20 Apr 2024 13:47:24 +0800 Subject: [PATCH 12/14] [Movement] Fix path finder --- src/strategy/actions/MovementActions.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index b9bb57fc..f5345e67 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1421,6 +1421,7 @@ const Movement::PointsArray MovementAction::SearchForBestPath(float x, float y, } // Start searching if (gen.GetPathType() & PATHFIND_NORMAL) { + modified_z = tempZ; found = true; } int count = 1; From 924c1a219770bfcc6f86500ddddf6de5c1fd7ee8 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sat, 20 Apr 2024 16:30:03 +0800 Subject: [PATCH 13/14] [Equip score] Weapon dps calculation --- src/PlayerbotFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index 245df3bc..32ceda4f 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -3593,9 +3593,9 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot) int meleeDps = 0, rangeDps = 0; float score = 0; if (proto->IsRangedWeapon()) { - rangeDps = (proto->Damage[0].DamageMin + proto->Damage[0].DamageMax) / 2 * proto->Delay / 1000; + rangeDps = (proto->Damage[0].DamageMin + proto->Damage[0].DamageMax) / 2 * 1000 / proto->Delay; } else if (proto->IsWeapon()) { - meleeDps = (proto->Damage[0].DamageMin + proto->Damage[0].DamageMax) / 2 * proto->Delay / 1000; + meleeDps = (proto->Damage[0].DamageMin + proto->Damage[0].DamageMax) / 2 * 1000 / proto->Delay; } armor += proto->Armor; block += proto->Block; From 45ffd4bd072fa6c23495d1b3292148ec59a0973d Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sat, 20 Apr 2024 16:43:31 +0800 Subject: [PATCH 14/14] [Equip score] Skip can take more check --- src/PlayerbotAI.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 68b4a3f6..5038832e 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -4408,11 +4408,12 @@ InventoryResult PlayerbotAI::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, if (pItem->IsBindedNotWith(bot)) return EQUIP_ERR_DONT_OWN_THAT_ITEM; - - // check count of items (skip for auto move for same player from bank) - InventoryResult res = bot->CanTakeMoreSimilarItems(pItem); - if (res != EQUIP_ERR_OK) - return res; + + // Yunfan: skip it + // // check count of items (skip for auto move for same player from bank) + // InventoryResult res = bot->CanTakeMoreSimilarItems(pItem); + // if (res != EQUIP_ERR_OK) + // return res; ScalingStatDistributionEntry const* ssd = pProto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(pProto->ScalingStatDistribution) : 0; // check allowed level (extend range to upper values if MaxLevel more or equal max player level, this let GM set high level with 1...max range items) @@ -4427,7 +4428,7 @@ InventoryResult PlayerbotAI::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, if (!bot->CanUseAttackType(bot->GetAttackBySlot(eslot))) return EQUIP_ERR_NOT_WHILE_DISARMED; - res = bot->CanUseItem(pItem, not_loading); + InventoryResult res = bot->CanUseItem(pItem, not_loading); if (res != EQUIP_ERR_OK) return res;