mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
- Refactored victory loss condition checks
- Added toString() method to EVictoryLossCheckResult enum class to improve debugging - Removed mostly unused CFunctionList2 - Added missing header files for vcmiclient project to CMakeLists - Tweaked SDL suggests bpp message a bit - Added showInfoDialogAndWait (info dialog and waits, used from client thread) and showOkDialog (callback to ok click, used from GUI thread) to player interface - Added showOkDialog method to CInfoWindow (unused for now, but may be used later)
This commit is contained in:
parent
2f698acf98
commit
c786a3076a
@ -752,10 +752,10 @@ static void setScreenRes(int w, int h, int bpp, bool fullscreen, bool resetVideo
|
||||
}
|
||||
|
||||
bool bufOnScreen = (screenBuf == screen);
|
||||
|
||||
|
||||
if(suggestedBpp != bpp)
|
||||
{
|
||||
logGlobal->warnStream() << "Note: SDL suggests to use " << suggestedBpp << " bpp instead of" << bpp << " bpp ";
|
||||
logGlobal->infoStream() << boost::format("Using %s bpp (bits per pixel) for the video mode. Default or overriden setting was %s bpp.") % suggestedBpp % bpp;
|
||||
}
|
||||
|
||||
//For some reason changing fullscreen via config window checkbox result in SDL_Quit event
|
||||
|
@ -6,17 +6,13 @@ include_directories(${SDL_INCLUDE_DIR} ${SDLIMAGE_INCLUDE_DIR} ${SDLMIXER_INCLUD
|
||||
include_directories(${Boost_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR} ${FFMPEG_INCLUDE_DIRS})
|
||||
|
||||
set(client_SRCS
|
||||
CPreGame.cpp
|
||||
Client.cpp
|
||||
CPlayerInterface.cpp
|
||||
CMT.cpp
|
||||
GUIClasses.cpp
|
||||
battle/CBattleInterface.cpp
|
||||
|
||||
../CCallback.cpp
|
||||
|
||||
battle/CBattleInterface.cpp
|
||||
battle/CBattleAnimations.cpp
|
||||
battle/CBattleInterfaceClasses.cpp
|
||||
battle/CCreatureAnimation.cpp
|
||||
|
||||
gui/CGuiHandler.cpp
|
||||
gui/CIntObject.cpp
|
||||
gui/CIntObjectClasses.cpp
|
||||
@ -24,6 +20,12 @@ set(client_SRCS
|
||||
gui/Geometries.cpp
|
||||
gui/CCursorHandler.cpp
|
||||
gui/SDL_Extensions.cpp
|
||||
|
||||
CPreGame.cpp
|
||||
Client.cpp
|
||||
CPlayerInterface.cpp
|
||||
CMT.cpp
|
||||
GUIClasses.cpp
|
||||
AdventureMapClasses.cpp
|
||||
CAdvmapInterface.cpp
|
||||
CAnimation.cpp
|
||||
@ -44,15 +46,22 @@ set(client_SRCS
|
||||
NetPacksClient.cpp
|
||||
)
|
||||
|
||||
set(client_HEADERS
|
||||
CSoundBase.h
|
||||
FunctionList.h
|
||||
|
||||
gui/SDL_Pixels.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
add_executable(vcmiclient WIN32 ${client_SRCS})
|
||||
add_executable(vcmiclient WIN32 ${client_SRCS} ${client_HEADERS})
|
||||
elseif(APPLE)
|
||||
# OS X specific includes
|
||||
include_directories(${SPARKLE_INCLUDE_DIR})
|
||||
|
||||
# OS X specific source files
|
||||
set(client_SRCS ${client_SRCS} SDLMain.m OSX.mm Info.plist vcmi.icns ../osx/vcmi_dsa_public.pem)
|
||||
add_executable(vcmiclient MACOSX_BUNDLE ${client_SRCS})
|
||||
add_executable(vcmiclient MACOSX_BUNDLE ${client_SRCS} ${client_HEADERS})
|
||||
|
||||
# OS X specific libraries
|
||||
target_link_libraries(vcmiclient ${SPARKLE_FRAMEWORK})
|
||||
@ -93,7 +102,7 @@ elseif(APPLE)
|
||||
|
||||
add_custom_command(TARGET vcmiclient POST_BUILD COMMAND ${MakeVCMIBundle})
|
||||
else()
|
||||
add_executable(vcmiclient ${client_SRCS})
|
||||
add_executable(vcmiclient ${client_SRCS} ${client_HEADERS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(vcmiclient vcmi ${Boost_LIBRARIES} ${SDL_LIBRARY} ${SDLIMAGE_LIBRARY} ${SDLMIXER_LIBRARY} ${SDLTTF_LIBRARY} ${ZLIB_LIBRARIES} ${FFMPEG_LIBRARIES} ${RT_LIB} ${DL_LIB})
|
||||
|
@ -1022,6 +1022,21 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::showInfoDialogAndWait(std::vector<Component> & components, const MetaString & text)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
std::vector<Component*> comps;
|
||||
for(auto & elem : components)
|
||||
{
|
||||
comps.push_back(&elem);
|
||||
}
|
||||
std::string str;
|
||||
text.toString(str);
|
||||
|
||||
showInfoDialog(str,comps, 0);
|
||||
waitWhileDialog();
|
||||
}
|
||||
|
||||
void CPlayerInterface::showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool DelComps, const std::vector<CComponent*> & components)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||
@ -1031,6 +1046,27 @@ void CPlayerInterface::showYesNoDialog(const std::string &text, CFunctionList<vo
|
||||
CInfoWindow::showYesNoDialog(text, &components, onYes, onNo, DelComps, playerID);
|
||||
}
|
||||
|
||||
void CPlayerInterface::showOkDialog(std::vector<Component> & components, const MetaString & text, const boost::function<void()> & onOk)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||
|
||||
std::vector<Component*> comps;
|
||||
for(auto & elem : components)
|
||||
{
|
||||
comps.push_back(&elem);
|
||||
}
|
||||
std::string str;
|
||||
text.toString(str);
|
||||
|
||||
stopMovement();
|
||||
showingDialog->setn(true);
|
||||
|
||||
std::vector<CComponent*> intComps;
|
||||
for(auto & component : comps)
|
||||
intComps.push_back(new CComponent(*component));
|
||||
CInfoWindow::showOkDialog(str, &intComps, onOk, true, playerID);
|
||||
}
|
||||
|
||||
void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector<Component> &components, QueryID askID, int soundID, bool selection, bool cancel )
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
@ -2251,6 +2287,31 @@ void CPlayerInterface::acceptTurn()
|
||||
|
||||
adventureInt->endTurn.callback();
|
||||
}
|
||||
|
||||
// warn player if he has no town
|
||||
if(cb->howManyTowns() == 0)
|
||||
{
|
||||
auto playerColor = *cb->getPlayerID();
|
||||
|
||||
std::vector<Component> components;
|
||||
components.push_back(Component(Component::FLAG, playerColor.getNum(), 0, 0));
|
||||
MetaString text;
|
||||
|
||||
auto daysWithoutCastle = cb->getPlayer(playerColor)->daysWithoutCastle;
|
||||
if(daysWithoutCastle == 6)
|
||||
{
|
||||
text.addTxt(MetaString::ARRAY_TXT,129); //%s, this is your last day to capture a town or you will be banished from this land.
|
||||
text.addReplacement(MetaString::COLOR, playerColor.getNum());
|
||||
}
|
||||
else
|
||||
{
|
||||
text.addTxt(MetaString::ARRAY_TXT,128); //%s, you only have %d days left to capture a town or you will be banished from this land.
|
||||
text.addReplacement(MetaString::COLOR, playerColor.getNum());
|
||||
text.addReplacement(7 - daysWithoutCastle);
|
||||
}
|
||||
|
||||
showInfoDialogAndWait(components, text);
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::tryDiggging(const CGHeroInstance *h)
|
||||
|
@ -229,9 +229,14 @@ public:
|
||||
void updateInfo(const CGObjectInstance * specific);
|
||||
void init(shared_ptr<CCallback> CB);
|
||||
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
|
||||
|
||||
// show dialogs
|
||||
void showInfoDialog(const std::string &text, CComponent * component);
|
||||
void showInfoDialog(const std::string &text, const std::vector<CComponent*> & components = std::vector<CComponent*>(), int soundID = 0, bool delComps = false);
|
||||
void showInfoDialogAndWait(std::vector<Component> & components, const MetaString & text);
|
||||
void showOkDialog(std::vector<Component> & components, const MetaString & text, const boost::function<void()> & onOk);
|
||||
void showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool DelComps = false, const std::vector<CComponent*> & components = std::vector<CComponent*>()); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close
|
||||
|
||||
void stopMovement();
|
||||
bool moveHero(const CGHeroInstance *h, CGPath path);
|
||||
void initMovement(const TryMoveHero &details, const CGHeroInstance * ho, const int3 &hp );//initializing objects and performing first step of move
|
||||
|
@ -83,48 +83,3 @@ public:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
class CFunctionList2
|
||||
{
|
||||
public:
|
||||
std::vector<boost::function<Signature> > funcs;
|
||||
|
||||
CFunctionList2(int){};
|
||||
CFunctionList2(){};
|
||||
template <typename Functor>
|
||||
CFunctionList2(const Functor &f)
|
||||
{
|
||||
funcs.push_back(boost::function<Signature>(f));
|
||||
}
|
||||
CFunctionList2(const boost::function<Signature> &first)
|
||||
{
|
||||
funcs.push_back(first);
|
||||
}
|
||||
CFunctionList2(boost::function<Signature> &first)
|
||||
{
|
||||
funcs.push_back(first);
|
||||
}
|
||||
CFunctionList2 & operator+=(const boost::function<Signature> &first)
|
||||
{
|
||||
funcs.push_back(first);
|
||||
return *this;
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
funcs.clear();
|
||||
}
|
||||
operator bool() const
|
||||
{
|
||||
return funcs.size();
|
||||
}
|
||||
template <typename Arg>
|
||||
void operator()(const Arg & a) const
|
||||
{
|
||||
std::vector<boost::function<Signature> > funcs2 = funcs; //backup
|
||||
for(size_t i=0;i<funcs2.size(); ++i)
|
||||
{
|
||||
funcs2[i](a);
|
||||
}
|
||||
}
|
||||
};
|
@ -742,6 +742,16 @@ void CInfoWindow::showYesNoDialog(const std::string & text, const std::vector<CC
|
||||
GH.pushInt(temp);
|
||||
}
|
||||
|
||||
void CInfoWindow::showOkDialog(const std::string & text, const std::vector<CComponent*> *components, const boost::function<void()> & onOk, bool delComps, PlayerColor player)
|
||||
{
|
||||
std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
|
||||
pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
|
||||
CInfoWindow * temp = new CInfoWindow(text, player, *components, pom, delComps);
|
||||
temp->buttons[0]->callback += onOk;
|
||||
|
||||
GH.pushInt(temp);
|
||||
}
|
||||
|
||||
CInfoWindow * CInfoWindow::create(const std::string &text, PlayerColor playerID /*= 1*/, const std::vector<CComponent*> *components /*= nullptr*/, bool DelComps)
|
||||
{
|
||||
std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
|
||||
|
@ -106,6 +106,7 @@ public:
|
||||
|
||||
//use only before the game starts! (showYesNoDialog in LOCPLINT must be used then)
|
||||
static void showInfoDialog( const std::string & text, const std::vector<CComponent*> *components, bool DelComps = true, PlayerColor player = PlayerColor(1));
|
||||
static void showOkDialog(const std::string & text, const std::vector<CComponent*> *components, const boost::function<void()> & onOk, bool delComps = true, PlayerColor player = PlayerColor(1));
|
||||
static void showYesNoDialog( const std::string & text, const std::vector<CComponent*> *components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, bool DelComps = true, PlayerColor player = PlayerColor(1));
|
||||
static CInfoWindow *create(const std::string &text, PlayerColor playerID = PlayerColor(1), const std::vector<CComponent*> *components = nullptr, bool DelComps = false);
|
||||
|
||||
|
@ -534,7 +534,7 @@ void CHighlightableButtonsGroup::addButton(const std::map<int,std::string> &tool
|
||||
buttons.push_back(bt);
|
||||
}
|
||||
|
||||
CHighlightableButtonsGroup::CHighlightableButtonsGroup(const CFunctionList2<void(int)> &OnChange, bool musicLikeButtons)
|
||||
CHighlightableButtonsGroup::CHighlightableButtonsGroup(const CFunctionList<void(int)> &OnChange, bool musicLikeButtons)
|
||||
: onChange(OnChange), musicLike(musicLikeButtons)
|
||||
{}
|
||||
|
||||
|
@ -171,14 +171,14 @@ public:
|
||||
class CHighlightableButtonsGroup : public CIntObject
|
||||
{
|
||||
public:
|
||||
CFunctionList2<void(int)> onChange; //called when changing selected button with new button's id
|
||||
CFunctionList<void(int)> onChange; //called when changing selected button with new button's id
|
||||
std::vector<CHighlightableButton*> buttons;
|
||||
bool musicLike; //determines the behaviour of this group
|
||||
|
||||
//void addButton(const std::map<int,std::string> &tooltip, const std::string &HelpBox, const std::string &defName, int x, int y, int uid);
|
||||
void addButton(CHighlightableButton* bt);//add existing button, it'll be deleted by CHighlightableButtonsGroup destructor
|
||||
void addButton(const std::map<int,std::string> &tooltip, const std::string &HelpBox, const std::string &defName, int x, int y, int uid, const CFunctionList<void()> &OnSelect=0, int key=0); //creates new button
|
||||
CHighlightableButtonsGroup(const CFunctionList2<void(int)> &OnChange, bool musicLikeButtons = false);
|
||||
CHighlightableButtonsGroup(const CFunctionList<void(int)> & OnChange, bool musicLikeButtons = false);
|
||||
~CHighlightableButtonsGroup();
|
||||
void select(int id, bool mode); //mode==0: id is serial; mode==1: id is unique button id
|
||||
void selectionChanged(int to);
|
||||
|
@ -3327,15 +3327,19 @@ bool EVictoryLossCheckResult::loss() const
|
||||
return !victory();
|
||||
}
|
||||
|
||||
std::string EVictoryLossCheckResult::toString() const
|
||||
{
|
||||
if(*this == EVictoryLossCheckResult::NO_VICTORY_OR_LOSS) return "No victory or loss";
|
||||
else if(*this == EVictoryLossCheckResult::VICTORY_STANDARD) return "Victory standard";
|
||||
else if(*this == EVictoryLossCheckResult::VICTORY_SPECIAL) return "Victory special";
|
||||
else if(*this == EVictoryLossCheckResult::LOSS_STANDARD_HEROES_AND_TOWNS) return "Loss standard heroes and towns";
|
||||
else if(*this == EVictoryLossCheckResult::LOSS_STANDARD_TOWNS_AND_TIME_OVER) return "Loss standard towns and time over";
|
||||
else if(*this == EVictoryLossCheckResult::LOSS_SPECIAL) return "Loss special";
|
||||
else return "Unknown type";
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
os << victoryLossCheckResult.toString();
|
||||
return os;
|
||||
}
|
||||
|
@ -371,6 +371,7 @@ public:
|
||||
bool operator!=(EVictoryLossCheckResult const & other) const;
|
||||
bool victory() const;
|
||||
bool loss() const;
|
||||
std::string toString() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
|
||||
#include "BattleHex.h"
|
||||
#include "../client/FunctionList.h"
|
||||
#include "ResourceSet.h"
|
||||
#include "int3.h"
|
||||
#include "GameConstants.h"
|
||||
|
@ -685,7 +685,9 @@ void CGameHandler::battleAfterLevelUp( const BattleResult &result )
|
||||
}
|
||||
visitObjectAfterVictory = false;
|
||||
|
||||
winLoseHandle(1<<finishingBattle->loser.getNum() | 1<<finishingBattle->victor.getNum()); //handle victory/loss of engaged players
|
||||
//handle victory/loss of engaged players
|
||||
std::set<PlayerColor> playerColors = boost::assign::list_of(finishingBattle->loser)(finishingBattle->victor);
|
||||
checkVictoryLossConditions(playerColors);
|
||||
|
||||
if(result.result == BattleResult::SURRENDER || result.result == BattleResult::ESCAPE) //loser has escaped or surrendered
|
||||
{
|
||||
@ -1411,39 +1413,7 @@ void CGameHandler::newTurn()
|
||||
elem->newTurn();
|
||||
}
|
||||
|
||||
winLoseHandle(0xff);
|
||||
|
||||
//warn players without town
|
||||
if(gs->day)
|
||||
{
|
||||
for (auto i=gs->players.cbegin() ; i!=gs->players.cend();i++)
|
||||
{
|
||||
if(i->second.status || i->second.towns.size() || i->second.color >= PlayerColor::PLAYER_LIMIT)
|
||||
continue;
|
||||
|
||||
InfoWindow iw;
|
||||
iw.player = i->first;
|
||||
iw.components.push_back(Component(Component::FLAG, i->first.getNum(), 0, 0));
|
||||
|
||||
if(!i->second.daysWithoutCastle)
|
||||
{
|
||||
iw.text.addTxt(MetaString::GENERAL_TXT,6); //%s, you have lost your last town. If you do not conquer another town in the next week, you will be eliminated.
|
||||
iw.text.addReplacement(MetaString::COLOR, i->first.getNum());
|
||||
}
|
||||
else if(i->second.daysWithoutCastle == 6)
|
||||
{
|
||||
iw.text.addTxt(MetaString::ARRAY_TXT,129); //%s, this is your last day to capture a town or you will be banished from this land.
|
||||
iw.text.addReplacement(MetaString::COLOR, i->first.getNum());
|
||||
}
|
||||
else
|
||||
{
|
||||
iw.text.addTxt(MetaString::ARRAY_TXT,128); //%s, you only have %d days left to capture a town or you will be banished from this land.
|
||||
iw.text.addReplacement(MetaString::COLOR, i->first.getNum());
|
||||
iw.text.addReplacement(7 - i->second.daysWithoutCastle);
|
||||
}
|
||||
sendAndApply(&iw);
|
||||
}
|
||||
}
|
||||
checkVictoryLossConditionsForAll();
|
||||
|
||||
synchronizeArtifactHandlerLists(); //new day events may have changed them. TODO better of managing that
|
||||
}
|
||||
@ -1515,27 +1485,21 @@ void CGameHandler::run(bool resume)
|
||||
resume = false;
|
||||
for(; i != gs->players.end(); i++)
|
||||
{
|
||||
if((i->second.towns.size()==0 && i->second.heroes.size()==0)
|
||||
|| i->first>=PlayerColor::PLAYER_LIMIT
|
||||
|| i->second.status)
|
||||
if(i->second.status == EPlayerStatus::INGAME)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
states.setFlag(i->first,&PlayerStatus::makingTurn,true);
|
||||
states.setFlag(i->first,&PlayerStatus::makingTurn,true);
|
||||
|
||||
{
|
||||
YourTurn yt;
|
||||
yt.player = i->first;
|
||||
applyAndSend(&yt);
|
||||
}
|
||||
|
||||
//wait till turn is done
|
||||
boost::unique_lock<boost::mutex> lock(states.mx);
|
||||
while(states.players.at(i->first).makingTurn && !end2)
|
||||
{
|
||||
static time_duration p = milliseconds(200);
|
||||
states.cv.timed_wait(lock,p);
|
||||
|
||||
//wait till turn is done
|
||||
boost::unique_lock<boost::mutex> lock(states.mx);
|
||||
while(states.players.at(i->first).makingTurn && !end2)
|
||||
{
|
||||
static time_duration p = milliseconds(200);
|
||||
states.cv.timed_wait(lock,p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1608,7 +1572,7 @@ bool CGameHandler::removeObject( const CGObjectInstance * obj )
|
||||
ro.id = obj->id;
|
||||
sendAndApply(&ro);
|
||||
|
||||
winLoseHandle(255); //eg if monster escaped (removing objs after battle is done dircetly by endBattle, not this function)
|
||||
checkVictoryLossConditionsForAll(); //eg if monster escaped (removing objs after battle is done dircetly by endBattle, not this function)
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1811,7 +1775,9 @@ void CGameHandler::setOwner(const CGObjectInstance * obj, PlayerColor owner)
|
||||
SetObjectProperty sop(obj->id, 1, owner.getNum());
|
||||
sendAndApply(&sop);
|
||||
|
||||
winLoseHandle(1<<owner.getNum() | 1<<oldOwner.getNum());
|
||||
std::set<PlayerColor> playerColors = boost::assign::list_of(owner)(oldOwner);
|
||||
checkVictoryLossConditions(playerColors);
|
||||
|
||||
if(owner < PlayerColor::PLAYER_LIMIT && dynamic_cast<const CGTownInstance *>(obj)) //town captured
|
||||
{
|
||||
const CGTownInstance * town = dynamic_cast<const CGTownInstance *>(obj);
|
||||
@ -1933,7 +1899,7 @@ void CGameHandler::heroVisitCastle(const CGTownInstance * obj, const CGHeroInsta
|
||||
giveSpells (obj, hero);
|
||||
|
||||
if(gs->map->victoryCondition.condition == EVictoryConditionType::TRANSPORTITEM)
|
||||
checkLossVictory(hero->tempOwner); //transported artifact?
|
||||
checkVictoryLossConditionsForPlayer(hero->tempOwner); //transported artifact?
|
||||
}
|
||||
|
||||
void CGameHandler::vistiCastleObjects (const CGTownInstance *t, const CGHeroInstance *h)
|
||||
@ -2178,28 +2144,28 @@ void CGameHandler::sendAndApply(CGarrisonOperationPack * info)
|
||||
{
|
||||
sendAndApply(static_cast<CPackForClient*>(info));
|
||||
if(gs->map->victoryCondition.condition == EVictoryConditionType::GATHERTROOP)
|
||||
winLoseHandle();
|
||||
checkVictoryLossConditionsForAll();
|
||||
}
|
||||
|
||||
void CGameHandler::sendAndApply( SetResource * info )
|
||||
{
|
||||
sendAndApply(static_cast<CPackForClient*>(info));
|
||||
if(gs->map->victoryCondition.condition == EVictoryConditionType::GATHERRESOURCE)
|
||||
checkLossVictory(info->player);
|
||||
checkVictoryLossConditionsForPlayer(info->player);
|
||||
}
|
||||
|
||||
void CGameHandler::sendAndApply( SetResources * info )
|
||||
{
|
||||
sendAndApply(static_cast<CPackForClient*>(info));
|
||||
if(gs->map->victoryCondition.condition == EVictoryConditionType::GATHERRESOURCE)
|
||||
checkLossVictory(info->player);
|
||||
checkVictoryLossConditionsForPlayer(info->player);
|
||||
}
|
||||
|
||||
void CGameHandler::sendAndApply( NewStructures * info )
|
||||
{
|
||||
sendAndApply(static_cast<CPackForClient*>(info));
|
||||
if(gs->map->victoryCondition.condition == EVictoryConditionType::BUILDCITY)
|
||||
checkLossVictory(getTown(info->tid)->tempOwner);
|
||||
checkVictoryLossConditionsForPlayer(getTown(info->tid)->tempOwner);
|
||||
}
|
||||
|
||||
void CGameHandler::save(const std::string & filename )
|
||||
@ -2525,7 +2491,7 @@ bool CGameHandler::buildStructure( ObjectInstanceID tid, BuildingID requestedID,
|
||||
if(t->garrisonHero)
|
||||
vistiCastleObjects (t, t->garrisonHero);
|
||||
|
||||
checkLossVictory(t->tempOwner);
|
||||
checkVictoryLossConditionsForPlayer(t->tempOwner);
|
||||
return true;
|
||||
}
|
||||
bool CGameHandler::razeStructure (ObjectInstanceID tid, BuildingID bid)
|
||||
@ -3927,7 +3893,7 @@ void CGameHandler::playerMessage( PlayerColor player, const std::string &message
|
||||
{
|
||||
SystemMessage temp_message(VLC->generaltexth->allTexts.at(260));
|
||||
sendAndApply(&temp_message);
|
||||
checkLossVictory(player);//Player enter win code or got required art\creature
|
||||
checkVictoryLossConditionsForPlayer(player);//Player enter win code or got required art\creature
|
||||
}
|
||||
}
|
||||
|
||||
@ -5055,21 +5021,28 @@ void CGameHandler::engageIntoBattle( PlayerColor player )
|
||||
sendAndApply(&pb);
|
||||
}
|
||||
|
||||
void CGameHandler::winLoseHandle(ui8 players )
|
||||
void CGameHandler::checkVictoryLossConditions(const std::set<PlayerColor> & playerColors)
|
||||
{
|
||||
for(size_t i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++)
|
||||
for(auto playerColor : playerColors)
|
||||
{
|
||||
if(players & 1<<i && gs->getPlayer(PlayerColor(i)))
|
||||
{
|
||||
checkLossVictory(PlayerColor(i));
|
||||
}
|
||||
if(gs->getPlayer(playerColor)) checkVictoryLossConditionsForPlayer(playerColor);
|
||||
}
|
||||
}
|
||||
|
||||
void CGameHandler::checkLossVictory( PlayerColor player )
|
||||
void CGameHandler::checkVictoryLossConditionsForAll()
|
||||
{
|
||||
std::set<PlayerColor> playerColors;
|
||||
for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; ++i)
|
||||
{
|
||||
playerColors.insert(PlayerColor(i));
|
||||
}
|
||||
checkVictoryLossConditions(playerColors);
|
||||
}
|
||||
|
||||
void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
|
||||
{
|
||||
const PlayerState *p = gs->getPlayer(player);
|
||||
if(p->status == EPlayerStatus::WINNER || p->status == EPlayerStatus::LOSER || p->status == EPlayerStatus::WRONG) return;
|
||||
if(p->status != EPlayerStatus::INGAME) return;
|
||||
|
||||
auto victoryLossCheckResult = gs->checkForVictoryAndLoss(player);
|
||||
|
||||
@ -5091,7 +5064,7 @@ void CGameHandler::checkLossVictory( PlayerColor player )
|
||||
|
||||
for (auto i = gs->players.cbegin(); i!=gs->players.cend(); i++)
|
||||
{
|
||||
if(i->first < PlayerColor::PLAYER_LIMIT && i->first != player)//FIXME: skip already eliminated players?
|
||||
if(i->first != player && gs->getPlayer(i->first)->status == EPlayerStatus::INGAME)
|
||||
{
|
||||
iw.player = i->first;
|
||||
sendAndApply(&iw);
|
||||
@ -5150,7 +5123,13 @@ void CGameHandler::checkLossVictory( PlayerColor player )
|
||||
}
|
||||
|
||||
//eliminating one player may cause victory of another:
|
||||
winLoseHandle(GameConstants::ALL_PLAYERS & ~(1<<player.getNum()));
|
||||
std::set<PlayerColor> playerColors;
|
||||
for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; ++i)
|
||||
{
|
||||
if(player.getNum() != i) playerColors.insert(PlayerColor(i));
|
||||
}
|
||||
|
||||
checkVictoryLossConditions(playerColors);
|
||||
}
|
||||
|
||||
//If player making turn has lost his turn must be over as well
|
||||
|
@ -106,8 +106,6 @@ public:
|
||||
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
|
||||
int moveStack(int stack, BattleHex dest); //returned value - travelled distance
|
||||
void runBattle();
|
||||
void checkLossVictory(PlayerColor player);
|
||||
void winLoseHandle(ui8 players=255); //players: bit field - colours of players to be checked; default: all
|
||||
|
||||
////used only in endBattle - don't touch elsewhere
|
||||
bool visitObjectAfterVictory;
|
||||
@ -293,6 +291,11 @@ public:
|
||||
private:
|
||||
void makeStackDoNothing(const CStack * next);
|
||||
void getVictoryLossMessage(PlayerColor player, EVictoryLossCheckResult victoryLossCheckResult, InfoWindow & out) const;
|
||||
|
||||
// Check for victory and loss conditions
|
||||
void checkVictoryLossConditionsForPlayer(PlayerColor player);
|
||||
void checkVictoryLossConditions(const std::set<PlayerColor> & playerColors);
|
||||
void checkVictoryLossConditionsForAll();
|
||||
};
|
||||
|
||||
void makeStackDoNothing();
|
||||
|
Loading…
Reference in New Issue
Block a user