1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-15 13:33:36 +02:00

- Refactoring for checking victory/loss conditions (use enum class instead of magic numbers)

- Improved showing player lost message for one special case
This commit is contained in:
beegee1 2013-11-17 17:57:04 +00:00
parent 2b6cdd5f41
commit 3e4407593f
12 changed files with 1008 additions and 910 deletions

View File

@ -192,14 +192,14 @@ void VCAI::showShipyardDialog(const IShipyard *obj)
NET_EVENT_HANDLER;
}
void VCAI::gameOver(PlayerColor player, bool victory)
void VCAI::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult)
{
LOG_TRACE_PARAMS(logAi, "victory '%i'", victory);
LOG_TRACE_PARAMS(logAi, "victoryLossCheckResult '%s'", victoryLossCheckResult);
NET_EVENT_HANDLER;
logAi->debugStream() << boost::format("Player %d: I heard that player %d %s.") % playerID % player.getNum() % (victory ? "won" : "lost");
logAi->debugStream() << boost::format("Player %d: I heard that player %d %s.") % playerID % player.getNum() % (victoryLossCheckResult.victory() ? "won" : "lost");
if(player == playerID)
{
if(victory)
if(victoryLossCheckResult.victory())
{
logAi->debugStream() << "VCAI: I won! Incredible!";
logAi->debugStream() << "Turn nr " << myCb->getDate();

View File

@ -188,7 +188,7 @@ public:
virtual void playerBlocked(int reason, bool start) override;
virtual void showPuzzleMap() override;
virtual void showShipyardDialog(const IShipyard *obj) override;
virtual void gameOver(PlayerColor player, bool victory) override;
virtual void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
virtual void artifactPut(const ArtifactLocation &al) override;
virtual void artifactRemoved(const ArtifactLocation &al) override;
virtual void stacksErased(const StackLocation &location) override;

View File

@ -2069,13 +2069,13 @@ void CPlayerInterface::finishMovement( const TryMoveHero &details, const int3 &h
std::stable_sort(CGI->mh->ttiles[details.end.x][details.end.y][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x][details.end.y][details.end.z].objects.end(), ocmptwo_cgin);
}
void CPlayerInterface::gameOver(PlayerColor player, bool victory )
void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult )
{
EVENT_HANDLER_CALLED_BY_CLIENT;
if(player == playerID)
{
if(!victory)
if(victoryLossCheckResult.loss())
showInfoDialog(CGI->generaltexth->allTexts[95]);
// else
// showInfoDialog("Placeholder message: you won!");
@ -2108,9 +2108,18 @@ void CPlayerInterface::gameOver(PlayerColor player, bool victory )
else
{
if(!victory && cb->getPlayerStatus(playerID) == EPlayerStatus::INGAME) //enemy has lost
if(victoryLossCheckResult.loss() && cb->getPlayerStatus(playerID) == EPlayerStatus::INGAME) //enemy has lost
{
std::string txt = CGI->generaltexth->allTexts[5]; //%s has been vanquished!
std::string txt;
if(victoryLossCheckResult == EVictoryLossCheckResult::LOSS_STANDARD_TOWNS_AND_TIME_OVER)
{
txt = CGI->generaltexth->allTexts[8]; // %s's heroes have abandoned him, and he is banished from this land.
}
else
{
txt = CGI->generaltexth->allTexts[5]; // %s has been vanquished!
}
boost::algorithm::replace_first(txt, "%s", CGI->generaltexth->capColors[player.getNum()]);
showInfoDialog(txt,std::vector<CComponent*>(1, new CComponent(CComponent::flag, player.getNum(), 0)));
}

View File

@ -184,7 +184,7 @@ public:
void centerView (int3 pos, int focusTime) override;
void objectPropertyChanged(const SetObjectProperty * sop) override;
void objectRemoved(const CGObjectInstance *obj) override;
void gameOver(PlayerColor player, bool victory) override;
void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active itnerface
void showComp(const Component &comp, std::string message) override; //display component in the advmapint infobox
void saveGame(COSer<CSaveFile> &h, const int version) override; //saving

View File

@ -292,7 +292,7 @@ void ChangeObjPos::applyCl( CClient *cl )
void PlayerEndsGame::applyCl( CClient *cl )
{
CALL_IN_ALL_INTERFACES(gameOver, player, victory);
CALL_IN_ALL_INTERFACES(gameOver, player, victoryLossCheckResult);
}
void RemoveBonus::applyCl( CClient *cl )

View File

@ -2032,23 +2032,29 @@ bool CGameState::checkForVisitableDir( const int3 & src, const TerrainTile *pom,
return true;
}
EVictoryLossCheckResult CGameState::checkForVictoryAndLoss(PlayerColor player) const
{
auto result = checkForVictory(player);
if (result == EVictoryLossCheckResult::NO_VICTORY_OR_LOSS) result = checkForLoss(player);
return result;
}
int CGameState::victoryCheck( PlayerColor player ) const
EVictoryLossCheckResult CGameState::checkForVictory( PlayerColor player ) const
{
const PlayerState *p = CGameInfoCallback::getPlayer(player);
if(map->victoryCondition.condition == EVictoryConditionType::WINSTANDARD || map->victoryCondition.allowNormalVictory
|| (!p->human && !map->victoryCondition.appliesToAI)) //if the special victory condition applies only to human, AI has the standard)
{
if(player == checkForStandardWin())
return -1;
return EVictoryLossCheckResult::VICTORY_STANDARD;
}
if (p->enteredWinningCheatCode)
{ //cheater or tester, but has entered the code...
if(map->victoryCondition.condition == EVictoryConditionType::WINSTANDARD)
return -1;
return EVictoryLossCheckResult::VICTORY_STANDARD;
else
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
}
if(p->human || map->victoryCondition.appliesToAI)
@ -2059,7 +2065,7 @@ int CGameState::victoryCheck( PlayerColor player ) const
//check if any hero has winning artifact
for(auto & elem : p->heroes)
if(elem->hasArt(map->victoryCondition.objectId))
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
break;
@ -2081,13 +2087,13 @@ int CGameState::victoryCheck( PlayerColor player ) const
}
if(total >= map->victoryCondition.count)
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
}
break;
case EVictoryConditionType::GATHERRESOURCE:
if(p->resources[map->victoryCondition.objectId] >= map->victoryCondition.count)
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
break;
@ -2095,7 +2101,7 @@ int CGameState::victoryCheck( PlayerColor player ) const
{
const CGTownInstance *t = static_cast<const CGTownInstance *>(map->victoryCondition.obj);
if(t->tempOwner == player && t->fortLevel()-1 >= map->victoryCondition.objectId && t->hallLevel()-1 >= map->victoryCondition.count)
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
}
break;
@ -2104,22 +2110,22 @@ int CGameState::victoryCheck( PlayerColor player ) const
if((t == map->victoryCondition.obj || !map->victoryCondition.obj)
&& t->tempOwner == player
&& t->hasBuilt(BuildingID::GRAIL))
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
break;
case EVictoryConditionType::BEATHERO:
if(map->victoryCondition.obj->tempOwner >= PlayerColor::PLAYER_LIMIT) //target hero not present on map
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
break;
case EVictoryConditionType::CAPTURECITY:
{
if(map->victoryCondition.obj->tempOwner == player)
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
}
break;
case EVictoryConditionType::BEATMONSTER:
if(!getObj(map->victoryCondition.obj->id)) //target monster not present on map
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
break;
case EVictoryConditionType::TAKEDWELLINGS:
for(auto & elem : map->objects)
@ -2131,11 +2137,11 @@ int CGameState::victoryCheck( PlayerColor player ) const
case Obj::CREATURE_GENERATOR1: case Obj::CREATURE_GENERATOR2:
case Obj::CREATURE_GENERATOR3: case Obj::CREATURE_GENERATOR4:
case Obj::RANDOM_DWELLING: case Obj::RANDOM_DWELLING_LVL: case Obj::RANDOM_DWELLING_FACTION:
return 0; //found not flagged dwelling - player not won
return EVictoryLossCheckResult::NO_VICTORY_OR_LOSS; //found not flagged dwelling - player not won
}
}
}
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
case EVictoryConditionType::TAKEMINES:
for(auto & elem : map->objects)
{
@ -2144,25 +2150,25 @@ int CGameState::victoryCheck( PlayerColor player ) const
switch(elem->ID)
{
case Obj::MINE: case Obj::ABANDONED_MINE:
return 0; //found not flagged mine - player not won
return EVictoryLossCheckResult::NO_VICTORY_OR_LOSS; //found not flagged mine - player not won
}
}
}
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
case EVictoryConditionType::TRANSPORTITEM:
{
const CGTownInstance *t = static_cast<const CGTownInstance *>(map->victoryCondition.obj);
if((t->visitingHero && t->visitingHero->hasArt(map->victoryCondition.objectId))
|| (t->garrisonHero && t->garrisonHero->hasArt(map->victoryCondition.objectId)))
{
return 1;
return EVictoryLossCheckResult::VICTORY_SPECIAL;
}
}
break;
}
}
return 0;
return EVictoryLossCheckResult::NO_VICTORY_OR_LOSS;
}
PlayerColor CGameState::checkForStandardWin() const
@ -2395,16 +2401,16 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
#undef FILL_FIELD
}
int CGameState::lossCheck( PlayerColor player ) const
EVictoryLossCheckResult CGameState::checkForLoss( PlayerColor player ) const
{
const PlayerState *p = CGameInfoCallback::getPlayer(player);
//if(map->lossCondition.typeOfLossCon == lossStandard)
if(checkForStandardLoss(player))
return -1;
return EVictoryLossCheckResult::LOSS_STANDARD_HEROES_AND_TOWNS;
if (p->enteredLosingCheatCode)
{
return 1;
return EVictoryLossCheckResult::LOSS_SPECIAL;
}
if(p->human) //special loss condition applies only to human player
@ -2417,20 +2423,20 @@ int CGameState::lossCheck( PlayerColor player ) const
const CGObjectInstance *obj = map->lossCondition.obj;
assert(obj);
if(obj->tempOwner != player)
return 1;
return EVictoryLossCheckResult::LOSS_SPECIAL;
}
break;
case ELossConditionType::TIMEEXPIRES:
if(map->lossCondition.timeLimit < day)
return 1;
return EVictoryLossCheckResult::LOSS_SPECIAL;
break;
}
}
if(!p->towns.size() && p->daysWithoutCastle >= 7)
return 2;
return EVictoryLossCheckResult::LOSS_STANDARD_TOWNS_AND_TIME_OVER;
return false;
return EVictoryLossCheckResult::NO_VICTORY_OR_LOSS;
}
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > CGameState::unusedHeroesFromPool()
@ -3283,3 +3289,53 @@ CPathfinder::CPathfinder(CPathsInfo &_out, CGameState *_gs, const CGHeroInstance
useSubterraneanGates = true;
allowEmbarkAndDisembark = true;
}
const EVictoryLossCheckResult EVictoryLossCheckResult::NO_VICTORY_OR_LOSS = EVictoryLossCheckResult(0);
const EVictoryLossCheckResult EVictoryLossCheckResult::VICTORY_STANDARD = EVictoryLossCheckResult(1);
const EVictoryLossCheckResult EVictoryLossCheckResult::VICTORY_SPECIAL = EVictoryLossCheckResult(2);
const EVictoryLossCheckResult EVictoryLossCheckResult::LOSS_STANDARD_HEROES_AND_TOWNS = EVictoryLossCheckResult(3);
const EVictoryLossCheckResult EVictoryLossCheckResult::LOSS_STANDARD_TOWNS_AND_TIME_OVER = EVictoryLossCheckResult(4);
const EVictoryLossCheckResult EVictoryLossCheckResult::LOSS_SPECIAL = EVictoryLossCheckResult(5);
EVictoryLossCheckResult::EVictoryLossCheckResult() : intValue(0)
{
}
EVictoryLossCheckResult::EVictoryLossCheckResult(si32 intValue) : intValue(intValue)
{
}
bool EVictoryLossCheckResult::operator==(EVictoryLossCheckResult const & other) const
{
return intValue == other.intValue;
}
bool EVictoryLossCheckResult::operator!=(EVictoryLossCheckResult const & other) const
{
return intValue != other.intValue;
}
bool EVictoryLossCheckResult::victory() const
{
return *this == VICTORY_STANDARD || *this == VICTORY_SPECIAL;
}
bool EVictoryLossCheckResult::loss() const
{
return !victory();
}
std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult)
{
if(victoryLossCheckResult == EVictoryLossCheckResult::NO_VICTORY_OR_LOSS) os << "No victory or loss";
else if(victoryLossCheckResult == EVictoryLossCheckResult::VICTORY_STANDARD) os << "Victory standard";
else if(victoryLossCheckResult == EVictoryLossCheckResult::VICTORY_SPECIAL) os << "Victory special";
else if(victoryLossCheckResult == EVictoryLossCheckResult::LOSS_STANDARD_HEROES_AND_TOWNS) os << "Loss standard heroes and towns";
else if(victoryLossCheckResult == EVictoryLossCheckResult::LOSS_STANDARD_TOWNS_AND_TIME_OVER) os << "Loss standard towns and time over";
else if(victoryLossCheckResult == EVictoryLossCheckResult::LOSS_SPECIAL) os << "Loss special";
else os << "Unknown type";
return os;
}

