2023-10-19 16:19:09 +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
*
*/
#pragma once
#include "bonuses/CBonusSystemNode.h"
#include "IGameCallback.h"
#include "LoadProgress.h"
#include "ConstTransitivePtr.h"
namespace boost
{
class shared_mutex ;
}
VCMI_LIB_NAMESPACE_BEGIN
class EVictoryLossCheckResult ;
class Services ;
class IMapService ;
class CMap ;
struct CPack ;
class CHeroClass ;
struct EventCondition ;
struct CampaignTravel ;
class CStackInstance ;
class CGameStateCampaign ;
class TavernHeroesPool ;
struct SThievesGuildInfo ;
template < typename T > class CApplier ;
class CBaseForGSApply ;
struct DLL_LINKAGE RumorState
{
enum ERumorType : ui8
{
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
};
ERumorType type ;
std :: map < ERumorType , std :: pair < int , int >> last ;
RumorState (){ type = TYPE_NONE ;};
bool update ( int id , int extra );
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & type ;
h & last ;
}
};
struct UpgradeInfo
{
CreatureID oldID ; //creature to be upgraded
std :: vector < CreatureID > newID ; //possible upgrades
std :: vector < ResourceSet > cost ; // cost[upgrade_serial] -> set of pairs<resource_ID,resource_amount>; cost is for single unit (not entire stack)
UpgradeInfo (){ oldID = CreatureID :: NONE ;};
};
class BattleInfo ;
DLL_LINKAGE std :: ostream & operator << ( std :: ostream & os , const EVictoryLossCheckResult & victoryLossCheckResult );
class DLL_LINKAGE CGameState : public CNonConstInfoCallback
{
friend class CGameStateCampaign ;
public :
2023-11-07 14:27:25 +02:00
/// Stores number of times each artifact was placed on map via randomization
std :: map < ArtifactID , int > allocatedArtifacts ;
2023-10-19 16:19:09 +02:00
/// List of currently ongoing battles
std :: vector < std :: unique_ptr < BattleInfo >> currentBattles ;
/// ID that can be allocated to next battle
BattleID nextBattleID = BattleID ( 0 );
//we have here all heroes available on this map that are not hired
std :: unique_ptr < TavernHeroesPool > heroesPool ;
/// list of players currently making turn. Usually - just one, except for simturns
std :: set < PlayerColor > actingPlayers ;
CGameState ();
virtual ~ CGameState ();
void preInit ( Services * services );
2023-10-22 18:36:41 +03:00
void init ( const IMapService * mapService , StartInfo * si , Load :: ProgressAccumulator & , bool allowSavingRandomMap = true );
2023-10-19 16:19:09 +02:00
void updateOnLoad ( StartInfo * si );
ConstTransitivePtr < StartInfo > scenarioOps , initialOpts ; //second one is a copy of settings received from pregame (not randomized)
ui32 day ; //total number of days in game
ConstTransitivePtr < CMap > map ;
std :: map < PlayerColor , PlayerState > players ;
std :: map < TeamID , TeamState > teams ;
CBonusSystemNode globalEffects ;
RumorState rumor ;
static boost :: shared_mutex mutex ;
void updateEntity ( Metatype metatype , int32_t index , const JsonNode & data ) override ;
bool giveHeroArtifact ( CGHeroInstance * h , const ArtifactID & aid );
2023-10-25 21:56:00 +03:00
/// picks next free hero type of the H3 hero init sequence -> chosen starting hero, then unused hero type randomly
HeroTypeID pickNextHeroType ( const PlayerColor & owner );
2023-10-19 16:19:09 +02:00
void apply ( CPack * pack );
BattleField battleGetBattlefieldType ( int3 tile , CRandomGenerator & rand );
void fillUpgradeInfo ( const CArmedInstance * obj , SlotID stackPos , UpgradeInfo & out ) const override ;
PlayerRelations getPlayerRelations ( PlayerColor color1 , PlayerColor color2 ) const override ;
bool checkForVisitableDir ( const int3 & src , const int3 & dst ) const ; //check if src tile is visitable from dst tile
void calculatePaths ( const CGHeroInstance * hero , CPathsInfo & out ) override ; //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
void calculatePaths ( const std :: shared_ptr < PathfinderConfig > & config ) override ;
int3 guardingCreaturePosition ( int3 pos ) const override ;
std :: vector < CGObjectInstance *> guardingCreatures ( int3 pos ) const ;
void updateRumor ();
2023-11-07 14:27:25 +02:00
/// Gets a artifact ID randomly and removes the selected artifact from this handler.
ArtifactID pickRandomArtifact ( CRandomGenerator & rand , int flags );
ArtifactID pickRandomArtifact ( CRandomGenerator & rand , std :: function < bool ( ArtifactID ) > accepts );
ArtifactID pickRandomArtifact ( CRandomGenerator & rand , int flags , std :: function < bool ( ArtifactID ) > accepts );
ArtifactID pickRandomArtifact ( CRandomGenerator & rand , std :: set < ArtifactID > filtered );
2023-10-19 16:19:09 +02:00
/// Returns battle in which selected player is engaged, or nullptr if none.
/// Can NOT be used with neutral player, use battle by ID instead
const BattleInfo * getBattle ( const PlayerColor & player ) const ;
/// Returns battle by its unique identifier, or nullptr if not found
const BattleInfo * getBattle ( const BattleID & battle ) const ;
BattleInfo * getBattle ( const BattleID & battle );
// ----- victory, loss condition checks -----
EVictoryLossCheckResult checkForVictoryAndLoss ( const PlayerColor & player ) const ;
bool checkForVictory ( const 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 ( const 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
bool isVisible ( int3 pos , const std :: optional < PlayerColor > & player ) const override ;
bool isVisible ( const CGObjectInstance * obj , const std :: optional < PlayerColor > & player ) const override ;
int getDate ( Date mode = Date :: DAY ) const override ; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
// ----- getters, setters -----
/// 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
CRandomGenerator & getRandomGenerator ();
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & scenarioOps ;
h & initialOpts ;
h & actingPlayers ;
h & day ;
h & map ;
h & players ;
h & teams ;
h & heroesPool ;
h & globalEffects ;
h & rand ;
h & rumor ;
h & campaign ;
2023-11-07 14:27:25 +02:00
h & allocatedArtifacts ;
2023-10-19 16:19:09 +02:00
BONUS_TREE_DESERIALIZATION_FIX
}
private :
// ----- initialization -----
void preInitAuto ();
void initNewGame ( const IMapService * mapService , bool allowSavingRandomMap , Load :: ProgressAccumulator & progressTracking );
void checkMapChecksum ();
void initGlobalBonuses ();
void initGrailPosition ();
void initRandomFactionsForPlayers ();
void randomizeMapObjects ();
void initPlayerStates ();
void placeStartingHeroes ();
void placeStartingHero ( const PlayerColor & playerColor , const HeroTypeID & heroTypeId , int3 townPos );
void removeHeroPlaceholders ();
void initDifficulty ();
void initHeroes ();
void placeHeroesInTowns ();
void initFogOfWar ();
void initStartingBonus ();
void initTowns ();
void initMapObjects ();
void initVisitingAndGarrisonedHeroes ();
void initCampaign ();
// ----- bonus system handling -----
void buildBonusSystemTree ();
void attachArmedObjects ();
void buildGlobalTeamPlayerTree ();
void deserializationFix ();
// ---- misc helpers -----
CGHeroInstance * getUsedHero ( const HeroTypeID & hid ) const ;
bool isUsedHero ( const HeroTypeID & hid ) const ; //looks in heroes and prisons
std :: set < HeroTypeID > getUnusedAllowedHeroes ( bool alsoIncludeNotAllowed = false ) const ;
HeroTypeID pickUnusedHeroTypeRandomly ( const PlayerColor & owner ); // picks a unused hero type randomly
UpgradeInfo fillUpgradeInfo ( const CStackInstance & stack ) const ;
// ---- data -----
std :: shared_ptr < CApplier < CBaseForGSApply >> applier ;
CRandomGenerator rand ;
Services * services ;
/// Ponter to campaign state manager. Nullptr for single scenarios
std :: unique_ptr < CGameStateCampaign > campaign ;
friend class IGameCallback ;
friend class CMapHandler ;
friend class CGameHandler ;
};
VCMI_LIB_NAMESPACE_END