mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 06:21:28 +00:00
Re-worked Bot::AI_Process(); Added 'leash,' 'main assist' and 'combat abort' features
This commit is contained in:
parent
dd2b12b517
commit
8805021960
@ -1,5 +1,16 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
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 ==
|
== 01/28/2018 ==
|
||||||
Mackal: Spell AI tweaks
|
Mackal: Spell AI tweaks
|
||||||
|
|
||||||
|
|||||||
@ -1007,6 +1007,28 @@ bool Mob::CheckLosFN(float posX, float posY, float posZ, float mobSize) {
|
|||||||
return zone->zonemap->CheckLoS(myloc, oloc);
|
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
|
//offensive spell aggro
|
||||||
int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
|
int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
|
||||||
{
|
{
|
||||||
|
|||||||
944
zone/bot.cpp
944
zone/bot.cpp
File diff suppressed because it is too large
Load Diff
18
zone/bot.h
18
zone/bot.h
@ -42,6 +42,8 @@
|
|||||||
#define BOT_FOLLOW_DISTANCE_DEFAULT_MAX 2500 // as DSq value (50 units)
|
#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_FOLLOW_DISTANCE_WALK 1000 // as DSq value (~31.623 units)
|
||||||
|
|
||||||
|
#define BOT_LEASH_DISTANCE 250000 // as DSq value (500 units)
|
||||||
|
|
||||||
extern WorldServer worldserver;
|
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
|
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();
|
bool IsStanding();
|
||||||
int GetBotWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.786f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143
|
int GetBotWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.786f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143
|
||||||
int GetBotRunspeed() const { return (int)((float)_GetRunSpeed() * 1.786f); }
|
int GetBotRunspeed() const { return (int)((float)_GetRunSpeed() * 1.786f); }
|
||||||
bool IsBotCasterAtCombatRange(Mob *target);
|
|
||||||
bool UseDiscipline(uint32 spell_id, uint32 target);
|
bool UseDiscipline(uint32 spell_id, uint32 target);
|
||||||
uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets);
|
uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets);
|
||||||
bool GetNeedsCured(Mob *tar);
|
bool GetNeedsCured(Mob *tar);
|
||||||
@ -404,7 +405,8 @@ public:
|
|||||||
bool AIHealRotation(Mob* tar, bool useFastHeals);
|
bool AIHealRotation(Mob* tar, bool useFastHeals);
|
||||||
bool GetPauseAI() { return _pauseAI; }
|
bool GetPauseAI() { return _pauseAI; }
|
||||||
void SetPauseAI(bool pause_flag) { _pauseAI = pause_flag; }
|
void SetPauseAI(bool pause_flag) { _pauseAI = pause_flag; }
|
||||||
|
void ForceMovementEnd();
|
||||||
|
void ForceMovementEnd(float new_heading);
|
||||||
|
|
||||||
// Mob AI Virtual Override Methods
|
// Mob AI Virtual Override Methods
|
||||||
virtual void AI_Process();
|
virtual void AI_Process();
|
||||||
@ -532,9 +534,7 @@ public:
|
|||||||
bool IsBotWISCaster() { return IsWISCasterClass(GetClass()); }
|
bool IsBotWISCaster() { return IsWISCasterClass(GetClass()); }
|
||||||
bool CanHeal();
|
bool CanHeal();
|
||||||
int GetRawACNoShield(int &shield_ac);
|
int GetRawACNoShield(int &shield_ac);
|
||||||
bool GetHasBeenSummoned() { return _hasBeenSummoned; }
|
|
||||||
const glm::vec3 GetPreSummonLocation() const { return m_PreSummonLocation; }
|
|
||||||
|
|
||||||
// new heal rotation code
|
// new heal rotation code
|
||||||
bool CreateHealRotation(uint32 cycle_duration_ms = 5000, bool fast_heals = false, bool adaptive_targeting = false, bool casting_override = false);
|
bool CreateHealRotation(uint32 cycle_duration_ms = 5000, bool fast_heals = false, bool adaptive_targeting = false, bool casting_override = false);
|
||||||
bool DestroyHealRotation();
|
bool DestroyHealRotation();
|
||||||
@ -628,9 +628,6 @@ public:
|
|||||||
void SetBotStance(BotStanceType botStance) { _botStance = ((botStance != BotStanceUnknown) ? (botStance) : (BotStancePassive)); }
|
void SetBotStance(BotStanceType botStance) { _botStance = ((botStance != BotStanceUnknown) ? (botStance) : (BotStancePassive)); }
|
||||||
void SetSpellRecastTimer(int timer_index, int32 recast_delay);
|
void SetSpellRecastTimer(int timer_index, int32 recast_delay);
|
||||||
void SetDisciplineRecastTimer(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 SetAltOutOfCombatBehavior(bool behavior_flag) { _altoutofcombatbehavior = behavior_flag;}
|
||||||
void SetShowHelm(bool showhelm) { _showhelm = showhelm; }
|
void SetShowHelm(bool showhelm) { _showhelm = showhelm; }
|
||||||
void SetBeardColor(uint8 value) { beardcolor = value; }
|
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 int32 CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 spell_id);
|
||||||
virtual void PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client);
|
virtual void PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client);
|
||||||
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
|
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
|
||||||
virtual float GetMaxMeleeRangeToTarget(Mob* target);
|
|
||||||
|
|
||||||
BotCastingRoles& GetCastingRoles() { return m_CastingRoles; }
|
BotCastingRoles& GetCastingRoles() { return m_CastingRoles; }
|
||||||
void SetGroupHealer(bool flag = true) { m_CastingRoles.GroupHealer = flag; }
|
void SetGroupHealer(bool flag = true) { m_CastingRoles.GroupHealer = flag; }
|
||||||
@ -734,9 +730,7 @@ private:
|
|||||||
int32 max_end;
|
int32 max_end;
|
||||||
int32 end_regen;
|
int32 end_regen;
|
||||||
uint32 timers[MaxTimer];
|
uint32 timers[MaxTimer];
|
||||||
bool _hasBeenSummoned;
|
|
||||||
glm::vec3 m_PreSummonLocation;
|
|
||||||
|
|
||||||
Timer evade_timer; // can be moved to pTimers at some point
|
Timer evade_timer; // can be moved to pTimers at some point
|
||||||
|
|
||||||
BotCastingRoles m_CastingRoles;
|
BotCastingRoles m_CastingRoles;
|
||||||
|
|||||||
@ -5146,10 +5146,10 @@ void bot_subcommand_bot_summon(Client *c, const Seperator *sep)
|
|||||||
if (!bot_iter)
|
if (!bot_iter)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Bot::BotGroupSay(bot_iter, "Whee!");
|
//Bot::BotGroupSay(bot_iter, "Whee!");
|
||||||
|
|
||||||
bot_iter->WipeHateList();
|
bot_iter->WipeHateList();
|
||||||
bot_iter->SetTarget(bot_iter->GetBotOwner());
|
bot_iter->SetTarget(nullptr);
|
||||||
bot_iter->Warp(glm::vec3(c->GetPosition()));
|
bot_iter->Warp(glm::vec3(c->GetPosition()));
|
||||||
bot_iter->DoAnim(0);
|
bot_iter->DoAnim(0);
|
||||||
|
|
||||||
@ -5157,7 +5157,7 @@ void bot_subcommand_bot_summon(Client *c, const Seperator *sep)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
bot_iter->GetPet()->WipeHateList();
|
bot_iter->GetPet()->WipeHateList();
|
||||||
bot_iter->GetPet()->SetTarget(bot_iter);
|
bot_iter->GetPet()->SetTarget(nullptr);
|
||||||
bot_iter->GetPet()->Warp(glm::vec3(c->GetPosition()));
|
bot_iter->GetPet()->Warp(glm::vec3(c->GetPosition()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -169,9 +169,10 @@ bool HealRotation::ClearMemberPool()
|
|||||||
m_casting_target_poke = false;
|
m_casting_target_poke = false;
|
||||||
m_active_heal_target = 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)
|
for (auto member_iter : clear_list)
|
||||||
member_iter->LeaveHealRotationMemberPool();
|
member_iter->LeaveHealRotationMemberPool();
|
||||||
|
|
||||||
@ -183,13 +184,23 @@ bool HealRotation::ClearTargetPool()
|
|||||||
m_hot_target = nullptr;
|
m_hot_target = nullptr;
|
||||||
m_hot_active = false;
|
m_hot_active = false;
|
||||||
m_is_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)
|
for (auto target_iter : clear_list)
|
||||||
target_iter->LeaveHealRotationTargetPool();
|
target_iter->LeaveHealRotationTargetPool();
|
||||||
|
|
||||||
m_casting_target_poke = false;
|
//m_casting_target_poke = false;
|
||||||
bias_targets();
|
//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();
|
return m_target_pool.empty();
|
||||||
}
|
}
|
||||||
|
|||||||
14
zone/mob.cpp
14
zone/mob.cpp
@ -2723,20 +2723,10 @@ bool Mob::HateSummon() {
|
|||||||
if(summon_level == 1) {
|
if(summon_level == 1) {
|
||||||
entity_list.MessageClose(this, true, 500, MT_Say, "%s says,'You will not evade me, %s!' ", GetCleanName(), target->GetCleanName() );
|
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);
|
target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Position.x, m_Position.y, m_Position.z, target->GetHeading(), 0, SummonPC);
|
||||||
}
|
else
|
||||||
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
|
|
||||||
target->GMMove(m_Position.x, m_Position.y, m_Position.z, target->GetHeading());
|
target->GMMove(m_Position.x, m_Position.y, m_Position.z, target->GetHeading());
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else if(summon_level == 2) {
|
} else if(summon_level == 2) {
|
||||||
|
|||||||
@ -612,6 +612,7 @@ public:
|
|||||||
std::list<struct_HateList*>& GetHateList() { return hate_list.GetHateList(); }
|
std::list<struct_HateList*>& GetHateList() { return hate_list.GetHateList(); }
|
||||||
bool CheckLosFN(Mob* other);
|
bool CheckLosFN(Mob* other);
|
||||||
bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
|
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 void SetChanged() { pLastChange = Timer::GetCurrentTime(); }
|
||||||
inline const uint32 LastChange() const { return pLastChange; }
|
inline const uint32 LastChange() const { return pLastChange; }
|
||||||
inline void SetLastLosState(bool value) { last_los_check = value; }
|
inline void SetLastLosState(bool value) { last_los_check = value; }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user