View File

@ -356,6 +356,34 @@ public:
struct BattleInfo;
class DLL_LINKAGE EVictoryLossCheckResult
{
public:
static const EVictoryLossCheckResult NO_VICTORY_OR_LOSS;
static const EVictoryLossCheckResult VICTORY_STANDARD;
static const EVictoryLossCheckResult VICTORY_SPECIAL;
static const EVictoryLossCheckResult LOSS_STANDARD_HEROES_AND_TOWNS;
static const EVictoryLossCheckResult LOSS_STANDARD_TOWNS_AND_TIME_OVER;
static const EVictoryLossCheckResult LOSS_SPECIAL;
EVictoryLossCheckResult();
bool operator==(EVictoryLossCheckResult const & other) const;
bool operator!=(EVictoryLossCheckResult const & other) const;
bool victory() const;
bool loss() const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & intValue;
}
private:
EVictoryLossCheckResult(si32 intValue);
si32 intValue;
};
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult);
class DLL_LINKAGE CGameState : public CNonConstInfoCallback
{
public:
@ -404,10 +432,8 @@ public:
void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src = int3(-1,-1,-1), int movement = -1); //calculates possible paths for hero, by default uses current hero position and movement left; returns pointer to newly allocated CPath or nullptr if path does not exists
int3 guardingCreaturePosition (int3 pos) const;
std::vector<CGObjectInstance*> guardingCreatures (int3 pos) const;
int victoryCheck(PlayerColor player) const; //checks if given player is winner; -1 if std victory, 1 if special victory, 0 else
int lossCheck(PlayerColor player) const; //checks if given player is loser; -1 if std loss, 1 if special, 0 else
PlayerColor checkForStandardWin() const; //returns color of player that accomplished standard victory conditions or 255 (NEUTRAL) if no winner
bool checkForStandardLoss(PlayerColor player) const; //checks if given player lost the game
EVictoryLossCheckResult checkForVictoryAndLoss(PlayerColor player) const;
void obtainPlayersStats(SThievesGuildInfo & tgi, int level); //fills tgi with info about other players that is available at given level of thieves' guild
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > unusedHeroesFromPool(); //heroes pool without heroes that are available in taverns
BattleInfo * setupBattle(int3 tile, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town);
@ -438,6 +464,12 @@ public:
friend class IGameCallback;
friend class CMapHandler;
friend class CGameHandler;
private:
EVictoryLossCheckResult checkForVictory(PlayerColor player) const; //checks if given player is winner
EVictoryLossCheckResult checkForLoss(PlayerColor player) const; //checks if given player is loser
PlayerColor checkForStandardWin() const; //returns color of player that accomplished standard victory conditions or 255 (NEUTRAL) if no winner
bool checkForStandardLoss(PlayerColor player) const; //checks if given player lost the game
};
struct DLL_LINKAGE QuestInfo //universal interface for human and AI

