mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
refactor(Core/RPG): Retry counter + give-up state replaces MoveRandomNear nudge on MoveFarTo failure
This commit is contained in:
parent
c61b311a1b
commit
fd34598e6a
@ -155,11 +155,17 @@ bool NewRpgGoGrindAction::Execute(Event /*event*/)
|
|||||||
if (auto* data = std::get_if<NewRpgInfo::GoGrind>(&botAI->rpgInfo.data))
|
if (auto* data = std::get_if<NewRpgInfo::GoGrind>(&botAI->rpgInfo.data))
|
||||||
{
|
{
|
||||||
if (MoveFarTo(data->pos))
|
if (MoveFarTo(data->pos))
|
||||||
|
{
|
||||||
|
botAI->rpgInfo.moveRetryCount = 0;
|
||||||
return true;
|
return true;
|
||||||
// Small nudge so the next tick's MoveFarTo starts from a
|
}
|
||||||
// slightly different position. Kept small so it doesn't look
|
// Reference pattern (TravelTarget retry counter): count
|
||||||
// like the bot is abandoning its destination.
|
// consecutive MoveFarTo failures, give up after N tries by
|
||||||
return MoveRandomNear(10.0f);
|
// transitioning out of the stuck state instead of nudging in
|
||||||
|
// place. Idle lets the status picker rotate to a new state.
|
||||||
|
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
||||||
|
botAI->rpgInfo.ChangeToIdle();
|
||||||
|
return true; // consume tick, no nudge
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -173,8 +179,13 @@ bool NewRpgGoCampAction::Execute(Event /*event*/)
|
|||||||
if (auto* data = std::get_if<NewRpgInfo::GoCamp>(&botAI->rpgInfo.data))
|
if (auto* data = std::get_if<NewRpgInfo::GoCamp>(&botAI->rpgInfo.data))
|
||||||
{
|
{
|
||||||
if (MoveFarTo(data->pos))
|
if (MoveFarTo(data->pos))
|
||||||
|
{
|
||||||
|
botAI->rpgInfo.moveRetryCount = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
||||||
|
botAI->rpgInfo.ChangeToIdle();
|
||||||
return true;
|
return true;
|
||||||
return MoveRandomNear(10.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -230,11 +241,20 @@ bool NewRpgWanderNpcAction::Execute(Event /*event*/)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (MoveWorldObjectTo(data.npcOrGo))
|
if (MoveWorldObjectTo(data.npcOrGo))
|
||||||
|
{
|
||||||
|
botAI->rpgInfo.moveRetryCount = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Retry counter (reference pattern): give up after N failures
|
||||||
|
// by clearing the picked NPC so next tick picks a different
|
||||||
|
// one. No nudge — stand still until retry.
|
||||||
|
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
||||||
|
{
|
||||||
|
data.npcOrGo = ObjectGuid();
|
||||||
|
data.lastReach = 0;
|
||||||
|
botAI->rpgInfo.moveRetryCount = 0;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
// NPC pathing failed (random offset in a wall, mmap hiccup, etc).
|
|
||||||
// Take a small random step so the next tick retries from a
|
|
||||||
// different spot instead of staring at the NPC from afar.
|
|
||||||
return MoveRandomNear(15.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -350,9 +370,16 @@ bool NewRpgDoQuestAction::DoIncompleteQuest(NewRpgInfo::DoQuest& data)
|
|||||||
// class strategy handles it.
|
// class strategy handles it.
|
||||||
|
|
||||||
if (MoveFarTo(data.pos))
|
if (MoveFarTo(data.pos))
|
||||||
|
{
|
||||||
|
botAI->rpgInfo.moveRetryCount = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Retry counter (reference pattern): on N consecutive
|
||||||
|
// failures, drop this objective and go idle so the picker can
|
||||||
|
// try another quest / state.
|
||||||
|
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
||||||
|
botAI->rpgInfo.ChangeToIdle();
|
||||||
return true;
|
return true;
|
||||||
// sampler found nothing — nudge so next tick tries a new pos
|
|
||||||
return MoveRandomNear(10.0f);
|
|
||||||
}
|
}
|
||||||
// Now we are near the quest objective
|
// Now we are near the quest objective
|
||||||
// kill mobs and looting quest should be done automatically by grind strategy
|
// kill mobs and looting quest should be done automatically by grind strategy
|
||||||
@ -551,8 +578,16 @@ bool NewRpgDoQuestAction::DoCompletedQuest(NewRpgInfo::DoQuest& data)
|
|||||||
if (bot->GetDistance(data.pos) > 10.0f && !data.lastReachPOI)
|
if (bot->GetDistance(data.pos) > 10.0f && !data.lastReachPOI)
|
||||||
{
|
{
|
||||||
if (MoveFarTo(data.pos))
|
if (MoveFarTo(data.pos))
|
||||||
|
{
|
||||||
|
botAI->rpgInfo.moveRetryCount = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Retry counter (reference pattern): mark quest as abandoned
|
||||||
|
// if turn-in POI is unreachable repeatedly so the bot doesn't
|
||||||
|
// sit on a broken handler.
|
||||||
|
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
||||||
|
botAI->rpgInfo.ChangeToIdle();
|
||||||
return true;
|
return true;
|
||||||
return MoveRandomNear(10.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we are near the qoi of reward
|
// Now we are near the qoi of reward
|
||||||
|
|||||||
@ -77,6 +77,7 @@ void NewRpgInfo::Reset()
|
|||||||
{
|
{
|
||||||
data = Idle{};
|
data = Idle{};
|
||||||
startT = getMSTime();
|
startT = getMSTime();
|
||||||
|
moveRetryCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NewRpgStatus NewRpgInfo::GetStatus()
|
NewRpgStatus NewRpgInfo::GetStatus()
|
||||||
|
|||||||
@ -78,6 +78,14 @@ struct NewRpgInfo
|
|||||||
|
|
||||||
uint32 startT{0}; // start timestamp of the current status
|
uint32 startT{0}; // start timestamp of the current status
|
||||||
|
|
||||||
|
// Counts consecutive MoveFarTo failures for the current state.
|
||||||
|
// Reset on every status change (via Reset) and on every successful
|
||||||
|
// MoveFarTo. When it crosses MAX_MOVE_RETRIES the failing action
|
||||||
|
// gives up and transitions out of the current state instead of
|
||||||
|
// sitting on a stuck objective forever.
|
||||||
|
uint8 moveRetryCount{0};
|
||||||
|
static constexpr uint8 MAX_MOVE_RETRIES = 10;
|
||||||
|
|
||||||
using RpgData = std::variant<
|
using RpgData = std::variant<
|
||||||
Idle,
|
Idle,
|
||||||
GoGrind,
|
GoGrind,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user