1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-10-31 00:07:39 +02:00
Files
vcmi/lib/mapObjects/CGTownInstance.h
Ivan Savenko 20d5b33ea6 Remove marketModes as member
marketModes are now generated in runtime and are not a member of
IMarket. Was not a bad change, but towns load buildings before town type
is randomized, leading to case where market modes are not actually known
when building is added to town (like random towns with market built)

Since altar requires CArtifactSet for work, IMarket will now always
contain it, but it will only be accessible if market supports altar
mode.
2024-08-27 14:07:00 +00:00

245 lines
8.6 KiB
C++

/*
* CGTownInstance.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 "IMarket.h"
#include "CGDwelling.h"
#include "../entities/faction/CFaction.h" // TODO: remove
#include "../entities/faction/CTown.h" // TODO: remove
VCMI_LIB_NAMESPACE_BEGIN
class CCastleEvent;
class CTown;
class TownBuildingInstance;
class TownRewardableBuildingInstance;
struct DamageRange;
template<typename ContainedClass>
class LogicalExpression;
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, const BuildingID & building, int _count);
Entry(int _count, std::string fullDescription);
};
std::vector<Entry> entries;
int totalGrowth() const;
int handicapPercentage;
};
class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public IMarket, public INativeTerrainProvider, public ICreatureUpgrader
{
std::string nameTextId; // name of town
std::map<BuildingID, TownRewardableBuildingInstance*> convertOldBuildings(std::vector<TownRewardableBuildingInstance*> oldVector);
std::set<BuildingID> builtBuildings;
public:
using CGDwelling::getPosition;
enum EFortLevel {NONE = 0, FORT = 1, CITADEL = 2, CASTLE = 3};
CTownAndVisitingHero townAndVis;
const CTown * town;
si32 built; //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)
PlayerColor alignmentToPlayer; // if set to non-neutral, random town will have same faction as specified player
std::set<BuildingID> forbiddenBuildings;
std::map<BuildingID, TownRewardableBuildingInstance*> rewardableBuildings;
std::vector<SpellID> possibleSpells, obligatorySpells;
std::vector<std::vector<SpellID> > spells; //spells[level] -> vector of spells, first will be available in guild
std::vector<CCastleEvent> events;
std::pair<si32, si32> bonusValue;//var to store town bonuses (rampart = resources from mystic pond, factory = save debts);
//////////////////////////////////////////////////////////////////////////
template <typename Handler> void serialize(Handler &h)
{
h & static_cast<CGDwelling&>(*this);
h & nameTextId;
h & built;
h & destroyed;
h & identifier;
h & garrisonHero;
h & visitingHero;
h & alignmentToPlayer;
h & forbiddenBuildings;
h & builtBuildings;
h & bonusValue;
h & possibleSpells;
h & obligatorySpells;
h & spells;
h & events;
if (h.version >= Handler::Version::NEW_TOWN_BUILDINGS)
{
h & rewardableBuildings;
}
else
{
std::vector<TownRewardableBuildingInstance*> oldVector;
h & oldVector;
rewardableBuildings = convertOldBuildings(oldVector);
}
if (h.saving)
{
CFaction * faction = town ? town->faction : nullptr;
h & faction;
}
else
{
CFaction * faction = nullptr;
h & faction;
town = faction ? faction->town : nullptr;
}
h & townAndVis;
BONUS_TREE_DESERIALIZATION_FIX
if (h.version < Handler::Version::NEW_TOWN_BUILDINGS)
{
std::set<BuildingID> overriddenBuildings;
h & overriddenBuildings;
}
if(!h.saving)
postDeserialize();
}
//////////////////////////////////////////////////////////////////////////
CBonusSystemNode & whatShouldBeAttached() override;
std::string nodeName() const override;
void updateMoraleBonusFromArmy() override;
void deserializationFix();
void postDeserialize();
void recreateBuildingsBonuses();
void setVisitingHero(CGHeroInstance *h);
void setGarrisonedHero(CGHeroInstance *h);
const CArmedInstance *getUpperArmy() const; //garrisoned hero if present or the town itself
std::string getNameTranslated() const;
std::string getNameTextID() const;
void setNameTextId(const std::string & newName);
//////////////////////////////////////////////////////////////////////////
bool passableFor(PlayerColor color) const override;
//int3 getSightCenter() const override; //"center" tile from which the sight distance is calculated
int getSightRadius() const override; //returns sight distance
BoatId 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
EGeneratorState shipyardStatus() const override;
const IObjectInterface * getObject() const override;
int getMarketEfficiency() const override; //=market count
std::set<EMarketMode> availableModes() const override;
std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const override;
ObjectInstanceID getObjInstanceID() const override;
void updateAppearance();
//////////////////////////////////////////////////////////////////////////
bool needsLastStack() const override;
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;
bool hasBuiltSomeTradeBuilding() const;
//checks if special building with type buildingID is constructed
bool hasBuilt(BuildingSubID::EBuildingSubID buildingID) const;
//checks if building is constructed and town has same subID
bool hasBuilt(const BuildingID & buildingID) const;
bool hasBuilt(const BuildingID & buildingID, FactionID townID) const;
void addBuilding(const BuildingID & buildingID);
void removeBuilding(const BuildingID & buildingID);
void removeAllBuildings();
std::set<BuildingID> getBuildings() const;
TResources getBuildingCost(const BuildingID & buildingID) const;
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;
LogicalExpression<BuildingID> genBuildingRequirements(const BuildingID & build, bool deep = false) const;
void mergeGarrisonOnSiege() const; // merge garrison into army of visiting hero
void removeCapitols(const PlayerColor & owner) const;
void clearArmy() const;
void addHeroToStructureVisitors(const CGHeroInstance *h, si64 structureInstanceID) const; //hero must be visiting or garrisoned in town
void deleteTownBonus(BuildingID bid);
/// Returns damage range for secondary towers of this town
DamageRange getTowerDamageRange() const;
/// Returns damage range for central tower(keep) of this town
DamageRange getKeepDamageRange() const;
const CTown * getTown() const;
/// INativeTerrainProvider
FactionID getFaction() const override;
TerrainId getNativeTerrain() const override;
CGTownInstance(IGameCallback *cb);
virtual ~CGTownInstance();
///IObjectInterface overrides
void newTurn(vstd::RNG & rand) const override;
void onHeroVisit(const CGHeroInstance * h) const override;
void onHeroLeave(const CGHeroInstance * h) const override;
void initObj(vstd::RNG & rand) override;
void pickRandomObject(vstd::RNG & rand) override;
void battleFinished(const CGHeroInstance * hero, const BattleResult & result) const override;
std::string getObjectName() const override;
void fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const override;
void afterAddToMap(CMap * map) override;
void afterRemoveFromMap(CMap * map) override;
inline bool isBattleOutsideTown(const CGHeroInstance * defendingHero) const
{
return defendingHero && garrisonHero && defendingHero != garrisonHero;
}
protected:
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
void serializeJsonOptions(JsonSerializeFormat & handler) override;
void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
private:
FactionID randomizeFaction(vstd::RNG & rand);
void setOwner(const PlayerColor & owner) const;
void onTownCaptured(const PlayerColor & winner) const;
int getDwellingBonus(const std::vector<CreatureID>& creatureIds, const std::vector<ConstTransitivePtr<CGDwelling> >& dwellings) const;
bool townEnvisagesBuilding(BuildingSubID::EBuildingSubID bid) const;
void initializeConfigurableBuildings(vstd::RNG & rand);
};
VCMI_LIB_NAMESPACE_END