View File

@ -45,6 +45,7 @@ struct BattleTriggerEffect;
class CComponent;
struct CObstacleInstance;
struct CPackForServer;
class EVictoryLossCheckResult;
class DLL_LINKAGE IBattleEventsReceiver
{
@ -128,7 +129,7 @@ public:
virtual void objectPropertyChanged(const SetObjectProperty * sop){}; //eg. mine has been flagged
virtual void objectRemoved(const CGObjectInstance *obj){}; //eg. collected resource, picked artifact, beaten hero
virtual void playerBlocked(int reason, bool start){}; //reason: 0 - upcoming battle
virtual void gameOver(PlayerColor player, bool victory){}; //player lost or won the game
virtual void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) {}; //player lost or won the game
virtual void playerStartsTurn(PlayerColor player){};
virtual void showComp(const Component &comp, std::string message) {}; //display component in the advmapint infobox

View File

@ -481,11 +481,11 @@ struct PlayerEndsGame : public CPackForClient //117
DLL_LINKAGE void applyGs(CGameState *gs);
PlayerColor player;
ui8 victory;
EVictoryLossCheckResult victoryLossCheckResult;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & player & victory;
h & player & victoryLossCheckResult;
}
};

View File

@ -274,7 +274,8 @@ DLL_LINKAGE void ChangeObjPos::applyGs( CGameState *gs )
DLL_LINKAGE void PlayerEndsGame::applyGs( CGameState *gs )
{
PlayerState *p = gs->getPlayer(player);
p->status = victory ? EPlayerStatus::WINNER : EPlayerStatus::LOSER;
if(victoryLossCheckResult.victory()) p->status = EPlayerStatus::WINNER;
else p->status = EPlayerStatus::LOSER;
}
DLL_LINKAGE void RemoveBonus::applyGs( CGameState *gs )

