Re-worked Bot::AI_Process(); Added 'leash,' 'main assist' and 'combat abort' features

This commit is contained in:
Uleat 2018-01-31 19:31:09 -05:00
parent dd2b12b517
commit 8805021960
8 changed files with 611 additions and 428 deletions

View File

@ -1,5 +1,16 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 01/31/2018 ==
Uleat: Re-work of Bot::AI_Process(). Overall behavior is much improved.
- Removed a 'ton' of unneeded packet updates
- Added a 'leash' to the distance a bot can travel
- Added a 'main assist' feature to target control (set using group roles)
- Added combat 'jitter' movement to complement the existing rogue movement
- Attack can now be aborted if target contains no leash owner nor bot hate and leash owner turns off auto-attack
- Please report any issues with the bot AI code
Added a work-around for heal rotations crashing the server - under certain conditions.
== 01/28/2018 ==
Mackal: Spell AI tweaks

View File

@ -1007,6 +1007,28 @@ bool Mob::CheckLosFN(float posX, float posY, float posZ, float mobSize) {
return zone->zonemap->CheckLoS(myloc, oloc);
}
bool Mob::CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarget, float sizeTarget) {
if (zone->zonemap == nullptr) {
//not sure what the best return is on error
//should make this a database variable, but im lazy today
#ifdef LOS_DEFAULT_CAN_SEE
return(true);
#else
return(false);
#endif
}
#define LOS_DEFAULT_HEIGHT 6.0f
posWatcher.z += (sizeWatcher == 0.0f ? LOS_DEFAULT_HEIGHT : sizeWatcher) / 2 * HEAD_POSITION;
posTarget.z += (sizeTarget == 0.0f ? LOS_DEFAULT_HEIGHT : sizeTarget) / 2 * SEE_POSITION;
#if LOSDEBUG>=5
Log(Logs::General, Logs::None, "LOS from (%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f) sizes: (%.2f, %.2f) [static]", posWatcher.x, posWatcher.y, posWatcher.z, posTarget.x, posTarget.y, posTarget.z, sizeWatcher, sizeTarget);
#endif
return zone->zonemap->CheckLoS(posWatcher, posTarget);
}
//offensive spell aggro
int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
{

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,8 @@
#define BOT_FOLLOW_DISTANCE_DEFAULT_MAX 2500 // as DSq value (50 units)
#define BOT_FOLLOW_DISTANCE_WALK 1000 // as DSq value (~31.623 units)
#define BOT_LEASH_DISTANCE 250000 // as DSq value (500 units)
extern WorldServer worldserver;
const int BotAISpellRange = 100; // TODO: Write a method that calcs what the bot's spell range is based on spell, equipment, AA, whatever and replace this
@ -337,7 +339,6 @@ public:
bool IsStanding();
int GetBotWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.786f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143
int GetBotRunspeed() const { return (int)((float)_GetRunSpeed() * 1.786f); }
bool IsBotCasterAtCombatRange(Mob *target);
bool UseDiscipline(uint32 spell_id, uint32 target);
uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets);
bool GetNeedsCured(Mob *tar);
@ -404,7 +405,8 @@ public:
bool AIHealRotation(Mob* tar, bool useFastHeals);
bool GetPauseAI() { return _pauseAI; }
void SetPauseAI(bool pause_flag) { _pauseAI = pause_flag; }
void ForceMovementEnd();
void ForceMovementEnd(float new_heading);
// Mob AI Virtual Override Methods
virtual void AI_Process();
@ -532,9 +534,7 @@ public:
bool IsBotWISCaster() { return IsWISCasterClass(GetClass()); }
bool CanHeal();
int GetRawACNoShield(int &shield_ac);
bool GetHasBeenSummoned() { return _hasBeenSummoned; }
const glm::vec3 GetPreSummonLocation() const { return m_PreSummonLocation; }
// new heal rotation code
bool CreateHealRotation(uint32 cycle_duration_ms = 5000, bool fast_heals = false, bool adaptive_targeting = false, bool casting_override = false);
bool DestroyHealRotation();
@ -628,9 +628,6 @@ public:
void SetBotStance(BotStanceType botStance) { _botStance = ((botStance != BotStanceUnknown) ? (botStance) : (BotStancePassive)); }
void SetSpellRecastTimer(int timer_index, int32 recast_delay);
void SetDisciplineRecastTimer(int timer_index, int32 recast_delay);
void SetHasBeenSummoned(bool s);
void SetPreSummonLocation(const glm::vec3& location) { m_PreSummonLocation = location; }
void SetAltOutOfCombatBehavior(bool behavior_flag) { _altoutofcombatbehavior = behavior_flag;}
void SetShowHelm(bool showhelm) { _showhelm = showhelm; }
void SetBeardColor(uint8 value) { beardcolor = value; }
@ -688,7 +685,6 @@ protected:
virtual int32 CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 spell_id);
virtual void PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client);
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
virtual float GetMaxMeleeRangeToTarget(Mob* target);
BotCastingRoles& GetCastingRoles() { return m_CastingRoles; }
void SetGroupHealer(bool flag = true) { m_CastingRoles.GroupHealer = flag; }
@ -734,9 +730,7 @@ private:
int32 max_end;
int32 end_regen;
uint32 timers[MaxTimer];
bool _hasBeenSummoned;
glm::vec3 m_PreSummonLocation;
Timer evade_timer; // can be moved to pTimers at some point
BotCastingRoles m_CastingRoles;

