Implement spell AI pulling, fix throw stone

This commit is contained in:
nytmyr
2024-12-02 07:32:30 -06:00
parent f74fd59b62
commit faf372d31d
5 changed files with 62 additions and 15 deletions
+3 -1
View File
@@ -834,8 +834,10 @@ RULE_BOOL(Bots, AllowMagicianEpicPet, false, "If enabled, magician bots can summ
RULE_INT(Bots, AllowMagicianEpicPetLevel, 50, "If AllowMagicianEpicPet is enabled, bots can start using their epic pets at this level")
RULE_INT(Bots, RequiredMagicianEpicPetItemID, 28034, "If AllowMagicianEpicPet is enabled and this is set, bots will be required to have this item ID equipped to cast their epic. Takes in to account AllowMagicianEpicPetLevel as well. Set to 0 to disable requirement")
RULE_STRING(Bots, EpicPetSpellName, "", "'teleport_zone' in the spell to be cast for epic pets. This must be in their spell list to cast.")
RULE_BOOL(Bots, AllowSpellPulling, true, "If enabled bots will use a spell to pull when within range. Uses PullSpellID.")
RULE_BOOL(Bots, UseSpellPulling, true, "If enabled bots will use a spell to pull when within range. Uses PullSpellID.")
RULE_INT(Bots, PullSpellID, 5225, "Default 5225 - Throw Stone. Spell that will be cast to pull by bots")
RULE_BOOL(Bots, AllowRangedPulling, true, "If enabled bots will pull with their ranged items if set to ranged.")
RULE_BOOL(Bots, AllowAISpellPulling, true, "If enabled bots will rely on their detrimental AI to pull when within range.")
RULE_BOOL(Bots, AllowBotEquipAnyClassGear, false, "Allows Bots to wear Equipment even if their class is not valid")
RULE_BOOL(Bots, BotArcheryConsumesAmmo, true, "Set to false to disable Archery Ammo Consumption")
RULE_BOOL(Bots, BotThrowingConsumesAmmo, true, "Set to false to disable Throwing Ammo Consumption")
+19
View File
@@ -3279,6 +3279,25 @@ bool IsCommandedSpellType(uint16 spellType) {
return false;
}
bool IsPullingSpellType(uint16 spellType) {
switch (spellType) {
case BotSpellTypes::Nuke:
case BotSpellTypes::Lifetap:
case BotSpellTypes::Snare:
case BotSpellTypes::DOT:
case BotSpellTypes::Dispel:
case BotSpellTypes::Slow:
case BotSpellTypes::Debuff:
case BotSpellTypes::Stun:
case BotSpellTypes::HateLine:
return true;
default:
return false;
}
return false;
}
bool BotSpellTypeRequiresLoS(uint16 spellType, uint8 cls) {
switch (spellType) {
case BotSpellTypes::Nuke:
+1 -1
View File
@@ -740,7 +740,6 @@ bool IsBotSpellTypeDetrimental (uint16 spellType, uint8 cls = 0);
bool IsBotSpellTypeBeneficial (uint16 spellType, uint8 cls = 0);
bool IsBotSpellTypeOtherBeneficial(uint16 spellType);
bool IsBotSpellTypeInnate (uint16 spellType);
bool IsBotSpellType (uint16 spellType);
bool IsAEBotSpellType(uint16 spellType);
bool IsGroupBotSpellType(uint16 spellType);
bool IsGroupTargetOnlyBotSpellType(uint16 spellType);
@@ -752,6 +751,7 @@ bool SpellTypeRequiresTarget(uint16 spellType, uint16 cls = 0);
bool SpellTypeRequiresCastChecks(uint16 spellType);
bool SpellTypeRequiresAEChecks(uint16 spellType);
bool IsCommandedSpellType(uint16 spellType);
bool IsPullingSpellType(uint16 spellType);
bool BotSpellTypeRequiresLoS(uint16 spellType, uint8 cls);
// These should not be used to determine spell category..
+36 -13
View File
@@ -101,6 +101,7 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm
LoadDefaultBotSettings();
SetCastedSpellType(UINT16_MAX);
SetCommandedSpell(false);
SetPullingSpell(false);
//DisableBotSpellTimers();
// Do this once and only in this constructor
@@ -178,6 +179,7 @@ Bot::Bot(
SetBotCharmer(false);
SetCastedSpellType(UINT16_MAX);
SetCommandedSpell(false);
SetPullingSpell(false);
bool stance_flag = false;
if (!database.botdb.LoadStance(this, stance_flag) && bot_owner) {
@@ -2200,36 +2202,53 @@ void Bot::AI_Process()
// PULLING FLAG (ACTIONABLE RANGE)
if (GetPullingFlag()) {
if (!IsBotNonSpellFighter() && !HOLDING && AI_HasSpells() && AI_EngagedCastCheck()) {
return;
if (!IsBotNonSpellFighter() && !HOLDING && AI_HasSpells()) {
SetPullingSpell(true);
if (AI_EngagedCastCheck()) {
SetPullingSpell(false);
return;
}
SetPullingSpell(false);
}
if (RuleB(Bots, AllowSpellPulling)) {
if (RuleB(Bots, UseSpellPulling)) {
uint16 pullSpell = RuleI(Bots, PullSpellID);
if (tar_distance <= (spells[pullSpell].range * spells[pullSpell].range)) {
if (tar_distance <= spells[pullSpell].range) {
StopMoving();
if (!TargetValidation(tar)) { return; }
CastSpell(pullSpell, tar->GetID());
SetPullingSpell(false);
return;
}
}
else {
//TODO bot rewrite - add casting AI to this
if (atCombatRange && IsBotRanged() && ranged_timer.Check(false)) {
StopMoving(CalculateHeadingToTarget(tar->GetX(), tar->GetY()));
if (atCombatRange) {
if (RuleB(Bots, AllowRangedPulling) && IsBotRanged() && ranged_timer.Check(false)) {
StopMoving(CalculateHeadingToTarget(tar->GetX(), tar->GetY()));
if (BotRangedAttack(tar) && CheckDoubleRangedAttack()) {
BotRangedAttack(tar, true);
if (BotRangedAttack(tar) && CheckDoubleRangedAttack()) {
BotRangedAttack(tar, true);
}
ranged_timer.Start();
SetPullingSpell(false);
return;
}
else if (RuleB(Bots, AllowAISpellPulling) && !IsBotNonSpellFighter() && !HOLDING && AI_HasSpells() && AI_EngagedCastCheck()) {
SetPullingSpell(false);
ranged_timer.Start();
return;
return;
}
}
return;
}
}
@@ -2624,7 +2643,7 @@ void Bot::DoAttackRounds(Mob* target, int hand) {
NPC_FLURRY,
GetCleanName(),
target->GetCleanName()
); //TODO bot rewrite - add output to others hits with flurry message
);
}
}
}
@@ -9346,6 +9365,10 @@ bool Bot::PrecastChecks(Mob* tar, uint16 spellType) {
return false;
}
if (IsPullingSpell() && IsPullingSpellType(spellType)) { //Skip remaining checks for commanded
return true;
}
if (GetManaRatio() < GetSpellTypeMinManaLimit(spellType) || GetManaRatio() > GetSpellTypeMaxManaLimit(spellType)) {
LogBotPreChecksDetail("{} says, 'Cancelling cast of [{}] on [{}] due to GetSpellTypeMinManaLimit or GetSpellTypeMaxManaLimit.'", GetCleanName(), GetSpellTypeNameByID(spellType), tar->GetCleanName()); //deleteme
return false;
+3
View File
@@ -410,6 +410,8 @@ public:
void SetPauseAI(bool pause_flag) { _pauseAI = pause_flag; }
bool IsCommandedSpell() const { return _commandedSpell; }
void SetCommandedSpell(bool value) { _commandedSpell = value; }
bool IsPullingSpell() const { return _pullingSpell; }
void SetPullingSpell(bool value) { _pullingSpell = value; }
void SetGuardMode();
void SetHoldMode();
@@ -1083,6 +1085,7 @@ private:
uint16 _castedSpellType;
bool _hasLoS;
bool _commandedSpell;
bool _pullingSpell;
// Private "base stats" Members
int32 _baseMR;