1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-11 11:31:52 +02:00

Support draw scenario (doesnt work properly)

This commit is contained in:
nordsoft 2022-11-16 02:50:47 +04:00
parent 9b597fc8d4
commit b253b19dc3
7 changed files with 39 additions and 25 deletions

View File

@ -707,12 +707,15 @@ void CPlayerInterface::battleStartBefore(const CCreatureSet *army1, const CCreat
void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
bool replay = (lastBattleArmies.first == army1 && lastBattleArmies.second == army2); bool replay = (lastBattleArmies.first == army1 && lastBattleArmies.second == army2); //will be true if player already refused auto-battle result
lastBattleArmies.first = army1; lastBattleArmies.first = army1;
lastBattleArmies.second = army2; lastBattleArmies.second = army2;
//quick combat with neutral creatures only //quick combat with neutral creatures only
auto * army2_object = dynamic_cast<const CGObjectInstance *>(army2); auto * army2_object = dynamic_cast<const CGObjectInstance *>(army2);
if(!replay && army2_object && army2_object->getOwner() == PlayerColor::UNFLAGGABLE && settings["adventure"]["quickCombat"].Bool()) if((!replay && army2_object
&& army2_object->getOwner() == PlayerColor::UNFLAGGABLE
&& settings["adventure"]["quickCombat"].Bool())
|| settings["adventure"]["alwaysSkipBattle"].Bool())
{ {
autofightingAI = CDynLibHandler::getNewBattleAI(settings["server"]["friendlyAI"].String()); autofightingAI = CDynLibHandler::getNewBattleAI(settings["server"]["friendlyAI"].String());
autofightingAI->init(env, cb); autofightingAI->init(env, cb);
@ -938,7 +941,8 @@ void CPlayerInterface::battleEnd(const BattleResult *br, QueryID queryID)
if(!battleInt) if(!battleInt)
{ {
auto wnd = std::make_shared<CBattleResultWindow>(*br, *this, true); bool replay = !settings["adventure"]["alwaysSkipCombat"].Bool(); //do not allow manual replay
auto wnd = std::make_shared<CBattleResultWindow>(*br, *this, replay);
wnd->resultCallback = [=](ui32 selection) wnd->resultCallback = [=](ui32 selection)
{ {
cb->selectionMade(selection, queryID); cb->selectionMade(selection, queryID);

View File

@ -600,7 +600,7 @@ void CClient::battleStarted(const BattleInfo * info)
if(vstd::contains(playerint, rightSide.color) && playerint[rightSide.color]->human) if(vstd::contains(playerint, rightSide.color) && playerint[rightSide.color]->human)
def = std::dynamic_pointer_cast<CPlayerInterface>(playerint[rightSide.color]); def = std::dynamic_pointer_cast<CPlayerInterface>(playerint[rightSide.color]);
//If quick combat is not, do not prepare interfaces for battleint //Remove player interfaces for auto battle (quickCombat option)
if(att && att->isAutoFightOn) if(att && att->isAutoFightOn)
{ {
att.reset(); att.reset();

View File

@ -570,9 +570,9 @@ void CBattleResultWindow::show(SDL_Surface * to)
CCS->videoh->update(pos.x + 107, pos.y + 70, screen, true, false); CCS->videoh->update(pos.x + 107, pos.y + 70, screen, true, false);
} }
void CBattleResultWindow::bExitf() void CBattleResultWindow::buttonPressed(int button)
{ {
resultCallback(0); resultCallback(button);
CPlayerInterface &intTmp = owner; //copy reference because "this" will be destructed soon CPlayerInterface &intTmp = owner; //copy reference because "this" will be destructed soon
close(); close();
@ -586,20 +586,14 @@ void CBattleResultWindow::bExitf()
CCS->videoh->close(); CCS->videoh->close();
} }
void CBattleResultWindow::bExitf()
{
buttonPressed(0);
}
void CBattleResultWindow::bRepeatf() void CBattleResultWindow::bRepeatf()
{ {
resultCallback(1); buttonPressed(1);
CPlayerInterface &intTmp = owner; //copy reference because "this" will be destructed soon
close();
if(dynamic_cast<CBattleInterface*>(GH.topInt().get()))
GH.popInts(1); //pop battle interface if present
//Result window and battle interface are gone. We requested all dialogs to be closed before opening the battle,
//so we can be sure that there is no dialogs left on GUI stack.
intTmp.showingDialog->setn(false);
CCS->videoh->close();
} }
Point CClickableHex::getXYUnitAnim(BattleHex hexNum, const CStack * stack, CBattleInterface * cbi) Point CClickableHex::getXYUnitAnim(BattleHex hexNum, const CStack * stack, CBattleInterface * cbi)

View File

@ -122,6 +122,8 @@ private:
std::vector<std::shared_ptr<CAnimImage>> icons; std::vector<std::shared_ptr<CAnimImage>> icons;
std::shared_ptr<CTextBox> description; std::shared_ptr<CTextBox> description;
CPlayerInterface & owner; CPlayerInterface & owner;
void buttonPressed(int button); //internal function for button callbacks
public: public:
CBattleResultWindow(const BattleResult & br, CPlayerInterface & _owner, bool allowReplay = false); CBattleResultWindow(const BattleResult & br, CPlayerInterface & _owner, bool allowReplay = false);
~CBattleResultWindow(); ~CBattleResultWindow();

View File

@ -124,7 +124,7 @@
"type" : "object", "type" : "object",
"additionalProperties" : false, "additionalProperties" : false,
"default": {}, "default": {},
"required" : [ "heroSpeed", "enemySpeed", "scrollSpeed", "heroReminder", "quickCombat" ], "required" : [ "heroSpeed", "enemySpeed", "scrollSpeed", "heroReminder", "quickCombat", "alwaysSkipCombat" ],
"properties" : { "properties" : {
"heroSpeed" : { "heroSpeed" : {
"type" : "number", "type" : "number",
@ -144,7 +144,13 @@
}, },
"quickCombat" : { "quickCombat" : {
"type" : "boolean", "type" : "boolean",
"default" : true "default" : true,
"description" : "enable to allow AI to play combats versus neutrals. Player can refuse battle result and replay it manually. This option can be switched from in-game menu"
},
"alwaysSkipCombat" : {
"type" : "boolean",
"default" : false,
"description" : "if enabled, all battles will be controlled by AI"
} }
} }
}, },

View File

@ -741,9 +741,9 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
CasualtiesAfterBattle cab1(bEndArmy1, battleInfo), cab2(bEndArmy2, battleInfo); //calculate casualties before deleting battle CasualtiesAfterBattle cab1(bEndArmy1, battleInfo), cab2(bEndArmy2, battleInfo); //calculate casualties before deleting battle
ChangeSpells cs; //for Eagle Eye ChangeSpells cs; //for Eagle Eye
if (finishingBattle->winnerHero) if(!finishingBattle->isDraw() && finishingBattle->winnerHero)
{ {
if (int eagleEyeLevel = finishingBattle->winnerHero->valOfBonuses(Bonus::SECONDARY_SKILL_VAL2, SecondarySkill::EAGLE_EYE)) if(int eagleEyeLevel = finishingBattle->winnerHero->valOfBonuses(Bonus::SECONDARY_SKILL_VAL2, SecondarySkill::EAGLE_EYE))
{ {
double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::EAGLE_EYE); double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::EAGLE_EYE);
for(auto & spellId : battleInfo->sides.at(!battleResult.data->winner).usedSpellsHistory) for(auto & spellId : battleInfo->sides.at(!battleResult.data->winner).usedSpellsHistory)
@ -756,7 +756,7 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
} }
std::vector<const CArtifactInstance *> arts; //display them in window std::vector<const CArtifactInstance *> arts; //display them in window
if (result == BattleResult::NORMAL && finishingBattle->winnerHero) if(result == BattleResult::NORMAL && !finishingBattle->isDraw() && finishingBattle->winnerHero)
{ {
auto sendMoveArtifact = [&](const CArtifactInstance *art, MoveArtifact *ma) auto sendMoveArtifact = [&](const CArtifactInstance *art, MoveArtifact *ma)
{ {
@ -890,6 +890,11 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
RemoveObject ro(finishingBattle->loserHero->id); RemoveObject ro(finishingBattle->loserHero->id);
sendAndApply(&ro); sendAndApply(&ro);
} }
if(finishingBattle->isDraw() && finishingBattle->winnerHero) //for draw case both heroes should be removed
{
RemoveObject ro(finishingBattle->winnerHero->id);
sendAndApply(&ro);
}
if(battleResult.data->winner == BattleSide::DEFENDER if(battleResult.data->winner == BattleSide::DEFENDER
&& finishingBattle->winnerHero && finishingBattle->winnerHero
@ -900,10 +905,10 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
swapGarrisonOnSiege(finishingBattle->winnerHero->visitedTown->id); //return defending visitor from garrison to its rightful place swapGarrisonOnSiege(finishingBattle->winnerHero->visitedTown->id); //return defending visitor from garrison to its rightful place
} }
//give exp //give exp
if(battleResult.data->exp[finishingBattle->winnerSide] && finishingBattle->winnerHero) if(!finishingBattle->isDraw() && battleResult.data->exp[finishingBattle->winnerSide] && finishingBattle->winnerHero)
changePrimSkill(finishingBattle->winnerHero, PrimarySkill::EXPERIENCE, battleResult.data->exp[finishingBattle->winnerSide]); changePrimSkill(finishingBattle->winnerHero, PrimarySkill::EXPERIENCE, battleResult.data->exp[finishingBattle->winnerSide]);
queries.popIfTop(battleQuery); //queries.popIfTop(battleQuery);
BattleResultAccepted raccepted; BattleResultAccepted raccepted;
raccepted.army1 = const_cast<CArmedInstance*>(bEndArmy1); raccepted.army1 = const_cast<CArmedInstance*>(bEndArmy1);
@ -914,6 +919,7 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
raccepted.exp[1] = battleResult.data->exp[1]; raccepted.exp[1] = battleResult.data->exp[1];
sendAndApply(&raccepted); sendAndApply(&raccepted);
queries.popIfTop(battleQuery);
//--> continuation (battleAfterLevelUp) occurs after level-up queries are handled or on removing query (above) //--> continuation (battleAfterLevelUp) occurs after level-up queries are handled or on removing query (above)
} }

View File

@ -309,6 +309,8 @@ public:
FinishingBattleHelper(); FinishingBattleHelper();
FinishingBattleHelper(std::shared_ptr<const CBattleQuery> Query, int RemainingBattleQueriesCount); FinishingBattleHelper(std::shared_ptr<const CBattleQuery> Query, int RemainingBattleQueriesCount);
inline bool isDraw() const {return winnerSide == 2;}
const CGHeroInstance *winnerHero, *loserHero; const CGHeroInstance *winnerHero, *loserHero;
PlayerColor victor, loser; PlayerColor victor, loser;
ui8 winnerSide; ui8 winnerSide;