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:
parent
2b6cdd5f41
commit
3e4407593f
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 )
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 )
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user