1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Fixed handling of tactics

This commit is contained in:
Ivan Savenko 2023-07-18 21:43:53 +03:00
parent 79be1c66fb
commit 556763fb7b
13 changed files with 41 additions and 23 deletions

View File

@ -249,6 +249,11 @@ BattleAction CBattleAI::selectStackAction(const CStack * stack)
return BattleAction::makeDefend(stack);
}
void CBattleAI::yourTacticPhase(int distance)
{
cb->battleMakeUnitAction(BattleAction::makeEndOFTacticPhase(cb->battleGetTacticsSide()));
}
void CBattleAI::activeStack( const CStack * stack )
{
LOG_TRACE_PARAMS(logAi, "stack: %s", stack->nodeName());

View File

@ -72,6 +72,7 @@ public:
void evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcast & ps); //for offensive damaging spells only
void activeStack(const CStack * stack) override; //called when it's turn of that stack
void yourTacticPhase(int distance) override;
std::optional<BattleAction> considerFleeingOrSurrendering();

View File

@ -89,7 +89,7 @@ PotentialTargets::PotentialTargets(const battle::Unit * attacker, const Hypothet
{
auto & bestAp = possibleAttacks[0];
logGlobal->info("Battle AI best: %s -> %s at %d from %d, affects %d units: d:%lld a:%lld c:%lld s:%lld",
logGlobal->debug("Battle AI best: %s -> %s at %d from %d, affects %d units: d:%lld a:%lld c:%lld s:%lld",
bestAp.attack.attacker->unitType()->getJsonKey(),
state.battleGetUnitByPos(bestAp.dest)->unitType()->getJsonKey(),
(int)bestAp.dest, (int)bestAp.from, (int)bestAp.affectedUnits.size(),

View File

@ -11,6 +11,7 @@
#include "CEmptyAI.h"
#include "../../lib/CRandomGenerator.h"
#include "../../lib/CStack.h"
void CEmptyAI::saveGame(BinarySerializer & h, const int version)
{
@ -33,6 +34,16 @@ void CEmptyAI::yourTurn()
cb->endTurn();
}
void CEmptyAI::activeStack(const CStack * stack)
{
cb->battleMakeUnitAction(BattleAction::makeDefend(stack));
}
void CEmptyAI::yourTacticPhase(int distance)
{
cb->battleMakeUnitAction(BattleAction::makeEndOFTacticPhase(cb->battleGetTacticsSide()));
}
void CEmptyAI::heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID)
{
cb->selectionMade(CRandomGenerator::getDefault().nextInt((int)skills.size() - 1), queryID);

View File

@ -24,6 +24,8 @@ public:
void initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override;
void yourTurn() override;
void yourTacticPhase(int distance) override;
void activeStack(const CStack * stack) override;
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override;
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override;

View File

@ -88,6 +88,11 @@ static bool willSecondHexBlockMoreEnemyShooters(const BattleHex &h1, const Battl
return shooters[0] < shooters[1];
}
void CStupidAI::yourTacticPhase(int distance)
{
cb->battleMakeUnitAction(BattleAction::makeEndOFTacticPhase(cb->battleGetTacticsSide()));
}
void CStupidAI::activeStack( const CStack * stack )
{
//boost::this_thread::sleep(boost::posix_time::seconds(2));

View File

@ -29,6 +29,7 @@ public:
void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero
void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero
void activeStack(const CStack * stack) override; //called when it's turn of that stack
void yourTacticPhase(int distance) override;
void battleAttack(const BattleAttack *ba) override; //called when stack is performing attack
void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, bool ranged) override; //called when stack receives damage (after battleAttack())

View File

@ -957,15 +957,7 @@ void CPlayerInterface::battleGateStateChanged(const EGateState state)
void CPlayerInterface::yourTacticPhase(int distance)
{
THREAD_CREATED_BY_CLIENT;
while(battleInt && battleInt->tacticsMode)
boost::this_thread::sleep(boost::posix_time::millisec(1));
}
void CPlayerInterface::forceEndTacticPhase()
{
if (battleInt)
battleInt->tacticsMode = false;
EVENT_HANDLER_CALLED_BY_CLIENT;
}
void CPlayerInterface::showInfoDialog(EInfoWindowMode type, const std::string &text, const std::vector<Component> & components, int soundID)

View File

@ -176,7 +176,6 @@ protected: // Call-ins from server, should not be called directly, but only via
void battleCatapultAttacked(const CatapultAttack & ca) override; //called when catapult makes an attack
void battleGateStateChanged(const EGateState state) override;
void yourTacticPhase(int distance) override;
void forceEndTacticPhase() override;
public: // public interface for use by client via LOCPLINT access

View File

@ -597,6 +597,13 @@ void CClient::battleStarted(const BattleInfo * info)
//Remove player interfaces for auto battle (quickCombat option)
if(att && att->isAutoFightOn)
{
if (att->cb->battleGetTacticDist())
{
auto side = att->cb->playerToSide(att->playerID);
auto action = BattleAction::makeEndOFTacticPhase(*side);
att->cb->battleMakeTacticAction(action);
}
att.reset();
def.reset();
}

View File

@ -629,6 +629,11 @@ void BattleInterface::tacticPhaseEnd()
{
stacksController->setActiveStack(nullptr);
tacticsMode = false;
auto side = tacticianInterface->cb->playerToSide(tacticianInterface->playerID);
auto action = BattleAction::makeEndOFTacticPhase(*side);
tacticianInterface->cb->battleMakeTacticAction(action);
}
static bool immobile(const CStack *s)
@ -709,8 +714,8 @@ void BattleInterface::requestAutofightingAIToTakeAction()
// 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);
tacticsMode = false;
}
else
{

View File

@ -152,14 +152,6 @@ std::shared_ptr<scripting::Module> CDynLibHandler::getNewScriptingModule(const b
}
#endif
void CGlobalAI::activeStack(const CStack * stack)
{
BattleAction ba;
ba.actionType = EActionType::DEFEND;
ba.stackNumber = stack->unitId();
assert(0);
}
CGlobalAI::CGlobalAI()
{
human = false;

View File

@ -79,8 +79,7 @@ public:
//battle call-ins
virtual void activeStack(const CStack * stack)=0; //called when it's turn of that stack
virtual void yourTacticPhase(int distance){}; //called when interface has opportunity to use Tactics skill -> use cb->battleMakeTacticAction from this function
virtual void forceEndTacticPhase(){}; //force the tatic phase to end to clean up the tactic phase thread
virtual void yourTacticPhase(int distance)=0; //called when interface has opportunity to use Tactics skill -> use cb->battleMakeTacticAction from this function
};
/// Central class for managing human player / AI interface logic
@ -132,7 +131,6 @@ class DLL_LINKAGE CGlobalAI : public CGameInterface // AI class (to derivate)
public:
std::shared_ptr<Environment> env;
CGlobalAI();
virtual void activeStack(const CStack * stack) override;
};
//class to be inherited by adventure-only AIs, it cedes battle actions to given battle-AI