2017-07-13 10:26:03 +02:00
/*
* CGameState . h , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
2011-12-14 00:23:17 +03:00
# pragma once
2010-12-20 23:22:53 +02:00
# include "CCreatureHandler.h"
2009-05-20 13:08:56 +03:00
# include "VCMI_Lib.h"
2010-05-02 21:20:26 +03:00
2010-02-10 04:56:00 +02:00
# include "HeroBonus.h"
2010-05-02 21:20:26 +03:00
# include "CCreatureSet.h"
2010-12-20 15:04:24 +02:00
# include "ConstTransitivePtr.h"
2011-05-10 01:20:47 +03:00
# include "IGameCallback.h"
2011-07-05 09:14:07 +03:00
# include "ResourceSet.h"
2011-12-14 00:23:17 +03:00
# include "int3.h"
2014-03-17 22:51:07 +03:00
# include "CRandomGenerator.h"
2014-06-25 17:11:07 +03:00
# include "CGameStateFwd.h"
2015-10-27 02:34:47 +02:00
# include "CPathfinder.h"
2010-05-02 21:20:26 +03:00
2008-12-27 03:01:59 +02:00
class CTown ;
class CCallback ;
2010-06-07 08:28:12 +03:00
class IGameCallback ;
2008-12-27 03:01:59 +02:00
class CCreatureSet ;
2012-05-16 20:29:05 +03:00
class CQuest ;
2008-12-27 03:01:59 +02:00
class CGHeroInstance ;
class CGTownInstance ;
class CArmedInstance ;
2009-10-24 22:21:32 +03:00
class CGDwelling ;
2008-12-27 03:01:59 +02:00
class CObjectScript ;
class CGObjectInstance ;
class CCreature ;
2012-11-03 22:31:16 +03:00
class CMap ;
2008-12-27 03:01:59 +02:00
struct StartInfo ;
class CMapHandler ;
struct SetObjectProperty ;
struct MetaString ;
2009-03-07 00:25:19 +02:00
struct CPack ;
2009-05-07 18:19:52 +03:00
class CSpell ;
2009-08-30 15:47:40 +03:00
struct TerrainTile ;
2010-02-07 17:06:14 +02:00
class CHeroClass ;
2010-05-08 21:56:38 +03:00
class CCampaign ;
2010-08-04 14:18:13 +03:00
class CCampaignState ;
2010-11-10 02:06:25 +02:00
class IModableArt ;
2011-05-03 06:14:18 +03:00
class CGGarrison ;
2011-12-14 00:23:17 +03:00
class CGameInfo ;
2012-05-16 20:29:05 +03:00
struct QuestInfo ;
2012-07-07 11:45:45 +03:00
class CQuest ;
2013-12-20 16:07:58 +03:00
class CCampaignScenario ;
2013-12-29 18:48:56 +03:00
struct EventCondition ;
2014-01-03 19:36:22 +03:00
class CScenarioTravel ;
2017-07-20 06:08:49 +02:00
class IMapService ;
2008-12-27 03:01:59 +02:00
namespace boost
{
class shared_mutex ;
}
2011-12-14 00:23:17 +03:00
struct DLL_LINKAGE SThievesGuildInfo
2010-02-01 19:51:33 +02:00
{
2013-03-03 20:06:03 +03:00
std : : vector < PlayerColor > playerColors ; //colors of players that are in-game
2010-02-01 19:51:33 +02:00
2013-03-03 20:06:03 +03:00
std : : vector < std : : vector < PlayerColor > > numOfTowns , numOfHeroes , gold , woodOre , mercSulfCrystGems , obelisks , artifacts , army , income ; // [place] -> [colours of players]
2010-02-01 19:51:33 +02:00
2013-03-03 20:06:03 +03:00
std : : map < PlayerColor , InfoAboutHero > colorToBestHero ; //maps player's color to his best heros'
2010-02-01 19:51:33 +02:00
2013-03-03 20:06:03 +03:00
std : : map < PlayerColor , EAiTactic : : EAiTactic > personality ; // color to personality // ai tactic
std : : map < PlayerColor , si32 > bestCreature ; // color to ID // id or -1 if not known
2010-02-06 15:49:14 +02:00
2017-07-31 15:35:42 +02:00
// template <typename Handler> void serialize(Handler &h, const int version)
// {
// h & playerColors;
// h & numOfTowns;
// h & numOfHeroes;
// h & gold;
// h & woodOre;
// h & mercSulfCrystGems;
// h & obelisks;
// h & artifacts;
// h & army;
// h & income;
// h & colorToBestHero;
// h & personality;
// h & bestCreature;
// }
2010-02-01 19:51:33 +02:00
} ;
2015-11-30 23:44:58 +02:00
struct DLL_LINKAGE RumorState
{
enum ERumorType : ui8
{
2015-12-04 21:58:14 +02:00
TYPE_NONE = 0 , TYPE_RAND , TYPE_SPECIAL , TYPE_MAP
} ;
enum ERumorTypeSpecial : ui8
{
RUMOR_OBELISKS = 208 ,
RUMOR_ARTIFACTS = 209 ,
RUMOR_ARMY = 210 ,
RUMOR_INCOME = 211 ,
RUMOR_GRAIL = 212
2015-11-30 23:44:58 +02:00
} ;
ERumorType type ;
std : : map < ERumorType , std : : pair < int , int > > last ;
2015-12-23 16:23:56 +02:00
RumorState ( ) { type = TYPE_NONE ; } ;
2015-12-01 03:57:52 +02:00
bool update ( int id , int extra ) ;
2015-11-30 23:44:58 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2017-07-31 15:35:42 +02:00
h & type ;
h & last ;
2015-11-30 23:44:58 +02:00
}
} ;
2008-12-27 03:01:59 +02:00
struct UpgradeInfo
{
2013-02-11 02:24:57 +03:00
CreatureID oldID ; //creature to be upgraded
std : : vector < CreatureID > newID ; //possible upgrades
2011-07-05 09:14:07 +03:00
std : : vector < TResources > cost ; // cost[upgrade_serial] -> set of pairs<resource_ID,resource_amount>; cost is for single unit (not entire stack)
2013-02-07 20:34:50 +03:00
UpgradeInfo ( ) { oldID = CreatureID : : NONE ; } ;
2008-12-27 03:01:59 +02:00
} ;
2017-07-20 06:08:49 +02:00
class BattleInfo ;
2010-12-25 21:23:30 +02:00
2013-11-17 20:57:04 +03:00
DLL_LINKAGE std : : ostream & operator < < ( std : : ostream & os , const EVictoryLossCheckResult & victoryLossCheckResult ) ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CGameState : public CNonConstInfoCallback
2008-12-27 03:01:59 +02:00
{
2009-03-07 00:11:17 +02:00
public :
2013-11-17 20:57:04 +03:00
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)
2014-03-17 22:51:07 +03:00
CGHeroInstance * pickHeroFor ( bool native , PlayerColor player , const CTown * town ,
std : : map < ui32 , ConstTransitivePtr < CGHeroInstance > > & available , CRandomGenerator & rand , const CHeroClass * bannedClass = nullptr ) const ;
2013-11-17 20:57:04 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2017-07-31 15:35:42 +02:00
h & heroesPool ;
h & pavailable ;
2009-01-06 20:42:20 +02:00
}
2008-12-27 03:01:59 +02:00
} hpool ; //we have here all heroes available on this map that are not hired
2013-12-18 21:18:12 +03:00
CGameState ( ) ;
virtual ~ CGameState ( ) ;
2011-05-10 01:20:47 +03:00
2017-07-20 06:08:49 +02:00
void init ( const IMapService * mapService , StartInfo * si , bool allowSavingRandomMap = false ) ;
2012-07-26 03:48:44 +03:00
2013-12-18 21:18:12 +03:00
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 ;
2015-11-30 23:44:58 +02:00
RumorState rumor ;
2013-12-18 21:18:12 +03:00
2017-06-14 06:59:41 +02:00
static boost : : shared_mutex mutex ;
2013-12-18 21:18:12 +03:00
2013-02-19 01:37:22 +03:00
void giveHeroArtifact ( CGHeroInstance * h , ArtifactID aid ) ;
2012-02-17 22:30:40 +03:00
2009-03-07 00:25:19 +02:00
void apply ( CPack * pack ) ;
2016-09-09 19:30:36 +02:00
BFieldType battleGetBattlefieldType ( int3 tile , CRandomGenerator & rand ) ;
2010-07-15 06:04:57 +03:00
UpgradeInfo getUpgradeInfo ( const CStackInstance & stack ) ;
2013-03-03 20:06:03 +03:00
PlayerRelations : : PlayerRelations getPlayerRelations ( PlayerColor color1 , PlayerColor color2 ) ;
2009-08-30 15:47:40 +03:00
bool checkForVisitableDir ( const int3 & src , const int3 & dst ) const ; //check if src tile is visitable from dst tile
2014-09-21 16:42:08 +03:00
void calculatePaths ( const CGHeroInstance * hero , CPathsInfo & out ) ; //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
2010-05-06 15:13:31 +03:00
int3 guardingCreaturePosition ( int3 pos ) const ;
2012-11-15 00:19:32 +03:00
std : : vector < CGObjectInstance * > guardingCreatures ( int3 pos ) const ;
2015-11-30 23:44:58 +02:00
void updateRumor ( ) ;
2013-12-29 14:27:38 +03:00
// ----- victory, loss condition checks -----
2013-11-17 20:57:04 +03:00
EVictoryLossCheckResult checkForVictoryAndLoss ( PlayerColor player ) const ;
2013-12-29 14:27:38 +03:00
bool checkForVictory ( PlayerColor player , const EventCondition & condition ) const ; //checks if given player is winner
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
2013-11-17 20:57:04 +03:00
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
2013-03-03 20:06:03 +03:00
bool isVisible ( int3 pos , PlayerColor player ) ;
bool isVisible ( const CGObjectInstance * obj , boost : : optional < PlayerColor > player ) ;
2009-07-30 15:49:45 +03:00
2013-02-02 11:29:57 +03:00
int getDate ( Date : : EDateType mode = Date : : DAY ) const ; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
2013-12-18 21:18:12 +03:00
2014-03-17 22:51:07 +03:00
// ----- getters, setters -----
2016-09-09 19:30:36 +02:00
/// This RNG should only be used inside GS or CPackForClient-derived applyGs
/// If this doesn't work for your code that mean you need a new netpack
///
/// Client-side must use CRandomGenerator::getDefault which is not serialized
///
/// CGameHandler have it's own getter for CRandomGenerator::getDefault
/// Any server-side code outside of GH must use CRandomGenerator::getDefault
2014-03-17 22:51:07 +03:00
CRandomGenerator & getRandomGenerator ( ) ;
2008-12-27 03:01:59 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2017-07-31 15:35:42 +02:00
h & scenarioOps ;
h & initialOpts ;
h & currentPlayer ;
h & day ;
h & map ;
h & players ;
h & teams ;
h & hpool ;
h & globalEffects ;
h & rand ;
2015-12-06 01:51:54 +02:00
if ( version > = 755 ) //save format backward compatibility
2015-11-30 23:44:58 +02:00
{
h & rumor ;
}
2015-12-01 01:14:11 +02:00
else if ( ! h . saving )
2017-07-31 15:35:42 +02:00
{
2015-11-30 23:44:58 +02:00
rumor = RumorState ( ) ;
2017-07-31 15:35:42 +02:00
}
2015-11-30 23:44:58 +02:00
2011-02-23 05:57:45 +02:00
BONUS_TREE_DESERIALIZATION_FIX
2008-12-27 03:01:59 +02:00
}
2013-11-17 20:57:04 +03:00
private :
2014-01-30 21:56:31 +03:00
struct CrossoverHeroesList
{
std : : vector < CGHeroInstance * > heroesFromPreviousScenario , heroesFromAnyPreviousScenarios ;
void addHeroToBothLists ( CGHeroInstance * hero ) ;
void removeHeroFromBothLists ( CGHeroInstance * hero ) ;
} ;
struct CampaignHeroReplacement
{
CampaignHeroReplacement ( CGHeroInstance * hero , ObjectInstanceID heroPlaceholderId ) ;
CGHeroInstance * hero ;
ObjectInstanceID heroPlaceholderId ;
} ;
2013-12-20 16:07:58 +03:00
// ----- initialization -----
2017-07-20 06:08:49 +02:00
void initNewGame ( const IMapService * mapService , bool allowSavingRandomMap ) ;
void initCampaign ( const IMapService * mapService ) ;
2013-12-18 21:18:12 +03:00
void checkMapChecksum ( ) ;
void initGrailPosition ( ) ;
void initRandomFactionsForPlayers ( ) ;
void randomizeMapObjects ( ) ;
void randomizeObject ( CGObjectInstance * cur ) ;
void initPlayerStates ( ) ;
2013-12-28 15:47:55 +03:00
void placeCampaignHeroes ( ) ;
2014-01-30 21:56:31 +03:00
CrossoverHeroesList getCrossoverHeroesFromPreviousScenarios ( ) const ;
2014-01-03 19:36:22 +03:00
/// returns heroes and placeholders in where heroes will be put
2014-01-30 21:56:31 +03:00
std : : vector < CampaignHeroReplacement > generateCampaignHeroesToReplace ( CrossoverHeroesList & crossoverHeroes ) ;
/// gets prepared and copied hero instances with crossover heroes from prev. scenario and travel options from current scenario
2016-09-09 19:30:36 +02:00
void prepareCrossoverHeroes ( std : : vector < CampaignHeroReplacement > & campaignHeroReplacements , const CScenarioTravel & travelOptions ) ;
2013-12-20 16:07:58 +03:00
2014-01-30 21:56:31 +03:00
void replaceHeroesPlaceholders ( const std : : vector < CampaignHeroReplacement > & campaignHeroReplacements ) ;
2013-12-18 21:18:12 +03:00
void placeStartingHeroes ( ) ;
2013-12-28 15:47:55 +03:00
void placeStartingHero ( PlayerColor playerColor , HeroTypeID heroTypeId , int3 townPos ) ;
2013-12-18 21:18:12 +03:00
void initStartingResources ( ) ;
void initHeroes ( ) ;
void giveCampaignBonusToHero ( CGHeroInstance * hero ) ;
void initFogOfWar ( ) ;
void initStartingBonus ( ) ;
void initTowns ( ) ;
void initMapObjects ( ) ;
void initVisitingAndGarrisonedHeroes ( ) ;
2013-12-20 16:07:58 +03:00
// ----- bonus system handling -----
2013-12-18 21:18:12 +03:00
void buildBonusSystemTree ( ) ;
void attachArmedObjects ( ) ;
void buildGlobalTeamPlayerTree ( ) ;
void deserializationFix ( ) ;
2013-12-20 16:07:58 +03:00
// ---- misc helpers -----
2013-12-30 18:34:28 +03:00
CGHeroInstance * getUsedHero ( HeroTypeID hid ) const ;
2013-12-18 21:18:12 +03:00
bool isUsedHero ( HeroTypeID hid ) const ; //looks in heroes and prisons
std : : set < HeroTypeID > getUnusedAllowedHeroes ( bool alsoIncludeNotAllowed = false ) const ;
std : : pair < Obj , int > pickObject ( CGObjectInstance * obj ) ; //chooses type of object to be randomized, returns <type, subtype>
2014-03-17 22:51:07 +03:00
int pickUnusedHeroTypeRandomly ( PlayerColor owner ) ; // picks a unused hero type randomly
int pickNextHeroType ( PlayerColor owner ) ; // picks next free hero type of the H3 hero init sequence -> chosen starting hero, then unused hero type randomly
// ---- data -----
CRandomGenerator rand ;
2013-12-18 21:18:12 +03:00
friend class CCallback ;
friend class CClient ;
friend class IGameCallback ;
friend class CMapHandler ;
friend class CGameHandler ;
2008-12-27 03:01:59 +02:00
} ;