Merge branch 'master' into master

This commit is contained in:
Bobblybook
2024-12-15 23:47:38 +11:00
committed by GitHub
23 changed files with 204 additions and 50 deletions

View File

@@ -10,8 +10,8 @@
#include "LootObjectStack.h"
#include "Playerbots.h"
#include "PossibleRpgTargetsValue.h"
#include "ServerFacade.h"
#include "PvpTriggers.h"
#include "ServerFacade.h"
bool AttackEnemyPlayerAction::isUseful()
{
@@ -129,3 +129,33 @@ bool DpsAssistAction::isUseful()
return true;
}
bool AttackRtiTargetAction::Execute(Event event)
{
Unit* rtiTarget = AI_VALUE(Unit*, "rti target");
if (rtiTarget && rtiTarget->IsInWorld() && rtiTarget->GetMapId() == bot->GetMapId())
{
botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Set({rtiTarget->GetGUID()});
bool result = Attack(botAI->GetUnit(rtiTarget->GetGUID()));
if (result)
{
context->GetValue<ObjectGuid>("pull target")->Set(rtiTarget->GetGUID());
return true;
}
}
else
{
botAI->TellError("I dont see my rti attack target");
}
return false;
}
bool AttackRtiTargetAction::isUseful()
{
if (botAI->ContainsStrategy(STRATEGY_TYPE_HEAL))
return false;
return true;
}

View File

@@ -69,6 +69,8 @@ public:
AttackRtiTargetAction(PlayerbotAI* botAI) : AttackAction(botAI, "attack rti target") {}
std::string const GetTargetName() override { return "rti target"; }
bool Execute(Event event) override;
bool isUseful() override;
};
class AttackEnemyFlagCarrierAction : public AttackAction

View File

@@ -68,6 +68,11 @@ bool CleanQuestLogAction::Execute(Event event)
return false;
}
if (!sPlayerbotAIConfig->dropObsoleteQuests)
{
return false;
}
// Only output this message if "debug rpg" strategy is enabled
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
{

View File

@@ -923,10 +923,10 @@ bool MovementAction::IsMovingAllowed()
if (botAI->IsInVehicle() && !botAI->IsInVehicle(true))
return false;
if (bot->isFrozen() || bot->IsPolymorphed() || (bot->isDead() && !bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) ||
bot->IsBeingTeleported() || bot->isInRoots() || bot->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION) ||
bot->HasAuraType(SPELL_AURA_MOD_CONFUSE) || bot->IsCharmed() || bot->HasAuraType(SPELL_AURA_MOD_STUN) ||
bot->HasUnitState(UNIT_STATE_IN_FLIGHT) || bot->HasUnitState(UNIT_STATE_LOST_CONTROL))
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))
return false;
if (bot->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) != NULL_MOTION_TYPE)
@@ -2537,9 +2537,9 @@ bool SetFacingTargetAction::isUseful() { return !AI_VALUE2(bool, "facing", "curr
bool SetFacingTargetAction::isPossible()
{
if (bot->isFrozen() || bot->IsPolymorphed() || (bot->isDead() && !bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) ||
bot->IsBeingTeleported() || bot->HasAuraType(SPELL_AURA_MOD_CONFUSE) || bot->IsCharmed() ||
bot->HasAuraType(SPELL_AURA_MOD_STUN) || bot->HasUnitState(UNIT_STATE_IN_FLIGHT) ||
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))
return false;

View File

@@ -22,7 +22,7 @@ bool ReleaseSpiritAction::Execute(Event event)
return false;
}
if (bot->GetCorpse() && bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
if (bot->GetCorpse() && bot->HasPlayerFlag(PLAYER_FLAGS_GHOST))
{
botAI->TellMasterNoFacing("I am already a spirit");
return false;
@@ -149,7 +149,7 @@ bool AutoReleaseSpiritAction::isUseful()
if (bot->InBattleground())
return true;
if (bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
if (bot->HasPlayerFlag(PLAYER_FLAGS_GHOST))
return false;
if (!bot->GetGroup())

View File

@@ -360,4 +360,4 @@ bool SpiritHealerAction::Execute(Event event)
return false;
}
bool SpiritHealerAction::isUseful() { return bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); }
bool SpiritHealerAction::isUseful() { return bot->HasPlayerFlag(PLAYER_FLAGS_GHOST); }

View File

@@ -80,7 +80,7 @@ bool MarkRtiAction::Execute(Event event)
for (uint8 i = 0; i < 8; i++)
{
ObjectGuid iconGUID = group->GetTargetIcon(i);
if (guid == unit->GetGUID())
if (iconGUID == unit->GetGUID())
{
marked = true;
break;

View File

@@ -5,6 +5,7 @@
#include "WorldBuffAction.h"
#include "AiFactory.h"
#include "Event.h"
#include "Playerbots.h"
@@ -39,6 +40,11 @@ std::vector<uint32> WorldBuffAction::NeedWorldBuffs(Unit* unit)
if (wb.classId != 0 && wb.classId != unit->getClass())
continue;
uint8 tab = AiFactory::GetPlayerSpecTab(unit->ToPlayer());
if (wb.specId != tab)
continue;
if (wb.minLevel != 0 && wb.minLevel > unit->GetLevel())
continue;

View File

@@ -25,4 +25,8 @@ bool PartyMemberNeedCureTrigger::IsActive()
return target && target->IsInWorld();
}
bool NeedWorldBuffTrigger::IsActive() { return !WorldBuffAction::NeedWorldBuffs(bot).empty(); }
bool NeedWorldBuffTrigger::IsActive()
{
std::any_of(WorldBuffAction::NeedWorldBuffs(bot).begin(), WorldBuffAction::NeedWorldBuffs(bot).end(),
[](const auto& wb) { return true; });
}

View File

@@ -175,7 +175,7 @@ bool AttackersValue::IsPossibleTarget(Unit* attacker, Player* bot, float range)
// !((attacker->IsPolymorphed() || botAI->HasAura("sap", attacker) || /*attacker->IsCharmed() ||*/
// attacker->isFeared()) && !rti) &&
/*!sServerFacade->IsInRoots(attacker) &&*/
!attacker->IsFriendlyTo(bot) && !attacker->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION) &&
!attacker->IsFriendlyTo(bot) && !attacker->HasSpiritOfRedemptionAura() &&
// !(attacker->GetGUID().IsPet() && enemy) &&
!(attacker->GetCreatureType() == CREATURE_TYPE_CRITTER && !attacker->IsInCombat()) &&
!attacker->HasUnitFlag(UNIT_FLAG_IMMUNE_TO_PC) && !attacker->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE) &&

View File

@@ -18,7 +18,7 @@ bool NearestEnemyPlayersValue::AcceptUnit(Unit* unit)
!enemy->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NON_ATTACKABLE_2) &&
((inCannon || !enemy->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))) &&
/*!enemy->HasStealthAura() && !enemy->HasInvisibilityAura()*/ enemy->CanSeeOrDetect(bot) &&
!(enemy->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)))
!(enemy->HasSpiritOfRedemptionAura()))
return true;
return false;

