mirror of
https://github.com/vcmi/vcmi.git
synced 2025-09-16 09:26:28 +02:00
Greatly simplify town buildings logic
This commit is contained in:
@@ -781,13 +781,6 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
|
||||
enterBuilding(building);
|
||||
break;
|
||||
|
||||
case BuildingSubID::BROTHERHOOD_OF_SWORD:
|
||||
if(upgrades == BuildingID::TAVERN)
|
||||
LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
|
||||
else
|
||||
enterBuilding(building);
|
||||
break;
|
||||
|
||||
case BuildingSubID::CASTLE_GATE:
|
||||
if (LOCPLINT->makingTurn)
|
||||
enterCastleGate();
|
||||
@@ -819,8 +812,11 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
|
||||
break;
|
||||
|
||||
default:
|
||||
if(upgrades == BuildingID::TAVERN)
|
||||
LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
|
||||
else
|
||||
enterBuilding(building);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@@ -4,7 +4,15 @@
|
||||
"mageGuild3": { "id" : 2, "upgrades" : "mageGuild2" },
|
||||
"mageGuild4": { "id" : 3, "upgrades" : "mageGuild3" },
|
||||
"mageGuild5": { "id" : 4, "upgrades" : "mageGuild4" },
|
||||
"tavern": { "id" : 5 },
|
||||
"tavern": {
|
||||
"id" : 5,
|
||||
"bonuses": [
|
||||
{
|
||||
"type": "MORALE",
|
||||
"val": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"shipyard": { "id" : 6 },
|
||||
"fort": { "id" : 7 },
|
||||
"citadel": { "id" : 8, "upgrades" : "fort" },
|
||||
@@ -37,5 +45,159 @@
|
||||
|
||||
"marketplace": { "id" : 14 },
|
||||
"resourceSilo": { "id" : 15, "requires" : [ "marketplace" ] },
|
||||
"blacksmith": { "id" : 16 }
|
||||
"blacksmith": { "id" : 16 },
|
||||
|
||||
// Previously hardcoded buildings that might be used by mods
|
||||
// Section 1 - building with bonuses during sieges
|
||||
"brotherhoodOfSword" : {
|
||||
"bonuses": [
|
||||
{
|
||||
"type": "MORALE",
|
||||
"val": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"fountainOfFortune" : {
|
||||
"bonuses": [
|
||||
{
|
||||
"type": "LUCK",
|
||||
"subtype": "primarySkill.knowledge",
|
||||
"val": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"spellPowerGarrisonBonus" : {
|
||||
"bonuses": [
|
||||
{
|
||||
"type": "PRIMARY_SKILL",
|
||||
"subtype": "primarySkill.knowledge",
|
||||
"val": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"attackGarrisonBonus" : {
|
||||
"bonuses": [
|
||||
{
|
||||
"type": "PRIMARY_SKILL",
|
||||
"subtype": "primarySkill.knowledge",
|
||||
"val": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"defenseGarrisonBonus" : {
|
||||
"bonuses": [
|
||||
{
|
||||
"type": "PRIMARY_SKILL",
|
||||
"subtype": "primarySkill.knowledge",
|
||||
"val": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"lighthouse" : {
|
||||
"bonuses": [
|
||||
{
|
||||
"propagator": "PLAYER_PROPAGATOR",
|
||||
"type": "MOVEMENT",
|
||||
"subtype": "heroMovementSea",
|
||||
"val": 500
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// Section 2 - buildings that are visitable by hero
|
||||
"stables": {
|
||||
"configuration" : {
|
||||
"visitMode" : "bonus",
|
||||
"rewards" : [
|
||||
{
|
||||
"message" : "@core.genrltxt.580",
|
||||
"movePoints" : 400,
|
||||
"bonuses" : [ { "type" : "MOVEMENT", "subtype" : "heroMovementLand", "val" : 400, "valueType" : "ADDITIVE_VALUE", "duration" : "ONE_WEEK"} ]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"manaVortex": {
|
||||
"configuration" : {
|
||||
"resetParameters" : {
|
||||
"period" : 7,
|
||||
"visitors" : true
|
||||
},
|
||||
"visitMode" : "hero", // Should be 'once' to match (somewhat buggy) H3 logic
|
||||
"rewards" : [
|
||||
{
|
||||
"limiter" : {
|
||||
"noneOf" : [ { "manaPercentage" : 200 } ]
|
||||
},
|
||||
"message" : "@core.genrltxt.579",
|
||||
"manaPercentage" : 200
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"attackVisitingBonus": {
|
||||
"configuration" : {
|
||||
"visitMode" : "hero",
|
||||
"rewards" : [
|
||||
{
|
||||
"message" : "@core.genrltxt.584",
|
||||
"primary" : { "attack" : 1 }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"defenceVisitingBonus": {
|
||||
"configuration" : {
|
||||
"visitMode" : "hero",
|
||||
"rewards" : [
|
||||
{
|
||||
"message" : "@core.genrltxt.585",
|
||||
"primary" : { "defence" : 1 }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"spellPowerVisitingBonus": {
|
||||
"configuration" : {
|
||||
"visitMode" : "hero",
|
||||
"rewards" : [
|
||||
{
|
||||
"message" : "@core.genrltxt.582",
|
||||
"primary" : { "spellpower" : 1 }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"knowledgeVisitingBonus": {
|
||||
"configuration" : {
|
||||
"visitMode" : "hero",
|
||||
"rewards" : [
|
||||
{
|
||||
"message" : "@core.genrltxt.581",
|
||||
"primary" : { "knowledge" : 1 }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"experienceVisitingBonus": {
|
||||
"configuration" : {
|
||||
"visitMode" : "hero",
|
||||
"rewards" : [
|
||||
{
|
||||
"message" : "@core.genrltxt.583",
|
||||
"heroExperience" : 1000
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@@ -174,19 +174,7 @@
|
||||
"horde1": { "id" : 18, "upgrades" : "dwellingLvl3" },
|
||||
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl3", "requires" : [ "horde1" ], "mode" : "auto" },
|
||||
"ship": { "id" : 20, "upgrades" : "shipyard" },
|
||||
"special2": {
|
||||
"type" : "configurable",
|
||||
"requires" : [ "dwellingLvl4" ],
|
||||
"configuration" : {
|
||||
"visitMode" : "bonus",
|
||||
"rewards" : [
|
||||
{
|
||||
"message" : "@core.genrltxt.580",
|
||||
"movePoints" : 400,
|
||||
"bonuses" : [ { "type" : "MOVEMENT", "subtype" : "heroMovementLand", "val" : 400, "valueType" : "ADDITIVE_VALUE", "duration" : "ONE_WEEK"} ]
|
||||
}
|
||||
]
|
||||
}
|
||||
"special2": { "type" : "stables", "requires" : [ "dwellingLvl4" ],
|
||||
},
|
||||
"special3": { "type" : "brotherhoodOfSword", "upgrades" : "tavern" },
|
||||
"grail": { "id" : 26, "mode" : "grail", "produce": { "gold": 5000 }, "bonuses": [ { "type": "MORALE", "val": 2, "propagator": "PLAYER_PROPAGATOR" } ] },
|
||||
|
@@ -174,39 +174,9 @@
|
||||
"special1": { "type" : "artifactMerchant", "requires" : [ "marketplace" ] },
|
||||
"horde1": { "id" : 18, "upgrades" : "dwellingLvl1" },
|
||||
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" },
|
||||
"special2": {
|
||||
"type" : "configurable",
|
||||
"requires" : [ "mageGuild1" ],
|
||||
"configuration" : {
|
||||
"resetParameters" : {
|
||||
"period" : 7,
|
||||
"visitors" : true
|
||||
},
|
||||
"visitMode" : "hero", // Should be 'once' to match (somewhat buggy) H3 logic
|
||||
"rewards" : [
|
||||
{
|
||||
"limiter" : {
|
||||
"noneOf" : [ { "manaPercentage" : 200 } ]
|
||||
},
|
||||
"message" : "@core.genrltxt.579",
|
||||
"manaPercentage" : 200
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"special2": { "type" : "manaVortex", "requires" : [ "mageGuild1" ] },
|
||||
"special3": { "type" : "portalOfSummoning" },
|
||||
"special4": {
|
||||
"type" : "configurable",
|
||||
"configuration" : {
|
||||
"visitMode" : "hero",
|
||||
"rewards" : [
|
||||
{
|
||||
"message" : "@core.genrltxt.583",
|
||||
"heroExperience" : 1000
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"special4": { "type" : "experienceVisitingBonus" },
|
||||
"grail": { "id" : 26, "mode" : "grail", "produce": { "gold": 5000 },
|
||||
"bonuses": [ { "type": "PRIMARY_SKILL", "subtype": "primarySkill.spellpower", "val": 12 } ] },
|
||||
|
||||
|
@@ -169,19 +169,7 @@
|
||||
"resourceSilo": { "produce": { "wood": 1, "ore": 1 } },
|
||||
"blacksmith": { },
|
||||
|
||||
"special1": {
|
||||
"type" : "configurable",
|
||||
"requires" : [ "allOf", [ "townHall" ], [ "special2" ] ],
|
||||
"configuration" : {
|
||||
"visitMode" : "hero",
|
||||
"rewards" : [
|
||||
{
|
||||
"message" : "@core.genrltxt.585",
|
||||
"primary" : { "defence" : 1 }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"special1": { "type" : "defenceVisitingBonus", "requires" : [ "allOf", [ "townHall" ], [ "special2" ] ] },
|
||||
"horde1": { "id" : 18, "upgrades" : "dwellingLvl1" },
|
||||
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" },
|
||||
"ship": { "id" : 20, "upgrades" : "shipyard" },
|
||||
|
@@ -175,19 +175,7 @@
|
||||
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" },
|
||||
"special2": { "type" : "spellPowerGarrisonBonus", "requires" : [ "fort" ] },
|
||||
"special3": { "type" : "castleGate", "requires" : [ "citadel" ] },
|
||||
"special4": {
|
||||
"type" : "configurable",
|
||||
"requires" : [ "mageGuild1" ],
|
||||
"configuration" : {
|
||||
"visitMode" : "hero",
|
||||
"rewards" : [
|
||||
{
|
||||
"message" : "@core.genrltxt.582",
|
||||
"primary" : { "spellpower" : 1 }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"special4": { "type" : "spellPowerVisitingBonus", "requires" : [ "mageGuild1" ] },
|
||||
"horde2": { "id" : 24, "upgrades" : "dwellingLvl3" },
|
||||
"horde2Upgr": { "id" : 25, "upgrades" : "dwellingUpLvl3", "requires" : [ "horde2" ], "mode" : "auto" },
|
||||
"grail": { "id" : 26, "mode" : "grail", "produce": { "gold": 5000 }},
|
||||
|
@@ -174,19 +174,7 @@
|
||||
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl2", "requires" : [ "horde1" ], "mode" : "auto" },
|
||||
"special2": { "type" : "lookoutTower", "height" : "high", "requires" : [ "fort" ] },
|
||||
"special3": { "type" : "library", "requires" : [ "mageGuild1" ] },
|
||||
"special4": {
|
||||
"type" : "configurable",
|
||||
"requires" : [ "mageGuild1" ],
|
||||
"configuration" : {
|
||||
"visitMode" : "hero",
|
||||
"rewards" : [
|
||||
{
|
||||
"message" : "@core.genrltxt.581",
|
||||
"primary" : { "knowledge" : 1 }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"special4": { "type" : "knowledgeVisitingBonus", "requires" : [ "mageGuild1" ] },
|
||||
"grail": { "height" : "skyship", "produce" : { "gold": 5000 }, "bonuses": [ { "type": "PRIMARY_SKILL", "subtype": "primarySkill.knowledge", "val": 15 } ] },
|
||||
|
||||
"dwellingLvl1": { "id" : 30, "requires" : [ "fort" ] },
|
||||
|
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"type" : {
|
||||
"type" : "string",
|
||||
"enum" : [ "mysticPond", "artifactMerchant", "freelancersGuild", "magicUniversity", "castleGate", "creatureTransformer", "portalOfSummoning", "ballistaYard", "lookoutTower", "library", "brotherhoodOfSword", "fountainOfFortune", "spellPowerGarrisonBonus", "attackGarrisonBonus", "defenseGarrisonBonus", "escapeTunnel", "lighthouse", "treasury", "thievesGuild", "bank", "configurable" ],
|
||||
"enum" : [ "mysticPond", "artifactMerchant", "freelancersGuild", "magicUniversity", "castleGate", "creatureTransformer", "portalOfSummoning", "ballistaYard", "lookoutTower", "library", "brotherhoodOfSword", "fountainOfFortune", "spellPowerGarrisonBonus", "attackGarrisonBonus", "defenseGarrisonBonus", "escapeTunnel", "lighthouse", "treasury", "thievesGuild", "bank", "configurable", "stables", "manaVortex", "attackVisitingBonus", "defenceVisitingBonus", "spellPowerVisitingBonus", "knowledgeVisitingBonus", "experienceVisitingBonus" ],
|
||||
"description" : "Subtype for some special buildings"
|
||||
},
|
||||
"mode" : {
|
||||
|
@@ -25,8 +25,6 @@ namespace BuildingSubID
|
||||
{
|
||||
DEFAULT = -50,
|
||||
NONE = -1,
|
||||
STABLES,
|
||||
BROTHERHOOD_OF_SWORD,
|
||||
CASTLE_GATE,
|
||||
CREATURE_TRANSFORMER,
|
||||
MYSTIC_POND,
|
||||
@@ -34,26 +32,15 @@ namespace BuildingSubID
|
||||
ARTIFACT_MERCHANT,
|
||||
LOOKOUT_TOWER,
|
||||
LIBRARY,
|
||||
MANA_VORTEX,
|
||||
PORTAL_OF_SUMMONING,
|
||||
ESCAPE_TUNNEL,
|
||||
FREELANCERS_GUILD,
|
||||
BALLISTA_YARD,
|
||||
ATTACK_VISITING_BONUS,
|
||||
MAGIC_UNIVERSITY,
|
||||
SPELL_POWER_GARRISON_BONUS,
|
||||
ATTACK_GARRISON_BONUS,
|
||||
DEFENSE_GARRISON_BONUS,
|
||||
DEFENSE_VISITING_BONUS,
|
||||
SPELL_POWER_VISITING_BONUS,
|
||||
KNOWLEDGE_VISITING_BONUS,
|
||||
EXPERIENCE_VISITING_BONUS,
|
||||
LIGHTHOUSE,
|
||||
TREASURY,
|
||||
THIEVES_GUILD,
|
||||
BANK,
|
||||
CUSTOM_VISITING_BONUS,
|
||||
CUSTOM_VISITING_REWARD
|
||||
CUSTOM_VISITING_BONUS
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -185,26 +185,13 @@ namespace MappedKeys
|
||||
{ "creatureTransformer", BuildingSubID::CREATURE_TRANSFORMER },//only skeleton transformer yet
|
||||
{ "portalOfSummoning", BuildingSubID::PORTAL_OF_SUMMONING },
|
||||
{ "ballistaYard", BuildingSubID::BALLISTA_YARD },
|
||||
{ "stables", BuildingSubID::STABLES },
|
||||
{ "manaVortex", BuildingSubID::MANA_VORTEX },
|
||||
{ "lookoutTower", BuildingSubID::LOOKOUT_TOWER },
|
||||
{ "library", BuildingSubID::LIBRARY },
|
||||
{ "brotherhoodOfSword", BuildingSubID::BROTHERHOOD_OF_SWORD },//morale garrison bonus
|
||||
{ "fountainOfFortune", BuildingSubID::FOUNTAIN_OF_FORTUNE },//luck garrison bonus
|
||||
{ "spellPowerGarrisonBonus", BuildingSubID::SPELL_POWER_GARRISON_BONUS },//such as 'stormclouds', but this name is not ok for good towns
|
||||
{ "attackGarrisonBonus", BuildingSubID::ATTACK_GARRISON_BONUS },
|
||||
{ "defenseGarrisonBonus", BuildingSubID::DEFENSE_GARRISON_BONUS },
|
||||
{ "escapeTunnel", BuildingSubID::ESCAPE_TUNNEL },
|
||||
{ "attackVisitingBonus", BuildingSubID::ATTACK_VISITING_BONUS },
|
||||
{ "defenceVisitingBonus", BuildingSubID::DEFENSE_VISITING_BONUS },
|
||||
{ "spellPowerVisitingBonus", BuildingSubID::SPELL_POWER_VISITING_BONUS },
|
||||
{ "knowledgeVisitingBonus", BuildingSubID::KNOWLEDGE_VISITING_BONUS },
|
||||
{ "experienceVisitingBonus", BuildingSubID::EXPERIENCE_VISITING_BONUS },
|
||||
{ "lighthouse", BuildingSubID::LIGHTHOUSE },
|
||||
{ "treasury", BuildingSubID::TREASURY },
|
||||
{ "thievesGuild", BuildingSubID::THIEVES_GUILD },
|
||||
{ "bank", BuildingSubID::BANK },
|
||||
{ "configurable", BuildingSubID::CUSTOM_VISITING_REWARD}
|
||||
{ "bank", BuildingSubID::BANK }
|
||||
};
|
||||
|
||||
static const std::map<std::string, EMarketMode> MARKET_NAMES_TO_TYPES =
|
||||
|
@@ -89,23 +89,6 @@ public:
|
||||
return bid == BuildingID::MARKETPLACE || subId == BuildingSubID::ARTIFACT_MERCHANT || subId == BuildingSubID::FREELANCERS_GUILD;
|
||||
}
|
||||
|
||||
STRONG_INLINE
|
||||
bool IsWeekBonus() const
|
||||
{
|
||||
return subId == BuildingSubID::STABLES || subId == BuildingSubID::MANA_VORTEX;
|
||||
}
|
||||
|
||||
STRONG_INLINE
|
||||
bool IsVisitingBonus() const
|
||||
{
|
||||
return subId == BuildingSubID::ATTACK_VISITING_BONUS ||
|
||||
subId == BuildingSubID::DEFENSE_VISITING_BONUS ||
|
||||
subId == BuildingSubID::SPELL_POWER_VISITING_BONUS ||
|
||||
subId == BuildingSubID::KNOWLEDGE_VISITING_BONUS ||
|
||||
subId == BuildingSubID::EXPERIENCE_VISITING_BONUS ||
|
||||
subId == BuildingSubID::CUSTOM_VISITING_BONUS;
|
||||
}
|
||||
|
||||
void addNewBonus(const std::shared_ptr<Bonus> & b, BonusList & bonusList) const;
|
||||
|
||||
friend class CTownHandler;
|
||||
|
@@ -78,14 +78,4 @@ BuildingID CTown::getBuildingType(BuildingSubID::EBuildingSubID subID) const
|
||||
return building == nullptr ? BuildingID::NONE : building->bid.num;
|
||||
}
|
||||
|
||||
std::string CTown::getGreeting(BuildingSubID::EBuildingSubID subID) const
|
||||
{
|
||||
return vstd::find_or(specialMessages, subID, std::string());
|
||||
}
|
||||
|
||||
void CTown::setGreeting(BuildingSubID::EBuildingSubID subID, const std::string & message) const
|
||||
{
|
||||
specialMessages.insert(std::pair<BuildingSubID::EBuildingSubID, const std::string>(subID, message));
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@@ -49,8 +49,6 @@ public:
|
||||
std::string getBuildingScope() const;
|
||||
std::set<si32> getAllBuildings() const;
|
||||
const CBuilding * getSpecialBuilding(BuildingSubID::EBuildingSubID subID) const;
|
||||
std::string getGreeting(BuildingSubID::EBuildingSubID subID) const;
|
||||
void setGreeting(BuildingSubID::EBuildingSubID subID, const std::string & message) const; //may affect only mutable field
|
||||
BuildingID getBuildingType(BuildingSubID::EBuildingSubID subID) const;
|
||||
|
||||
std::string getRandomNameTextID(size_t index) const;
|
||||
@@ -106,10 +104,6 @@ public:
|
||||
std::string towerIconLarge;
|
||||
|
||||
} clientInfo;
|
||||
|
||||
private:
|
||||
///generated bonusing buildings messages for all towns of this type.
|
||||
mutable std::map<BuildingSubID::EBuildingSubID, const std::string> specialMessages; //may be changed by CGTownBuilding::getVisitingBonusGreeting() const
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@@ -242,43 +242,6 @@ void CTownHandler::loadBuildingRequirements(CBuilding * building, const JsonNode
|
||||
bidsToLoad.push_back(hlp);
|
||||
}
|
||||
|
||||
void CTownHandler::addBonusesForVanilaBuilding(CBuilding * building) const
|
||||
{
|
||||
std::shared_ptr<Bonus> b;
|
||||
static const TPropagatorPtr playerPropagator = std::make_shared<CPropagatorNodeType>(CBonusSystemNode::ENodeTypes::PLAYER);
|
||||
|
||||
if(building->bid == BuildingID::TAVERN)
|
||||
{
|
||||
b = createBonus(building, BonusType::MORALE, +1);
|
||||
}
|
||||
|
||||
switch(building->subId)
|
||||
{
|
||||
case BuildingSubID::BROTHERHOOD_OF_SWORD:
|
||||
b = createBonus(building, BonusType::MORALE, +2);
|
||||
building->overrideBids.insert(BuildingID::TAVERN);
|
||||
break;
|
||||
case BuildingSubID::FOUNTAIN_OF_FORTUNE:
|
||||
b = createBonus(building, BonusType::LUCK, +2);
|
||||
break;
|
||||
case BuildingSubID::SPELL_POWER_GARRISON_BONUS:
|
||||
b = createBonus(building, BonusType::PRIMARY_SKILL, +2, BonusSubtypeID(PrimarySkill::SPELL_POWER));
|
||||
break;
|
||||
case BuildingSubID::ATTACK_GARRISON_BONUS:
|
||||
b = createBonus(building, BonusType::PRIMARY_SKILL, +2, BonusSubtypeID(PrimarySkill::ATTACK));
|
||||
break;
|
||||
case BuildingSubID::DEFENSE_GARRISON_BONUS:
|
||||
b = createBonus(building, BonusType::PRIMARY_SKILL, +2, BonusSubtypeID(PrimarySkill::DEFENSE));
|
||||
break;
|
||||
case BuildingSubID::LIGHTHOUSE:
|
||||
b = createBonus(building, BonusType::MOVEMENT, +500, BonusCustomSubtype::heroMovementSea, playerPropagator);
|
||||
break;
|
||||
}
|
||||
|
||||
if(b)
|
||||
building->addNewBonus(b, building->buildingBonuses);
|
||||
}
|
||||
|
||||
std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType type, int val) const
|
||||
{
|
||||
return createBonus(build, type, val, BonusSubtypeID(), emptyPropagator());
|
||||
@@ -355,17 +318,12 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons
|
||||
ret->resources = TResources(source["cost"]);
|
||||
ret->produce = TResources(source["produce"]);
|
||||
|
||||
if(ret->bid == BuildingID::TAVERN)
|
||||
addBonusesForVanilaBuilding(ret);
|
||||
else if(ret->bid.IsSpecialOrGrail())
|
||||
if(ret->bid.IsSpecialOrGrail())
|
||||
{
|
||||
loadSpecialBuildingBonuses(source["bonuses"], ret->buildingBonuses, ret);
|
||||
|
||||
if(ret->buildingBonuses.empty())
|
||||
{
|
||||
ret->subId = vstd::find_or(MappedKeys::SPECIAL_BUILDINGS, source["type"].String(), BuildingSubID::NONE);
|
||||
addBonusesForVanilaBuilding(ret);
|
||||
}
|
||||
|
||||
loadSpecialBuildingBonuses(source["onVisitBonuses"], ret->onVisitBonuses, ret);
|
||||
|
||||
@@ -378,34 +336,24 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons
|
||||
bonus->sid = BonusSourceID(ret->getUniqueTypeID());
|
||||
}
|
||||
|
||||
if(ret->subId == BuildingSubID::CUSTOM_VISITING_REWARD)
|
||||
if(!source["configuration"].isNull())
|
||||
ret->rewardableObjectInfo.init(source["configuration"], ret->getBaseTextID());
|
||||
}
|
||||
//MODS COMPATIBILITY FOR 0.96
|
||||
if(!ret->produce.nonZero())
|
||||
if(!ret->produce.nonZero() && ret->bid == BuildingID::RESOURCE_SILO)
|
||||
{
|
||||
switch (ret->bid.toEnum()) {
|
||||
break; case BuildingID::VILLAGE_HALL: ret->produce[EGameResID::GOLD] = 500;
|
||||
break; case BuildingID::TOWN_HALL : ret->produce[EGameResID::GOLD] = 1000;
|
||||
break; case BuildingID::CITY_HALL : ret->produce[EGameResID::GOLD] = 2000;
|
||||
break; case BuildingID::CAPITOL : ret->produce[EGameResID::GOLD] = 4000;
|
||||
break; case BuildingID::GRAIL : ret->produce[EGameResID::GOLD] = 5000;
|
||||
break; case BuildingID::RESOURCE_SILO :
|
||||
{
|
||||
switch (ret->town->primaryRes.toEnum())
|
||||
{
|
||||
case EGameResID::GOLD:
|
||||
ret->produce[ret->town->primaryRes] = 500;
|
||||
break;
|
||||
case EGameResID::WOOD_AND_ORE:
|
||||
ret->produce[EGameResID::WOOD] = 1;
|
||||
ret->produce[EGameResID::ORE] = 1;
|
||||
break;
|
||||
default:
|
||||
ret->produce[ret->town->primaryRes] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (ret->town->primaryRes.toEnum())
|
||||
{
|
||||
case EGameResID::GOLD:
|
||||
ret->produce[ret->town->primaryRes] = 500;
|
||||
break;
|
||||
case EGameResID::WOOD_AND_ORE:
|
||||
ret->produce[EGameResID::WOOD] = 1;
|
||||
ret->produce[EGameResID::ORE] = 1;
|
||||
break;
|
||||
default:
|
||||
ret->produce[ret->town->primaryRes] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
loadBuildingRequirements(ret, source["requires"], requirementsToLoad);
|
||||
|
@@ -80,7 +80,6 @@ public:
|
||||
|
||||
void loadObject(std::string scope, std::string name, const JsonNode & data) override;
|
||||
void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
|
||||
void addBonusesForVanilaBuilding(CBuilding * building) const;
|
||||
|
||||
void loadCustom() override;
|
||||
void afterLoadFinalization() override;
|
||||
|
@@ -28,9 +28,10 @@ CGTownBuilding::CGTownBuilding(IGameCallback * cb)
|
||||
, town(nullptr)
|
||||
{}
|
||||
|
||||
CGTownBuilding::CGTownBuilding(CGTownInstance * town)
|
||||
CGTownBuilding::CGTownBuilding(CGTownInstance * town, const BuildingID & index)
|
||||
: IObjectInterface(town->cb)
|
||||
, town(town)
|
||||
, bID(index)
|
||||
{}
|
||||
|
||||
PlayerColor CGTownBuilding::getOwner() const
|
||||
@@ -58,272 +59,13 @@ int3 CGTownBuilding::getPosition() const
|
||||
return town->getPosition();
|
||||
}
|
||||
|
||||
std::string CGTownBuilding::getVisitingBonusGreeting() const
|
||||
{
|
||||
auto bonusGreeting = town->getTown()->getGreeting(bType);
|
||||
|
||||
if(!bonusGreeting.empty())
|
||||
return bonusGreeting;
|
||||
|
||||
switch(bType)
|
||||
{
|
||||
case BuildingSubID::MANA_VORTEX:
|
||||
bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingManaVortex"));
|
||||
break;
|
||||
case BuildingSubID::KNOWLEDGE_VISITING_BONUS:
|
||||
bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingKnowledge"));
|
||||
break;
|
||||
case BuildingSubID::SPELL_POWER_VISITING_BONUS:
|
||||
bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingSpellPower"));
|
||||
break;
|
||||
case BuildingSubID::ATTACK_VISITING_BONUS:
|
||||
bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingAttack"));
|
||||
break;
|
||||
case BuildingSubID::EXPERIENCE_VISITING_BONUS:
|
||||
bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingExperience"));
|
||||
break;
|
||||
case BuildingSubID::DEFENSE_VISITING_BONUS:
|
||||
bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingDefence"));
|
||||
break;
|
||||
}
|
||||
auto buildingName = town->getTown()->getSpecialBuilding(bType)->getNameTranslated();
|
||||
|
||||
if(bonusGreeting.empty())
|
||||
{
|
||||
bonusGreeting = "Error: Bonus greeting for '%s' is not localized.";
|
||||
logGlobal->error("'%s' building of '%s' faction has not localized bonus greeting.", buildingName, town->getTown()->faction->getNameTranslated());
|
||||
}
|
||||
boost::algorithm::replace_first(bonusGreeting, "%s", buildingName);
|
||||
town->getTown()->setGreeting(bType, bonusGreeting);
|
||||
return bonusGreeting;
|
||||
}
|
||||
|
||||
std::string CGTownBuilding::getCustomBonusGreeting(const Bonus & bonus) const
|
||||
{
|
||||
if(bonus.type == BonusType::TOWN_MAGIC_WELL)
|
||||
{
|
||||
MetaString wellGreeting = MetaString::createFromTextID("vcmi.townHall.greetingInTownMagicWell");
|
||||
|
||||
wellGreeting.replaceTextID(town->getTown()->getSpecialBuilding(bType)->getNameTextID());
|
||||
return wellGreeting.toString();
|
||||
}
|
||||
|
||||
MetaString greeting = MetaString::createFromTextID("vcmi.townHall.greetingCustomBonus");
|
||||
|
||||
std::string paramTextID;
|
||||
std::string until;
|
||||
|
||||
if(bonus.type == BonusType::MORALE)
|
||||
paramTextID = "core.genrltxt.384"; // Morale
|
||||
|
||||
if(bonus.type == BonusType::LUCK)
|
||||
paramTextID = "core.genrltxt.385"; // Luck
|
||||
|
||||
greeting.replaceTextID(town->getTown()->getSpecialBuilding(bType)->getNameTextID());
|
||||
greeting.replaceNumber(bonus.val);
|
||||
greeting.replaceTextID(paramTextID);
|
||||
|
||||
if (bonus.duration == BonusDuration::ONE_BATTLE)
|
||||
greeting.replaceTextID("vcmi.townHall.greetingCustomUntil");
|
||||
else
|
||||
greeting.replaceRawString(".");
|
||||
|
||||
return greeting.toString();
|
||||
}
|
||||
|
||||
COPWBonus::COPWBonus(IGameCallback *cb)
|
||||
: CGTownBuilding(cb)
|
||||
{}
|
||||
|
||||
COPWBonus::COPWBonus(const BuildingID & bid, BuildingSubID::EBuildingSubID subId, CGTownInstance * cgTown)
|
||||
: CGTownBuilding(cgTown)
|
||||
{
|
||||
bID = bid;
|
||||
bType = subId;
|
||||
indexOnTV = static_cast<si32>(town->bonusingBuildings.size());
|
||||
}
|
||||
|
||||
void COPWBonus::setProperty(ObjProperty what, ObjPropertyID identifier)
|
||||
{
|
||||
switch (what)
|
||||
{
|
||||
case ObjProperty::VISITORS:
|
||||
visitors.insert(identifier.as<ObjectInstanceID>());
|
||||
break;
|
||||
case ObjProperty::STRUCTURE_CLEAR_VISITORS:
|
||||
visitors.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
|
||||
{
|
||||
ObjectInstanceID heroID = h->id;
|
||||
if(town->hasBuilt(bID))
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = h->tempOwner;
|
||||
|
||||
switch (this->bType)
|
||||
{
|
||||
case BuildingSubID::STABLES:
|
||||
if(!h->hasBonusFrom(BonusSource::OBJECT_TYPE, BonusSourceID(Obj(Obj::STABLES)))) //does not stack with advMap Stables
|
||||
{
|
||||
GiveBonus gb;
|
||||
gb.bonus = Bonus(BonusDuration::ONE_WEEK, BonusType::MOVEMENT, BonusSource::OBJECT_TYPE, 600, BonusSourceID(Obj(Obj::STABLES)), BonusCustomSubtype::heroMovementLand);
|
||||
gb.id = heroID;
|
||||
cb->giveHeroBonus(&gb);
|
||||
|
||||
cb->setMovePoints(heroID, 600, false);
|
||||
|
||||
iw.text.appendRawString(VLC->generaltexth->allTexts[580]);
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
break;
|
||||
|
||||
case BuildingSubID::MANA_VORTEX:
|
||||
if(visitors.empty())
|
||||
{
|
||||
if(h->mana < h->manaLimit() * 2)
|
||||
{
|
||||
cb->setManaPoints (heroID, 2 * h->manaLimit());
|
||||
//TODO: investigate line below
|
||||
//cb->setObjProperty (town->id, ObjProperty::VISITED, true);
|
||||
iw.text.appendRawString(getVisitingBonusGreeting());
|
||||
cb->showInfoDialog(&iw);
|
||||
town->addHeroToStructureVisitors(h, indexOnTV);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTownBonus::CTownBonus(IGameCallback *cb)
|
||||
: CGTownBuilding(cb)
|
||||
{}
|
||||
|
||||
CTownBonus::CTownBonus(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * cgTown)
|
||||
: CGTownBuilding(cgTown)
|
||||
{
|
||||
bID = index;
|
||||
bType = subId;
|
||||
indexOnTV = static_cast<si32>(town->bonusingBuildings.size());
|
||||
}
|
||||
|
||||
void CTownBonus::setProperty(ObjProperty what, ObjPropertyID identifier)
|
||||
{
|
||||
if(what == ObjProperty::VISITORS)
|
||||
visitors.insert(identifier.as<ObjectInstanceID>());
|
||||
}
|
||||
|
||||
void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
|
||||
{
|
||||
ObjectInstanceID heroID = h->id;
|
||||
if(town->hasBuilt(bID) && visitors.find(heroID) == visitors.end())
|
||||
{
|
||||
si64 val = 0;
|
||||
InfoWindow iw;
|
||||
PrimarySkill what = PrimarySkill::NONE;
|
||||
|
||||
switch(bType)
|
||||
{
|
||||
case BuildingSubID::KNOWLEDGE_VISITING_BONUS: //wall of knowledge
|
||||
what = PrimarySkill::KNOWLEDGE;
|
||||
val = 1;
|
||||
iw.components.emplace_back(ComponentType::PRIM_SKILL, PrimarySkill::KNOWLEDGE, 1);
|
||||
break;
|
||||
|
||||
case BuildingSubID::SPELL_POWER_VISITING_BONUS: //order of fire
|
||||
what = PrimarySkill::SPELL_POWER;
|
||||
val = 1;
|
||||
iw.components.emplace_back(ComponentType::PRIM_SKILL, PrimarySkill::SPELL_POWER, 1);
|
||||
break;
|
||||
|
||||
case BuildingSubID::ATTACK_VISITING_BONUS: //hall of Valhalla
|
||||
what = PrimarySkill::ATTACK;
|
||||
val = 1;
|
||||
iw.components.emplace_back(ComponentType::PRIM_SKILL, PrimarySkill::ATTACK, 1);
|
||||
break;
|
||||
|
||||
case BuildingSubID::EXPERIENCE_VISITING_BONUS: //academy of battle scholars
|
||||
what = PrimarySkill::EXPERIENCE;
|
||||
val = static_cast<int>(h->calculateXp(1000));
|
||||
iw.components.emplace_back(ComponentType::EXPERIENCE, val);
|
||||
break;
|
||||
|
||||
case BuildingSubID::DEFENSE_VISITING_BONUS: //cage of warlords
|
||||
what = PrimarySkill::DEFENSE;
|
||||
val = 1;
|
||||
iw.components.emplace_back(ComponentType::PRIM_SKILL, PrimarySkill::DEFENSE, 1);
|
||||
break;
|
||||
|
||||
case BuildingSubID::CUSTOM_VISITING_BONUS:
|
||||
const auto building = town->getTown()->buildings.at(bID);
|
||||
if(!h->hasBonusFrom(BonusSource::TOWN_STRUCTURE, BonusSourceID(building->getUniqueTypeID())))
|
||||
{
|
||||
const auto & bonuses = building->onVisitBonuses;
|
||||
applyBonuses(const_cast<CGHeroInstance *>(h), bonuses);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(what != PrimarySkill::NONE)
|
||||
{
|
||||
iw.player = cb->getOwner(heroID);
|
||||
iw.text.appendRawString(getVisitingBonusGreeting());
|
||||
cb->showInfoDialog(&iw);
|
||||
if (what == PrimarySkill::EXPERIENCE)
|
||||
cb->giveExperience(cb->getHero(heroID), val);
|
||||
else
|
||||
cb->changePrimSkill(cb->getHero(heroID), what, val);
|
||||
|
||||
town->addHeroToStructureVisitors(h, indexOnTV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTownBonus::applyBonuses(CGHeroInstance * h, const BonusList & bonuses) const
|
||||
{
|
||||
auto addToVisitors = false;
|
||||
|
||||
for(const auto & bonus : bonuses)
|
||||
{
|
||||
GiveBonus gb;
|
||||
InfoWindow iw;
|
||||
|
||||
if(bonus->type == BonusType::TOWN_MAGIC_WELL)
|
||||
{
|
||||
if(h->mana >= h->manaLimit())
|
||||
return;
|
||||
cb->setManaPoints(h->id, h->manaLimit());
|
||||
bonus->duration = BonusDuration::ONE_DAY;
|
||||
}
|
||||
gb.bonus = * bonus;
|
||||
gb.id = h->id;
|
||||
cb->giveHeroBonus(&gb);
|
||||
|
||||
if(bonus->duration == BonusDuration::PERMANENT)
|
||||
addToVisitors = true;
|
||||
|
||||
iw.player = cb->getOwner(h->id);
|
||||
iw.text.appendRawString(getCustomBonusGreeting(gb.bonus));
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
if(addToVisitors)
|
||||
town->addHeroToStructureVisitors(h, indexOnTV);
|
||||
}
|
||||
|
||||
CTownRewardableBuilding::CTownRewardableBuilding(IGameCallback *cb)
|
||||
: CGTownBuilding(cb)
|
||||
{}
|
||||
|
||||
CTownRewardableBuilding::CTownRewardableBuilding(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * cgTown, vstd::RNG & rand)
|
||||
: CGTownBuilding(cgTown)
|
||||
CTownRewardableBuilding::CTownRewardableBuilding(CGTownInstance * town, const BuildingID & index, vstd::RNG & rand)
|
||||
: CGTownBuilding(town, index)
|
||||
{
|
||||
bID = index;
|
||||
bType = subId;
|
||||
indexOnTV = static_cast<si32>(town->bonusingBuildings.size());
|
||||
initObj(rand);
|
||||
}
|
||||
|
||||
@@ -336,7 +78,7 @@ void CTownRewardableBuilding::initObj(vstd::RNG & rand)
|
||||
Rewardable::Configuration CTownRewardableBuilding::generateConfiguration(vstd::RNG & rand) const
|
||||
{
|
||||
Rewardable::Configuration result;
|
||||
auto building = town->town->buildings.at(bID);
|
||||
auto building = town->town->buildings.at(getBuildingType());
|
||||
|
||||
building->rewardableObjectInfo.configureObject(result, rand, cb);
|
||||
for(auto & rewardInfo : result.info)
|
||||
@@ -355,11 +97,11 @@ void CTownRewardableBuilding::newTurn(vstd::RNG & rand) const
|
||||
if (configuration.resetParameters.period != 0 && cb->getDate(Date::DAY) > 1 && ((cb->getDate(Date::DAY)-1) % configuration.resetParameters.period) == 0)
|
||||
{
|
||||
auto newConfiguration = generateConfiguration(rand);
|
||||
cb->setRewardableObjectConfiguration(town->id, bID, newConfiguration);
|
||||
cb->setRewardableObjectConfiguration(town->id, getBuildingType(), newConfiguration);
|
||||
|
||||
if(configuration.resetParameters.visitors)
|
||||
{
|
||||
cb->setObjPropertyValue(town->id, ObjProperty::STRUCTURE_CLEAR_VISITORS, indexOnTV);
|
||||
cb->setObjPropertyValue(town->id, ObjProperty::STRUCTURE_CLEAR_VISITORS, getBuildingType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,7 +148,7 @@ void CTownRewardableBuilding::blockingDialogAnswered(const CGHeroInstance *hero,
|
||||
|
||||
void CTownRewardableBuilding::grantReward(ui32 rewardID, const CGHeroInstance * hero) const
|
||||
{
|
||||
town->addHeroToStructureVisitors(hero, indexOnTV);
|
||||
town->addHeroToStructureVisitors(hero, getBuildingType());
|
||||
|
||||
grantRewardBeforeLevelup(cb, configuration.info.at(rewardID), hero);
|
||||
|
||||
@@ -429,7 +171,7 @@ bool CTownRewardableBuilding::wasVisitedBefore(const CGHeroInstance * contextHer
|
||||
return false; //not supported
|
||||
case Rewardable::VISIT_BONUS:
|
||||
{
|
||||
const auto building = town->getTown()->buildings.at(bID);
|
||||
const auto building = town->getTown()->buildings.at(getBuildingType());
|
||||
return contextHero->hasBonusFrom(BonusSource::TOWN_STRUCTURE, BonusSourceID(building->getUniqueTypeID()));
|
||||
}
|
||||
case Rewardable::VISIT_HERO:
|
||||
@@ -448,7 +190,7 @@ void CTownRewardableBuilding::onHeroVisit(const CGHeroInstance *h) const
|
||||
auto vi = configuration.info.at(index);
|
||||
logGlobal->debug("Granting reward %d. Message says: %s", index, vi.message.toString());
|
||||
|
||||
town->addHeroToStructureVisitors(h, indexOnTV); //adding to visitors
|
||||
town->addHeroToStructureVisitors(h, getBuildingType()); //adding to visitors
|
||||
|
||||
InfoWindow iw;
|
||||
iw.player = h->tempOwner;
|
||||
@@ -476,7 +218,8 @@ void CTownRewardableBuilding::onHeroVisit(const CGHeroInstance *h) const
|
||||
cb->showBlockingDialog(&sd);
|
||||
};
|
||||
|
||||
if(!town->hasBuilt(bID))
|
||||
assert(town->hasBuilt(getBuildingType()));
|
||||
if(!town->hasBuilt(getBuildingType()))
|
||||
return;
|
||||
|
||||
if(!wasVisitedBefore(h))
|
||||
|
@@ -22,31 +22,18 @@ class DLL_LINKAGE CGTownBuilding : public IObjectInterface
|
||||
{
|
||||
///basic class for town structures handled as map objects
|
||||
public:
|
||||
CGTownBuilding(CGTownInstance * town);
|
||||
CGTownBuilding(CGTownInstance * town, const BuildingID & index);
|
||||
CGTownBuilding(IGameCallback *cb);
|
||||
|
||||
si32 indexOnTV = 0; //identifies its index on towns vector
|
||||
|
||||
CGTownInstance * town;
|
||||
|
||||
STRONG_INLINE
|
||||
BuildingSubID::EBuildingSubID getBuildingSubtype() const
|
||||
{
|
||||
return bType;
|
||||
}
|
||||
|
||||
STRONG_INLINE
|
||||
const BuildingID & getBuildingType() const
|
||||
{
|
||||
return bID;
|
||||
}
|
||||
|
||||
STRONG_INLINE
|
||||
void setBuildingSubtype(BuildingSubID::EBuildingSubID subId)
|
||||
{
|
||||
bType = subId;
|
||||
}
|
||||
|
||||
PlayerColor getOwner() const override;
|
||||
MapObjectID getObjGroupIndex() const override;
|
||||
MapObjectSubID getObjTypeIndex() const override;
|
||||
@@ -57,55 +44,23 @@ public:
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & bID;
|
||||
h & indexOnTV;
|
||||
h & bType;
|
||||
}
|
||||
if (h.version >= Handler::Version::NEW_TOWN_BUILDINGS)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
else
|
||||
{
|
||||
si32 indexOnTV = 0; //identifies its index on towns vector
|
||||
BuildingSubID::EBuildingSubID bType = BuildingSubID::NONE;
|
||||
|
||||
protected:
|
||||
BuildingID bID; //from buildig list
|
||||
BuildingSubID::EBuildingSubID bType = BuildingSubID::NONE;
|
||||
h & indexOnTV;
|
||||
h & bType;
|
||||
|
||||
std::string getVisitingBonusGreeting() const;
|
||||
std::string getCustomBonusGreeting(const Bonus & bonus) const;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE COPWBonus : public CGTownBuilding
|
||||
{///used for OPW bonusing structures
|
||||
public:
|
||||
std::set<ObjectInstanceID> visitors;
|
||||
void setProperty(ObjProperty what, ObjPropertyID identifier) override;
|
||||
void onHeroVisit (const CGHeroInstance * h) const override;
|
||||
|
||||
COPWBonus(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * TOWN);
|
||||
COPWBonus(IGameCallback *cb);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
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(ObjProperty what, ObjPropertyID identifier) override;
|
||||
void onHeroVisit (const CGHeroInstance * h) const override;
|
||||
|
||||
CTownBonus(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * TOWN);
|
||||
CTownBonus(IGameCallback *cb);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<CGTownBuilding&>(*this);
|
||||
h & visitors;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void applyBonuses(CGHeroInstance * h, const BonusList & bonuses) const;
|
||||
BuildingID bID; //from building list
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CTownRewardableBuilding : public CGTownBuilding, public Rewardable::Interface
|
||||
@@ -135,7 +90,7 @@ public:
|
||||
/// applies player selection of reward
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
|
||||
|
||||
CTownRewardableBuilding(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * town, vstd::RNG & rand);
|
||||
CTownRewardableBuilding(CGTownInstance * town, const BuildingID & index, vstd::RNG & rand);
|
||||
CTownRewardableBuilding(IGameCallback *cb);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
@@ -146,4 +101,46 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// Compatibility for old code
|
||||
class DLL_LINKAGE CTownCompatBuilding1 : public CTownRewardableBuilding
|
||||
{
|
||||
public:
|
||||
using CTownRewardableBuilding::CTownRewardableBuilding;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
if (h.version >= Handler::Version::NEW_TOWN_BUILDINGS)
|
||||
{
|
||||
h & static_cast<CTownRewardableBuilding&>(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
h & static_cast<CGTownBuilding&>(*this);
|
||||
std::set<ObjectInstanceID> visitors;
|
||||
h & visitors;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Compatibility for old code
|
||||
class DLL_LINKAGE CTownCompatBuilding2 : public CTownRewardableBuilding
|
||||
{
|
||||
public:
|
||||
using CTownRewardableBuilding::CTownRewardableBuilding;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
if (h.version >= Handler::Version::NEW_TOWN_BUILDINGS)
|
||||
{
|
||||
h & static_cast<CTownRewardableBuilding&>(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
h & static_cast<CGTownBuilding&>(*this);
|
||||
std::set<ObjectInstanceID> visitors;
|
||||
h & visitors;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@@ -380,31 +380,12 @@ void CGTownInstance::initOverriddenBids()
|
||||
}
|
||||
}
|
||||
|
||||
bool CGTownInstance::isBonusingBuildingAdded(BuildingID bid) const
|
||||
{
|
||||
auto present = std::find_if(bonusingBuildings.begin(), bonusingBuildings.end(), [&](CGTownBuilding* building)
|
||||
{
|
||||
return building->getBuildingType() == bid;
|
||||
});
|
||||
|
||||
return present != bonusingBuildings.end();
|
||||
}
|
||||
|
||||
void CGTownInstance::addTownBonuses(vstd::RNG & rand)
|
||||
void CGTownInstance::initializeConfigurableBuildings(vstd::RNG & rand)
|
||||
{
|
||||
for(const auto & kvp : town->buildings)
|
||||
{
|
||||
if(vstd::contains(overriddenBuildings, kvp.first))
|
||||
continue;
|
||||
|
||||
if(kvp.second->IsVisitingBonus())
|
||||
bonusingBuildings.push_back(new CTownBonus(kvp.second->bid, kvp.second->subId, this));
|
||||
|
||||
if(kvp.second->IsWeekBonus())
|
||||
bonusingBuildings.push_back(new COPWBonus(kvp.second->bid, kvp.second->subId, this));
|
||||
|
||||
if(kvp.second->subId == BuildingSubID::CUSTOM_VISITING_REWARD)
|
||||
bonusingBuildings.push_back(new CTownRewardableBuilding(kvp.second->bid, kvp.second->subId, this, rand));
|
||||
if(!kvp.second->rewardableObjectInfo.getParameters().isNull())
|
||||
bonusingBuildings.push_back(new CTownRewardableBuilding(this, kvp.second->bid, rand));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,15 +441,7 @@ void CGTownInstance::deleteTownBonus(BuildingID bid)
|
||||
if(freeIt == nullptr)
|
||||
return;
|
||||
|
||||
auto building = town->buildings.at(bid);
|
||||
auto isVisitingBonus = building->IsVisitingBonus();
|
||||
auto isWeekBonus = building->IsWeekBonus();
|
||||
|
||||
if(!isVisitingBonus && !isWeekBonus)
|
||||
return;
|
||||
|
||||
bonusingBuildings.erase(bonusingBuildings.begin() + i);
|
||||
|
||||
delete freeIt;
|
||||
}
|
||||
|
||||
@@ -527,7 +500,7 @@ void CGTownInstance::initObj(vstd::RNG & rand) ///initialize town structures
|
||||
}
|
||||
}
|
||||
initOverriddenBids();
|
||||
addTownBonuses(rand); //add special bonuses from buildings to the bonusingBuildings vector.
|
||||
initializeConfigurableBuildings(rand);
|
||||
recreateBuildingsBonuses();
|
||||
updateAppearance();
|
||||
}
|
||||
@@ -549,9 +522,6 @@ void CGTownInstance::newTurn(vstd::RNG & rand) const
|
||||
cb->setObjPropertyValue(id, ObjProperty::BONUS_VALUE_FIRST, resID);
|
||||
cb->setObjPropertyValue(id, ObjProperty::BONUS_VALUE_SECOND, resVal);
|
||||
}
|
||||
|
||||
for(const auto * manaVortex : getBonusingBuildings(BuildingSubID::MANA_VORTEX))
|
||||
cb->setObjPropertyValue(id, ObjProperty::STRUCTURE_CLEAR_VISITORS, manaVortex->indexOnTV); //reset visitors for Mana Vortex
|
||||
|
||||
if (tempOwner == PlayerColor::NEUTRAL) //garrison growth for neutral towns
|
||||
{
|
||||
@@ -606,7 +576,7 @@ void CGTownInstance::newTurn(vstd::RNG & rand) const
|
||||
}
|
||||
}
|
||||
|
||||
for(const auto * rewardableBuilding : getBonusingBuildings(BuildingSubID::CUSTOM_VISITING_REWARD))
|
||||
for(const auto * rewardableBuilding : bonusingBuildings)
|
||||
rewardableBuilding->newTurn(rand);
|
||||
|
||||
if(hasBuilt(BuildingSubID::BANK) && bonusValue.second > 0)
|
||||
@@ -979,18 +949,6 @@ const CArmedInstance * CGTownInstance::getUpperArmy() const
|
||||
return this;
|
||||
}
|
||||
|
||||
std::vector<const CGTownBuilding *> CGTownInstance::getBonusingBuildings(BuildingSubID::EBuildingSubID subId) const
|
||||
{
|
||||
std::vector<const CGTownBuilding *> ret;
|
||||
for(auto * const building : bonusingBuildings)
|
||||
{
|
||||
if(building->getBuildingSubtype() == subId)
|
||||
ret.push_back(building);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool CGTownInstance::hasBuiltSomeTradeBuilding() const
|
||||
{
|
||||
for(const auto & bid : builtBuildings)
|
||||
|
@@ -165,7 +165,6 @@ public:
|
||||
GrowthInfo getGrowthInfo(int level) const;
|
||||
bool hasFort() const;
|
||||
bool hasCapitol() const;
|
||||
std::vector<const CGTownBuilding *> getBonusingBuildings(BuildingSubID::EBuildingSubID subId) const;
|
||||
bool hasBuiltSomeTradeBuilding() const;
|
||||
//checks if special building with type buildingID is constructed
|
||||
bool hasBuilt(BuildingSubID::EBuildingSubID buildingID) const;
|
||||
@@ -231,9 +230,8 @@ private:
|
||||
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;
|
||||
bool isBonusingBuildingAdded(BuildingID bid) const;
|
||||
void initOverriddenBids();
|
||||
void addTownBonuses(vstd::RNG & rand);
|
||||
void initializeConfigurableBuildings(vstd::RNG & rand);
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@@ -95,7 +95,6 @@ public:
|
||||
// class DLL_LINKAGE CGPyramid : public CBank
|
||||
|
||||
// EXTRA
|
||||
// class DLL_LINKAGE COPWBonus : public CGTownBuilding
|
||||
// class DLL_LINKAGE CTownBonus : public CGTownBuilding
|
||||
// class DLL_LINKAGE CGKeys : public CGObjectInstance //Base class for Keymaster and guards
|
||||
// class DLL_LINKAGE CGKeymasterTent : public CGKeys
|
||||
|
@@ -87,8 +87,8 @@ void registerTypesMapObjects(Serializer &s)
|
||||
|
||||
//Other object-related
|
||||
s.template registerType<IObjectInterface, CGTownBuilding>();
|
||||
s.template registerType<CGTownBuilding, CTownBonus>();
|
||||
s.template registerType<CGTownBuilding, COPWBonus>();
|
||||
s.template registerType<CGTownBuilding, CTownCompatBuilding1>();
|
||||
s.template registerType<CGTownBuilding, CTownCompatBuilding2>();
|
||||
s.template registerType<CGTownBuilding, CTownRewardableBuilding>();
|
||||
|
||||
s.template registerType<CGObjectInstance, CRewardableObject>();
|
||||
|
@@ -63,6 +63,7 @@ enum class ESerializationVersion : int32_t
|
||||
STATISTICS, // 852 - removed random number generators from library classes
|
||||
CAMPAIGN_REGIONS, // 853 - configurable campaign regions
|
||||
EVENTS_PLAYER_SET, // 854 - map & town events use std::set instead of bitmask to store player list
|
||||
NEW_TOWN_BUILDINGS, // 855 - old bonusing buildings have been removed
|
||||
|
||||
CURRENT = EVENTS_PLAYER_SET
|
||||
CURRENT = NEW_TOWN_BUILDINGS
|
||||
};
|
||||
|
Reference in New Issue
Block a user