1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

Configurable Conflux University

This commit is contained in:
Ivan Savenko
2025-06-08 16:49:27 +03:00
parent 342705921d
commit f71db8af07
9 changed files with 57 additions and 12 deletions

View File

@@ -178,7 +178,16 @@
"horde1": { "id" : 18, "upgrades" : "dwellingLvl1" }, "horde1": { "id" : 18, "upgrades" : "dwellingLvl1" },
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" }, "horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" },
"ship": { "id" : 20, "upgrades" : "shipyard" }, "ship": { "id" : 20, "upgrades" : "shipyard" },
"special2": { "requires" : [ "mageGuild1" ], "marketModes" : ["resource-skill"] }, "special2": {
"requires" : [ "mageGuild1" ],
"marketModes" : ["resource-skill"],
"marketOffer" : [
"fireMagic",
"airMagic",
"waterMagic",
"earthMagic"
]
},
"grail": { "id" : 26, "mode" : "grail", "produce": { "gold": 5000 }}, "grail": { "id" : 26, "mode" : "grail", "produce": { "gold": 5000 }},
"extraTownHall": { "id" : 27, "requires" : [ "townHall" ], "mode" : "auto" }, "extraTownHall": { "id" : 27, "requires" : [ "townHall" ], "mode" : "auto" },
"extraCityHall": { "id" : 28, "requires" : [ "cityHall" ], "mode" : "auto" }, "extraCityHall": { "id" : 28, "requires" : [ "cityHall" ], "mode" : "auto" },

View File

@@ -134,5 +134,13 @@
}, },
"description" : "List of modes available in this market" "description" : "List of modes available in this market"
} }
"marketOffer" : {
"type" : "array",
"items" : {
"type" : "string"
},
"description" : "List of predefined items available on market from this building"
}
} }
} }

View File

@@ -213,6 +213,10 @@ These are just a couple of examples of what can be done in VCMI. See vcmi config
// If the building is a market, it requires market mode. // If the building is a market, it requires market mode.
"marketModes" : [ "resource-resource", "resource-player" ], "marketModes" : [ "resource-resource", "resource-player" ],
// Required if building offers resource-skill trade.
// NOTE: multiple resource-skill buildings in the same town are not supported
"marketOffer" : [ "fireMagic", "airMagic", "waterMagic", "earthMagic" ],
} }
``` ```

View File

@@ -15,6 +15,7 @@
#include "../../LogicalExpression.h" #include "../../LogicalExpression.h"
#include "../../ResourceSet.h" #include "../../ResourceSet.h"
#include "../../bonuses/BonusList.h" #include "../../bonuses/BonusList.h"
#include "../../networkPacks/TradeItem.h"
#include "../../rewardable/Info.h" #include "../../rewardable/Info.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -39,6 +40,7 @@ public:
ArtifactID warMachine; ArtifactID warMachine;
TownFortifications fortifications; TownFortifications fortifications;
std::set<EMarketMode> marketModes; std::set<EMarketMode> marketModes;
std::vector<TradeItemBuy> marketOffer;
BuildingID bid; //structure ID BuildingID bid; //structure ID
BuildingID upgrade; /// indicates that building "upgrade" can be improved by this, -1 = empty BuildingID upgrade; /// indicates that building "upgrade" can be improved by this, -1 = empty

View File

@@ -386,7 +386,23 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons
for(const auto & element : source["marketModes"].Vector()) for(const auto & element : source["marketModes"].Vector())
{ {
if(MappedKeys::MARKET_NAMES_TO_TYPES.count(element.String())) if(MappedKeys::MARKET_NAMES_TO_TYPES.count(element.String()))
ret->marketModes.insert(MappedKeys::MARKET_NAMES_TO_TYPES.at(element.String())); {
auto mode = MappedKeys::MARKET_NAMES_TO_TYPES.at(element.String());
ret->marketModes.insert(mode);
if (mode == EMarketMode::RESOURCE_SKILL)
{
const auto & items = source["marketOffer"].Vector();
ret->marketOffer.resize(items.size());
for (int i = 0; i < items.size(); ++i)
{
LIBRARY->identifiers()->requestIdentifier("secondarySkill", items[i], [ret, i](si32 identifier)
{
ret->marketOffer[i] = SecondarySkill(identifier);
});
}
}
}
} }
registerObject(source.getModScope(), ret->town->getBuildingScope(), ret->identifier, ret->bid.getNum()); registerObject(source.getModScope(), ret->town->getBuildingScope(), ret->identifier, ret->bid.getNum());