View File

@ -5146,10 +5146,10 @@ void bot_subcommand_bot_summon(Client *c, const Seperator *sep)
if (!bot_iter)
continue;
Bot::BotGroupSay(bot_iter, "Whee!");
//Bot::BotGroupSay(bot_iter, "Whee!");
bot_iter->WipeHateList();
bot_iter->SetTarget(bot_iter->GetBotOwner());
bot_iter->SetTarget(nullptr);
bot_iter->Warp(glm::vec3(c->GetPosition()));
bot_iter->DoAnim(0);
@ -5157,7 +5157,7 @@ void bot_subcommand_bot_summon(Client *c, const Seperator *sep)
continue;
bot_iter->GetPet()->WipeHateList();
bot_iter->GetPet()->SetTarget(bot_iter);
bot_iter->GetPet()->SetTarget(nullptr);
bot_iter->GetPet()->Warp(glm::vec3(c->GetPosition()));
}

View File

@ -169,9 +169,10 @@ bool HealRotation::ClearMemberPool()
m_casting_target_poke = false;
m_active_heal_target = false;
ClearTargetPool();
if (!ClearTargetPool())
Log(Logs::General, Logs::Error, "HealRotation::ClearTargetPool() failed to clear m_target_pool (size: %u)", m_target_pool.size());
auto clear_list = m_member_pool;
auto clear_list = const_cast<const std::list<Bot*>&>(m_member_pool);
for (auto member_iter : clear_list)
member_iter->LeaveHealRotationMemberPool();
@ -183,13 +184,23 @@ bool HealRotation::ClearTargetPool()
m_hot_target = nullptr;
m_hot_active = false;
m_is_active = false;
auto clear_list = m_target_pool;
auto clear_list = const_cast<const std::list<Mob*>&>(m_target_pool);
for (auto target_iter : clear_list)
target_iter->LeaveHealRotationTargetPool();
m_casting_target_poke = false;
bias_targets();
//m_casting_target_poke = false;
//bias_targets();
// strange crash point...
// bias_targets() should be returning on m_target_pool.empty()
// and setting this two properties as below
m_casting_target_poke = true;
m_active_heal_target = false;
// instead, the list retains mob shared_ptrs and
// attempts to process them - and crashes program
// predominate when adaptive_healing = true
// (shared_ptr now has a delayed gc action? this did work before...)
return m_target_pool.empty();
}

View File

@ -2723,20 +2723,10 @@ bool Mob::HateSummon() {
if(summon_level == 1) {
entity_list.MessageClose(this, true, 500, MT_Say, "%s says,'You will not evade me, %s!' ", GetCleanName(), target->GetCleanName() );
if (target->IsClient()) {
if (target->IsClient())
target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Position.x, m_Position.y, m_Position.z, target->GetHeading(), 0, SummonPC);
}
else {
#ifdef BOTS
if(target && target->IsBot()) {
// set pre summoning info to return to (to get out of melee range for caster)
target->CastToBot()->SetHasBeenSummoned(true);
target->CastToBot()->SetPreSummonLocation(glm::vec3(target->GetPosition()));
}
#endif //BOTS
else
target->GMMove(m_Position.x, m_Position.y, m_Position.z, target->GetHeading());
}
return true;
} else if(summon_level == 2) {

View File

@ -612,6 +612,7 @@ public:
std::list<struct_HateList*>& GetHateList() { return hate_list.GetHateList(); }
bool CheckLosFN(Mob* other);
bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
static bool CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarget, float sizeTarget);
inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); }
inline const uint32 LastChange() const { return pLastChange; }
inline void SetLastLosState(bool value) { last_los_check = value; }