mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 10:31:29 +00:00
Bot movement behavior change..still in-work
This commit is contained in:
parent
d8519bc270
commit
b0ad9524bc
@ -1,5 +1,8 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 01/31/2017 ==
|
||||
Uleat: Modifed bot movement behavior in an attempt to 'normalize' it. This is a hack fix and will be revisited at some point. (Probably just need a follow function rather than use movement, when the leader of the follow chain is moving.)
|
||||
|
||||
== 01/26/2017 ==
|
||||
Uleat: Change rogue bot behavior to eliminate twirling combat. They will only get behind the mob if they are not the mob's target or if the mob is feared or fleeing. This may lower rogue bot dps a small fraction..but, is more in-line with realistic game mechanics.
|
||||
|
||||
|
||||
119
zone/bot.cpp
119
zone/bot.cpp
@ -2305,10 +2305,6 @@ void Bot::AI_Process() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Could add a bot accessor like..
|
||||
// bool NeedsHateRedux() { return (GetClass() == Rogue && evade_timer.check(false)); } - or something like this
|
||||
// ..then add hate redux spells to caster combat repertoires
|
||||
}
|
||||
else if (!BehindMob(GetTarget(), GetX(), GetY())) {
|
||||
// Move the rogue to behind the mob
|
||||
@ -2472,42 +2468,67 @@ void Bot::AI_Process() {
|
||||
BotMeditate(true);
|
||||
}
|
||||
} else {
|
||||
SetTarget(0);
|
||||
SetTarget(nullptr);
|
||||
if (m_PlayerState & static_cast<uint32>(PlayerState::Aggressive))
|
||||
SendRemovePlayerState(PlayerState::Aggressive);
|
||||
|
||||
if(!IsMoving() && AI_think_timer->Check() && !spellend_timer.Enabled()) {
|
||||
if(GetBotStance() != BotStancePassive) {
|
||||
if(!AI_IdleCastCheck() && !IsCasting())
|
||||
BotMeditate(true);
|
||||
}
|
||||
else
|
||||
BotMeditate(true);
|
||||
}
|
||||
Mob* follow = entity_list.GetMob(GetFollowID());
|
||||
if (!follow)
|
||||
return;
|
||||
|
||||
if(AI_movement_timer->Check()) {
|
||||
if(GetFollowID()) {
|
||||
Mob* follow = entity_list.GetMob(GetFollowID());
|
||||
if(follow) {
|
||||
float dist = DistanceSquared(m_Position, follow->GetPosition());
|
||||
int speed = follow->GetRunspeed();
|
||||
if(dist < GetFollowDistance() + 1000)
|
||||
speed = follow->GetWalkspeed();
|
||||
float cur_dist = DistanceSquared(m_Position, follow->GetPosition());
|
||||
|
||||
if(dist > GetFollowDistance()) {
|
||||
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
|
||||
if(rest_timer.Enabled())
|
||||
rest_timer.Disable();
|
||||
return;
|
||||
} else {
|
||||
if(moved) {
|
||||
moved = false;
|
||||
SetCurrentSpeed(0);
|
||||
}
|
||||
if (!IsMoving() && cur_dist <= GetFollowDistance()) {
|
||||
if (AI_think_timer->Check()) {
|
||||
if (!spellend_timer.Enabled()) {
|
||||
if (GetBotStance() != BotStancePassive) {
|
||||
if (!AI_IdleCastCheck() && !IsCasting() && GetClass() != BARD)
|
||||
BotMeditate(true);
|
||||
}
|
||||
else {
|
||||
if (GetClass() != BARD)
|
||||
BotMeditate(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(AI_movement_timer->Check()) {
|
||||
int speed = GetRunspeed();
|
||||
if (cur_dist < GetFollowDistance() + 1000) {
|
||||
speed = GetWalkspeed();
|
||||
}
|
||||
else if (cur_dist >= GetFollowDistance() + 8000) {
|
||||
auto leader = follow;
|
||||
while (leader->GetFollowID()) {
|
||||
leader = entity_list.GetMob(leader->GetFollowID());
|
||||
if (!leader || leader == this)
|
||||
break;
|
||||
}
|
||||
if (leader && leader != this && leader->GetRunspeed() > speed)
|
||||
speed = leader->GetRunspeed();
|
||||
speed = (float)speed * 1.8f; // special bot sprint mod
|
||||
}
|
||||
|
||||
// this needs work..
|
||||
// could probably eliminate the sprint mod with the correct logic
|
||||
if (cur_dist > GetFollowDistance()) {
|
||||
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
|
||||
if (rest_timer.Enabled())
|
||||
rest_timer.Disable();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (moved) {
|
||||
moved = false;
|
||||
SetCurrentSpeed(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (IsMoving()) {
|
||||
if (GetBotStance() != BotStancePassive && GetClass() == BARD && !spellend_timer.Enabled() && AI_think_timer->Check()) {
|
||||
AI_IdleCastCheck();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7989,6 +8010,42 @@ bool Bot::GetNeedsCured(Mob *tar) {
|
||||
return needCured;
|
||||
}
|
||||
|
||||
bool Bot::GetNeedsHateRedux(Mob *tar) {
|
||||
// This really should be a scalar function based in class Mob that returns 'this' state..but, is inline with current Bot coding...
|
||||
// TODO: Good starting point..but, can be refined..
|
||||
// TODO: Still awaiting bot spell rework..
|
||||
if (!tar || !tar->HasTargetReflection())
|
||||
return false;
|
||||
|
||||
if (tar->IsClient()) {
|
||||
switch (tar->GetClass()) {
|
||||
// TODO: figure out affectable classes..
|
||||
// Might need flag to allow player to determine redux req...
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (tar->IsBot()) {
|
||||
switch (tar->GetClass()) {
|
||||
case ROGUE:
|
||||
if (tar->CastToBot()->evade_timer.Check(false))
|
||||
return false;
|
||||
case CLERIC:
|
||||
case DRUID:
|
||||
case SHAMAN:
|
||||
case NECROMANCER:
|
||||
case WIZARD:
|
||||
case MAGICIAN:
|
||||
case ENCHANTER:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Bot::HasOrMayGetAggro() {
|
||||
bool mayGetAggro = false;
|
||||
if(GetTarget() && GetTarget()->GetHateTop()) {
|
||||
|
||||
@ -293,6 +293,7 @@ public:
|
||||
bool UseDiscipline(uint32 spell_id, uint32 target);
|
||||
uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets);
|
||||
bool GetNeedsCured(Mob *tar);
|
||||
bool GetNeedsHateRedux(Mob *tar);
|
||||
bool HasOrMayGetAggro();
|
||||
void SetDefaultBotStance();
|
||||
void CalcChanceToCast();
|
||||
|
||||
@ -422,7 +422,7 @@ public:
|
||||
strn0cpy(name, GetName(), 64); return; };
|
||||
inline Mob* GetTarget() const { return target; }
|
||||
virtual void SetTarget(Mob* mob);
|
||||
inline bool HasTargetReflection() const { return (target && target->target == this); }
|
||||
inline bool HasTargetReflection() const { return (target && target != this && target->target == this); }
|
||||
virtual inline float GetHPRatio() const { return max_hp == 0 ? 0 : ((float)cur_hp/max_hp*100); }
|
||||
virtual inline int GetIntHPRatio() const { return max_hp == 0 ? 0 : static_cast<int>(cur_hp * 100 / max_hp); }
|
||||
inline int32 GetAC() const { return AC; }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user