View File

@@ -787,12 +787,6 @@ void CGameState::initTowns(vstd::RNG & randomGenerator)
if (campaign) if (campaign)
campaign->initTowns(); campaign->initTowns();
map->townUniversitySkills.clear();
map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::FIRE_MAGIC));
map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::AIR_MAGIC));
map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::WATER_MAGIC));
map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::EARTH_MAGIC));
for (const auto & townID : map->getAllTowns()) for (const auto & townID : map->getAllTowns())
{ {
auto vti = getTown(townID); auto vti = getTown(townID);

View File

@@ -683,7 +683,15 @@ std::vector<TradeItemBuy> CGTownInstance::availableItemsIds(EMarketMode mode) co
} }
else if ( mode == EMarketMode::RESOURCE_SKILL ) else if ( mode == EMarketMode::RESOURCE_SKILL )
{ {
return cb->gameState().getMap().townUniversitySkills; for (const auto & buildingID : builtBuildings)
{
const auto * buildingPtr = getTown()->buildings.at(buildingID).get();
if (vstd::contains(buildingPtr->marketModes, mode))
return buildingPtr->marketOffer;
}
logMod->warn("Town has resource-skill trade but has no skills to offer!");
return {};
} }
else else
return IMarket::availableItemsIds(mode); return IMarket::availableItemsIds(mode);

View File

@@ -272,7 +272,6 @@ public:
std::map<TeamID, ui8> obelisksVisited; //map: team_id => how many obelisks has been visited std::map<TeamID, ui8> obelisksVisited; //map: team_id => how many obelisks has been visited
std::vector<ArtifactID> townMerchantArtifacts; std::vector<ArtifactID> townMerchantArtifacts;
std::vector<TradeItemBuy> townUniversitySkills;
void overrideGameSettings(const JsonNode & input); void overrideGameSettings(const JsonNode & input);
void overrideGameSetting(EGameSettings option, const JsonNode & input); void overrideGameSetting(EGameSettings option, const JsonNode & input);
@@ -345,7 +344,11 @@ public:
h & obeliskCount; h & obeliskCount;
h & obelisksVisited; h & obelisksVisited;
h & townMerchantArtifacts; h & townMerchantArtifacts;
h & townUniversitySkills; if (!h.hasFeature(Handler::Version::STORE_UID_COUNTER_IN_CMAP))
{
std::vector<TradeItemBuy> townUniversitySkills;
h & townUniversitySkills;
}
h & instanceNames; h & instanceNames;
h & *gameSettings; h & *gameSettings;

View File

@@ -45,8 +45,9 @@ enum class ESerializationVersion : int32_t
CUSTOM_BONUS_ICONS, // support for custom icons in bonuses CUSTOM_BONUS_ICONS, // support for custom icons in bonuses
SERVER_STATISTICS, // statistics now only saved on server SERVER_STATISTICS, // statistics now only saved on server
OPPOSITE_SIDE_LIMITER_OWNER, // opposite side limiter no longer stores owner in itself OPPOSITE_SIDE_LIMITER_OWNER, // opposite side limiter no longer stores owner in itself
UNIVERSITY_CONFIG, // town university is configurable
CURRENT = OPPOSITE_SIDE_LIMITER_OWNER, CURRENT = UNIVERSITY_CONFIG,
}; };
static_assert(ESerializationVersion::MINIMAL <= ESerializationVersion::CURRENT, "Invalid serialization version definition!"); static_assert(ESerializationVersion::MINIMAL <= ESerializationVersion::CURRENT, "Invalid serialization version definition!");