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 11:26:03 +03:00
# pragma once
2023-06-02 21:47:37 +03:00
# include "IMarket.h"
2023-04-26 22:55:56 +04:00
# include "CGDwelling.h"
2024-07-21 10:49:40 +00:00
# include "../entities/faction/CFaction.h" // TODO: remove
# include "../entities/faction/CTown.h" // TODO: remove
2014-06-05 19:52:14 +03:00
2022-07-26 16:07:42 +03:00
VCMI_LIB_NAMESPACE_BEGIN
2014-06-05 19:52:14 +03:00
class CCastleEvent ;
2024-08-16 13:16:53 +00:00
class CTown ;
2024-08-16 14:49:42 +00:00
class TownBuildingInstance ;
2024-08-28 19:33:56 +00:00
struct TownFortifications ;
2024-08-16 14:49:42 +00:00
class TownRewardableBuildingInstance ;
2023-03-23 17:49:33 +02:00
struct DamageRange ;
2014-06-05 19:52:14 +03:00
2024-08-16 13:16:53 +00:00
template < typename ContainedClass >
class LogicalExpression ;
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 ) ;
2023-02-12 23:39:17 +03:00
Entry ( int subID , const BuildingID & building , int _count ) ;
Entry ( int _count , std : : string fullDescription ) ;
2014-06-05 19:52:14 +03:00
} ;
std : : vector < Entry > entries ;
int totalGrowth ( ) const ;
2024-07-29 22:54:42 +02:00
int handicapPercentage ;
2014-06-05 19:52:14 +03:00
} ;
2024-08-25 15:04:44 +00:00
class DLL_LINKAGE CGTownInstance : public CGDwelling , public IShipyard , public IMarket , public INativeTerrainProvider , public ICreatureUpgrader
2014-06-05 19:52:14 +03:00
{
2024-10-05 19:37:52 +00:00
friend class CTownInstanceConstructor ;
2023-09-27 23:57:05 +02:00
std : : string nameTextId ; // name of town
2024-08-16 14:49:42 +00:00
std : : map < BuildingID , TownRewardableBuildingInstance * > convertOldBuildings ( std : : vector < TownRewardableBuildingInstance * > oldVector ) ;
2024-08-17 22:06:48 +03:00
std : : set < BuildingID > builtBuildings ;
2025-03-09 21:51:33 +00:00
ObjectInstanceID garrisonHero ;
ObjectInstanceID visitingHero ;
2014-06-05 19:52:14 +03:00
public :
enum EFortLevel { NONE = 0 , FORT = 1 , CITADEL = 2 , CASTLE = 3 } ;
CTownAndVisitingHero townAndVis ;
2024-06-24 03:23:26 +02:00
si32 built ; //how many buildings has been built this turn
2014-06-05 19:52:14 +03:00
si32 destroyed ; //how many buildings has been destroyed this turn
ui32 identifier ; //special identifier from h3m (only > RoE maps)
2023-04-02 19:56:10 +03:00
PlayerColor alignmentToPlayer ; // if set to non-neutral, random town will have same faction as specified player
2021-01-14 01:02:13 +03:00
std : : set < BuildingID > forbiddenBuildings ;
2025-03-30 22:07:17 +03:00
std : : map < BuildingID , std : : unique_ptr < TownRewardableBuildingInstance > > rewardableBuildings ;
2014-06-05 19:52:14 +03:00
std : : vector < SpellID > possibleSpells , obligatorySpells ;
std : : vector < std : : vector < SpellID > > spells ; //spells[level] -> vector of spells, first will be available in guild
2024-07-16 21:16:26 +02:00
std : : vector < CCastleEvent > events ;
2024-08-04 17:52:40 +02:00
std : : pair < si32 , si32 > bonusValue ; //var to store town bonuses (rampart = resources from mystic pond, factory = save debts);
2024-10-01 16:32:28 +02:00
int spellResearchCounterDay ;
int spellResearchAcceptedCounter ;
2024-09-28 14:25:11 +02:00
bool spellResearchAllowed ;
2014-06-05 19:52:14 +03:00
//////////////////////////////////////////////////////////////////////////
2024-01-20 20:34:51 +02:00
template < typename Handler > void serialize ( Handler & h )
2014-06-05 19:52:14 +03:00
{
h & static_cast < CGDwelling & > ( * this ) ;
2023-09-27 23:57:05 +02:00
h & nameTextId ;
2024-06-24 03:23:26 +02:00
h & built ;
2017-07-31 16:35:42 +03:00
h & destroyed ;
h & identifier ;
2025-04-16 17:05:52 +03:00
if ( h . hasFeature ( Handler : : Version : : NO_RAW_POINTERS_IN_SERIALIZER ) )
{
h & garrisonHero ;
h & visitingHero ;
}
else
{
std : : shared_ptr < CGObjectInstance > ptrGarr ;
std : : shared_ptr < CGObjectInstance > ptrVisit ;
h & ptrGarr ;
h & ptrVisit ;
garrisonHero = ptrGarr ? ptrGarr - > id : ObjectInstanceID ( ) ;
visitingHero = ptrVisit ? ptrVisit - > id : ObjectInstanceID ( ) ;
}
2023-04-02 19:56:10 +03:00
h & alignmentToPlayer ;
2017-07-31 16:35:42 +03:00
h & forbiddenBuildings ;
h & builtBuildings ;
h & bonusValue ;
h & possibleSpells ;
h & obligatorySpells ;
h & spells ;
h & events ;
2025-03-18 11:35:15 +00:00
h & spellResearchCounterDay ;
h & spellResearchAcceptedCounter ;
h & spellResearchAllowed ;
h & rewardableBuildings ;
2017-07-31 16:35:42 +03:00
h & townAndVis ;
2014-06-05 19:52:14 +03:00
2021-03-23 17:47:07 +03:00
if ( ! h . saving )
2024-08-16 13:16:53 +00:00
postDeserialize ( ) ;
2014-06-05 19:52:14 +03:00
}
//////////////////////////////////////////////////////////////////////////
2022-11-06 03:26:13 +04:00
CBonusSystemNode & whatShouldBeAttached ( ) override ;
2014-06-05 19:52:14 +03:00
std : : string nodeName ( ) const override ;
void updateMoraleBonusFromArmy ( ) override ;
2024-08-16 13:16:53 +00:00
void postDeserialize ( ) ;
2014-06-05 19:52:14 +03:00
void recreateBuildingsBonuses ( ) ;
void setVisitingHero ( CGHeroInstance * h ) ;
void setGarrisonedHero ( CGHeroInstance * h ) ;
const CArmedInstance * getUpperArmy ( ) const ; //garrisoned hero if present or the town itself
2025-03-09 21:51:33 +00:00
const CGHeroInstance * getVisitingHero ( ) const ;
const CGHeroInstance * getGarrisonHero ( ) const ;
2014-06-05 19:52:14 +03:00
2023-01-04 15:17:50 +02:00
std : : string getNameTranslated ( ) const ;
2023-11-26 18:53:34 +02:00
std : : string getNameTextID ( ) const ;
2023-09-27 23:57:05 +02:00
void setNameTextId ( const std : : string & newName ) ;
2023-01-04 15:17:50 +02:00
2014-06-05 19:52:14 +03:00
//////////////////////////////////////////////////////////////////////////
2015-10-12 16:47:10 +03: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 18:01:58 +03:00
int getSightRadius ( ) const override ; //returns sight distance
2023-04-20 21:20:51 +04:00
BoatId getBoatType ( ) const override ; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
2015-10-12 16:47:10 +03:00
void getOutOffsets ( std : : vector < int3 > & offsets ) const override ; //offsets to obj pos when we boat can be placed. Parameter will be cleared
2023-06-07 01:55:21 +03:00
EGeneratorState shipyardStatus ( ) const override ;
const IObjectInterface * getObject ( ) const override ;
2014-06-05 19:52:14 +03:00
int getMarketEfficiency ( ) const override ; //=market count
2024-08-27 13:44:30 +00:00
std : : set < EMarketMode > availableModes ( ) const override ;
2023-11-08 17:49:08 +02:00
std : : vector < TradeItemBuy > availableItemsIds ( EMarketMode mode ) const override ;
2024-08-20 17:15:50 +03:00
ObjectInstanceID getObjInstanceID ( ) const override ;
2014-06-05 19:52:14 +03:00
void updateAppearance ( ) ;
//////////////////////////////////////////////////////////////////////////
2015-10-12 16:47:10 +03:00
bool needsLastStack ( ) const override ;
2014-06-05 19:52:14 +03:00
CGTownInstance : : EFortLevel fortLevel ( ) const ;
2024-08-28 19:33:56 +00:00
TownFortifications fortificationsLevel ( ) const ;
2014-06-05 19:52:14 +03:00
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-15 15:03:01 +03:00
bool hasBuiltSomeTradeBuilding ( ) const ;
2020-10-03 00:55:46 +03: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
2023-02-12 23:39:17 +03:00
bool hasBuilt ( const BuildingID & buildingID ) const ;
2023-11-02 17:12:58 +02:00
bool hasBuilt ( const BuildingID & buildingID , FactionID townID ) const ;
2024-08-16 18:00:02 +03:00
void addBuilding ( const BuildingID & buildingID ) ;
void removeBuilding ( const BuildingID & buildingID ) ;
2024-08-17 22:06:48 +03:00
void removeAllBuildings ( ) ;
std : : set < BuildingID > getBuildings ( ) const ;
2020-10-03 00:55:46 +03:00
2023-02-12 23:39:17 +03:00
TResources getBuildingCost ( const BuildingID & buildingID ) const ;
2024-08-24 20:42:19 +00:00
ResourceSet dailyIncome ( ) const override ;
2024-08-25 15:04:44 +00:00
std : : vector < CreatureID > providedCreatures ( ) const override ;
2024-08-24 20:42:19 +00:00
2014-06-05 19:52:14 +03:00
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 ;
2024-07-21 10:49:40 +00:00
LogicalExpression < BuildingID > genBuildingRequirements ( const BuildingID & build , bool deep = false ) const ;
2014-08-07 19:40:22 +03:00
2025-05-13 15:24:45 +03:00
void mergeGarrisonOnSiege ( IGameEventCallback & gameEvents ) const ; // merge garrison into army of visiting hero
void removeCapitols ( IGameEventCallback & gameEvents , const PlayerColor & owner ) const ;
void clearArmy ( IGameEventCallback & gameEvents ) const ;
void addHeroToStructureVisitors ( IGameEventCallback & gameEvents , const CGHeroInstance * h , si64 structureInstanceID ) const ; //hero must be visiting or garrisoned in town
2023-08-20 00:22:31 +03:00
void deleteTownBonus ( BuildingID bid ) ;
2014-06-05 19:52:14 +03:00
2023-01-16 18:28:05 +02:00
/// Returns damage range for secondary towers of this town
2023-03-23 17:49:33 +02:00
DamageRange getTowerDamageRange ( ) const ;
2023-01-16 18:28:05 +02:00
/// Returns damage range for central tower(keep) of this town
2023-03-23 17:49:33 +02:00
DamageRange getKeepDamageRange ( ) const ;
2023-01-16 18:28:05 +02:00
2023-04-09 18:26:32 +03:00
const CTown * getTown ( ) const ;
2024-10-05 19:37:52 +00:00
const CFaction * getFaction ( ) const ;
2023-04-09 18:26:32 +03:00
/// INativeTerrainProvider
2024-10-05 19:37:52 +00:00
FactionID getFactionID ( ) const override ;
2023-04-09 18:26:32 +03:00
TerrainId getNativeTerrain ( ) const override ;
2016-11-13 13:38:42 +03:00
2024-08-23 15:29:47 +00:00
/// Returns ID of war machine that is produced by specified building or NONE if this is not built or if building does not produce war machines
ArtifactID getWarMachineInBuilding ( BuildingID ) const ;
/// Returns true if provided war machine is available in any of built buildings of this town
bool isWarMachineAvailable ( ArtifactID ) const ;
2025-05-14 15:50:13 +03:00
CGTownInstance ( IGameInfoCallback * cb ) ;
2014-06-05 19:52:14 +03:00
virtual ~ CGTownInstance ( ) ;
///IObjectInterface overrides
2025-05-16 17:20:56 +03:00
void newTurn ( IGameEventCallback & gameEvents , IGameRandomizer & gameRandomizer ) const override ;
2025-05-13 15:24:45 +03:00
void onHeroVisit ( IGameEventCallback & gameEvents , const CGHeroInstance * h ) const override ;
void onHeroLeave ( IGameEventCallback & gameEvents , const CGHeroInstance * h ) const override ;
2025-05-16 17:20:56 +03:00
void initObj ( IGameRandomizer & gameRandomizer ) override ;
void pickRandomObject ( IGameRandomizer & gameRandomizer ) override ;
2025-05-13 15:24:45 +03:00
void battleFinished ( IGameEventCallback & gameEvents , const CGHeroInstance * hero , const BattleResult & result ) const override ;
2014-06-24 20:39:36 +03:00
std : : string getObjectName ( ) const override ;
2017-05-28 16:23:42 +03:00
2023-06-06 19:19:30 +03:00
void fillUpgradeInfo ( UpgradeInfo & info , const CStackInstance & stack ) const override ;
2017-05-28 16:23:42 +03:00
void afterAddToMap ( CMap * map ) override ;
2022-09-17 15:04:01 +04:00
void afterRemoveFromMap ( CMap * map ) override ;
2020-10-15 15:03:01 +03:00
2021-08-19 01:45:28 +03:00
inline bool isBattleOutsideTown ( const CGHeroInstance * defendingHero ) const
2021-03-23 17:47:07 +03:00
{
2025-03-09 21:51:33 +00:00
return defendingHero & & getGarrisonHero ( ) & & defendingHero ! = getGarrisonHero ( ) ;
2021-03-23 17:47:07 +03:00
}
2014-06-05 19:52:14 +03:00
protected :
2023-11-06 18:27:16 +02:00
void setPropertyDer ( ObjProperty what , ObjPropertyID identifier ) override ;
2016-02-22 02:37:19 +03:00
void serializeJsonOptions ( JsonSerializeFormat & handler ) override ;
2020-10-15 15:03:01 +03:00
2017-10-07 07:42:33 -07:00
private :
2024-06-01 15:28:17 +00:00
FactionID randomizeFaction ( vstd : : RNG & rand ) ;
2025-05-13 15:24:45 +03:00
void setOwner ( IGameEventCallback & gameEvents , const PlayerColor & owner ) const ;
void onTownCaptured ( IGameEventCallback & gameEvents , const PlayerColor & winner ) const ;
2024-08-25 15:04:44 +00:00
int getDwellingBonus ( const std : : vector < CreatureID > & creatureIds , const std : : vector < const CGObjectInstance * > & dwellings ) const ;
2020-10-15 15:03:01 +03:00
bool townEnvisagesBuilding ( BuildingSubID : : EBuildingSubID bid ) const ;
2025-05-16 17:20:56 +03:00
void initializeConfigurableBuildings ( IGameRandomizer & gameRandomizer ) ;
2024-08-29 15:46:22 +00:00
void initializeNeutralTownGarrison ( vstd : : RNG & rand ) ;
2014-06-05 19:52:14 +03:00
} ;
2022-07-26 16:07:42 +03:00
VCMI_LIB_NAMESPACE_END