mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
feat(Core/Debug): Combat-aware state label + retry counter visibility + give-up event emit
This commit is contained in:
parent
e854e9beca
commit
5baba708e0
@ -62,7 +62,9 @@ void MovementAction::EmitDebugMove(char const* method, char const* generator, fl
|
|||||||
|
|
||||||
NewRpgInfo& info = botAI->rpgInfo;
|
NewRpgInfo& info = botAI->rpgInfo;
|
||||||
NewRpgStatus status = info.GetStatus();
|
NewRpgStatus status = info.GetStatus();
|
||||||
|
bool const inCombat = botAI->GetState() == BOT_STATE_COMBAT;
|
||||||
char const* statusName =
|
char const* statusName =
|
||||||
|
inCombat ? "combat" :
|
||||||
status == RPG_IDLE ? "idle" :
|
status == RPG_IDLE ? "idle" :
|
||||||
status == RPG_GO_GRIND ? "go-grind" :
|
status == RPG_GO_GRIND ? "go-grind" :
|
||||||
status == RPG_GO_CAMP ? "go-camp" :
|
status == RPG_GO_CAMP ? "go-camp" :
|
||||||
@ -73,14 +75,22 @@ void MovementAction::EmitDebugMove(char const* method, char const* generator, fl
|
|||||||
status == RPG_TRAVEL_FLIGHT ? "travel-flight" :
|
status == RPG_TRAVEL_FLIGHT ? "travel-flight" :
|
||||||
status == RPG_OUTDOOR_PVP ? "outdoor-pvp" : "?";
|
status == RPG_OUTDOOR_PVP ? "outdoor-pvp" : "?";
|
||||||
|
|
||||||
// Resolve a human-readable target name from the RPG context. When
|
// Resolve a human-readable target name. In combat, the bot is
|
||||||
// we can name the target (quest objective, wander NPC, flight
|
// actively engaging an enemy that is unrelated to the RPG state's
|
||||||
// master, travel-node hop, etc.), it replaces the loc=(x,y,z)
|
// target — show that enemy instead of the now-stale RPG goal.
|
||||||
// field — names are far more useful than coordinates. When no
|
// Out of combat, fall back to the RPG context: quest objective,
|
||||||
// target can be named (combat moves, follow, flee, ad-hoc), we
|
// wander NPC, flight master, etc. Names are far more useful than
|
||||||
// fall through to loc=(x,y,z).
|
// coordinates; loc=(x,y,z) only when nothing nameable applies.
|
||||||
std::string targetName;
|
std::string targetName;
|
||||||
switch (status)
|
if (inCombat)
|
||||||
|
{
|
||||||
|
Unit* current = *botAI->GetAiObjectContext()->GetValue<Unit*>("current target");
|
||||||
|
Unit* enemyPlayer = *botAI->GetAiObjectContext()->GetValue<Unit*>("enemy player target");
|
||||||
|
Unit* enemy = current ? current : enemyPlayer;
|
||||||
|
if (enemy)
|
||||||
|
targetName = std::string("vs:") + enemy->GetName();
|
||||||
|
}
|
||||||
|
else switch (status)
|
||||||
{
|
{
|
||||||
case RPG_DO_QUEST:
|
case RPG_DO_QUEST:
|
||||||
if (auto* data = std::get_if<NewRpgInfo::DoQuest>(&info.data))
|
if (auto* data = std::get_if<NewRpgInfo::DoQuest>(&info.data))
|
||||||
@ -164,6 +174,11 @@ void MovementAction::EmitDebugMove(char const* method, char const* generator, fl
|
|||||||
<< " | " << statusName
|
<< " | " << statusName
|
||||||
<< " | " << std::fixed << std::setprecision(2) << dis << " yard"
|
<< " | " << std::fixed << std::setprecision(2) << dis << " yard"
|
||||||
<< " | " << (targetName.empty() ? "-" : targetName.c_str());
|
<< " | " << (targetName.empty() ? "-" : targetName.c_str());
|
||||||
|
// Surface the RPG MoveFarTo retry counter so when bots get stuck
|
||||||
|
// it's obvious from the whisper alone (retry=N/MAX) — and the
|
||||||
|
// "give-up" event emitters below show retry=MAX/MAX explicitly.
|
||||||
|
if (info.moveRetryCount > 0)
|
||||||
|
out << " | retry=" << uint32(info.moveRetryCount) << "/" << uint32(NewRpgInfo::MAX_MOVE_RETRIES);
|
||||||
if (extra && *extra)
|
if (extra && *extra)
|
||||||
out << " | " << extra;
|
out << " | " << extra;
|
||||||
botAI->TellMasterNoFacing(out);
|
botAI->TellMasterNoFacing(out);
|
||||||
|
|||||||
@ -164,7 +164,12 @@ bool NewRpgGoGrindAction::Execute(Event /*event*/)
|
|||||||
// transitioning out of the stuck state instead of nudging in
|
// transitioning out of the stuck state instead of nudging in
|
||||||
// place. Idle lets the status picker rotate to a new state.
|
// place. Idle lets the status picker rotate to a new state.
|
||||||
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
||||||
|
{
|
||||||
|
EmitDebugMove("MoveFar", "give-up",
|
||||||
|
data->pos.GetPositionX(), data->pos.GetPositionY(), data->pos.GetPositionZ(),
|
||||||
|
"idle");
|
||||||
botAI->rpgInfo.ChangeToIdle();
|
botAI->rpgInfo.ChangeToIdle();
|
||||||
|
}
|
||||||
return true; // consume tick, no nudge
|
return true; // consume tick, no nudge
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +189,12 @@ bool NewRpgGoCampAction::Execute(Event /*event*/)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
||||||
|
{
|
||||||
|
EmitDebugMove("MoveFar", "give-up",
|
||||||
|
data->pos.GetPositionX(), data->pos.GetPositionY(), data->pos.GetPositionZ(),
|
||||||
|
"idle");
|
||||||
botAI->rpgInfo.ChangeToIdle();
|
botAI->rpgInfo.ChangeToIdle();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,6 +260,9 @@ bool NewRpgWanderNpcAction::Execute(Event /*event*/)
|
|||||||
// one. No nudge — stand still until retry.
|
// one. No nudge — stand still until retry.
|
||||||
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
||||||
{
|
{
|
||||||
|
EmitDebugMove("MoveFar", "give-up",
|
||||||
|
bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||||
|
"drop-npc");
|
||||||
data.npcOrGo = ObjectGuid();
|
data.npcOrGo = ObjectGuid();
|
||||||
data.lastReach = 0;
|
data.lastReach = 0;
|
||||||
botAI->rpgInfo.moveRetryCount = 0;
|
botAI->rpgInfo.moveRetryCount = 0;
|
||||||
@ -386,6 +399,12 @@ bool NewRpgDoQuestAction::DoIncompleteQuest(NewRpgInfo::DoQuest& data)
|
|||||||
// catches it next tick.
|
// catches it next tick.
|
||||||
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
||||||
{
|
{
|
||||||
|
std::ostringstream nx;
|
||||||
|
nx << "next-spawn(" << (data.currentSpawnIdx + 1) << "/"
|
||||||
|
<< data.candidateSpawns.size() << ")";
|
||||||
|
EmitDebugMove("MoveFar", "give-up",
|
||||||
|
target.GetPositionX(), target.GetPositionY(), target.GetPositionZ(),
|
||||||
|
nx.str().c_str());
|
||||||
++data.currentSpawnIdx;
|
++data.currentSpawnIdx;
|
||||||
data.lastReachPOI = 0;
|
data.lastReachPOI = 0;
|
||||||
botAI->rpgInfo.moveRetryCount = 0;
|
botAI->rpgInfo.moveRetryCount = 0;
|
||||||
@ -514,7 +533,12 @@ bool NewRpgDoQuestAction::DoCompletedQuest(NewRpgInfo::DoQuest& data)
|
|||||||
// if turn-in POI is unreachable repeatedly so the bot doesn't
|
// if turn-in POI is unreachable repeatedly so the bot doesn't
|
||||||
// sit on a broken handler.
|
// sit on a broken handler.
|
||||||
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
if (++botAI->rpgInfo.moveRetryCount >= NewRpgInfo::MAX_MOVE_RETRIES)
|
||||||
|
{
|
||||||
|
EmitDebugMove("MoveFar", "give-up",
|
||||||
|
data.pos.GetPositionX(), data.pos.GetPositionY(), data.pos.GetPositionZ(),
|
||||||
|
"idle(turn-in)");
|
||||||
botAI->rpgInfo.ChangeToIdle();
|
botAI->rpgInfo.ChangeToIdle();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user