Move melee distance calculations to better function

This commit is contained in:
nytmyr
2025-01-24 12:23:10 -06:00
parent 9134516847
commit 8b863f4402
3 changed files with 94 additions and 111 deletions
+73 -83
View File
@@ -2287,19 +2287,29 @@ void Bot::AI_Process()
} }
// COMBAT RANGE CALCS // COMBAT RANGE CALCS
bool at_combat_range = false;
bool behind_mob = BehindMob(tar, GetX(), GetY());
bool front_mob = InFrontMob(tar, GetX(), GetY()); bool front_mob = InFrontMob(tar, GetX(), GetY());
bool behind_mob = BehindMob(tar, GetX(), GetY());
uint8 stop_melee_level = GetStopMeleeLevel(); uint8 stop_melee_level = GetStopMeleeLevel();
const EQ::ItemInstance* p_item; tar_distance = sqrt(tar_distance); // sqrt this for future calculations
const EQ::ItemInstance* s_item;
float melee_distance_min = 0.0f;
float melee_distance_max = 0.0f;
float melee_distance = 0.0f;
tar_distance = sqrt(tar_distance);
CheckCombatRange(tar, tar_distance, at_combat_range, behind_mob, p_item, s_item, melee_distance_min, melee_distance, melee_distance_max, stop_melee_level); CombatRangeInput input = {
.target = tar,
.target_distance = tar_distance,
.behind_mob = behind_mob,
.stop_melee_level = stop_melee_level
};
CombatRangeOutput o = EvaluateCombatRange(input);
// Combat range variables
bool at_combat_range = o.at_combat_range;
float melee_distance_min = o.melee_distance_min;
float melee_distance = o.melee_distance;
float melee_distance_max = o.melee_distance_max;
// Item variables
const EQ::ItemInstance* p_item = GetBotItem(EQ::invslot::slotPrimary);
const EQ::ItemInstance* s_item = GetBotItem(EQ::invslot::slotSecondary);
// PULLING FLAG (ACTIONABLE RANGE) // PULLING FLAG (ACTIONABLE RANGE)
@@ -3021,31 +3031,11 @@ bool Bot::TryEvade(Mob* tar) {
return false; return false;
} }
void Bot::CheckCombatRange(Mob* tar, float tar_distance, bool& at_combat_range, bool behind_mob, const EQ::ItemInstance*& p_item, const EQ::ItemInstance*& s_item, float& melee_distance_min, float& melee_distance, float& melee_distance_max, uint8 stop_melee_level) { CombatRangeOutput Bot::EvaluateCombatRange(const CombatRangeInput& input) {
at_combat_range = false; CombatRangeOutput o;
p_item = GetBotItem(EQ::invslot::slotPrimary);
s_item = GetBotItem(EQ::invslot::slotSecondary);
bool backstab_weapon = false;
if (GetBehindMob()) {
if (GetClass() == Class::Rogue) {
backstab_weapon = p_item && p_item->GetItemBackstabDamage();
}
}
// Calculate melee distances
CalcMeleeDistances(tar, p_item, s_item, backstab_weapon, behind_mob, melee_distance_min, melee_distance, melee_distance_max, stop_melee_level);
if (tar_distance <= melee_distance) {
at_combat_range = true;
}
}
void Bot::CalcMeleeDistances(const Mob* tar, const EQ::ItemInstance* const& p_item, const EQ::ItemInstance* const& s_item, bool backstab_weapon, bool behind_mob, float& melee_distance_min, float& melee_distance, float& melee_distance_max, uint8 stop_melee_level) {
float size_mod = GetSize(); float size_mod = GetSize();
float other_size_mod = tar->GetSize(); float other_size_mod = input.target->GetSize();
// For races with a fixed size // For races with a fixed size
if (GetRace() == Race::LavaDragon || GetRace() == Race::Wurm || GetRace() == Race::GhostDragon) { if (GetRace() == Race::LavaDragon || GetRace() == Race::Wurm || GetRace() == Race::GhostDragon) {
@@ -3056,7 +3046,7 @@ void Bot::CalcMeleeDistances(const Mob* tar, const EQ::ItemInstance* const& p_it
} }
// For races with a fixed size // For races with a fixed size
if (tar->GetRace() == Race::LavaDragon || tar->GetRace() == Race::Wurm || tar->GetRace() == Race::GhostDragon) { if (input.target->GetRace() == Race::LavaDragon || input.target->GetRace() == Race::Wurm || input.target->GetRace() == Race::GhostDragon) {
other_size_mod = 60.0f; other_size_mod = 60.0f;
} }
else if (other_size_mod < 6.0f) { else if (other_size_mod < 6.0f) {
@@ -3077,12 +3067,12 @@ void Bot::CalcMeleeDistances(const Mob* tar, const EQ::ItemInstance* const& p_it
size_mod *= (size_mod * 4.0f); size_mod *= (size_mod * 4.0f);
} }
if (tar->GetRace() == Race::VeliousDragon) // Lord Vyemm and other velious dragons if (input.target->GetRace() == Race::VeliousDragon) // Lord Vyemm and other velious dragons
{ {
size_mod *= 1.75; size_mod *= 1.75;
} }
if (tar->GetRace() == Race::DragonSkeleton) // Dracoliche in Fear. Skeletal Dragon if (input.target->GetRace() == Race::DragonSkeleton) // Dracoliche in Fear. Skeletal Dragon
{ {
size_mod *= 2.25; size_mod *= 2.25;
} }
@@ -3094,86 +3084,82 @@ void Bot::CalcMeleeDistances(const Mob* tar, const EQ::ItemInstance* const& p_it
size_mod = (size_mod / 7.0f); size_mod = (size_mod / 7.0f);
} }
melee_distance_max = size_mod; o.melee_distance_max = size_mod;
if (!RuleB(Bots, UseFlatNormalMeleeRange)) { if (!RuleB(Bots, UseFlatNormalMeleeRange)) {
bool is_two_hander = input.p_item && input.p_item->GetItem()->IsType2HWeapon();
bool is_shield = input.s_item && input.s_item->GetItem()->IsTypeShield();
bool is_backstab_weapon = input.p_item && input.p_item->GetItemBackstabDamage();
switch (GetClass()) { switch (GetClass()) {
case Class::Warrior: case Class::Warrior:
case Class::Paladin: case Class::Paladin:
case Class::ShadowKnight: case Class::ShadowKnight:
if (p_item && p_item->GetItem()->IsType2HWeapon()) { o.melee_distance = (
melee_distance = melee_distance_max * 0.45f; is_two_hander ? o.melee_distance_max * 0.45f
} : is_shield ? o.melee_distance_max * 0.35f
else if ((s_item && s_item->GetItem()->IsTypeShield()) || (!p_item && !s_item)) { : o.melee_distance_max * 0.40f
melee_distance = melee_distance_max * 0.35f; );
}
else {
melee_distance = melee_distance_max * 0.40f;
}
break; break;
case Class::Necromancer: case Class::Necromancer:
case Class::Wizard: case Class::Wizard:
case Class::Magician: case Class::Magician:
case Class::Enchanter: case Class::Enchanter:
if (p_item && p_item->GetItem()->IsType2HWeapon()) { o.melee_distance = (
melee_distance = melee_distance_max * 0.95f; is_two_hander ? o.melee_distance_max * 0.95f
} : o.melee_distance_max * 0.75f
else { );
melee_distance = melee_distance_max * 0.75f;
}
break; break;
case Class::Rogue: case Class::Rogue:
if (behind_mob && backstab_weapon) { o.melee_distance = (
if (p_item->GetItem()->IsType2HWeapon()) { input.behind_mob && is_backstab_weapon
melee_distance = melee_distance_max * 0.30f; ? o.melee_distance_max * 0.35f
} : o.melee_distance_max * 0.50f
else { );
melee_distance = melee_distance_max * 0.25f;
}
break; break;
}
// Fall-through
default: default:
if (p_item && p_item->GetItem()->IsType2HWeapon()) { o.melee_distance = (
melee_distance = melee_distance_max * 0.70f; is_two_hander ? o.melee_distance_max * 0.70f
} : o.melee_distance_max * 0.50f
else { );
melee_distance = melee_distance_max * 0.50f;
}
break; break;
} }
melee_distance = sqrt(melee_distance); o.melee_distance = sqrt(o.melee_distance);
melee_distance_max = sqrt(melee_distance_max); o.melee_distance_max = sqrt(o.melee_distance_max);
} }
else { else {
melee_distance_max = sqrt(melee_distance_max); o.melee_distance_max = sqrt(o.melee_distance_max);
melee_distance = melee_distance_max * RuleR(Bots, NormalMeleeRangeDistance); o.melee_distance = o.melee_distance_max * RuleR(Bots, NormalMeleeRangeDistance);
} }
if (melee_distance > RuleR(Bots, MaxDistanceForMelee)) { if (o.melee_distance > RuleR(Bots, MaxDistanceForMelee)) {
melee_distance = RuleR(Bots, MaxDistanceForMelee); o.melee_distance = RuleR(Bots, MaxDistanceForMelee);
} }
melee_distance_min = melee_distance * RuleR(Bots, PercentMinMeleeDistance); o.melee_distance_min = o.melee_distance * RuleR(Bots, PercentMinMeleeDistance);
if (IsTaunting()) { if (IsTaunting()) {
melee_distance_min = melee_distance * RuleR(Bots, PercentTauntMinMeleeDistance); o.melee_distance_min = o.melee_distance * RuleR(Bots, PercentTauntMinMeleeDistance);
melee_distance = melee_distance * RuleR(Bots, TauntNormalMeleeRangeDistance); o.melee_distance = o.melee_distance * RuleR(Bots, TauntNormalMeleeRangeDistance);
} }
bool is_stop_melee_level = GetLevel() >= stop_melee_level; bool is_stop_melee_level = GetLevel() >= input.stop_melee_level;
if (!IsTaunting() && !IsBotRanged() && !is_stop_melee_level && GetMaxMeleeRange()) { if (!IsTaunting() && !IsBotRanged() && !is_stop_melee_level && GetMaxMeleeRange()) {
melee_distance_min = melee_distance_max * RuleR(Bots, PercentMinMaxMeleeRangeDistance); o.melee_distance_min = o.melee_distance_max * RuleR(Bots, PercentMinMaxMeleeRangeDistance);
melee_distance = melee_distance_max * RuleR(Bots, PercentMaxMeleeRangeDistance); o.melee_distance = o.melee_distance_max * RuleR(Bots, PercentMaxMeleeRangeDistance);
} }
if (is_stop_melee_level && !IsBotRanged()) { if (is_stop_melee_level && !IsBotRanged()) {
float desired_range = GetBotDistanceRanged(); float desired_range = GetBotDistanceRanged();
melee_distance_min = std::max(melee_distance, (desired_range / 2)); o.melee_distance_min = std::max(o.melee_distance, (desired_range / 2));
melee_distance = std::max((melee_distance + 1), desired_range); o.melee_distance = std::max((o.melee_distance + 1), desired_range);
} }
if (IsBotRanged()) { if (IsBotRanged()) {
@@ -3181,9 +3167,13 @@ void Bot::CalcMeleeDistances(const Mob* tar, const EQ::ItemInstance* const& p_it
float max_distance = GetBotRangedValue(); float max_distance = GetBotRangedValue();
float desired_range = GetBotDistanceRanged(); float desired_range = GetBotDistanceRanged();
max_distance = (max_distance == 0 ? desired_range : max_distance); // stay ranged if set to ranged even if items/ammo aren't correct max_distance = (max_distance == 0 ? desired_range : max_distance); // stay ranged if set to ranged even if items/ammo aren't correct
melee_distance_min = std::max(min_distance, (desired_range / 2)); o.melee_distance_min = std::max(min_distance, (desired_range / 2));
melee_distance = std::min(max_distance, desired_range); o.melee_distance = std::min(max_distance, desired_range);
} }
o.at_combat_range = (input.target_distance <= o.melee_distance);
return o;
} }
bool Bot::IsValidTarget( bool Bot::IsValidTarget(
+3 -26
View File
@@ -1006,36 +1006,13 @@ public:
bool ReturningFlagChecks(Client* bot_owner, Mob* leash_owner, float fm_distance); bool ReturningFlagChecks(Client* bot_owner, Mob* leash_owner, float fm_distance);
void BotPullerProcess(Client* bot_owner, Raid* raid); void BotPullerProcess(Client* bot_owner, Raid* raid);
// Movement Methods
void CalcMeleeDistances(
const Mob* tar,
const EQ::ItemInstance* const& p_item,
const EQ::ItemInstance* const& s_item,
bool behind_mob,
bool backstab_weapon,
float& melee_distance_min,
float& melee_distance,
float& melee_distance_max,
uint8 stop_melee_level
);
// Combat Checks // Combat Checks
CombatRangeOutput EvaluateCombatRange(const CombatRangeInput& input);
void SetBerserkState(); void SetBerserkState();
bool CheckIfCasting(float fm_distance); bool CheckIfCasting(float fm_distance);
void HealRotationChecks(); void HealRotationChecks();
void CheckCombatRange(
Mob* tar,
float tar_distance,
bool& at_combat_range,
bool behind_mob,
const EQ::ItemInstance*& p_item,
const EQ::ItemInstance*& s_item,
float& melee_distance_min,
float& melee_distance,
float& melee_distance_max,
uint8 stop_melee_level
);
bool GetCombatJitterFlag() { return m_combat_jitter_flag; } bool GetCombatJitterFlag() { return m_combat_jitter_flag; }
void SetCombatJitterFlag(bool flag = true) { m_combat_jitter_flag = flag; } void SetCombatJitterFlag(bool flag = true) { m_combat_jitter_flag = flag; }
bool GetCombatOutOfRangeJitterFlag() { return m_combat_out_of_range_jitter_flag; } bool GetCombatOutOfRangeJitterFlag() { return m_combat_out_of_range_jitter_flag; }
+16
View File
@@ -127,4 +127,20 @@ struct BotSpellTypesByClass_Struct {
std::string description; std::string description;
}; };
struct CombatRangeInput {
Mob* target;
float target_distance;
bool behind_mob;
uint8 stop_melee_level;
const EQ::ItemInstance* p_item;
const EQ::ItemInstance* s_item;
};
struct CombatRangeOutput {
bool at_combat_range = false;
float melee_distance_min = 0.0f;
float melee_distance = 0.0f;
float melee_distance_max = 0.0f;
};
#endif // BOT_STRUCTS #endif // BOT_STRUCTS