View File

@ -5057,7 +5057,6 @@ void CGameHandler::engageIntoBattle( PlayerColor player )
void CGameHandler::winLoseHandle(ui8 players )
{
for(size_t i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++)
{
if(players & 1<<i && gs->getPlayer(PlayerColor(i)))
@ -5070,27 +5069,24 @@ void CGameHandler::winLoseHandle(ui8 players )
void CGameHandler::checkLossVictory( PlayerColor player )
{
const PlayerState *p = gs->getPlayer(player);
if(p->status) //player already won / lost
return;
int loss = gs->lossCheck(player);
int vic = gs->victoryCheck(player);
if(!loss && !vic)
return;
if(p->status == EPlayerStatus::WINNER || p->status == EPlayerStatus::LOSER || p->status == EPlayerStatus::WRONG) return;
auto victoryLossCheckResult = gs->checkForVictoryAndLoss(player);
if(victoryLossCheckResult != EVictoryLossCheckResult::NO_VICTORY_OR_LOSS)
{
InfoWindow iw;
getLossVicMessage(player, vic ? vic : loss , vic, iw);
getVictoryLossMessage(player, victoryLossCheckResult, iw);
sendAndApply(&iw);
PlayerEndsGame peg;
peg.player = player;
peg.victory = vic;
peg.victoryLossCheckResult = victoryLossCheckResult;
sendAndApply(&peg);
if(vic) //one player won -> all enemies lost
if(victoryLossCheckResult.victory())
{
//one player won -> all enemies lost
iw.text.localStrings.front().second++; //message about losing because enemy won first is just after victory message
for (auto i = gs->players.cbegin(); i!=gs->players.cend(); i++)
@ -5101,28 +5097,13 @@ void CGameHandler::checkLossVictory( PlayerColor player )
sendAndApply(&iw);
peg.player = i->first;
peg.victory = gameState()->getPlayerRelations(player, i->first) == PlayerRelations::ALLIES; // ally of winner
peg.victoryLossCheckResult = gameState()->getPlayerRelations(player, i->first) == PlayerRelations::ALLIES ?
victoryLossCheckResult : EVictoryLossCheckResult::LOSS_STANDARD_HEROES_AND_TOWNS; // ally of winner
sendAndApply(&peg);
}
}
}
else //player lost -> all his objects become unflagged (neutral)
{
auto hlp = p->heroes;
for (auto i = hlp.cbegin(); i != hlp.cend(); i++) //eliminate heroes
removeObject(*i);
for (auto i = gs->map->objects.cbegin(); i != gs->map->objects.cend(); i++) //unflag objs
{
if(*i && (*i)->tempOwner == player)
setOwner(*i,PlayerColor::NEUTRAL);
}
//eliminating one player may cause victory of another:
winLoseHandle(GameConstants::ALL_PLAYERS & ~(1<<player.getNum()));
}
if(vic && p->human)
if(p->human)
{
end2 = true;
@ -5154,15 +5135,33 @@ void CGameHandler::checkLossVictory( PlayerColor player )
sendAndApply(&ucs);
}
}
}
else
{
//player lost -> all his objects become unflagged (neutral)
auto hlp = p->heroes;
for (auto i = hlp.cbegin(); i != hlp.cend(); i++) //eliminate heroes
removeObject(*i);
for (auto i = gs->map->objects.cbegin(); i != gs->map->objects.cend(); i++) //unflag objs
{
if(*i && (*i)->tempOwner == player)
setOwner(*i,PlayerColor::NEUTRAL);
}
//eliminating one player may cause victory of another:
winLoseHandle(GameConstants::ALL_PLAYERS & ~(1<<player.getNum()));
}
//If player making turn has lost his turn must be over as well
if(gs->getPlayer(gs->currentPlayer)->status != EPlayerStatus::INGAME)
{
states.setFlag(gs->currentPlayer, &PlayerStatus::makingTurn, false);
}
}
}
void CGameHandler::getLossVicMessage( PlayerColor player, si8 standard, bool victory, InfoWindow &out ) const
void CGameHandler::getVictoryLossMessage(PlayerColor player, EVictoryLossCheckResult victoryLossCheckResult, InfoWindow & out) const
{
// const PlayerState *p = gs->getPlayer(player);
// if(!p->human)
@ -5170,9 +5169,7 @@ void CGameHandler::getLossVicMessage( PlayerColor player, si8 standard, bool vic
out.player = player;
if(victory)
{
if(standard > 0) //not std loss
if(victoryLossCheckResult == EVictoryLossCheckResult::VICTORY_SPECIAL)
{
switch(gs->map->victoryCondition.condition)
{
@ -5226,14 +5223,17 @@ void CGameHandler::getLossVicMessage( PlayerColor player, si8 standard, bool vic
break;
}
}
else
else if(victoryLossCheckResult == EVictoryLossCheckResult::VICTORY_STANDARD)
{
out.text.addTxt(MetaString::GENERAL_TXT, 659); //Congratulations! You have reached your destination, precious cargo intact, and can claim victory!
out.text.addTxt(MetaString::GENERAL_TXT, 659); // Congratulations! All your enemies have been defeated! Victory is yours!
}
}
else
else if(victoryLossCheckResult == EVictoryLossCheckResult::LOSS_STANDARD_TOWNS_AND_TIME_OVER)
{
if(standard > 0) //not std loss
out.text.addTxt(MetaString::GENERAL_TXT, 7);//%s, your heroes abandon you, and you are banished from this land.
out.text.addReplacement(MetaString::COLOR, player.getNum());
out.components.push_back(Component(Component::FLAG, player.getNum(), 0, 0));
}
else if(victoryLossCheckResult == EVictoryLossCheckResult::LOSS_SPECIAL)
{
switch(gs->map->lossCondition.typeOfLossCon)
{
@ -5258,16 +5258,14 @@ void CGameHandler::getLossVicMessage( PlayerColor player, si8 standard, bool vic
break;
}
}
else if(standard == 2)
{
out.text.addTxt(MetaString::GENERAL_TXT, 7);//%s, your heroes abandon you, and you are banished from this land.
out.text.addReplacement(MetaString::COLOR, player.getNum());
out.components.push_back(Component(Component::FLAG, player.getNum(), 0, 0));
}
else //lost all towns and heroes
else if(victoryLossCheckResult == EVictoryLossCheckResult::LOSS_STANDARD_HEROES_AND_TOWNS)
{
out.text.addTxt(MetaString::GENERAL_TXT, 660); //All your forces have been defeated, and you are banished from this land!
}
else
{
assert(0);
logGlobal->warnStream() << "Unknown victory loss check result";
}
}

View File

@ -81,8 +81,6 @@ struct CasualtiesAfterBattle
class CGameHandler : public IGameCallback, CBattleInfoCallback
{
private:
void makeStackDoNothing(const CStack * next);
public:
//use enums as parameters, because doMove(sth, true, false, true) is not readable
enum EGuardLook {CHECK_FOR_GUARDS, IGNORE_GUARDS};
@ -110,7 +108,6 @@ public:
void runBattle();
void checkLossVictory(PlayerColor player);
void winLoseHandle(ui8 players=255); //players: bit field - colours of players to be checked; default: all
void getLossVicMessage(PlayerColor player, si8 standard, bool victory, InfoWindow &out) const;
////used only in endBattle - don't touch elsewhere
bool visitObjectAfterVictory;
@ -292,6 +289,10 @@ public:
void spawnWanderingMonsters(CreatureID creatureID);
friend class CVCMIServer;
friend class CScriptCallback;
private:
void makeStackDoNothing(const CStack * next);
void getVictoryLossMessage(PlayerColor player, EVictoryLossCheckResult victoryLossCheckResult, InfoWindow & out) const;
};
void makeStackDoNothing();