1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

Fix autocombat AI threading

This commit is contained in:
Ivan Savenko
2023-07-19 12:09:03 +03:00
parent 556763fb7b
commit 9e58f67ab5
2 changed files with 29 additions and 22 deletions

View File

@@ -786,6 +786,9 @@ void CPlayerInterface::activeStack(const CStack * stack) //called when it's turn
{ {
if (isAutoFightOn) if (isAutoFightOn)
{ {
//FIXME: we want client rendering to proceed while AI is making actions
// so unlock mutex while AI is busy since this might take quite a while, especially if hero has many spells
auto unlockPim = vstd::makeUnlockGuard(*pim);
autofightingAI->activeStack(stack); autofightingAI->activeStack(stack);
return; return;
} }

View File

@@ -701,35 +701,39 @@ void BattleInterface::requestAutofightingAIToTakeAction()
{ {
assert(curInt->isAutoFightOn); assert(curInt->isAutoFightOn);
boost::thread aiThread([&]() if(curInt->cb->battleIsFinished())
{ {
if(curInt->cb->battleIsFinished()) return; // battle finished with spellcast
{ }
return; // battle finished with spellcast
}
if (tacticsMode) if (tacticsMode)
{
// Always end tactics mode. Player interface is blocked currently, so it's not possible that
// the AI can take any action except end tactics phase (AI actions won't be triggered)
//TODO implement the possibility that the AI will be triggered for further actions
//TODO any solution to merge tactics phase & normal phase in the way it is handled by the player and battle interface?
tacticPhaseEnd();
stacksController->setActiveStack(nullptr);
}
else
{
const CStack* activeStack = stacksController->getActiveStack();
// If enemy is moving, activeStack can be null
if (activeStack)
{ {
// Always end tactics mode. Player interface is blocked currently, so it's not possible that
// the AI can take any action except end tactics phase (AI actions won't be triggered)
//TODO implement the possibility that the AI will be triggered for further actions
//TODO any solution to merge tactics phase & normal phase in the way it is handled by the player and battle interface?
tacticPhaseEnd();
stacksController->setActiveStack(nullptr); stacksController->setActiveStack(nullptr);
}
else
{
const CStack* activeStack = stacksController->getActiveStack();
// If enemy is moving, activeStack can be null // FIXME: unsafe
if (activeStack) // Run task in separate thread to avoid UI lock while AI is making turn (which might take some time)
// HOWEVER this thread won't atttempt to lock game state, potentially leading to races
boost::thread aiThread([&]()
{
curInt->autofightingAI->activeStack(activeStack); curInt->autofightingAI->activeStack(activeStack);
});
stacksController->setActiveStack(nullptr); aiThread.detach();
} }
}); }
aiThread.detach();
} }
void BattleInterface::castThisSpell(SpellID spellID) void BattleInterface::castThisSpell(SpellID spellID)