mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 01:11:29 +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)
|
||||
-------------------------------------------------------
|
||||
== 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
|
||||
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
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_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;
|
||||
|
||||
@ -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()));
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
14
zone/mob.cpp
14
zone/mob.cpp
@ -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) {
|
||||
|
||||
@ -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; }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user