mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +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();
|
||||
@ -959,13 +959,13 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, BuildingID building, unsi
|
||||
TResources currentRes = cb->getResourceAmount();
|
||||
TResources income = estimateIncome();
|
||||
//TODO: calculate if we have enough resources to build it in maxDays
|
||||
|
||||
for(const auto & buildID : toBuild)
|
||||
{
|
||||
const CBuilding *b = t->town->buildings.at(buildID);
|
||||
|
||||
EBuildingState::EBuildingState canBuild = cb->canBuildStructure(t, buildID);
|
||||
if(canBuild == EBuildingState::ALLOWED)
|
||||
|
||||
for(const auto & buildID : toBuild)
|
||||
{
|
||||
const CBuilding *b = t->town->buildings.at(buildID);
|
||||
|
||||
EBuildingState::EBuildingState canBuild = cb->canBuildStructure(t, buildID);
|
||||
if(canBuild == EBuildingState::ALLOWED)
|
||||
{
|
||||
if(!containsSavedRes(b->resources))
|
||||
{
|
||||
@ -974,13 +974,13 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, BuildingID building, unsi
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if(canBuild == EBuildingState::NO_RESOURCES)
|
||||
{
|
||||
TResources cost = t->town->buildings.at(buildID)->resources;
|
||||
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++)
|
||||
{
|
||||
int diff = currentRes[i] - cost[i] + income[i];
|
||||
}
|
||||
else if(canBuild == EBuildingState::NO_RESOURCES)
|
||||
{
|
||||
TResources cost = t->town->buildings.at(buildID)->resources;
|
||||
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++)
|
||||
{
|
||||
int diff = currentRes[i] - cost[i] + income[i];
|
||||
if(diff < 0)
|
||||
saving[i] = 1;
|
||||
}
|
||||
|
@ -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 )
|
||||
@ -409,30 +409,30 @@ void NewStructures::applyCl( CClient *cl )
|
||||
{
|
||||
CGTownInstance *town = GS(cl)->getTown(tid);
|
||||
for(const auto & id : bid)
|
||||
{
|
||||
if(id == BuildingID::CAPITOL) //fort or capitol
|
||||
{
|
||||
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->capitols.at(town->subID).get());
|
||||
}
|
||||
if(id == BuildingID::FORT)
|
||||
{
|
||||
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->gobjs.at(Obj::TOWN).at(town->subID).get());
|
||||
}
|
||||
if(vstd::contains(cl->playerint,town->tempOwner))
|
||||
cl->playerint[town->tempOwner]->buildChanged(town,id,1);
|
||||
{
|
||||
if(id == BuildingID::CAPITOL) //fort or capitol
|
||||
{
|
||||
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->capitols.at(town->subID).get());
|
||||
}
|
||||
if(id == BuildingID::FORT)
|
||||
{
|
||||
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->gobjs.at(Obj::TOWN).at(town->subID).get());
|
||||
}
|
||||
if(vstd::contains(cl->playerint,town->tempOwner))
|
||||
cl->playerint[town->tempOwner]->buildChanged(town,id,1);
|
||||
}
|
||||
}
|
||||
void RazeStructures::applyCl (CClient *cl)
|
||||
{
|
||||
CGTownInstance *town = GS(cl)->getTown(tid);
|
||||
for(const auto & id : bid)
|
||||
{
|
||||
if (id == BuildingID::CAPITOL) //fort or capitol
|
||||
{
|
||||
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->gobjs.at(Obj::TOWN).at(town->subID).get());
|
||||
}
|
||||
if(vstd::contains (cl->playerint,town->tempOwner))
|
||||
cl->playerint[town->tempOwner]->buildChanged (town,id,2);
|
||||
{
|
||||
if (id == BuildingID::CAPITOL) //fort or capitol
|
||||
{
|
||||
town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->gobjs.at(Obj::TOWN).at(town->subID).get());
|
||||
}
|
||||
if(vstd::contains (cl->playerint,town->tempOwner))
|
||||
cl->playerint[town->tempOwner]->buildChanged (town,id,2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -532,13 +532,13 @@ void InfoWindow::applyCl( CClient *cl )
|
||||
comps.push_back(&elem);
|
||||
}
|
||||
std::string str;
|
||||
text.toString(str);
|
||||
|
||||
if(vstd::contains(cl->playerint,player))
|
||||
cl->playerint.at(player)->showInfoDialog(str,comps,(soundBase::soundID)soundID);
|
||||
else
|
||||
logNetwork->warnStream() << "We received InfoWindow for not our player...";
|
||||
}
|
||||
text.toString(str);
|
||||
|
||||
if(vstd::contains(cl->playerint,player))
|
||||
cl->playerint.at(player)->showInfoDialog(str,comps,(soundBase::soundID)soundID);
|
||||
else
|
||||
logNetwork->warnStream() << "We received InfoWindow for not our player...";
|
||||
}
|
||||
|
||||
void SetObjectProperty::applyCl( CClient *cl )
|
||||
{
|
||||
@ -575,26 +575,26 @@ void CommanderLevelUp::applyCl( CClient *cl )
|
||||
void BlockingDialog::applyCl( CClient *cl )
|
||||
{
|
||||
std::string str;
|
||||
text.toString(str);
|
||||
|
||||
if(vstd::contains(cl->playerint,player))
|
||||
cl->playerint.at(player)->showBlockingDialog(str,components,queryID,(soundBase::soundID)soundID,selection(),cancel());
|
||||
else
|
||||
logNetwork->warnStream() << "We received YesNoDialog for not our player...";
|
||||
}
|
||||
text.toString(str);
|
||||
|
||||
if(vstd::contains(cl->playerint,player))
|
||||
cl->playerint.at(player)->showBlockingDialog(str,components,queryID,(soundBase::soundID)soundID,selection(),cancel());
|
||||
else
|
||||
logNetwork->warnStream() << "We received YesNoDialog for not our player...";
|
||||
}
|
||||
|
||||
void GarrisonDialog::applyCl(CClient *cl)
|
||||
{
|
||||
const CGHeroInstance *h = cl->getHero(hid);
|
||||
const CArmedInstance *obj = static_cast<const CArmedInstance*>(cl->getObj(objid));
|
||||
|
||||
if(!vstd::contains(cl->playerint,h->getOwner()))
|
||||
return;
|
||||
|
||||
cl->playerint.at(h->getOwner())->showGarrisonDialog(obj,h,removableUnits,queryID);
|
||||
}
|
||||
|
||||
void ExchangeDialog::applyCl(CClient *cl)
|
||||
if(!vstd::contains(cl->playerint,h->getOwner()))
|
||||
return;
|
||||
|
||||
cl->playerint.at(h->getOwner())->showGarrisonDialog(obj,h,removableUnits,queryID);
|
||||
}
|
||||
|
||||
void ExchangeDialog::applyCl(CClient *cl)
|
||||
{
|
||||
assert(heroes[0] && heroes[1]);
|
||||
INTERFACE_CALL_IF_PRESENT(heroes[0]->tempOwner, heroExchangeStarted, heroes[0]->id, heroes[1]->id, queryID);
|
||||
@ -945,13 +945,13 @@ void SetAvailableArtifacts::applyCl(CClient *cl)
|
||||
INTERFACE_CALL_IF_PRESENT(cl->getTile(bm->visitablePos())->visitableObjects.back()->tempOwner, availableArtifactsChanged, bm);
|
||||
}
|
||||
}
|
||||
|
||||
void TradeComponents::applyCl(CClient *cl)
|
||||
{///Shop handler
|
||||
switch (CGI->mh->map->objects.at(objectid)->ID)
|
||||
{
|
||||
case Obj::BLACK_MARKET:
|
||||
break;
|
||||
|
||||
void TradeComponents::applyCl(CClient *cl)
|
||||
{///Shop handler
|
||||
switch (CGI->mh->map->objects.at(objectid)->ID)
|
||||
{
|
||||
case Obj::BLACK_MARKET:
|
||||
break;
|
||||
case Obj::TAVERN:
|
||||
break;
|
||||
case Obj::DEN_OF_THIEVES:
|
||||
|
@ -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,27 +356,55 @@ 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:
|
||||
ConstTransitivePtr<StartInfo> scenarioOps, initialOpts; //second one is a copy of settings received from pregame (not randomized)
|
||||
PlayerColor currentPlayer; //ID of player currently having turn
|
||||
ConstTransitivePtr<BattleInfo> curB; //current battle
|
||||
ui32 day; //total number of days in game
|
||||
ConstTransitivePtr<CMap> map;
|
||||
std::map<PlayerColor, PlayerState> players;
|
||||
std::map<TeamID, TeamState> teams;
|
||||
CBonusSystemNode globalEffects;
|
||||
|
||||
struct DLL_LINKAGE HeroesPool
|
||||
{
|
||||
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > heroesPool; //[subID] - heroes available to buy; nullptr if not available
|
||||
std::map<ui32,ui8> pavailable; // [subid] -> which players can recruit hero (binary flags)
|
||||
|
||||
CGHeroInstance * pickHeroFor(bool native, PlayerColor player, const CTown *town, std::map<ui32, ConstTransitivePtr<CGHeroInstance> > &available, const CHeroClass *bannedClass = nullptr) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
ConstTransitivePtr<BattleInfo> curB; //current battle
|
||||
ui32 day; //total number of days in game
|
||||
ConstTransitivePtr<CMap> map;
|
||||
std::map<PlayerColor, PlayerState> players;
|
||||
std::map<TeamID, TeamState> teams;
|
||||
CBonusSystemNode globalEffects;
|
||||
|
||||
struct DLL_LINKAGE HeroesPool
|
||||
{
|
||||
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > heroesPool; //[subID] - heroes available to buy; nullptr if not available
|
||||
std::map<ui32,ui8> pavailable; // [subid] -> which players can recruit hero (binary flags)
|
||||
|
||||
CGHeroInstance * pickHeroFor(bool native, PlayerColor player, const CTown *town, std::map<ui32, ConstTransitivePtr<CGHeroInstance> > &available, const CHeroClass *bannedClass = nullptr) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & heroesPool & pavailable;
|
||||
}
|
||||
} hpool; //we have here all heroes available on this map that are not hired
|
||||
@ -404,15 +432,13 @@ 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
|
||||
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);
|
||||
|
||||
void buildBonusSystemTree();
|
||||
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);
|
||||
|
||||
void buildBonusSystemTree();
|
||||
void attachArmedObjects();
|
||||
void buildGlobalTeamPlayerTree();
|
||||
void deserializationFix();
|
||||
@ -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 )
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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…
Reference in New Issue
Block a user