2014-06-05 19:52:14 +03:00
/*
2014-06-05 20:26:50 +03:00
* CGTownInstance . h , part of VCMI engine
2014-06-05 19:52:14 +03:00
*
* 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
*
*/
2017-07-13 10:26:03 +02:00
# pragma once
# include "CObjectHandler.h"
# include "CGMarket.h" // For IMarket interface
# include "CArmedInstance.h"
# include "../CTownHandler.h" // For CTown
2014-06-05 19:52:14 +03:00
class CCastleEvent ;
2014-06-25 17:11:07 +03:00
class CGTownInstance ;
2016-11-13 12:38:42 +02:00
class CGDwelling ;
2014-06-05 19:52:14 +03:00
class DLL_LINKAGE CSpecObjInfo
{
public :
2017-05-28 13:23:02 +02:00
CSpecObjInfo ( ) ;
2016-11-13 12:38:42 +02:00
virtual ~ CSpecObjInfo ( ) = default ;
virtual void serializeJson ( JsonSerializeFormat & handler ) = 0 ;
const CGDwelling * owner ;
2014-06-05 19:52:14 +03:00
} ;
class DLL_LINKAGE CCreGenAsCastleInfo : public virtual CSpecObjInfo
{
public :
2017-05-28 13:23:02 +02:00
CCreGenAsCastleInfo ( ) ;
2014-06-05 19:52:14 +03:00
bool asCastle ;
2016-11-13 12:38:42 +02:00
ui32 identifier ; //h3m internal identifier
std : : vector < bool > allowedFactions ;
std : : string instanceId ; //vcmi map instance identifier
void serializeJson ( JsonSerializeFormat & handler ) override ;
2014-06-05 19:52:14 +03:00
} ;
class DLL_LINKAGE CCreGenLeveledInfo : public virtual CSpecObjInfo
{
public :
2017-05-28 13:23:02 +02:00
CCreGenLeveledInfo ( ) ;
2016-11-13 12:38:42 +02:00
ui8 minLevel , maxLevel ; //minimal and maximal level of creature in dwelling: <1, 7>
void serializeJson ( JsonSerializeFormat & handler ) override ;
2014-06-05 19:52:14 +03:00
} ;
class DLL_LINKAGE CCreGenLeveledCastleInfo : public CCreGenAsCastleInfo , public CCreGenLeveledInfo
{
2016-11-13 12:38:42 +02:00
public :
CCreGenLeveledCastleInfo ( ) = default ;
void serializeJson ( JsonSerializeFormat & handler ) override ;
2014-06-05 19:52:14 +03:00
} ;
class DLL_LINKAGE CGDwelling : public CArmedInstance
{
public :
typedef std : : vector < std : : pair < ui32 , std : : vector < CreatureID > > > TCreaturesSet ;
2016-11-13 12:38:42 +02:00
CSpecObjInfo * info ; //random dwelling options; not serialized
2014-06-05 19:52:14 +03:00
TCreaturesSet creatures ; //creatures[level] -> <vector of alternative ids (base creature and upgrades, creatures amount>
2016-11-13 12:38:42 +02:00
CGDwelling ( ) ;
virtual ~ CGDwelling ( ) ;
void initRandomObjectInfo ( ) ;
2016-01-23 18:53:02 +02:00
protected :
2016-02-22 01:37:19 +02:00
void serializeJsonOptions ( JsonSerializeFormat & handler ) override ;
2016-01-23 18:53:02 +02:00
2015-12-02 22:34:13 +02:00
private :
2016-09-09 19:30:36 +02:00
void initObj ( CRandomGenerator & rand ) override ;
2014-06-05 19:52:14 +03:00
void onHeroVisit ( const CGHeroInstance * h ) const override ;
2016-09-09 19:30:36 +02:00
void newTurn ( CRandomGenerator & rand ) const override ;
2014-06-24 20:39:36 +03:00
void setPropertyDer ( ui8 what , ui32 val ) override ;
2014-06-05 19:52:14 +03:00
void battleFinished ( const CGHeroInstance * hero , const BattleResult & result ) const override ;
void blockingDialogAnswered ( const CGHeroInstance * hero , ui32 answer ) const override ;
2015-06-05 11:28:14 +02:00
void updateGuards ( ) const ;
2014-06-05 19:52:14 +03:00
void heroAcceptsCreatures ( const CGHeroInstance * h ) const ;
2015-12-02 22:34:13 +02:00
public :
template < typename Handler > void serialize ( Handler & h , const int version )
{
2017-07-31 15:35:42 +02:00
h & static_cast < CArmedInstance & > ( * this ) ;
h & creatures ;
2015-12-02 22:34:13 +02:00
}
2014-06-05 19:52:14 +03:00
} ;
class DLL_LINKAGE CGTownBuilding : public IObjectInterface
{
///basic class for town structures handled as map objects
public :
2020-10-02 23:55:46 +02:00
si32 indexOnTV ; //identifies its index on towns vector
2014-06-05 19:52:14 +03:00
CGTownInstance * town ;
2020-10-02 23:55:46 +02:00
CGTownBuilding ( ) : bType ( BuildingSubID : : NONE ) , indexOnTV ( 0 ) , town ( nullptr ) { } ;
STRONG_INLINE
BuildingSubID : : EBuildingSubID getBuildingSubtype ( ) const
{
return bType ;
}
2014-06-05 19:52:14 +03:00
2020-10-07 14:12:32 +02:00
STRONG_INLINE
const BuildingID & getBuildingType ( ) const
{
return bID ;
}
STRONG_INLINE
void setBuildingSubtype ( BuildingSubID : : EBuildingSubID subId )
{
bType = subId ;
}
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
PlayerColor getOwner ( ) const override ;
int32_t getObjGroupIndex ( ) const override ;
int32_t getObjTypeIndex ( ) const override ;
int3 visitablePos ( ) const override ;
int3 getPosition ( ) const override ;
2014-06-05 19:52:14 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2020-10-02 23:55:46 +02:00
h & bID ;
h & indexOnTV ;
if ( version > = 792 )
h & bType ;
2014-06-05 19:52:14 +03:00
}
2020-10-25 00:04:34 +02:00
2020-10-02 23:55:46 +02:00
protected :
BuildingID bID ; //from buildig list
BuildingSubID : : EBuildingSubID bType ;
2020-10-25 00:04:34 +02:00
const std : : string getVisitingBonusGreeting ( ) const ;
2021-02-01 17:35:15 +02:00
const std : : string getCustomBonusGreeting ( const Bonus & bonus ) const ;
2014-06-05 19:52:14 +03:00
} ;
2020-10-02 23:55:46 +02:00
2014-06-05 19:52:14 +03:00
class DLL_LINKAGE COPWBonus : public CGTownBuilding
{ ///used for OPW bonusing structures
public :
std : : set < si32 > visitors ;
void setProperty ( ui8 what , ui32 val ) override ;
void onHeroVisit ( const CGHeroInstance * h ) const override ;
2020-10-02 23:55:46 +02:00
COPWBonus ( BuildingID index , BuildingSubID : : EBuildingSubID subId , CGTownInstance * TOWN ) ;
COPWBonus ( ) { } ;
2014-06-05 19:52:14 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < CGTownBuilding & > ( * this ) ;
h & visitors ;
}
} ;
class DLL_LINKAGE CTownBonus : public CGTownBuilding
{
///used for one-time bonusing structures
///feel free to merge inheritance tree
public :
std : : set < ObjectInstanceID > visitors ;
void setProperty ( ui8 what , ui32 val ) override ;
void onHeroVisit ( const CGHeroInstance * h ) const override ;
2020-10-19 21:38:06 +02:00
CTownBonus ( BuildingID index , BuildingSubID : : EBuildingSubID subId , CGTownInstance * TOWN ) ;
2020-10-02 23:55:46 +02:00
CTownBonus ( ) { } ;
2014-06-05 19:52:14 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < CGTownBuilding & > ( * this ) ;
h & visitors ;
}
2021-01-14 00:02:13 +02:00
private :
void applyBonuses ( CGHeroInstance * h , const BonusList & bonuses ) const ;
2014-06-05 19:52:14 +03:00
} ;
class DLL_LINKAGE CTownAndVisitingHero : public CBonusSystemNode
{
public :
CTownAndVisitingHero ( ) ;
} ;
struct DLL_LINKAGE GrowthInfo
{
struct Entry
{
int count ;
std : : string description ;
Entry ( const std : : string & format , int _count ) ;
Entry ( int subID , BuildingID building , int _count ) ;
2015-09-04 18:38:42 +02:00
Entry ( int _count , const std : : string & fullDescription ) ;
2014-06-05 19:52:14 +03:00
} ;
std : : vector < Entry > entries ;
int totalGrowth ( ) const ;
} ;
class DLL_LINKAGE CGTownInstance : public CGDwelling , public IShipyard , public IMarket
{
public :
enum EFortLevel { NONE = 0 , FORT = 1 , CITADEL = 2 , CASTLE = 3 } ;
CTownAndVisitingHero townAndVis ;
const CTown * town ;
std : : string name ; // name of town
si32 builded ; //how many buildings has been built this turn
si32 destroyed ; //how many buildings has been destroyed this turn
ConstTransitivePtr < CGHeroInstance > garrisonHero , visitingHero ;
ui32 identifier ; //special identifier from h3m (only > RoE maps)
si32 alignment ;
2021-01-14 00:02:13 +02:00
std : : set < BuildingID > forbiddenBuildings ;
std : : set < BuildingID > builtBuildings ;
std : : set < BuildingID > overriddenBuildings ; ///buildings which bonuses are overridden and should not be applied
2014-06-05 19:52:14 +03:00
std : : vector < CGTownBuilding * > bonusingBuildings ;
std : : vector < SpellID > possibleSpells , obligatorySpells ;
std : : vector < std : : vector < SpellID > > spells ; //spells[level] -> vector of spells, first will be available in guild
std : : list < CCastleEvent > events ;
std : : pair < si32 , si32 > bonusValue ; //var to store town bonuses (rampart = resources from mystic pond);
//////////////////////////////////////////////////////////////////////////
static std : : vector < const CArtifact * > merchantArtifacts ; //vector of artifacts available at Artifact merchant, NULLs possible (for making empty space when artifact is bought)
static std : : vector < int > universitySkills ; //skills for university of magic
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < CGDwelling & > ( * this ) ;
h & static_cast < IShipyard & > ( * this ) ;
h & static_cast < IMarket & > ( * this ) ;
2017-07-31 15:35:42 +02:00
h & name ;
h & builded ;
h & destroyed ;
h & identifier ;
h & garrisonHero ;
h & visitingHero ;
h & alignment ;
h & forbiddenBuildings ;
h & builtBuildings ;
h & bonusValue ;
h & possibleSpells ;
h & obligatorySpells ;
h & spells ;
h & events ;
h & bonusingBuildings ;
2014-06-05 19:52:14 +03:00
2021-01-14 00:02:13 +02:00
for ( auto * bonusingBuilding : bonusingBuildings )
bonusingBuilding - > town = this ;
2014-06-05 19:52:14 +03:00
2017-07-31 15:35:42 +02:00
h & town ;
h & townAndVis ;
2014-06-05 19:52:14 +03:00
BONUS_TREE_DESERIALIZATION_FIX
vstd : : erase_if ( builtBuildings , [ this ] ( BuildingID building ) - > bool
{
if ( ! town - > buildings . count ( building ) | | ! town - > buildings . at ( building ) )
{
2017-08-11 19:03:05 +02:00
logGlobal - > error ( " #1444-like issue in CGTownInstance::serialize. From town %s at %s removing the bogus builtBuildings item %s " , name , pos . toString ( ) , building ) ;
2014-06-05 19:52:14 +03:00
return true ;
}
return false ;
} ) ;
2020-10-07 14:12:32 +02:00
2020-10-25 00:04:34 +02:00
if ( ! h . saving & & version < 793 )
2020-10-07 14:12:32 +02:00
updateBonusingBuildings ( ) ;
2021-01-14 00:02:13 +02:00
if ( version > = 794 )
h & overriddenBuildings ;
else if ( ! h . saving )
updateTown794 ( ) ;
2021-03-23 16:47:07 +02:00
if ( ! h . saving )
this - > setNodeType ( CBonusSystemNode : : TOWN ) ;
2014-06-05 19:52:14 +03:00
}
//////////////////////////////////////////////////////////////////////////
CBonusSystemNode * whatShouldBeAttached ( ) override ;
std : : string nodeName ( ) const override ;
void updateMoraleBonusFromArmy ( ) override ;
void deserializationFix ( ) ;
void recreateBuildingsBonuses ( ) ;
void setVisitingHero ( CGHeroInstance * h ) ;
void setGarrisonedHero ( CGHeroInstance * h ) ;
const CArmedInstance * getUpperArmy ( ) const ; //garrisoned hero if present or the town itself
//////////////////////////////////////////////////////////////////////////
2015-10-12 15:47:10 +02:00
bool passableFor ( PlayerColor color ) const override ;
2014-06-24 02:26:36 +03:00
//int3 getSightCenter() const override; //"center" tile from which the sight distance is calculated
2016-01-31 17:01:58 +02:00
int getSightRadius ( ) const override ; //returns sight distance
2015-10-12 15:47:10 +02:00
int getBoatType ( ) const override ; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
void getOutOffsets ( std : : vector < int3 > & offsets ) const override ; //offsets to obj pos when we boat can be placed. Parameter will be cleared
2014-06-05 19:52:14 +03:00
int getMarketEfficiency ( ) const override ; //=market count
2015-10-12 15:47:10 +02:00
bool allowsTrade ( EMarketMode : : EMarketMode mode ) const override ;
std : : vector < int > availableItemsIds ( EMarketMode : : EMarketMode mode ) const override ;
2014-06-05 19:52:14 +03:00
2015-10-12 15:47:10 +02:00
void setType ( si32 ID , si32 subID ) override ;
2014-06-05 19:52:14 +03:00
void updateAppearance ( ) ;
//////////////////////////////////////////////////////////////////////////
2015-10-12 15:47:10 +02:00
bool needsLastStack ( ) const override ;
2014-06-05 19:52:14 +03:00
CGTownInstance : : EFortLevel fortLevel ( ) const ;
int hallLevel ( ) const ; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
int mageGuildLevel ( ) const ; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
int getHordeLevel ( const int & HID ) const ; //HID - 0 or 1; returns creature level or -1 if that horde structure is not present
int creatureGrowth ( const int & level ) const ;
GrowthInfo getGrowthInfo ( int level ) const ;
bool hasFort ( ) const ;
bool hasCapitol ( ) const ;
2020-10-02 23:55:46 +02:00
const CGTownBuilding * getBonusingBuilding ( BuildingSubID : : EBuildingSubID subId ) const ;
2020-10-15 14:03:01 +02:00
bool hasBuiltSomeTradeBuilding ( ) const ;
2020-10-02 23:55:46 +02:00
//checks if special building with type buildingID is constructed
bool hasBuilt ( BuildingSubID : : EBuildingSubID buildingID ) const ;
2014-06-05 19:52:14 +03:00
//checks if building is constructed and town has same subID
bool hasBuilt ( BuildingID buildingID ) const ;
bool hasBuilt ( BuildingID buildingID , int townID ) const ;
2020-10-02 23:55:46 +02:00
2018-07-26 12:06:55 +02:00
TResources getBuildingCost ( BuildingID buildingID ) const ;
2014-06-05 19:52:14 +03:00
TResources dailyIncome ( ) const ; //calculates daily income of this town
int spellsAtLevel ( int level , bool checkGuild ) const ; //levels are counted from 1 (1 - 5)
bool armedGarrison ( ) const ; //true if town has creatures in garrison or garrisoned hero
int getTownLevel ( ) const ;
2016-09-10 19:38:49 +02:00
CBuilding : : TRequired genBuildingRequirements ( BuildingID build , bool deep = false ) const ;
2014-08-07 19:40:22 +03:00
2016-02-21 21:23:47 +02:00
void mergeGarrisonOnSiege ( ) const ; // merge garrison into army of visiting hero
2014-06-05 19:52:14 +03:00
void removeCapitols ( PlayerColor owner ) const ;
2016-02-22 02:33:15 +02:00
void clearArmy ( ) const ;
2020-10-02 23:55:46 +02:00
void addHeroToStructureVisitors ( const CGHeroInstance * h , si64 structureInstanceID ) const ; //hero must be visiting or garrisoned in town
2021-01-14 00:02:13 +02:00
void deleteTownBonus ( BuildingID : : EBuildingID bid ) ;
2014-06-05 19:52:14 +03:00
2016-11-13 12:38:42 +02:00
const CTown * getTown ( ) const ;
2014-06-05 19:52:14 +03:00
CGTownInstance ( ) ;
virtual ~ CGTownInstance ( ) ;
///IObjectInterface overrides
2016-09-09 19:30:36 +02:00
void newTurn ( CRandomGenerator & rand ) const override ;
2014-06-05 19:52:14 +03:00
void onHeroVisit ( const CGHeroInstance * h ) const override ;
void onHeroLeave ( const CGHeroInstance * h ) const override ;
2016-09-09 19:30:36 +02:00
void initObj ( CRandomGenerator & rand ) override ;
2014-06-05 19:52:14 +03:00
void battleFinished ( const CGHeroInstance * hero , const BattleResult & result ) const override ;
2014-06-24 20:39:36 +03:00
std : : string getObjectName ( ) const override ;
2017-05-28 15:23:42 +02:00
void afterAddToMap ( CMap * map ) override ;
2018-01-05 19:21:07 +02:00
static void reset ( ) ;
2020-10-15 14:03:01 +02:00
2021-03-23 16:47:07 +02:00
STRONG_INLINE bool isBattleOutsideTown ( const CGHeroInstance * defendingHero ) const
{
return defendingHero & & garrisonHero & & defendingHero ! = garrisonHero ;
}
2014-06-05 19:52:14 +03:00
protected :
void setPropertyDer ( ui8 what , ui32 val ) override ;
2016-02-22 01:37:19 +02:00
void serializeJsonOptions ( JsonSerializeFormat & handler ) override ;
2020-10-15 14:03:01 +02:00
2017-10-07 16:42:33 +02:00
private :
2021-03-23 16:47:07 +02:00
void setOwner ( const PlayerColor owner ) const ;
2017-10-07 16:42:33 +02:00
int getDwellingBonus ( const std : : vector < CreatureID > & creatureIds , const std : : vector < ConstTransitivePtr < CGDwelling > > & dwellings ) const ;
2020-10-07 14:12:32 +02:00
void updateBonusingBuildings ( ) ;
bool hasBuiltInOldWay ( ETownType : : ETownType type , BuildingID bid ) const ;
2020-10-15 14:03:01 +02:00
bool townEnvisagesBuilding ( BuildingSubID : : EBuildingSubID bid ) const ;
2020-10-19 21:38:06 +02:00
void tryAddOnePerWeekBonus ( BuildingSubID : : EBuildingSubID subID ) ;
void tryAddVisitingBonus ( BuildingSubID : : EBuildingSubID subID ) ;
2021-01-14 00:02:13 +02:00
void initOverriddenBids ( ) ;
2020-10-19 21:38:06 +02:00
void addTownBonuses ( ) ;
2021-01-14 00:02:13 +02:00
void updateTown794 ( ) ; //populate overriddenBuildings and vanila bonuses for old saves
2014-06-05 19:52:14 +03:00
} ;