View File

@@ -21,7 +21,7 @@ bool InvalidTargetValue::Calculate()
return target->GetMapId() != bot->GetMapId() || target->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE) ||
target->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE) || target->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE_2) ||
!target->IsVisible() || !target->IsAlive() || target->IsPolymorphed() || target->IsCharmed() ||
target->isFeared() || target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsFriendlyTo(bot) ||
target->HasFearAura() || target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsFriendlyTo(bot) ||
!AttackersValue::IsValidTarget(target, bot);
}

View File

@@ -48,9 +48,6 @@ Unit* RtiTargetValue::Calculate()
if (!guid)
return nullptr;
if (!bot->IsInCombat())
return nullptr;
//////////////////////////////////////////////////////begin: delete below check
// Some units that need to be killed in battle are not on the list of attackers,
// such as the Kor'kron Battle-Mage in Icecrown Citadel.
@@ -62,7 +59,7 @@ Unit* RtiTargetValue::Calculate()
//////////////////////////////////////////////////////end: delete below check
Unit* unit = botAI->GetUnit(guid);
if (!unit || unit->isDead() || !bot->IsWithinLOSInMap(unit) || !AttackersValue::IsValidTarget(unit, bot) ||
if (!unit || unit->isDead() || !bot->IsWithinLOSInMap(unit) || !AttackersValue::IsValidTarget(unit, bot) ||
sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, unit),
sPlayerbotAIConfig->sightDistance))
return nullptr;

View File

@@ -23,3 +23,5 @@ bool CastFearOnCcAction::isPossible() { return botAI->CanCastSpell("fear", GetTa
bool CastFearOnCcAction::isUseful() { return true; }
bool CastLifeTapAction::isUseful() { return AI_VALUE2(uint8, "health", "self target") > sPlayerbotAIConfig->lowHealth; }
Unit* UseSoulstoneAction::GetTarget() { return botAI->GetMaster(); }

View File

@@ -7,6 +7,7 @@
#define _PLAYERBOT_WARLOCKACTIONS_H
#include "GenericSpellActions.h"
#include "UseItemAction.h"
class PlayerbotAI;
class Unit;
@@ -302,4 +303,12 @@ class CastIncinerateAction : public CastSpellAction
public:
CastIncinerateAction(PlayerbotAI* ai) : CastSpellAction(ai, "incinerate") {}
};
class UseSoulstoneAction : public UseSpellItemAction
{
public:
UseSoulstoneAction(PlayerbotAI* ai) : UseSpellItemAction(ai, "soulstone") {}
Unit* GetTarget() override;
};
#endif

View File

@@ -184,6 +184,7 @@ public:
creators["metamorphosis"] = &WarlockAiObjectContextInternal::metamorphosis;
creators["soul fire"] = &WarlockAiObjectContextInternal::soul_fire;
creators["incinerate"] = &WarlockAiObjectContextInternal::incinerate;
creators["soulstone"] = &WarlockAiObjectContextInternal::soulstone;
}
private:
@@ -239,6 +240,7 @@ private:
static Action* metamorphosis(PlayerbotAI* ai) { return new CastMetamorphosisAction(ai); }
static Action* soul_fire(PlayerbotAI* ai) { return new CastSoulFireAction(ai); }
static Action* incinerate(PlayerbotAI* ai) { return new CastIncinerateAction(ai); }
static Action* soulstone(PlayerbotAI* ai) { return new UseSoulstoneAction(ai); }
};
WarlockAiObjectContext::WarlockAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI)