diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 4ca16af7..5038832e 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); @@ -2477,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; @@ -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; 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; diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index cd5ff65f..f5345e67 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" @@ -177,7 +178,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,26 +1410,29 @@ 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(); 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; } // Start searching - if (gen.GetPathType() == PATHFIND_NORMAL) { - found = true; + if (gen.GetPathType() & PATHFIND_NORMAL) { modified_z = tempZ; + found = true; } 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) { + if ((gen.GetPathType() & PATHFIND_NORMAL) && gen.getPathLength() < min_length) { found = true; min_length = gen.getPathLength(); result = gen.GetPath(); @@ -1436,10 +1440,13 @@ 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) { + if ((gen.GetPathType() & PATHFIND_NORMAL) && gen.getPathLength() < min_length) { found = true; min_length = gen.getPathLength(); result = gen.GetPath(); @@ -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,22 +1511,26 @@ bool AvoidAoeAction::Execute(Event event) return true; } // Case #3: Trigger npc (e.g. Lesser shadow fissure) + if (AvoidUnitWithDamageAura()) { + return true; + } return false; } 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; @@ -1575,7 +1588,7 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage() // } // } if (bot->GetDistance(go) > radius) { - return false; + continue; } std::ostringstream name; name << "[" << spellInfo->SpellName[0] << "] (object)"; @@ -1587,11 +1600,57 @@ 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& 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; + } + } + } + } + } + } + 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); @@ -1774,4 +1833,4 @@ bool RotateAroundTheCenterPointAction::Execute(Event event) return true; } return false; -} \ No newline at end of file +} 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/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/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()); diff --git a/src/strategy/values/AoeValues.cpp b/src/strategy/values/AoeValues.cpp index 3d93640c..e6295349 100644 --- a/src/strategy/values/AoeValues.cpp +++ b/src/strategy/values/AoeValues.cpp @@ -120,23 +120,25 @@ 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(); - bool isPositive = aura->GetSpellInfo()->IsPositive(); - if (type == DYNOBJ_AURA_TYPE && !isPositive) { - DynamicObject* dynOwner = aura->GetDynobjOwner(); - if (!dynOwner) { - continue; + // 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); + 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; + 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; } - } + } return nullptr; } \ No newline at end of file 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; 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/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/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..ddef5ccc 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,27 @@ 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& 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) { + return true; + } + } + } + } + return false; } - 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;