Implement more commanded types properly, move shadownight hate to hateline type...

Add incapacitated checks to casting logic and checks.
Add candocombat zone check, summon other's corpse for bot, in/out combat spell checks, mute checks, level restriction
This commit is contained in:
nytmyr
2024-11-27 13:51:37 -06:00
parent ee9651b4f1
commit b2590b5056
9 changed files with 587 additions and 247 deletions
@@ -764,31 +764,6 @@ VALUES
(3006, 34863, 101, 96, 254), (3006, 34863, 101, 96, 254),
(3006, 34864, 101, 96, 254), (3006, 34864, 101, 96, 254),
(3006, 34862, 101, 96, 254), (3006, 34862, 101, 96, 254),
(3007, 4614, 101, 35, 49),
(3007, 4683, 101, 50, 56),
(3007, 4684, 101, 57, 63),
(3007, 4698, 101, 64, 64),
(3007, 5019, 101, 65, 254),
(3007, 5020, 101, 65, 254),
(3007, 6175, 101, 69, 70),
(3007, 10949, 101, 71, 75),
(3007, 10947, 101, 71, 75),
(3007, 10948, 101, 71, 75),
(3007, 14800, 101, 76, 80),
(3007, 14801, 101, 76, 80),
(3007, 14799, 101, 76, 80),
(3007, 18905, 101, 81, 85),
(3007, 18906, 101, 81, 85),
(3007, 18904, 101, 81, 85),
(3007, 25912, 101, 86, 90),
(3007, 25913, 101, 86, 90),
(3007, 25911, 101, 86, 90),
(3007, 29006, 101, 91, 95),
(3007, 29007, 101, 91, 95),
(3007, 29008, 101, 91, 95),
(3007, 35047, 101, 96, 254),
(3007, 35048, 101, 96, 254),
(3007, 35049, 101, 96, 254),
(3008, 728, 101, 8, 60), (3008, 728, 101, 8, 60),
(3008, 3361, 101, 61, 254), (3008, 3361, 101, 61, 254),
(3008, 5370, 101, 66, 70), (3008, 5370, 101, 66, 70),
@@ -1090,6 +1065,104 @@ VALUES
(3011, 25555, 112, 86, 90), (3011, 25555, 112, 86, 90),
(3011, 28632, 112, 91, 95), (3011, 28632, 112, 91, 95),
(3011, 34662, 112, 96, 254); (3011, 34662, 112, 96, 254);
)"
},
ManifestEntry{
.version = 9051,
.description = "2024_11_26_remove_sk_icb.sql",
.check = "SELECT * FROM `bot_spells_entries` where `type` = 55",
.condition = "empty",
.match = "",
.sql = R"(
DELETE
FROM bot_spells_entries
WHERE `npc_spells_id` = 3005
AND `type` = 10;
INSERT INTO `bot_spells_entries` (`npc_spells_id`, `spell_id`, `type`, `minlevel`, `maxlevel`)
VALUES
(3003, 10175, 55, 72, 76),
(3003, 10173, 55, 72, 76),
(3003, 10174, 55, 72, 76),
(3003, 14956, 55, 77, 81),
(3003, 14954, 55, 77, 81),
(3003, 14955, 55, 77, 81),
(3003, 19070, 55, 82, 86),
(3003, 19068, 55, 82, 86),
(3003, 19069, 55, 82, 86),
(3003, 25298, 55, 87, 91),
(3003, 25299, 55, 87, 91),
(3003, 25297, 55, 87, 91),
(3003, 28348, 55, 92, 96),
(3003, 28349, 55, 92, 96),
(3003, 28347, 55, 92, 96),
(3003, 34351, 55, 97, 254),
(3003, 34352, 55, 97, 254),
(3003, 34350, 55, 97, 254),
(3003, 40078, 55, 98, 254),
(3003, 40079, 55, 98, 254),
(3003, 40080, 55, 98, 254),
(3005, 1221, 55, 33, 41),
(3005, 1222, 55, 42, 52),
(3005, 1223, 55, 53, 58),
(3005, 1224, 55, 59, 62),
(3005, 3405, 55, 63, 66),
(3005, 5329, 55, 67, 70),
(3005, 5336, 55, 69, 73),
(3005, 10258, 55, 71, 71),
(3005, 10259, 55, 71, 71),
(3005, 10257, 55, 71, 71),
(3005, 10261, 55, 72, 76),
(3005, 10262, 55, 72, 76),
(3005, 10260, 55, 72, 76),
(3005, 10291, 55, 74, 78),
(3005, 10292, 55, 74, 78),
(3005, 10293, 55, 74, 78),
(3005, 15160, 55, 76, 76),
(3005, 15161, 55, 76, 76),
(3005, 15162, 55, 76, 76),
(3005, 15165, 55, 77, 81),
(3005, 15163, 55, 77, 81),
(3005, 15164, 55, 77, 81),
(3005, 15186, 55, 79, 83),
(3005, 15184, 55, 79, 83),
(3005, 15185, 55, 79, 83),
(3005, 19315, 55, 81, 81),
(3005, 19313, 55, 81, 81),
(3005, 19314, 55, 81, 81),
(3005, 19317, 55, 82, 86),
(3005, 19318, 55, 82, 86),
(3005, 19316, 55, 82, 86),
(3005, 19338, 55, 84, 88),
(3005, 19339, 55, 84, 88),
(3005, 19337, 55, 84, 88),
(3005, 25581, 55, 86, 86),
(3005, 25582, 55, 86, 86),
(3005, 25580, 55, 86, 86),
(3005, 25586, 55, 87, 91),
(3005, 25587, 55, 87, 91),
(3005, 25588, 55, 87, 91),
(3005, 25641, 55, 89, 93),
(3005, 25642, 55, 89, 93),
(3005, 25643, 55, 89, 93),
(3005, 28659, 55, 91, 91),
(3005, 28657, 55, 91, 91),
(3005, 28658, 55, 91, 91),
(3005, 28665, 55, 92, 96),
(3005, 28663, 55, 92, 96),
(3005, 28664, 55, 92, 96),
(3005, 28735, 55, 94, 98),
(3005, 28733, 55, 94, 98),
(3005, 28734, 55, 94, 98),
(3005, 34688, 55, 96, 96),
(3005, 34689, 55, 96, 96),
(3005, 34687, 55, 96, 96),
(3005, 34694, 55, 97, 254),
(3005, 34695, 55, 97, 254),
(3005, 34693, 55, 97, 254),
(3005, 34752, 55, 99, 254),
(3005, 34753, 55, 99, 254),
(3005, 34751, 55, 99, 254);
)" )"
} }
// -- template; copy/paste this when you need to create a new entry // -- template; copy/paste this when you need to create a new entry
+1
View File
@@ -806,6 +806,7 @@ RULE_INT(Bots, PercentChanceToCastSnare, 75, "The chance for a bot to attempt to
RULE_INT(Bots, PercentChanceToCastDOT, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.") RULE_INT(Bots, PercentChanceToCastDOT, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
RULE_INT(Bots, PercentChanceToCastDispel, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.") RULE_INT(Bots, PercentChanceToCastDispel, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
RULE_INT(Bots, PercentChanceToCastInCombatBuff, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.") RULE_INT(Bots, PercentChanceToCastInCombatBuff, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
RULE_INT(Bots, PercentChanceToCastHateLine, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
RULE_INT(Bots, PercentChanceToCastMez, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.") RULE_INT(Bots, PercentChanceToCastMez, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
RULE_INT(Bots, PercentChanceToCastSlow, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.") RULE_INT(Bots, PercentChanceToCastSlow, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
RULE_INT(Bots, PercentChanceToCastDebuff, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.") RULE_INT(Bots, PercentChanceToCastDebuff, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
+42 -25
View File
@@ -2843,13 +2843,8 @@ bool BOT_SPELL_TYPES_DETRIMENTAL(uint16 spellType, uint8 cls) {
case BotSpellTypes::AELifetap: case BotSpellTypes::AELifetap:
case BotSpellTypes::PBAENuke: case BotSpellTypes::PBAENuke:
case BotSpellTypes::Lull: case BotSpellTypes::Lull:
case BotSpellTypes::HateLine:
return true; return true;
case BotSpellTypes::InCombatBuff:
if (cls == Class::ShadowKnight) {
return true;
}
return false;
default: default:
return false; return false;
} }
@@ -2898,12 +2893,6 @@ bool BOT_SPELL_TYPES_BENEFICIAL(uint16 spellType, uint8 cls) {
case BotSpellTypes::MovementSpeed: case BotSpellTypes::MovementSpeed:
case BotSpellTypes::SendHome: case BotSpellTypes::SendHome:
case BotSpellTypes::SummonCorpse: case BotSpellTypes::SummonCorpse:
return true;
case BotSpellTypes::InCombatBuff:
if (cls == Class::ShadowKnight) {
return false;
}
return true; return true;
default: default:
return false; return false;
@@ -3134,12 +3123,7 @@ bool SpellTypeRequiresLoS(uint16 spellType, uint16 cls) {
case BotSpellTypes::PetFastHeals: case BotSpellTypes::PetFastHeals:
case BotSpellTypes::PetVeryFastHeals: case BotSpellTypes::PetVeryFastHeals:
case BotSpellTypes::PetHoTHeals: case BotSpellTypes::PetHoTHeals:
return false;
case BotSpellTypes::InCombatBuff: case BotSpellTypes::InCombatBuff:
if (cls && cls == Class::ShadowKnight) {
return true;
}
return false; return false;
default: default:
return true; return true;
@@ -3150,13 +3134,44 @@ bool SpellTypeRequiresLoS(uint16 spellType, uint16 cls) {
bool SpellTypeRequiresTarget(uint16 spellType, uint16 cls) { bool SpellTypeRequiresTarget(uint16 spellType, uint16 cls) {
switch (spellType) { switch (spellType) {
case BotSpellTypes::Escape:
if (cls == Class::ShadowKnight) {
return false;
}
return true;
case BotSpellTypes::Pet: case BotSpellTypes::Pet:
case BotSpellTypes::Succor:
return false;
default:
return true;
}
return true;
}
bool SpellTypeRequiresCastChecks(uint16 spellType) {
switch (spellType) {
case BotSpellTypes::AEDebuff:
case BotSpellTypes::AEDispel:
case BotSpellTypes::AEDoT:
case BotSpellTypes::AEFear:
case BotSpellTypes::AELifetap:
case BotSpellTypes::AEMez:
case BotSpellTypes::AENukes:
case BotSpellTypes::AERains:
case BotSpellTypes::AERoot:
case BotSpellTypes::AESlow:
case BotSpellTypes::AESnare:
case BotSpellTypes::AEStun:
case BotSpellTypes::PBAENuke:
case BotSpellTypes::Mez:
case BotSpellTypes::SummonCorpse:
return false;
default:
return true;
}
return true;
}
bool SpellTypeRequiresAEChecks(uint16 spellType) {
switch (spellType) {
case BotSpellTypes::AEMez:
return false; return false;
default: default:
return true; return true;
@@ -3263,6 +3278,10 @@ bool IsDamageShieldOnlySpell(uint16 spell_id) {
bool IsCommandedSpellType(uint16 spellType) { bool IsCommandedSpellType(uint16 spellType) {
switch (spellType) { switch (spellType) {
case BotSpellTypes::Charm:
case BotSpellTypes::AEFear:
case BotSpellTypes::Fear:
case BotSpellTypes::Resurrect:
case BotSpellTypes::Lull: case BotSpellTypes::Lull:
case BotSpellTypes::Teleport: case BotSpellTypes::Teleport:
case BotSpellTypes::Succor: case BotSpellTypes::Succor:
@@ -3276,8 +3295,6 @@ bool IsCommandedSpellType(uint16 spellType) {
case BotSpellTypes::MovementSpeed: case BotSpellTypes::MovementSpeed:
case BotSpellTypes::SendHome: case BotSpellTypes::SendHome:
case BotSpellTypes::SummonCorpse: case BotSpellTypes::SummonCorpse:
//case BotSpellTypes::Charm:
//case BotSpellTypes::Resurrect:
//case BotSpellTypes::Cure: //case BotSpellTypes::Cure:
//case BotSpellTypes::GroupCures: //case BotSpellTypes::GroupCures:
//case BotSpellTypes::DamageShields: //case BotSpellTypes::DamageShields:
+4 -1
View File
@@ -708,6 +708,7 @@ namespace BotSpellTypes
constexpr uint16 ResistBuffs = 52; constexpr uint16 ResistBuffs = 52;
constexpr uint16 PetDamageShields = 53; constexpr uint16 PetDamageShields = 53;
constexpr uint16 PetResistBuffs = 54; constexpr uint16 PetResistBuffs = 54;
constexpr uint16 HateLine = 55;
// Command Spell Types // Command Spell Types
constexpr uint16 Teleport = 100; // this is handled by ^depart so uses other logic constexpr uint16 Teleport = 100; // this is handled by ^depart so uses other logic
@@ -725,7 +726,7 @@ namespace BotSpellTypes
constexpr uint16 SummonCorpse = 112; constexpr uint16 SummonCorpse = 112;
constexpr uint16 START = BotSpellTypes::Nuke; // Do not remove or change this constexpr uint16 START = BotSpellTypes::Nuke; // Do not remove or change this
constexpr uint16 END = BotSpellTypes::PetResistBuffs; // Do not remove this, increment as needed constexpr uint16 END = BotSpellTypes::HateLine; // Do not remove this, increment as needed
constexpr uint16 COMMANDED_START = BotSpellTypes::Lull; // Do not remove or change this constexpr uint16 COMMANDED_START = BotSpellTypes::Lull; // Do not remove or change this
constexpr uint16 COMMANDED_END = BotSpellTypes::SummonCorpse; // Do not remove this, increment as needed constexpr uint16 COMMANDED_END = BotSpellTypes::SummonCorpse; // Do not remove this, increment as needed
} }
@@ -747,6 +748,8 @@ bool IsClientBotSpellType(uint16 spellType);
bool IsHealBotSpellType(uint16 spellType); bool IsHealBotSpellType(uint16 spellType);
bool SpellTypeRequiresLoS(uint16 spellType, uint16 cls = 0); bool SpellTypeRequiresLoS(uint16 spellType, uint16 cls = 0);
bool SpellTypeRequiresTarget(uint16 spellType, uint16 cls = 0); bool SpellTypeRequiresTarget(uint16 spellType, uint16 cls = 0);
bool SpellTypeRequiresCastChecks(uint16 spellType);
bool SpellTypeRequiresAEChecks(uint16 spellType);
bool IsCommandedSpellType(uint16 spellType); bool IsCommandedSpellType(uint16 spellType);
// These should not be used to determine spell category.. // These should not be used to determine spell category..
+177 -111
View File
@@ -5664,9 +5664,7 @@ bool Bot::CastSpell(
casting_spell_id || casting_spell_id ||
delaytimer || delaytimer ||
spellend_timer.Enabled() || spellend_timer.Enabled() ||
IsStunned() || ((IsStunned() || IsMezzed() || DivineAura()) && !IsCastNotStandingSpell(spell_id)) ||
IsFeared() ||
IsMezzed() ||
(IsSilenced() && !IsDiscipline(spell_id)) || (IsSilenced() && !IsDiscipline(spell_id)) ||
(IsAmnesiad() && IsDiscipline(spell_id)) (IsAmnesiad() && IsDiscipline(spell_id))
) { ) {
@@ -9403,7 +9401,12 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spellType, bool doPrechec
if (doPrechecks) { if (doPrechecks) {
if (spells[spell_id].target_type == ST_Self && tar != this) { if (spells[spell_id].target_type == ST_Self && tar != this) {
tar = this; if (IsEffectInSpell(spell_id, SE_SummonCorpse) && RuleB(Bots, AllowCommandedSummonCorpse)) {
//tar = this;
}
else {
tar = this;
}
} }
if (!PrecastChecks(tar, spellType)) { if (!PrecastChecks(tar, spellType)) {
@@ -9419,11 +9422,30 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spellType, bool doPrechec
return false; return false;
} }
if (spells[spell_id].target_type == ST_Self && tar != this) { if (IsFeared() || IsSilenced() || IsAmnesiad()) {
LogBotPreChecksDetail("{} says, 'Cancelling cast of {} on {} due to Incapacitated.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
return false;
}
if ((IsStunned() || IsMezzed() || DivineAura()) && !IsCastNotStandingSpell(spell_id)) {
LogBotPreChecksDetail("{} says, 'Cancelling cast of {} on {} due to !IsCastNotStandingSpell.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
return false;
}
if (
spells[spell_id].target_type == ST_Self
&& tar != this &&
(spellType != BotSpellTypes::SummonCorpse || RuleB(Bots, AllowCommandedSummonCorpse))
) {
LogBotPreChecksDetail("{} says, 'Cancelling cast of {} on {} due to ST_Self.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme LogBotPreChecksDetail("{} says, 'Cancelling cast of {} on {} due to ST_Self.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
return false; return false;
} }
if (IsDetrimentalSpell(spell_id) && !zone->CanDoCombat()) {
LogBotPreChecksDetail("{} says, 'Cancelling cast of {} on {} due to !CanDoCombat.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
return false;
}
if (!CheckSpellRecastTimer(spell_id)) { if (!CheckSpellRecastTimer(spell_id)) {
LogBotPreChecksDetail("{} says, 'Cancelling cast of {} due to !CheckSpellRecastTimer.'", GetCleanName(), GetSpellName(spell_id)); //deleteme LogBotPreChecksDetail("{} says, 'Cancelling cast of {} due to !CheckSpellRecastTimer.'", GetCleanName(), GetSpellName(spell_id)); //deleteme
return false; return false;
@@ -9439,6 +9461,42 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spellType, bool doPrechec
return false; return false;
} }
if (this == tar && IsSacrificeSpell(spell_id)) {
LogBotPreChecks("{} says, 'Cancelling cast of {} due to IsSacrificeSpell.'", GetCleanName(), GetSpellName(spell_id)); //deleteme
return false;
}
if (spells[spell_id].caster_requirement_id && !PassCastRestriction(spells[spell_id].caster_requirement_id)) {
LogBotPreChecks("{} says, 'Cancelling cast of {} due to !PassCastRestriction.'", GetCleanName(), GetSpellName(spell_id)); //deleteme
return false;
}
if (!spells[spell_id].can_cast_in_combat && spells[spell_id].can_cast_out_of_combat) {
if (IsBeneficialSpell(spell_id)) {
if (IsEngaged()) {
LogBotPreChecks("{} says, 'Cancelling cast of {} due to !can_cast_in_combat.'", GetCleanName(), GetSpellName(spell_id)); //deleteme
return false;
}
}
}
else if (spells[spell_id].can_cast_in_combat && !spells[spell_id].can_cast_out_of_combat) {
if (IsBeneficialSpell(spell_id)) {
if (!IsEngaged()) {
LogBotPreChecks("{} says, 'Cancelling cast of {} due to !can_cast_out_of_combat.'", GetCleanName(), GetSpellName(spell_id)); //deleteme
return false;
}
}
}
if (!IsDiscipline(spell_id)) {
int chance = GetFocusEffect(focusFcMute, spell_id);
if (chance && zone->random.Roll(chance)) {
LogBotPreChecks("{} says, 'Cancelling cast of {} due to focusFcMute.'", GetCleanName(), GetSpellName(spell_id)); //deleteme
return(false);
}
}
if (!zone->CanLevitate() && IsEffectInSpell(spell_id, SE_Levitate)) { if (!zone->CanLevitate() && IsEffectInSpell(spell_id, SE_Levitate)) {
LogBotPreChecks("{} says, 'Cancelling cast of {} due to !CanLevitate.'", GetCleanName(), GetSpellName(spell_id)); //deleteme LogBotPreChecks("{} says, 'Cancelling cast of {} due to !CanLevitate.'", GetCleanName(), GetSpellName(spell_id)); //deleteme
return false; return false;
@@ -9523,6 +9581,7 @@ bool Bot::CanCastSpellType(uint16 spellType, uint16 spell_id, Mob* tar) {
case BotSpellTypes::Buff: case BotSpellTypes::Buff:
case BotSpellTypes::PetBuffs: case BotSpellTypes::PetBuffs:
case BotSpellTypes::PreCombatBuff: case BotSpellTypes::PreCombatBuff:
case BotSpellTypes::InCombatBuff:
case BotSpellTypes::DamageShields: case BotSpellTypes::DamageShields:
case BotSpellTypes::PetDamageShields: case BotSpellTypes::PetDamageShields:
case BotSpellTypes::ResistBuffs: case BotSpellTypes::ResistBuffs:
@@ -9556,6 +9615,11 @@ bool Bot::CanCastSpellType(uint16 spellType, uint16 spell_id, Mob* tar) {
return false; return false;
} }
if (!tar->CheckSpellLevelRestriction(this, spell_id)) {
LogBotPreChecks("{} says, 'Cancelling cast of {} on {} due to CheckSpellLevelRestriction.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
return false;
}
if ((spellType != BotSpellTypes::Teleport && spellType != BotSpellTypes::Succor) && (IsEffectInSpell(spell_id, SE_Teleport) || IsEffectInSpell(spell_id, SE_Succor))) { if ((spellType != BotSpellTypes::Teleport && spellType != BotSpellTypes::Succor) && (IsEffectInSpell(spell_id, SE_Teleport) || IsEffectInSpell(spell_id, SE_Succor))) {
LogBotPreChecks("{} says, 'Cancelling cast of {} on {} due to Teleport.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme LogBotPreChecks("{} says, 'Cancelling cast of {} on {} due to Teleport.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
return false; return false;
@@ -9668,6 +9732,13 @@ bool Bot::CanCastSpellType(uint16 spellType, uint16 spell_id, Mob* tar) {
} }
} }
break;
case BotSpellTypes::Lull:
if (IsHarmonySpell(spell_id) && !HarmonySpellLevelCheck(spell_id, tar)) {
LogBotPreChecksDetail("{} says, 'Cancelling cast of {} on {} due to HarmonySpellLevelCheck.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
return false;
}
break; break;
default: default:
break; break;
@@ -10494,50 +10565,48 @@ uint16 Bot::GetDefaultSpellTypeEngagedPriority(uint16 spellType, uint8 botClass,
return 20; return 20;
case BotSpellTypes::Mez: case BotSpellTypes::Mez:
return 21; return 21;
case BotSpellTypes::AEDispel: case BotSpellTypes::HateLine:
return 22; return 22;
case BotSpellTypes::Dispel: case BotSpellTypes::AEDispel:
return 23; return 23;
case BotSpellTypes::AEDebuff: case BotSpellTypes::Dispel:
return 24; return 24;
case BotSpellTypes::Debuff: case BotSpellTypes::AEDebuff:
return 25; return 25;
case BotSpellTypes::AESnare: case BotSpellTypes::Debuff:
return 26; return 26;
case BotSpellTypes::Snare: case BotSpellTypes::AESnare:
return 27; return 27;
case BotSpellTypes::AEFear: case BotSpellTypes::Snare:
return 28; return 28;
case BotSpellTypes::Fear:
return 29;
case BotSpellTypes::AESlow: case BotSpellTypes::AESlow:
return 30; return 29;
case BotSpellTypes::Slow: case BotSpellTypes::Slow:
return 31; return 30;
case BotSpellTypes::AERoot: case BotSpellTypes::AERoot:
return 32; return 31;
case BotSpellTypes::Root: case BotSpellTypes::Root:
return 33; return 32;
case BotSpellTypes::AEDoT: case BotSpellTypes::AEDoT:
return 34; return 33;
case BotSpellTypes::DOT: case BotSpellTypes::DOT:
return 35; return 34;
case BotSpellTypes::AEStun: case BotSpellTypes::AEStun:
return 36; return 35;
case BotSpellTypes::PBAENuke: case BotSpellTypes::PBAENuke:
return 37; return 36;
case BotSpellTypes::AENukes: case BotSpellTypes::AENukes:
return 38; return 37;
case BotSpellTypes::AERains: case BotSpellTypes::AERains:
return 39; return 38;
case BotSpellTypes::Stun: case BotSpellTypes::Stun:
return 40; return 39;
case BotSpellTypes::Nuke: case BotSpellTypes::Nuke:
return 41; return 40;
case BotSpellTypes::InCombatBuff: case BotSpellTypes::InCombatBuff:
return 42; return 41;
case BotSpellTypes::InCombatBuffSong: case BotSpellTypes::InCombatBuffSong:
return 43; return 42;
default: default:
return 0; return 0;
} }
@@ -10904,8 +10973,6 @@ uint16 Bot::GetSpellListSpellType(uint16 spellType) {
case BotSpellTypes::PetDamageShields: case BotSpellTypes::PetDamageShields:
case BotSpellTypes::ResistBuffs: case BotSpellTypes::ResistBuffs:
case BotSpellTypes::PetResistBuffs: case BotSpellTypes::PetResistBuffs:
case BotSpellTypes::Teleport:
case BotSpellTypes::Succor:
case BotSpellTypes::BindAffinity: case BotSpellTypes::BindAffinity:
case BotSpellTypes::Identify: case BotSpellTypes::Identify:
case BotSpellTypes::Levitate: case BotSpellTypes::Levitate:
@@ -10914,8 +10981,6 @@ uint16 Bot::GetSpellListSpellType(uint16 spellType) {
case BotSpellTypes::Size: case BotSpellTypes::Size:
case BotSpellTypes::Invisibility: case BotSpellTypes::Invisibility:
case BotSpellTypes::MovementSpeed: case BotSpellTypes::MovementSpeed:
case BotSpellTypes::SendHome:
case BotSpellTypes::SummonCorpse:
return BotSpellTypes::Buff; return BotSpellTypes::Buff;
case BotSpellTypes::AEMez: case BotSpellTypes::AEMez:
case BotSpellTypes::Mez: case BotSpellTypes::Mez:
@@ -10950,6 +11015,7 @@ uint16 Bot::GetSpellListSpellType(uint16 spellType) {
case BotSpellTypes::Charm: case BotSpellTypes::Charm:
case BotSpellTypes::Escape: case BotSpellTypes::Escape:
case BotSpellTypes::HateRedux: case BotSpellTypes::HateRedux:
case BotSpellTypes::HateLine:
case BotSpellTypes::InCombatBuff: case BotSpellTypes::InCombatBuff:
case BotSpellTypes::InCombatBuffSong: case BotSpellTypes::InCombatBuffSong:
case BotSpellTypes::OutOfCombatBuffSong: case BotSpellTypes::OutOfCombatBuffSong:
@@ -11021,84 +11087,84 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spellType, uint16 spell_id) {
} }
return false; return false;
case BotSpellTypes::Lull: //case BotSpellTypes::Lull:
if (!IsHarmonySpell(spell_id)) { // if (IsHarmonySpell(spell_id)) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::Teleport: //case BotSpellTypes::Teleport:
if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_Teleport) || IsEffectInSpell(spell_id, SE_Translocate))) { // if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_Teleport) || IsEffectInSpell(spell_id, SE_Translocate))) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::Succor: //case BotSpellTypes::Succor:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_Succor)) { // if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_Succor)) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::BindAffinity: //case BotSpellTypes::BindAffinity:
if (IsEffectInSpell(spell_id, SE_BindAffinity)) { // if (IsEffectInSpell(spell_id, SE_BindAffinity)) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::Identify: //case BotSpellTypes::Identify:
if (IsEffectInSpell(spell_id, SE_Identify)) { // if (IsEffectInSpell(spell_id, SE_Identify)) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::Levitate: //case BotSpellTypes::Levitate:
if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_Levitate))) { // if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_Levitate))) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::Rune: //case BotSpellTypes::Rune:
if (IsEffectInSpell(spell_id, SE_AbsorbMagicAtt) || IsEffectInSpell(spell_id, SE_Rune)) { // if (IsEffectInSpell(spell_id, SE_AbsorbMagicAtt) || IsEffectInSpell(spell_id, SE_Rune)) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::WaterBreathing: //case BotSpellTypes::WaterBreathing:
if (IsEffectInSpell(spell_id, SE_WaterBreathing)) { // if (IsEffectInSpell(spell_id, SE_WaterBreathing)) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::Size: //case BotSpellTypes::Size:
if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_ModelSize) || IsEffectInSpell(spell_id, SE_ChangeHeight))) { // if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_ModelSize) || IsEffectInSpell(spell_id, SE_ChangeHeight))) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::Invisibility: //case BotSpellTypes::Invisibility:
if (IsEffectInSpell(spell_id, SE_SeeInvis) || IsInvisibleSpell(spell_id)) { // if (IsEffectInSpell(spell_id, SE_SeeInvis) || IsInvisibleSpell(spell_id)) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::MovementSpeed: //case BotSpellTypes::MovementSpeed:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_MovementSpeed)) { // if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_MovementSpeed)) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::SendHome: //case BotSpellTypes::SendHome:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_GateToHomeCity)) { // if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_GateToHomeCity)) {
return true; // return true;
} // }
//
return false; // return false;
case BotSpellTypes::SummonCorpse: //case BotSpellTypes::SummonCorpse:
if (IsEffectInSpell(spell_id, SE_SummonCorpse)) { // if (IsEffectInSpell(spell_id, SE_SummonCorpse)) {
return true; // return true;
} // }
//
return false; // return false;
default: default:
return true; return true;
} }
@@ -11331,7 +11397,7 @@ bool Bot::HasValidAETarget(Bot* botCaster, uint16 spell_id, uint16 spellType, Mo
break; break;
} }
if (!m->IsNPC() || !m->CastToNPC()->IsOnHatelist(botCaster->GetOwner())) { if (!m->IsNPC() || (!IsCommandedSpell() && !m->CastToNPC()->IsOnHatelist(botCaster->GetOwner()))) {
continue; continue;
} }
+17 -9
View File
@@ -308,7 +308,7 @@ void bot_command_cast(Client* c, const Seperator* sep)
} }
Mob* tar = c->GetTarget(); Mob* tar = c->GetTarget();
LogTestDebug("{}: 'Attempting {} [{}] on {}'", __LINE__, c->GetSpellTypeNameByID(spellType), (subType != UINT16_MAX ? c->GetSubTypeNameByID(subType) : "Standard"), (tar ? tar->GetCleanName() : "NOBODY")); //deleteme //LogTestDebug("{}: 'Attempting {} [{}-{}] on {}'", __LINE__, c->GetSpellTypeNameByID(spellType), (subType != UINT16_MAX ? c->GetSubTypeNameByID(subType) : "Standard"), (subTargetType != UINT16_MAX ? c->GetSubTypeNameByID(subTargetType) : "Standard"), (tar ? tar->GetCleanName() : "NOBODY")); //deleteme
if (!tar) { if (!tar) {
if (spellType != BotSpellTypes::Escape && spellType != BotSpellTypes::Pet) { if (spellType != BotSpellTypes::Escape && spellType != BotSpellTypes::Pet) {
@@ -338,7 +338,17 @@ void bot_command_cast(Client* c, const Seperator* sep)
break; break;
default: default:
if (BOT_SPELL_TYPES_DETRIMENTAL(spellType) && !c->IsAttackAllowed(tar)) { if (
(BOT_SPELL_TYPES_DETRIMENTAL(spellType) && !c->IsAttackAllowed(tar)) ||
(
spellType == BotSpellTypes::Charm &&
(
tar->IsClient() ||
tar->IsCorpse() ||
tar->GetOwner()
)
)
) {
c->Message(Chat::Yellow, "You cannot attack [%s].", tar->GetCleanName()); c->Message(Chat::Yellow, "You cannot attack [%s].", tar->GetCleanName());
return; return;
@@ -395,18 +405,16 @@ void bot_command_cast(Client* c, const Seperator* sep)
/* /*
TODO bot rewrite - TODO bot rewrite -
FIX: Depart, SummonCorpse, Lull, FIX: Depart
Group Cures, Precombat, Fear/AE Fear Group Cures, Precombat
ICB (SK) casting hate on friendly but not hostile?
NEED TO CHECK: precombat, AE Dispel, AE Lifetap NEED TO CHECK: precombat, AE Dispel, AE Lifetap
DO I NEED A PBAE CHECK???
*/ */
if (bot_iter->GetBotStance() == Stance::Passive || bot_iter->GetHoldFlag() || bot_iter->GetAppearance() == eaDead || bot_iter->IsFeared() || bot_iter->IsStunned() || bot_iter->IsMezzed() || bot_iter->DivineAura() || bot_iter->GetHP() < 0) { if (bot_iter->GetBotStance() == Stance::Passive || bot_iter->GetHoldFlag() || bot_iter->GetAppearance() == eaDead || bot_iter->IsFeared() || bot_iter->IsSilenced() || bot_iter->IsAmnesiad() || bot_iter->GetHP() < 0) {
continue; continue;
} }
Mob* newTar = tar; Mob* newTar = tar;
LogTestDebug("{}: {} says, 'Attempting {} [{}] on {}'", __LINE__, bot_iter->GetCleanName(), c->GetSpellTypeNameByID(spellType), (subType != UINT16_MAX ? c->GetSubTypeNameByID(subType) : "Standard"), (newTar ? newTar->GetCleanName() : "NOBODY")); //deleteme //LogTestDebug("{}: {} says, 'Attempting {} [{}-{}] on {}'", __LINE__, bot_iter->GetCleanName(), c->GetSpellTypeNameByID(spellType), (subType != UINT16_MAX ? c->GetSubTypeNameByID(subType) : "Standard"), (subTargetType != UINT16_MAX ? c->GetSubTypeNameByID(subTargetType) : "Standard"), (newTar ? newTar->GetCleanName() : "NOBODY")); //deleteme
if (!SpellTypeRequiresTarget(spellType, bot_iter->GetClass())) { if (!SpellTypeRequiresTarget(spellType, bot_iter->GetClass())) {
newTar = bot_iter; newTar = bot_iter;
} }
@@ -435,7 +443,7 @@ void bot_command_cast(Client* c, const Seperator* sep)
continue; continue;
} }
LogTestDebug("{}: {} says, 'Attempting {} [{}] on {}'", __LINE__, bot_iter->GetCleanName(), c->GetSpellTypeNameByID(spellType), (subType != UINT16_MAX ? c->GetSubTypeNameByID(subType) : "Standard"), (newTar ? newTar->GetCleanName() : "NOBODY")); //deleteme LogTestDebug("{}: {} says, 'Attempting {} [{}-{}] on {}'", __LINE__, bot_iter->GetCleanName(), c->GetSpellTypeNameByID(spellType), (subType != UINT16_MAX ? c->GetSubTypeNameByID(subType) : "Standard"), (subTargetType != UINT16_MAX ? c->GetSubTypeNameByID(subTargetType) : "Standard"), (newTar ? newTar->GetCleanName() : "NOBODY")); //deleteme
bot_iter->SetCommandedSpell(true); bot_iter->SetCommandedSpell(true);
+173 -66
View File
@@ -116,11 +116,13 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 spellType, uint16 subTarge
break; break;
case BotSpellTypes::InCombatBuff: case BotSpellTypes::InCombatBuff:
if (GetClass() == Class::ShadowKnight && (tar->IsOfClientBot() || (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()))) { if (!IsCommandedSpell() && GetClass() != Class::Shaman && spellType == BotSpellTypes::InCombatBuff && IsCasterClass(GetClass()) && GetLevel() >= GetStopMeleeLevel()) {
return false; return false;
} }
if (!IsCommandedSpell() && GetClass() != Class::Shaman && spellType == BotSpellTypes::InCombatBuff && IsCasterClass(GetClass()) && GetLevel() >= GetStopMeleeLevel()) { break;
case BotSpellTypes::HateLine:
if (!tar->IsNPC()) {
return false; return false;
} }
@@ -198,7 +200,6 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 spellType, uint16 subTarge
return BotCastPet(tar, botClass, botSpell, spellType); return BotCastPet(tar, botClass, botSpell, spellType);
case BotSpellTypes::Resurrect: case BotSpellTypes::Resurrect:
case BotSpellTypes::SummonCorpse:
if (!tar->IsCorpse() || !tar->CastToCorpse()->IsPlayerCorpse()) { if (!tar->IsCorpse() || !tar->CastToCorpse()->IsPlayerCorpse()) {
return false; return false;
} }
@@ -267,6 +268,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 spellType, uint16 subTarge
return true; return true;
} }
else { LogTestDebug("{} says, '{} [#{}] - [{}] FAILED AIDoSpellCast on {}.'", GetCleanName(), spells[s.SpellId].name, s.SpellId, GetSpellTypeNameByID(spellType), tar->GetCleanName()); } //deleteme
} }
return false; return false;
@@ -631,7 +633,7 @@ bool Bot::AIDoSpellCast(int32 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain
} }
bool Bot::AI_PursueCastCheck() { bool Bot::AI_PursueCastCheck() {
if (GetAppearance() == eaDead || IsFeared() || IsStunned() || IsMezzed() || DivineAura() || GetHP() < 0) { if (GetAppearance() == eaDead || IsFeared() || IsSilenced() || IsAmnesiad() || GetHP() < 0) {
return false; return false;
} }
@@ -656,11 +658,11 @@ bool Bot::AI_PursueCastCheck() {
continue; continue;
} }
if (RuleB(Bots, AllowAIMez) && (currentCast.spellType == BotSpellTypes::AEMez || currentCast.spellType == BotSpellTypes::Mez)) { if (!RuleB(Bots, AllowAIMez) && (currentCast.spellType == BotSpellTypes::AEMez || currentCast.spellType == BotSpellTypes::Mez)) {
continue; continue;
} }
if (IsCommandedSpellType(currentCast.spellType) || currentCast.spellType == BotSpellTypes::Resurrect || currentCast.spellType == BotSpellTypes::Charm) { // Unsupported by AI currently. if (IsCommandedSpellType(currentCast.spellType)) { // Unsupported by AI currently.
continue; continue;
} }
@@ -680,7 +682,7 @@ bool Bot::AI_PursueCastCheck() {
} }
bool Bot::AI_IdleCastCheck() { bool Bot::AI_IdleCastCheck() {
if (GetAppearance() == eaDead || IsFeared() || IsStunned() || IsMezzed() || DivineAura() || GetHP() < 0) { if (GetAppearance() == eaDead || IsFeared() || IsSilenced() || IsAmnesiad() || GetHP() < 0) {
return false; return false;
} }
@@ -719,11 +721,11 @@ bool Bot::AI_IdleCastCheck() {
continue; continue;
} }
if (RuleB(Bots, AllowAIMez) && (currentCast.spellType == BotSpellTypes::AEMez || currentCast.spellType == BotSpellTypes::Mez)) { if (!RuleB(Bots, AllowAIMez) && (currentCast.spellType == BotSpellTypes::AEMez || currentCast.spellType == BotSpellTypes::Mez)) {
continue; continue;
} }
if (IsCommandedSpellType(currentCast.spellType) || currentCast.spellType == BotSpellTypes::Resurrect || currentCast.spellType == BotSpellTypes::Charm) { // Unsupported by AI currently. if (IsCommandedSpellType(currentCast.spellType)) { // Unsupported by AI currently.
continue; continue;
} }
@@ -743,7 +745,7 @@ bool Bot::AI_IdleCastCheck() {
} }
bool Bot::AI_EngagedCastCheck() { bool Bot::AI_EngagedCastCheck() {
if (GetAppearance() == eaDead || IsFeared() || IsStunned() || IsMezzed() || DivineAura() || GetHP() < 0) { if (GetAppearance() == eaDead || IsFeared() || IsSilenced() || IsAmnesiad() || GetHP() < 0) {
return false; return false;
} }
@@ -769,11 +771,11 @@ bool Bot::AI_EngagedCastCheck() {
continue; continue;
} }
if (RuleB(Bots, AllowAIMez) && (currentCast.spellType == BotSpellTypes::AEMez || currentCast.spellType == BotSpellTypes::Mez)) { if (!RuleB(Bots, AllowAIMez) && (currentCast.spellType == BotSpellTypes::AEMez || currentCast.spellType == BotSpellTypes::Mez)) {
continue; continue;
} }
if (IsCommandedSpellType(currentCast.spellType) || currentCast.spellType == BotSpellTypes::Resurrect || currentCast.spellType == BotSpellTypes::Charm) { // Unsupported by AI currently. if (IsCommandedSpellType(currentCast.spellType)) { // Unsupported by AI currently.
continue; continue;
} }
@@ -1045,18 +1047,8 @@ std::list<BotSpell_wPriority> Bot::GetPrioritizedBotSpellsBySpellType(Bot* botCa
} }
if ( if (
( (!botCaster->IsCommandedSpell() || (botCaster->IsCommandedSpell() && SpellTypeRequiresCastChecks(spellType))) &&
!botCaster->IsCommandedSpell() || (!IsPBAESpell(botSpellList[i].spellid) && !botCaster->CastChecks(botSpellList[i].spellid, tar, spellType, false, IsAEBotSpellType(spellType)))
(
botCaster->IsCommandedSpell() &&
(spellType != BotSpellTypes::Mez && spellType != BotSpellTypes::AEMez)
)
)
&&
(
!IsPBAESpell(botSpellList[i].spellid) &&
!botCaster->CastChecks(botSpellList[i].spellid, tar, spellType, false, IsAEBotSpellType(spellType))
)
) { ) {
continue; continue;
} }
@@ -1064,9 +1056,10 @@ std::list<BotSpell_wPriority> Bot::GetPrioritizedBotSpellsBySpellType(Bot* botCa
if ( if (
botCaster->IsCommandedSpell() || botCaster->IsCommandedSpell() ||
!AE || !AE ||
(spellType == BotSpellTypes::GroupCures) || (
(spellType == BotSpellTypes::AEMez) || SpellTypeRequiresAEChecks(spellType) &&
(AE && botCaster->HasValidAETarget(botCaster, botSpellList[i].spellid, spellType, tar)) botCaster->HasValidAETarget(botCaster, botSpellList[i].spellid, spellType, tar)
)
) { ) {
BotSpell_wPriority botSpell; BotSpell_wPriority botSpell;
botSpell.SpellId = botSpellList[i].spellid; botSpell.SpellId = botSpellList[i].spellid;
@@ -2099,18 +2092,6 @@ uint8 Bot::GetChanceToCastBySpellType(uint16 spellType)
case BotSpellTypes::PetResistBuffs: case BotSpellTypes::PetResistBuffs:
case BotSpellTypes::DamageShields: case BotSpellTypes::DamageShields:
case BotSpellTypes::PetDamageShields: case BotSpellTypes::PetDamageShields:
case BotSpellTypes::Teleport:
case BotSpellTypes::Succor:
case BotSpellTypes::BindAffinity:
case BotSpellTypes::Identify:
case BotSpellTypes::Levitate:
case BotSpellTypes::Rune:
case BotSpellTypes::WaterBreathing:
case BotSpellTypes::Size:
case BotSpellTypes::Invisibility:
case BotSpellTypes::MovementSpeed:
case BotSpellTypes::SendHome:
case BotSpellTypes::SummonCorpse:
return RuleI(Bots, PercentChanceToCastBuff); return RuleI(Bots, PercentChanceToCastBuff);
case BotSpellTypes::Escape: case BotSpellTypes::Escape:
return RuleI(Bots, PercentChanceToCastEscape); return RuleI(Bots, PercentChanceToCastEscape);
@@ -2124,6 +2105,8 @@ uint8 Bot::GetChanceToCastBySpellType(uint16 spellType)
return RuleI(Bots, PercentChanceToCastDispel); return RuleI(Bots, PercentChanceToCastDispel);
case BotSpellTypes::InCombatBuff: case BotSpellTypes::InCombatBuff:
return RuleI(Bots, PercentChanceToCastInCombatBuff); return RuleI(Bots, PercentChanceToCastInCombatBuff);
case BotSpellTypes::HateLine:
return RuleI(Bots, PercentChanceToCastHateLine);
case BotSpellTypes::Mez: case BotSpellTypes::Mez:
return RuleI(Bots, PercentChanceToCastMez); return RuleI(Bots, PercentChanceToCastMez);
case BotSpellTypes::Slow: case BotSpellTypes::Slow:
@@ -2842,65 +2825,71 @@ void Bot::CheckBotSpells() {
switch (s.type) { switch (s.type) {
case BotSpellTypes::Nuke: //DONE case BotSpellTypes::Nuke:
if (IsAnyNukeOrStunSpell(spell_id) && !IsEffectInSpell(spell_id, SE_Root) && !IsDebuffSpell(spell_id)) { if (IsAnyNukeOrStunSpell(spell_id) && !IsEffectInSpell(spell_id, SE_Root) && !IsDebuffSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::RegularHeal: //DONE case BotSpellTypes::RegularHeal:
//if (IsAnyHealSpell(spell_id) && !IsEscapeSpell(spell_id) && (IsRegularPetHealSpell(spell_id) || !IsCureSpell(spell_id))) {
if (IsAnyHealSpell(spell_id) && !IsEscapeSpell(spell_id)) { if (IsAnyHealSpell(spell_id) && !IsEscapeSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::Root: //DONE case BotSpellTypes::Root:
if (IsEffectInSpell(spell_id, SE_Root)) { if (IsEffectInSpell(spell_id, SE_Root)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::Buff: //DONE case BotSpellTypes::Buff:
if (IsAnyBuffSpell(spell_id)) { if (IsAnyBuffSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::Pet: //DONE case BotSpellTypes::Pet:
if (IsSummonPetSpell(spell_id) || IsEffectInSpell(spell_id, SE_TemporaryPets)) { if (IsSummonPetSpell(spell_id) || IsEffectInSpell(spell_id, SE_TemporaryPets)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::Lifetap: //DONE case BotSpellTypes::Lifetap:
if (IsLifetapSpell(spell_id)) { if (IsLifetapSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::Snare: //DONE case BotSpellTypes::Snare:
if (IsEffectInSpell(spell_id, SE_MovementSpeed) && IsDetrimentalSpell(spell_id)) { if (IsEffectInSpell(spell_id, SE_MovementSpeed) && IsDetrimentalSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::DOT: //DONE case BotSpellTypes::DOT:
if (IsStackableDOT(spell_id) || IsDamageOverTimeSpell(spell_id)) { if (IsStackableDOT(spell_id) || IsDamageOverTimeSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::Dispel: //DONE case BotSpellTypes::Dispel:
if (IsDispelSpell(spell_id)) { if (IsDispelSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::InCombatBuff: //DONE case BotSpellTypes::InCombatBuff:
if ( if (
IsSelfConversionSpell(spell_id) || IsSelfConversionSpell(spell_id) ||
IsAnyBuffSpell(spell_id) || IsAnyBuffSpell(spell_id)
) {
valid = true;
break;
}
break;
case BotSpellTypes::HateLine:
if (
(IsEffectInSpell(spell_id, SE_Hate) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_Hate)] > 0) || (IsEffectInSpell(spell_id, SE_Hate) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_Hate)] > 0) ||
(IsEffectInSpell(spell_id, SE_InstantHate) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_InstantHate)] > 0) (IsEffectInSpell(spell_id, SE_InstantHate) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_InstantHate)] > 0)
) { ) {
@@ -2908,37 +2897,37 @@ void Bot::CheckBotSpells() {
break; break;
} }
break; break;
case BotSpellTypes::Mez: //DONE case BotSpellTypes::Mez:
if (IsMesmerizeSpell(spell_id)) { if (IsMesmerizeSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::Charm: //DONE case BotSpellTypes::Charm:
if (IsCharmSpell(spell_id)) { if (IsCharmSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::Slow: //DONE case BotSpellTypes::Slow:
if (IsSlowSpell(spell_id)) { if (IsSlowSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::Debuff: //DONE case BotSpellTypes::Debuff:
if (IsDebuffSpell(spell_id) && !IsEscapeSpell(spell_id) && !IsHateReduxSpell(spell_id)) { if (IsDebuffSpell(spell_id) && !IsEscapeSpell(spell_id) && !IsHateReduxSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::Cure: //DONE case BotSpellTypes::Cure:
if (IsCureSpell(spell_id)) { if (IsCureSpell(spell_id)) {
valid = true; valid = true;
break; break;
} }
break; break;
case BotSpellTypes::PreCombatBuff: //DONE case BotSpellTypes::PreCombatBuff:
if ( if (
IsBuffSpell(spell_id) && IsBuffSpell(spell_id) &&
IsBeneficialSpell(spell_id) && IsBeneficialSpell(spell_id) &&
@@ -2950,9 +2939,9 @@ void Bot::CheckBotSpells() {
break; break;
} }
break; break;
case BotSpellTypes::InCombatBuffSong: //DONE case BotSpellTypes::InCombatBuffSong:
case BotSpellTypes::OutOfCombatBuffSong: //DONE case BotSpellTypes::OutOfCombatBuffSong:
case BotSpellTypes::PreCombatBuffSong: //DONE case BotSpellTypes::PreCombatBuffSong:
if ( if (
IsBuffSpell(spell_id) && IsBuffSpell(spell_id) &&
IsBeneficialSpell(spell_id) && IsBeneficialSpell(spell_id) &&
@@ -2964,7 +2953,7 @@ void Bot::CheckBotSpells() {
break; break;
} }
break; break;
case BotSpellTypes::Fear: //DONE case BotSpellTypes::Fear:
if (IsFearSpell(spell_id)) { if (IsFearSpell(spell_id)) {
valid = true; valid = true;
break; break;
@@ -2988,7 +2977,84 @@ void Bot::CheckBotSpells() {
break; break;
} }
break; break;
//TODO bot rewrite - add commanded types case BotSpellTypes::Lull:
if (IsHarmonySpell(spell_id)) {
valid = true;
break;
}
break;
case BotSpellTypes::Teleport:
if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_Teleport) || IsEffectInSpell(spell_id, SE_Translocate))) {
valid = true;
break;
}
break;
case BotSpellTypes::Succor:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_Succor)) {
valid = true;
break;
}
break;
case BotSpellTypes::BindAffinity:
if (IsEffectInSpell(spell_id, SE_BindAffinity)) {
valid = true;
break;
}
break;
case BotSpellTypes::Identify:
if (IsEffectInSpell(spell_id, SE_Identify)) {
valid = true;
break;
}
break;
case BotSpellTypes::Levitate:
if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_Levitate))) {
valid = true;
break;
}
break;
case BotSpellTypes::Rune:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_AbsorbMagicAtt) || IsEffectInSpell(spell_id, SE_Rune)) {
valid = true;
break;
}
break;
case BotSpellTypes::WaterBreathing:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_WaterBreathing)) {
valid = true;
break;
}
break;
case BotSpellTypes::Size:
if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_ModelSize) || IsEffectInSpell(spell_id, SE_ChangeHeight))) {
valid = true;
break;
}
break;
case BotSpellTypes::Invisibility:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_SeeInvis) || IsInvisibleSpell(spell_id)) {
valid = true;
break;
}
break;
case BotSpellTypes::MovementSpeed:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_MovementSpeed)) {
valid = true;
break;
}
break;
case BotSpellTypes::SendHome:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_GateToHomeCity)) {
valid = true;
break;
}
break;
case BotSpellTypes::SummonCorpse:
if (IsEffectInSpell(spell_id, SE_SummonCorpse)) {
valid = true;
break;
}
break;
default: default:
break; break;
@@ -2997,7 +3063,6 @@ void Bot::CheckBotSpells() {
if (IsAnyNukeOrStunSpell(spell_id) && !IsEffectInSpell(spell_id, SE_Root) && !IsDebuffSpell(spell_id)) { if (IsAnyNukeOrStunSpell(spell_id) && !IsEffectInSpell(spell_id, SE_Root) && !IsDebuffSpell(spell_id)) {
correctType = BotSpellTypes::Nuke; correctType = BotSpellTypes::Nuke;
} }
//else if (IsAnyHealSpell(spell_id) && !IsEscapeSpell(spell_id) && (IsRegularPetHealSpell(spell_id) || !IsCureSpell(spell_id))) {
else if (IsAnyHealSpell(spell_id) && !IsEscapeSpell(spell_id)) { else if (IsAnyHealSpell(spell_id) && !IsEscapeSpell(spell_id)) {
correctType = BotSpellTypes::RegularHeal; correctType = BotSpellTypes::RegularHeal;
} }
@@ -3024,11 +3089,15 @@ void Bot::CheckBotSpells() {
} }
else if ( else if (
IsSelfConversionSpell(spell_id) || IsSelfConversionSpell(spell_id) ||
IsAnyBuffSpell(spell_id) || IsAnyBuffSpell(spell_id)
) {
correctType = BotSpellTypes::InCombatBuff;
}
else if (
(IsEffectInSpell(spell_id, SE_Hate) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_Hate)] > 0) || (IsEffectInSpell(spell_id, SE_Hate) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_Hate)] > 0) ||
(IsEffectInSpell(spell_id, SE_InstantHate) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_InstantHate)] > 0) (IsEffectInSpell(spell_id, SE_InstantHate) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_InstantHate)] > 0)
) { ) {
correctType = BotSpellTypes::InCombatBuff; correctType = BotSpellTypes::HateLine;
} }
else if (IsMesmerizeSpell(spell_id)) { else if (IsMesmerizeSpell(spell_id)) {
correctType = BotSpellTypes::Mez; correctType = BotSpellTypes::Mez;
@@ -3084,7 +3153,45 @@ void Bot::CheckBotSpells() {
else if (IsEffectInSpell(spell_id, SE_Revive)) { else if (IsEffectInSpell(spell_id, SE_Revive)) {
correctType = BotSpellTypes::Resurrect; correctType = BotSpellTypes::Resurrect;
} }
//TODO bot rewrite - add commanded types else if (IsHarmonySpell(spell_id)) {
correctType = BotSpellTypes::Lull;
}
else if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_Teleport) || IsEffectInSpell(spell_id, SE_Translocate))) {
correctType = BotSpellTypes::Teleport;
}
else if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_Succor)) {
correctType = BotSpellTypes::Succor;
}
else if (IsEffectInSpell(spell_id, SE_BindAffinity)) {
correctType = BotSpellTypes::BindAffinity;
}
else if (IsEffectInSpell(spell_id, SE_Identify)) {
correctType = BotSpellTypes::Identify;
}
else if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_Levitate))) {
correctType = BotSpellTypes::Levitate;
}
else if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_AbsorbMagicAtt) || IsEffectInSpell(spell_id, SE_Rune)) {
correctType = BotSpellTypes::Rune;
}
else if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_WaterBreathing)) {
correctType = BotSpellTypes::WaterBreathing;
}
else if (IsBeneficialSpell(spell_id) && (IsEffectInSpell(spell_id, SE_ModelSize) || IsEffectInSpell(spell_id, SE_ChangeHeight))) {
correctType = BotSpellTypes::Size;
}
else if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_SeeInvis) || IsInvisibleSpell(spell_id)) {
correctType = BotSpellTypes::Invisibility;
}
else if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_MovementSpeed)) {
correctType = BotSpellTypes::MovementSpeed;
}
else if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_GateToHomeCity)) {
correctType = BotSpellTypes::SendHome;
}
else if (IsEffectInSpell(spell_id, SE_SummonCorpse)) {
correctType = BotSpellTypes::SummonCorpse;
}
if (!valid || (correctType == UINT16_MAX) || (s.type != correctType)) { if (!valid || (correctType == UINT16_MAX) || (s.type != correctType)) {
LogBotSpellTypeChecks("{} [#{}] is incorrect. It is currently set as {} [#{}] and should be {} [#{}]" LogBotSpellTypeChecks("{} [#{}] is incorrect. It is currently set as {} [#{}] and should be {} [#{}]"
+60 -6
View File
@@ -8881,6 +8881,9 @@ std::string Mob::GetSpellTypeNameByID(uint16 spellType) {
case BotSpellTypes::PetResistBuffs: case BotSpellTypes::PetResistBuffs:
spellTypeName = "Pet Resist Buff"; spellTypeName = "Pet Resist Buff";
break; break;
case BotSpellTypes::HateLine:
spellTypeName = "Hate Line";
break;
case BotSpellTypes::Lull: case BotSpellTypes::Lull:
spellTypeName = "Lull"; spellTypeName = "Lull";
break; break;
@@ -9096,6 +9099,9 @@ std::string Mob::GetSpellTypeShortNameByID(uint16 spellType) {
case BotSpellTypes::PetResistBuffs: case BotSpellTypes::PetResistBuffs:
spellTypeName = "petresistbuffs"; spellTypeName = "petresistbuffs";
break; break;
case BotSpellTypes::HateLine:
spellTypeName = "hateline";
break;
case BotSpellTypes::Lull: case BotSpellTypes::Lull:
spellTypeName = "lull"; spellTypeName = "lull";
break; break;
@@ -9214,8 +9220,11 @@ bool Mob::GetDefaultSpellHold(uint16 spellType, uint8 stance) {
case BotSpellTypes::AEFear: case BotSpellTypes::AEFear:
case BotSpellTypes::Fear: case BotSpellTypes::Fear:
return true; return true;
case BotSpellTypes::Mez:
case BotSpellTypes::AEMez: case BotSpellTypes::AEMez:
case BotSpellTypes::Debuff:
case BotSpellTypes::AEDebuff: case BotSpellTypes::AEDebuff:
case BotSpellTypes::Slow:
case BotSpellTypes::AESlow: case BotSpellTypes::AESlow:
case BotSpellTypes::HateRedux: case BotSpellTypes::HateRedux:
switch (stance) { switch (stance) {
@@ -9232,12 +9241,7 @@ bool Mob::GetDefaultSpellHold(uint16 spellType, uint8 stance) {
case Stance::Assist: case Stance::Assist:
return true; return true;
default: default:
if (GetClass() == Class::Wizard) { return false;
return true;
}
else {
return false;
}
} }
case BotSpellTypes::InCombatBuffSong: case BotSpellTypes::InCombatBuffSong:
case BotSpellTypes::OutOfCombatBuffSong: case BotSpellTypes::OutOfCombatBuffSong:
@@ -9248,6 +9252,55 @@ bool Mob::GetDefaultSpellHold(uint16 spellType, uint8 stance) {
else { else {
return true; return true;
} }
case BotSpellTypes::HateLine:
if (GetClass() == Class::ShadowKnight || GetClass() == Class::Paladin) {
switch (stance) {
case Stance::Aggressive:
return false;
default:
return true;
}
}
else {
return true;
}
case BotSpellTypes::Cure:
case BotSpellTypes::GroupCures:
switch (stance) {
case Stance::Aggressive:
case Stance::AEBurn:
case Stance::Burn:
return true;
default:
return false;
}
case BotSpellTypes::GroupCompleteHeals:
case BotSpellTypes::GroupHeals:
case BotSpellTypes::GroupHoTHeals:
case BotSpellTypes::HoTHeals:
case BotSpellTypes::CompleteHeal:
case BotSpellTypes::PetCompleteHeals:
case BotSpellTypes::PetFastHeals:
case BotSpellTypes::PetHoTHeals:
case BotSpellTypes::PetRegularHeals:
case BotSpellTypes::PetVeryFastHeals:
case BotSpellTypes::RegularHeal:
switch (stance) {
case Stance::Aggressive:
case Stance::AEBurn:
case Stance::Burn:
return true;
default:
return false;
}
case BotSpellTypes::FastHeals:
case BotSpellTypes::VeryFastHeals:
case BotSpellTypes::Pet:
case BotSpellTypes::Escape:
case BotSpellTypes::Lifetap:
case BotSpellTypes::Buff:
case BotSpellTypes::InCombatBuff:
case BotSpellTypes::PreCombatBuff:
default: default:
return false; return false;
} }
@@ -9470,6 +9523,7 @@ uint8 Mob::GetDefaultSpellMaxThreshold(uint16 spellType, uint8 stance) {
case BotSpellTypes::PetResistBuffs: case BotSpellTypes::PetResistBuffs:
case BotSpellTypes::ResistBuffs: case BotSpellTypes::ResistBuffs:
case BotSpellTypes::Resurrect: case BotSpellTypes::Resurrect:
case BotSpellTypes::HateLine:
return 100; return 100;
case BotSpellTypes::GroupHoTHeals: case BotSpellTypes::GroupHoTHeals:
case BotSpellTypes::HoTHeals: case BotSpellTypes::HoTHeals:
+13 -2
View File
@@ -796,7 +796,12 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
if (IsGroupSpell(spell_id)) { if (IsGroupSpell(spell_id)) {
return true; return true;
} else if (spells[spell_id].target_type == ST_Self) { } else if (spells[spell_id].target_type == ST_Self) {
spell_target = this; if (IsBot() && (IsEffectInSpell(spell_id, SE_SummonCorpse) && RuleB(Bots, AllowCommandedSummonCorpse))) {
//spell_target = this;
}
else {
spell_target = this;
}
} }
} else { } else {
if (IsGroupSpell(spell_id) && spell_target != this) { if (IsGroupSpell(spell_id) && spell_target != this) {
@@ -1937,7 +1942,13 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce
// single target spells // single target spells
case ST_Self: case ST_Self:
{ {
spell_target = this; if (IsBot() && (IsEffectInSpell(spell_id, SE_SummonCorpse) && RuleB(Bots, AllowCommandedSummonCorpse))) {
//spell_target = this;
}
else {
spell_target = this;
}
CastAction = SingleTarget; CastAction = SingleTarget;
break; break;
} }