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

Merge pull request #6136 from Laserlicht/resource

Configurable resources
This commit is contained in:
Ivan Savenko
2025-09-28 21:51:10 +03:00
committed by GitHub
96 changed files with 674 additions and 314 deletions

View File

@@ -15,6 +15,7 @@
#include "../../lib/UnlockGuard.h" #include "../../lib/UnlockGuard.h"
#include "../../lib/CConfigHandler.h" #include "../../lib/CConfigHandler.h"
#include "../../lib/entities/artifact/CArtifact.h" #include "../../lib/entities/artifact/CArtifact.h"
#include "../../lib/entities/ResourceTypeHandler.h"
#include "../../lib/mapObjects/MapObjects.h" #include "../../lib/mapObjects/MapObjects.h"
#include "../../lib/mapObjects/CQuest.h" #include "../../lib/mapObjects/CQuest.h"
#include "../../lib/mapping/TerrainTile.h" #include "../../lib/mapping/TerrainTile.h"
@@ -470,7 +471,7 @@ int32_t getArtifactBonusScoreImpl(const std::shared_ptr<Bonus> & bonus)
case BonusType::UNDEAD_RAISE_PERCENTAGE: case BonusType::UNDEAD_RAISE_PERCENTAGE:
return bonus->val * 400; return bonus->val * 400;
case BonusType::GENERATE_RESOURCE: case BonusType::GENERATE_RESOURCE:
return bonus->val * LIBRARY->objh->resVals.at(bonus->subtype.as<GameResID>().getNum()) * 10; return bonus->val * bonus->subtype.as<GameResID>().toResource()->getPrice() * 10;
case BonusType::SPELL_DURATION: case BonusType::SPELL_DURATION:
return bonus->val * 200; return bonus->val * 200;
case BonusType::MAGIC_RESISTANCE: case BonusType::MAGIC_RESISTANCE:

View File

@@ -12,6 +12,7 @@
#include "Nullkiller.h" #include "Nullkiller.h"
#include "../../../lib/entities/artifact/CArtifact.h" #include "../../../lib/entities/artifact/CArtifact.h"
#include "../../../lib/entities/ResourceTypeHandler.h"
#include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h" #include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h"
#include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h" #include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h"
#include "../../../lib/mapObjects/CGResource.h" #include "../../../lib/mapObjects/CGResource.h"
@@ -22,6 +23,7 @@
#include "../../../lib/StartInfo.h" #include "../../../lib/StartInfo.h"
#include "../../../lib/GameSettings.h" #include "../../../lib/GameSettings.h"
#include "../../../lib/filesystem/Filesystem.h" #include "../../../lib/filesystem/Filesystem.h"
#include "../../../lib/entities/ResourceTypeHandler.h"
#include "../Goals/ExecuteHeroChain.h" #include "../Goals/ExecuteHeroChain.h"
#include "../Goals/BuildThis.h" #include "../Goals/BuildThis.h"
#include "../Goals/StayAtTown.h" #include "../Goals/StayAtTown.h"
@@ -136,7 +138,7 @@ int32_t getResourcesGoldReward(const TResources & res)
{ {
int32_t result = 0; int32_t result = 0;
for(auto r : GameResID::ALL_RESOURCES()) for(auto r : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
if(res[r] > 0) if(res[r] > 0)
result += r == EGameResID::GOLD ? res[r] : res[r] * 100; result += r == EGameResID::GOLD ? res[r] : res[r] * 100;
@@ -1589,7 +1591,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier)
needed.positive(); needed.positive();
int turnsTo = needed.maxPurchasableCount(income); int turnsTo = needed.maxPurchasableCount(income);
bool haveEverythingButGold = true; bool haveEverythingButGold = true;
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++) for (auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
if (i != GameResID::GOLD && resourcesAvailable[i] < evaluationContext.buildingCost[i]) if (i != GameResID::GOLD && resourcesAvailable[i] < evaluationContext.buildingCost[i])
haveEverythingButGold = false; haveEverythingButGold = false;

View File

@@ -12,6 +12,7 @@
#include "../AIGateway.h" #include "../AIGateway.h"
#include "../../../lib/constants/StringConstants.h" #include "../../../lib/constants/StringConstants.h"
#include "../../../lib/entities/artifact/CArtifact.h" #include "../../../lib/entities/artifact/CArtifact.h"
#include "../../../lib/entities/ResourceTypeHandler.h"
namespace NKAI namespace NKAI
{ {
@@ -43,13 +44,13 @@ std::string AbstractGoal::toString() const
switch(goalType) switch(goalType)
{ {
case COLLECT_RES: case COLLECT_RES:
desc = "COLLECT RESOURCE " + GameConstants::RESOURCE_NAMES[resID] + " (" + std::to_string(value) + ")"; desc = "COLLECT RESOURCE " + GameResID(resID).toResource()->getJsonKey() + " (" + std::to_string(value) + ")";
break; break;
case TRADE: case TRADE:
{ {
auto obj = cb->getObjInstance(ObjectInstanceID(objid)); auto obj = cb->getObjInstance(ObjectInstanceID(objid));
if (obj) if (obj)
desc = (boost::format("TRADE %d of %s at %s") % value % GameConstants::RESOURCE_NAMES[resID] % obj->getObjectName()).str(); desc = (boost::format("TRADE %d of %s at %s") % value % GameResID(resID).toResource()->getJsonKey() % obj->getObjectName()).str();
} }
break; break;
case GATHER_TROOPS: case GATHER_TROOPS:

View File

@@ -16,6 +16,7 @@
#include "../BuildingManager.h" #include "../BuildingManager.h"
#include "../../../lib/constants/StringConstants.h" #include "../../../lib/constants/StringConstants.h"
#include "../../../lib/entities/artifact/CArtifact.h" #include "../../../lib/entities/artifact/CArtifact.h"
#include "../../../lib/entities/ResourceTypeHandler.h"
using namespace Goals; using namespace Goals;
@@ -56,13 +57,13 @@ std::string AbstractGoal::name() const //TODO: virtualize
case BUILD_STRUCTURE: case BUILD_STRUCTURE:
return "BUILD STRUCTURE"; return "BUILD STRUCTURE";
case COLLECT_RES: case COLLECT_RES:
desc = "COLLECT RESOURCE " + GameConstants::RESOURCE_NAMES[resID] + " (" + std::to_string(value) + ")"; desc = "COLLECT RESOURCE " + GameResID(resID).toResource()->getJsonKey() + " (" + std::to_string(value) + ")";
break; break;
case TRADE: case TRADE:
{ {
auto obj = cb->getObjInstance(ObjectInstanceID(objid)); auto obj = cb->getObjInstance(ObjectInstanceID(objid));
if (obj) if (obj)
desc = (boost::format("TRADE %d of %s at %s") % value % GameConstants::RESOURCE_NAMES[resID] % obj->getObjectName()).str(); desc = (boost::format("TRADE %d of %s at %s") % value % GameResID(resID).toResource()->getJsonKey() % obj->getObjectName()).str();
} }
break; break;
case GATHER_TROOPS: case GATHER_TROOPS:

View File

@@ -18,6 +18,7 @@
#include "../../../lib/mapObjects/CGMarket.h" #include "../../../lib/mapObjects/CGMarket.h"
#include "../../../lib/mapObjects/CGResource.h" #include "../../../lib/mapObjects/CGResource.h"
#include "../../../lib/constants/StringConstants.h" #include "../../../lib/constants/StringConstants.h"
#include "../../../lib/entities/ResourceTypeHandler.h"
using namespace Goals; using namespace Goals;
@@ -171,7 +172,7 @@ TSubgoal CollectRes::whatToDoToTrade()
const IMarket * m = markets.back(); const IMarket * m = markets.back();
//attempt trade at back (best prices) //attempt trade at back (best prices)
int howManyCanWeBuy = 0; int howManyCanWeBuy = 0;
for (GameResID i = EGameResID::WOOD; i <= EGameResID::GOLD; ++i) for (auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
if (i.getNum() == resID) if (i.getNum() == resID)
continue; continue;

View File

@@ -31,10 +31,12 @@
#include "../CPlayerInterface.h" #include "../CPlayerInterface.h"
#include "../PlayerLocalState.h" #include "../PlayerLocalState.h"
#include "../../lib/GameLibrary.h"
#include "../../lib/callback/CCallback.h" #include "../../lib/callback/CCallback.h"
#include "../../lib/constants/StringConstants.h" #include "../../lib/constants/StringConstants.h"
#include "../../lib/mapping/CMapHeader.h" #include "../../lib/mapping/CMapHeader.h"
#include "../../lib/filesystem/ResourcePath.h" #include "../../lib/filesystem/ResourcePath.h"
#include "../../lib/entities/ResourceTypeHandler.h"
AdventureMapWidget::AdventureMapWidget( std::shared_ptr<AdventureMapShortcuts> shortcuts ) AdventureMapWidget::AdventureMapWidget( std::shared_ptr<AdventureMapShortcuts> shortcuts )
: shortcuts(shortcuts) : shortcuts(shortcuts)
@@ -294,14 +296,14 @@ std::shared_ptr<CIntObject> AdventureMapWidget::buildResourceDateBar(const JsonN
auto result = std::make_shared<CResDataBar>(image, area.topLeft()); auto result = std::make_shared<CResDataBar>(image, area.topLeft());
for(auto i = 0; i < GameConstants::RESOURCE_QUANTITY; i++) for (auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
const auto & node = input[GameConstants::RESOURCE_NAMES[i]]; const auto & node = input[i.toResource()->getJsonKey()];
if(node.isNull()) if(node.isNull())
continue; continue;
result->setResourcePosition(GameResID(i), Point(node["x"].Integer(), node["y"].Integer())); result->setResourcePosition(i, Point(node["x"].Integer(), node["y"].Integer()));
} }
result->setDatePosition(Point(input["date"]["x"].Integer(), input["date"]["y"].Integer())); result->setDatePosition(Point(input["date"]["x"].Integer(), input["date"]["y"].Integer()));

View File

@@ -18,15 +18,21 @@
#include "../GameInstance.h" #include "../GameInstance.h"
#include "../gui/TextAlignment.h" #include "../gui/TextAlignment.h"
#include "../widgets/Images.h" #include "../widgets/Images.h"
#include "../widgets/CComponent.h"
#include "../windows/InfoWindows.h"
#include "../../lib/CConfigHandler.h" #include "../../lib/CConfigHandler.h"
#include "../../lib/callback/CCallback.h" #include "../../lib/callback/CCallback.h"
#include "../../lib/texts/CGeneralTextHandler.h" #include "../../lib/texts/CGeneralTextHandler.h"
#include "../../lib/ResourceSet.h" #include "../../lib/ResourceSet.h"
#include "../../lib/GameLibrary.h" #include "../../lib/GameLibrary.h"
#include "../../lib/entities/ResourceTypeHandler.h"
#include "../../lib/networkPacks/Component.h"
CResDataBar::CResDataBar(const ImagePath & imageName, const Point & position) CResDataBar::CResDataBar(const ImagePath & imageName, const Point & position)
{ {
addUsedEvents(SHOW_POPUP);
pos.x += position.x; pos.x += position.x;
pos.y += position.y; pos.y += position.y;
@@ -89,3 +95,12 @@ void CResDataBar::setPlayerColor(PlayerColor player)
{ {
background->setPlayerColor(player); background->setPlayerColor(player);
} }
void CResDataBar::showPopupWindow(const Point & cursorPosition)
{
std::vector<std::shared_ptr<CComponent>> comp;
for (auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
comp.push_back(std::make_shared<CComponent>(ComponentType::RESOURCE, i, GAME->interface()->cb->getResourceAmount(i)));
CRClickPopup::createAndPush(LIBRARY->generaltexth->translate("core.genrltxt.270"), comp);
}

View File

@@ -35,6 +35,7 @@ public:
void setResourcePosition(const GameResID & resource, const Point & position); void setResourcePosition(const GameResID & resource, const Point & position);
void setPlayerColor(PlayerColor player); void setPlayerColor(PlayerColor player);
void showPopupWindow(const Point & cursorPosition) override;
void showAll(Canvas & to) override; void showAll(Canvas & to) override;
}; };

View File

@@ -41,6 +41,7 @@
#include "../../lib/entities/faction/CTownHandler.h" #include "../../lib/entities/faction/CTownHandler.h"
#include "../../lib/entities/hero/CHeroHandler.h" #include "../../lib/entities/hero/CHeroHandler.h"
#include "../../lib/entities/hero/CHeroClass.h" #include "../../lib/entities/hero/CHeroClass.h"
#include "../../lib/entities/ResourceTypeHandler.h"
#include "../../lib/filesystem/Filesystem.h" #include "../../lib/filesystem/Filesystem.h"
#include "../../lib/networkPacks/PacksForLobby.h" #include "../../lib/networkPacks/PacksForLobby.h"
#include "../../lib/texts/CGeneralTextHandler.h" #include "../../lib/texts/CGeneralTextHandler.h"
@@ -161,8 +162,6 @@ size_t OptionsTab::CPlayerSettingsHelper::getImageIndex(bool big)
return GEM; return GEM;
case EGameResID::GOLD: case EGameResID::GOLD:
return GOLD; return GOLD;
case EGameResID::MITHRIL:
return MITHRIL;
} }
} }
} }
@@ -1057,7 +1056,7 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con
{ {
auto str = MetaString::createFromTextID("vcmi.lobby.handicap"); auto str = MetaString::createFromTextID("vcmi.lobby.handicap");
str.appendRawString(":\n"); str.appendRawString(":\n");
for(auto & res : EGameResID::ALL_RESOURCES()) for(auto & res : LIBRARY->resourceTypeHandler->getAllObjects())
if(s->handicap.startBonus[res] != 0) if(s->handicap.startBonus[res] != 0)
{ {
str.appendRawString("\n"); str.appendRawString("\n");

View File

@@ -28,6 +28,7 @@
#include "../windows/InfoWindows.h" #include "../windows/InfoWindows.h"
#include "../widgets/Slider.h" #include "../widgets/Slider.h"
#include "../../lib/entities/ResourceTypeHandler.h"
#include "../../lib/gameState/GameStatistics.h" #include "../../lib/gameState/GameStatistics.h"
#include "../../lib/gameState/CGameState.h" #include "../../lib/gameState/CGameState.h"
#include "../../lib/texts/CGeneralTextHandler.h" #include "../../lib/texts/CGeneralTextHandler.h"
@@ -76,10 +77,10 @@ void CStatisticScreen::onSelectButton()
else else
{ {
auto content = static_cast<Content>(selectedIndex); auto content = static_cast<Content>(selectedIndex);
auto possibleRes = std::vector<EGameResID>{EGameResID::GOLD, EGameResID::WOOD, EGameResID::MERCURY, EGameResID::ORE, EGameResID::SULFUR, EGameResID::CRYSTAL, EGameResID::GEMS}; auto possibleRes = LIBRARY->resourceTypeHandler->getAllObjects();
std::vector<std::string> resourceText; std::vector<std::string> resourceText;
for(const auto & res : possibleRes) for(const auto & res : possibleRes)
resourceText.emplace_back(LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", res.getNum()).get())); resourceText.emplace_back(res.toResource()->getNameTranslated());
ENGINE->windows().createAndPushWindow<StatisticSelector>(resourceText, [this, content, possibleRes](int index) ENGINE->windows().createAndPushWindow<StatisticSelector>(resourceText, [this, content, possibleRes](int index)
{ {
@@ -169,7 +170,7 @@ std::shared_ptr<CIntObject> CStatisticScreen::getContent(Content c, EGameResID r
case CHART_RESOURCES: case CHART_RESOURCES:
plotData = extractData(statistic, [res](const StatisticDataSetEntry & val) -> float { return val.resources[res]; }); plotData = extractData(statistic, [res](const StatisticDataSetEntry & val) -> float { return val.resources[res]; });
return std::make_shared<LineChart>(contentArea.resize(-5), LIBRARY->generaltexth->translate(std::get<0>(contentInfo[c])) + " - " + LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", res.getNum()).get()), plotData, icons, 0); return std::make_shared<LineChart>(contentArea.resize(-5), LIBRARY->generaltexth->translate(std::get<0>(contentInfo[c])) + " - " + res.toResource()->getNameTranslated(), plotData, icons, 0);
case CHART_INCOME: case CHART_INCOME:
plotData = extractData(statistic, [](const StatisticDataSetEntry & val) -> float { return val.income; }); plotData = extractData(statistic, [](const StatisticDataSetEntry & val) -> float { return val.income; });
@@ -193,7 +194,7 @@ std::shared_ptr<CIntObject> CStatisticScreen::getContent(Content c, EGameResID r
case CHART_NUMBER_OF_MINES: case CHART_NUMBER_OF_MINES:
plotData = extractData(statistic, [res](StatisticDataSetEntry val) -> float { return val.numMines[res]; }); plotData = extractData(statistic, [res](StatisticDataSetEntry val) -> float { return val.numMines[res]; });
return std::make_shared<LineChart>(contentArea.resize(-5), LIBRARY->generaltexth->translate(std::get<0>(contentInfo[c])) + " - " + LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", res.getNum()).get()), plotData, icons, 0); return std::make_shared<LineChart>(contentArea.resize(-5), LIBRARY->generaltexth->translate(std::get<0>(contentInfo[c])) + " - " + res.toResource()->getNameTranslated(), plotData, icons, 0);
case CHART_ARMY_STRENGTH: case CHART_ARMY_STRENGTH:
plotData = extractData(statistic, [](const StatisticDataSetEntry & val) -> float { return val.armyStrength; }); plotData = extractData(statistic, [](const StatisticDataSetEntry & val) -> float { return val.armyStrength; });
@@ -205,11 +206,11 @@ std::shared_ptr<CIntObject> CStatisticScreen::getContent(Content c, EGameResID r
case CHART_RESOURCES_SPENT_ARMY: case CHART_RESOURCES_SPENT_ARMY:
plotData = extractData(statistic, [res](const StatisticDataSetEntry & val) -> float { return val.spentResourcesForArmy[res]; }); plotData = extractData(statistic, [res](const StatisticDataSetEntry & val) -> float { return val.spentResourcesForArmy[res]; });
return std::make_shared<LineChart>(contentArea.resize(-5), LIBRARY->generaltexth->translate(std::get<0>(contentInfo[c])) + " - " + LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", res.getNum()).get()), plotData, icons, 0); return std::make_shared<LineChart>(contentArea.resize(-5), LIBRARY->generaltexth->translate(std::get<0>(contentInfo[c])) + " - " + res.toResource()->getNameTranslated(), plotData, icons, 0);
case CHART_RESOURCES_SPENT_BUILDINGS: case CHART_RESOURCES_SPENT_BUILDINGS:
plotData = extractData(statistic, [res](const StatisticDataSetEntry & val) -> float { return val.spentResourcesForBuildings[res]; }); plotData = extractData(statistic, [res](const StatisticDataSetEntry & val) -> float { return val.spentResourcesForBuildings[res]; });
return std::make_shared<LineChart>(contentArea.resize(-5), LIBRARY->generaltexth->translate(std::get<0>(contentInfo[c])) + " - " + LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", res.getNum()).get()), plotData, icons, 0); return std::make_shared<LineChart>(contentArea.resize(-5), LIBRARY->generaltexth->translate(std::get<0>(contentInfo[c])) + " - " + res.toResource()->getNameTranslated(), plotData, icons, 0);
case CHART_MAP_EXPLORED: case CHART_MAP_EXPLORED:
plotData = extractData(statistic, [](const StatisticDataSetEntry & val) -> float { return val.mapExploredRatio; }); plotData = extractData(statistic, [](const StatisticDataSetEntry & val) -> float { return val.mapExploredRatio; });
@@ -330,43 +331,43 @@ OverviewPanel::OverviewPanel(Rect position, std::string title, const StatisticDa
} }
}, },
{ {
LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", EGameResID::GOLD).get()), [this](PlayerColor color){ LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + GameResID(EGameResID::GOLD).toResource()->getNameTranslated(), [this](PlayerColor color){
auto val = playerDataFilter(color).back(); auto val = playerDataFilter(color).back();
return std::to_string(val.tradeVolume[EGameResID::GOLD]); return std::to_string(val.tradeVolume[EGameResID::GOLD]);
} }
}, },
{ {
LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", EGameResID::WOOD).get()), [this](PlayerColor color){ LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + GameResID(EGameResID::WOOD).toResource()->getNameTranslated(), [this](PlayerColor color){
auto val = playerDataFilter(color).back(); auto val = playerDataFilter(color).back();
return std::to_string(val.tradeVolume[EGameResID::WOOD]); return std::to_string(val.tradeVolume[EGameResID::WOOD]);
} }
}, },
{ {
LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", EGameResID::MERCURY).get()), [this](PlayerColor color){ LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + GameResID(EGameResID::MERCURY).toResource()->getNameTranslated(), [this](PlayerColor color){
auto val = playerDataFilter(color).back(); auto val = playerDataFilter(color).back();
return std::to_string(val.tradeVolume[EGameResID::MERCURY]); return std::to_string(val.tradeVolume[EGameResID::MERCURY]);
} }
}, },
{ {
LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", EGameResID::ORE).get()), [this](PlayerColor color){ LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + GameResID(EGameResID::ORE).toResource()->getNameTranslated(), [this](PlayerColor color){
auto val = playerDataFilter(color).back(); auto val = playerDataFilter(color).back();
return std::to_string(val.tradeVolume[EGameResID::ORE]); return std::to_string(val.tradeVolume[EGameResID::ORE]);
} }
}, },
{ {
LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", EGameResID::SULFUR).get()), [this](PlayerColor color){ LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + GameResID(EGameResID::SULFUR).toResource()->getNameTranslated(), [this](PlayerColor color){
auto val = playerDataFilter(color).back(); auto val = playerDataFilter(color).back();
return std::to_string(val.tradeVolume[EGameResID::SULFUR]); return std::to_string(val.tradeVolume[EGameResID::SULFUR]);
} }
}, },
{ {
LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", EGameResID::CRYSTAL).get()), [this](PlayerColor color){ LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + GameResID(EGameResID::CRYSTAL).toResource()->getNameTranslated(), [this](PlayerColor color){
auto val = playerDataFilter(color).back(); auto val = playerDataFilter(color).back();
return std::to_string(val.tradeVolume[EGameResID::CRYSTAL]); return std::to_string(val.tradeVolume[EGameResID::CRYSTAL]);
} }
}, },
{ {
LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", EGameResID::GEMS).get()), [this](PlayerColor color){ LIBRARY->generaltexth->translate("vcmi.statisticWindow.param.tradeVolume") + " - " + GameResID(EGameResID::GEMS).toResource()->getNameTranslated(), [this](PlayerColor color){
auto val = playerDataFilter(color).back(); auto val = playerDataFilter(color).back();
return std::to_string(val.tradeVolume[EGameResID::GEMS]); return std::to_string(val.tradeVolume[EGameResID::GEMS]);
} }

View File

@@ -25,7 +25,6 @@
#include "../GameEngine.h" #include "../GameEngine.h"
#include "../widgets/TextControls.h" #include "../widgets/TextControls.h"
#include "../../lib/mapObjects/CObjectHandler.h"
#include "../../lib/int3.h" #include "../../lib/int3.h"
MapViewCache::~MapViewCache() = default; MapViewCache::~MapViewCache() = default;

View File

@@ -43,6 +43,7 @@
#include <vcmi/Services.h> #include <vcmi/Services.h>
#include <vcmi/SkillService.h> #include <vcmi/SkillService.h>
#include <vcmi/spells/Service.h> #include <vcmi/spells/Service.h>
#include <vcmi/ResourceTypeService.h>
RenderHandler::RenderHandler() RenderHandler::RenderHandler()
:assetGenerator(std::make_unique<AssetGenerator>()) :assetGenerator(std::make_unique<AssetGenerator>())
@@ -494,6 +495,7 @@ void RenderHandler::onLibraryLoadingFinished(const Services * services)
addImageListEntries(services->factions()); addImageListEntries(services->factions());
addImageListEntries(services->spells()); addImageListEntries(services->spells());
addImageListEntries(services->skills()); addImageListEntries(services->skills());
addImageListEntries(services->resources());
if (settings["mods"]["validation"].String() == "full") if (settings["mods"]["validation"].String() == "full")
{ {

View File

@@ -227,7 +227,7 @@ void CMinorResDataBar::showAll(Canvas & to)
{ {
CIntObject::showAll(to); CIntObject::showAll(to);
for (GameResID i=EGameResID::WOOD; i<=EGameResID::GOLD; ++i) for (GameResID i=EGameResID::WOOD; i<=EGameResID::GOLD; ++i) //todo: configurable resource support
{ {
std::string text = std::to_string(GAME->interface()->cb->getResourceAmount(i)); std::string text = std::to_string(GAME->interface()->cb->getResourceAmount(i));

View File

@@ -23,6 +23,7 @@
#include "../../../lib/entities/artifact/CArtHandler.h" #include "../../../lib/entities/artifact/CArtHandler.h"
#include "../../../lib/texts/CGeneralTextHandler.h" #include "../../../lib/texts/CGeneralTextHandler.h"
#include "../../../lib/mapObjects/CGHeroInstance.h" #include "../../../lib/mapObjects/CGHeroInstance.h"
#include "../../../lib/entities/ResourceTypeHandler.h"
CTradeableItem::CTradeableItem(const Rect & area, EType Type, int32_t ID, int32_t serial) CTradeableItem::CTradeableItem(const Rect & area, EType Type, int32_t ID, int32_t serial)
: SelectableSlot(area, Point(1, 1)) : SelectableSlot(area, Point(1, 1))
@@ -175,7 +176,7 @@ void CTradeableItem::hover(bool on)
ENGINE->statusbar()->write(LIBRARY->artifacts()->getByIndex(id)->getNameTranslated()); ENGINE->statusbar()->write(LIBRARY->artifacts()->getByIndex(id)->getNameTranslated());
break; break;
case EType::RESOURCE: case EType::RESOURCE:
ENGINE->statusbar()->write(LIBRARY->generaltexth->restypes[id]); ENGINE->statusbar()->write(GameResID(id).toResource()->getNameTranslated());
break; break;
case EType::PLAYER: case EType::PLAYER:
ENGINE->statusbar()->write(LIBRARY->generaltexth->capColors[id]); ENGINE->statusbar()->write(LIBRARY->generaltexth->capColors[id]);

View File

@@ -58,6 +58,7 @@
#include "../../lib/campaign/CampaignState.h" #include "../../lib/campaign/CampaignState.h"
#include "../../lib/entities/artifact/CArtifact.h" #include "../../lib/entities/artifact/CArtifact.h"
#include "../../lib/entities/building/CBuilding.h" #include "../../lib/entities/building/CBuilding.h"
#include "../../lib/entities/ResourceTypeHandler.h"
#include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/mapObjects/CGTownInstance.h"
#include "../../lib/mapObjects/TownBuildingInstance.h" #include "../../lib/mapObjects/TownBuildingInstance.h"
@@ -292,7 +293,7 @@ CDwellingInfoBox::CDwellingInfoBox(int centerX, int centerY, const CGTownInstanc
available = std::make_shared<CLabel>(80,190, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, LIBRARY->generaltexth->allTexts[217] + text); available = std::make_shared<CLabel>(80,190, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, LIBRARY->generaltexth->allTexts[217] + text);
costPerTroop = std::make_shared<CLabel>(80, 227, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, LIBRARY->generaltexth->allTexts[346]); costPerTroop = std::make_shared<CLabel>(80, 227, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, LIBRARY->generaltexth->allTexts[346]);
for(int i = 0; i<GameConstants::RESOURCE_QUANTITY; i++) for (auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
auto res = static_cast<EGameResID>(i); auto res = static_cast<EGameResID>(i);
if(creature->getRecruitCost(res)) if(creature->getRecruitCost(res))
@@ -1126,7 +1127,7 @@ void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID:
else //Mystic Pond produced something; else //Mystic Pond produced something;
{ {
descr += "\n\n" + hasProduced; descr += "\n\n" + hasProduced;
boost::algorithm::replace_first(descr,"%s",LIBRARY->generaltexth->restypes[town->bonusValue.first]); boost::algorithm::replace_first(descr,"%s",GameResID(town->bonusValue.first).toResource()->getNameTranslated());
boost::algorithm::replace_first(descr,"%d",std::to_string(town->bonusValue.second)); boost::algorithm::replace_first(descr,"%d",std::to_string(town->bonusValue.second));
} }
} }
@@ -1795,7 +1796,7 @@ CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Buildin
//Create components for all required resources //Create components for all required resources
std::vector<std::shared_ptr<CComponent>> components; std::vector<std::shared_ptr<CComponent>> components;
for(GameResID i : GameResID::ALL_RESOURCES()) for(GameResID i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
if(building->resources[i]) if(building->resources[i])
{ {
@@ -2211,7 +2212,8 @@ void CMageGuildScreen::Scroll::clickPressed(const Point & cursorPosition)
return; return;
} }
auto costBase = TResources(GAME->interface()->cb->getSettings().getValue(EGameSettings::TOWNS_SPELL_RESEARCH_COST).Vector()[level]); ResourceSet costBase;
costBase.resolveFromJson(GAME->interface()->cb->getSettings().getValue(EGameSettings::TOWNS_SPELL_RESEARCH_COST).Vector()[level]);
auto costExponent = GAME->interface()->cb->getSettings().getValue(EGameSettings::TOWNS_SPELL_RESEARCH_COST_EXPONENT_PER_RESEARCH).Vector()[level].Float(); auto costExponent = GAME->interface()->cb->getSettings().getValue(EGameSettings::TOWNS_SPELL_RESEARCH_COST_EXPONENT_PER_RESEARCH).Vector()[level].Float();
auto cost = costBase * std::pow(town->spellResearchAcceptedCounter + 1, costExponent); auto cost = costBase * std::pow(town->spellResearchAcceptedCounter + 1, costExponent);

View File

@@ -46,6 +46,7 @@
#include "../lib/entities/building/CBuilding.h" #include "../lib/entities/building/CBuilding.h"
#include "../lib/entities/faction/CTownHandler.h" #include "../lib/entities/faction/CTownHandler.h"
#include "../lib/entities/hero/CHeroHandler.h" #include "../lib/entities/hero/CHeroHandler.h"
#include "../lib/entities/ResourceTypeHandler.h"
#include "../lib/mapObjectConstructors/CObjectClassesHandler.h" #include "../lib/mapObjectConstructors/CObjectClassesHandler.h"
#include "../lib/mapObjectConstructors/CommonConstructors.h" #include "../lib/mapObjectConstructors/CommonConstructors.h"
#include "../lib/mapObjects/CGHeroInstance.h" #include "../lib/mapObjects/CGHeroInstance.h"
@@ -830,7 +831,7 @@ CShipyardWindow::CShipyardWindow(const TResources & cost, int state, BoatId boat
build = std::make_shared<CButton>(Point(42, 312), AnimationPath::builtin("IBUY30"), CButton::tooltip(LIBRARY->generaltexth->allTexts[598]), std::bind(&CShipyardWindow::close, this), EShortcut::GLOBAL_ACCEPT); build = std::make_shared<CButton>(Point(42, 312), AnimationPath::builtin("IBUY30"), CButton::tooltip(LIBRARY->generaltexth->allTexts[598]), std::bind(&CShipyardWindow::close, this), EShortcut::GLOBAL_ACCEPT);
build->addCallback(onBuy); build->addCallback(onBuy);
for(GameResID i = EGameResID::WOOD; i <= EGameResID::GOLD; ++i) for(auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
if(cost[i] > GAME->interface()->cb->getResourceAmount(i)) if(cost[i] > GAME->interface()->cb->getResourceAmount(i))
{ {
@@ -1215,7 +1216,6 @@ void CHillFortWindow::updateGarrisons()
for(int i=0; i<slotsCount; i++) for(int i=0; i<slotsCount; i++)
{ {
std::fill(costs[i].begin(), costs[i].end(), 0);
State newState = getState(SlotID(i)); State newState = getState(SlotID(i));
if(newState != State::EMPTY) if(newState != State::EMPTY)
{ {

View File

@@ -464,7 +464,7 @@ private:
enum class State { UNAFFORDABLE, ALREADY_UPGRADED, MAKE_UPGRADE, EMPTY, UNAVAILABLE }; enum class State { UNAFFORDABLE, ALREADY_UPGRADED, MAKE_UPGRADE, EMPTY, UNAVAILABLE };
static constexpr std::size_t slotsCount = 7; static constexpr std::size_t slotsCount = 7;
//todo: mithril support //todo: configurable resource support
static constexpr std::size_t resCount = 7; static constexpr std::size_t resCount = 7;
const CGObjectInstance * fort; const CGObjectInstance * fort;

View File

@@ -4,31 +4,31 @@
{ {
"pawn": "pawn":
{ {
"resources": { "wood" : 30, "mercury": 15, "ore": 30, "sulfur": 15, "crystal": 15, "gems": 15, "gold": 30000, "mithril": 0 }, "resources": { "wood" : 30, "mercury": 15, "ore": 30, "sulfur": 15, "crystal": 15, "gems": 15, "gold": 30000 },
"globalBonuses": [], "globalBonuses": [],
"battleBonuses": [] "battleBonuses": []
}, },
"knight": "knight":
{ {
"resources": { "wood" : 20, "mercury": 10, "ore": 20, "sulfur": 10, "crystal": 10, "gems": 10, "gold": 20000, "mithril": 0 }, "resources": { "wood" : 20, "mercury": 10, "ore": 20, "sulfur": 10, "crystal": 10, "gems": 10, "gold": 20000 },
"globalBonuses": [], "globalBonuses": [],
"battleBonuses": [] "battleBonuses": []
}, },
"rook": "rook":
{ {
"resources": { "wood" : 15, "mercury": 7, "ore": 15, "sulfur": 7, "crystal": 7, "gems": 7, "gold": 15000, "mithril": 0 }, "resources": { "wood" : 15, "mercury": 7, "ore": 15, "sulfur": 7, "crystal": 7, "gems": 7, "gold": 15000 },
"globalBonuses": [], "globalBonuses": [],
"battleBonuses": [] "battleBonuses": []
}, },
"queen": "queen":
{ {
"resources": { "wood" : 10, "mercury": 4, "ore": 10, "sulfur": 4, "crystal": 4, "gems": 4, "gold": 10000, "mithril": 0 }, "resources": { "wood" : 10, "mercury": 4, "ore": 10, "sulfur": 4, "crystal": 4, "gems": 4, "gold": 10000 },
"globalBonuses": [], "globalBonuses": [],
"battleBonuses": [] "battleBonuses": []
}, },
"king": "king":
{ {
"resources": { "wood" : 0, "mercury": 0, "ore": 0, "sulfur": 0, "crystal": 0, "gems": 0, "gold": 0, "mithril": 0 }, "resources": { "wood" : 0, "mercury": 0, "ore": 0, "sulfur": 0, "crystal": 0, "gems": 0, "gold": 0 },
"globalBonuses": [], "globalBonuses": [],
"battleBonuses": [] "battleBonuses": []
} }
@@ -37,31 +37,31 @@
{ {
"pawn": "pawn":
{ {
"resources": { "wood" : 5, "mercury": 2, "ore": 5, "sulfur": 2, "crystal": 2, "gems": 2, "gold": 5000, "mithril": 0 }, "resources": { "wood" : 5, "mercury": 2, "ore": 5, "sulfur": 2, "crystal": 2, "gems": 2, "gold": 5000 },
"globalBonuses": [], "globalBonuses": [],
"battleBonuses": [] "battleBonuses": []
}, },
"knight": "knight":
{ {
"resources": { "wood" : 10, "mercury": 4, "ore": 10, "sulfur": 4, "crystal": 4, "gems": 4, "gold": 7500, "mithril": 0 }, "resources": { "wood" : 10, "mercury": 4, "ore": 10, "sulfur": 4, "crystal": 4, "gems": 4, "gold": 7500 },
"globalBonuses": [], "globalBonuses": [],
"battleBonuses": [] "battleBonuses": []
}, },
"rook": "rook":
{ {
"resources": { "wood" : 15, "mercury": 7, "ore": 15, "sulfur": 7, "crystal": 7, "gems": 7, "gold": 10000, "mithril": 0 }, "resources": { "wood" : 15, "mercury": 7, "ore": 15, "sulfur": 7, "crystal": 7, "gems": 7, "gold": 10000 },
"globalBonuses": [], "globalBonuses": [],
"battleBonuses": [] "battleBonuses": []
}, },
"queen": "queen":
{ {
"resources": { "wood" : 15, "mercury": 7, "ore": 15, "sulfur": 7, "crystal": 7, "gems": 7, "gold": 10000, "mithril": 0 }, "resources": { "wood" : 15, "mercury": 7, "ore": 15, "sulfur": 7, "crystal": 7, "gems": 7, "gold": 10000 },
"globalBonuses": [], "globalBonuses": [],
"battleBonuses": [] "battleBonuses": []
}, },
"king": "king":
{ {
"resources": { "wood" : 15, "mercury": 7, "ore": 15, "sulfur": 7, "crystal": 7, "gems": 7, "gold": 10000, "mithril": 0 }, "resources": { "wood" : 15, "mercury": 7, "ore": 15, "sulfur": 7, "crystal": 7, "gems": 7, "gold": 10000 },
"globalBonuses": [], "globalBonuses": [],
"battleBonuses": [] "battleBonuses": []
} }

View File

@@ -111,6 +111,10 @@
[ [
"config/terrains.json" "config/terrains.json"
], ],
"resources" :
[
"config/resources.json"
],
"roads": "roads":
[ [
"config/roads.json" "config/roads.json"

View File

@@ -1,4 +1,36 @@
{ {
// Price of each resource in gold, in usual resource order "wood": {
"resources_prices": [ 250, 500, 250, 500, 500, 500, 1, 0 ] "index" : 0,
"price": 250
},
"mercury": {
"index" : 1,
"price": 500
},
"ore": {
"index" : 2,
"price": 250
},
"sulfur": {
"index" : 3,
"price": 500
},
"crystal": {
"index" : 4,
"price": 500
},
"gems": {
"index" : 5,
"price": 500
},
"gold": {
"index" : 6,
"price": 1
}
} }

View File

@@ -93,17 +93,10 @@
}, },
"cost" : { "cost" : {
"type" : "object", "type" : "object",
"additionalProperties" : false, "additionalProperties" : {
"description" : "Cost to recruit this creature", "type" : "number"
"properties" : { },
"gold" : { "type" : "number"}, "description" : "Cost to recruit this creature"
"wood" : { "type" : "number"},
"ore" : { "type" : "number"},
"mercury" : { "type" : "number"},
"sulfur" : { "type" : "number"},
"crystal" : { "type" : "number"},
"gems" : { "type" : "number"}
}
}, },
"speed" : { "type" : "number" }, "speed" : { "type" : "number" },
"hitPoints" : { "type" : "number" }, "hitPoints" : { "type" : "number" },

View File

@@ -35,17 +35,10 @@
"dailyIncome" : { "dailyIncome" : {
"type" : "object", "type" : "object",
"additionalProperties" : false, "additionalProperties" : {
"type" : "number"
},
"description" : "Daily income that this building provides to owner, if any", "description" : "Daily income that this building provides to owner, if any",
"properties" : {
"gold" : { "type" : "number"},
"wood" : { "type" : "number"},
"ore" : { "type" : "number"},
"mercury" : { "type" : "number"},
"sulfur" : { "type" : "number"},
"crystal" : { "type" : "number"},
"gems" : { "type" : "number"}
}
}, },
// Properties that might appear since this node is shared with object config // Properties that might appear since this node is shared with object config

View File

@@ -65,7 +65,7 @@
}, },
"modType" : { "modType" : {
"type" : "string", "type" : "string",
"enum" : [ "Translation", "Town", "Test", "Templates", "Spells", "Music", "Maps", "Sounds", "Skills", "Other", "Objects", "Mechanics", "Interface", "Heroes", "Graphical", "Expansion", "Creatures", "Compatibility", "Campaigns", "Artifacts", "AI" ], "enum" : [ "Translation", "Town", "Test", "Templates", "Spells", "Music", "Maps", "Sounds", "Skills", "Other", "Objects", "Mechanics", "Interface", "Heroes", "Graphical", "Expansion", "Creatures", "Compatibility", "Campaigns", "Artifacts", "AI", "Resources" ],
"description" : "Type of mod, e.g. Town, Artifacts, Graphical." "description" : "Type of mod, e.g. Town, Artifacts, Graphical."
}, },
"author" : { "author" : {
@@ -303,6 +303,10 @@
"description" : "List of configuration files for terrains", "description" : "List of configuration files for terrains",
"$ref" : "#/definitions/fileListOrObject" "$ref" : "#/definitions/fileListOrObject"
}, },
"resources" : {
"description" : "List of configuration files for resources",
"$ref" : "#/definitions/fileListOrObject"
},
"roads" : { "roads" : {
"description" : "List of configuration files for roads", "description" : "List of configuration files for roads",
"$ref" : "#/definitions/fileListOrObject" "$ref" : "#/definitions/fileListOrObject"

View File

@@ -0,0 +1,44 @@
{
"type" : "object",
"$schema" : "http://json-schema.org/draft-04/schema",
"title" : "VCMI resources format",
"description" : "Format used to define new resources in VCMI",
"required" : [ "name", "price" ],
"additionalProperties" : false,
"properties" : {
"index" : {
"type" : "number",
"description" : "numeric id of h3 resource, prohibited for new resources"
},
"name" : {
"type" : "string",
"description" : "Localizable name of this resource"
},
"images" : {
"type" : "object",
"description" : "Resource icons of varying size",
"required" : [ "small", "medium", "large"],
"properties" : {
"small" : {
"type" : "string",
"description" : "20x18 resource icon",
"format" : "imageFile"
},
"medium" : {
"type" : "string",
"description" : "32x32 resource icon",
"format" : "imageFile"
},
"large" : {
"type" : "string",
"description" : "82x93 resource icon",
"format" : "imageFile"
}
}
},
"price" : {
"type" : "number",
"description" : "Price of resource in gold"
}
}
}

View File

@@ -139,15 +139,8 @@
}, },
"mines" : { "mines" : {
"type" : "object", "type" : "object",
"additionalProperties" : false, "additionalProperties" : {
"properties" : { "type" : "number"
"gold" : { "type" : "number"},
"wood" : { "type" : "number"},
"ore" : { "type" : "number"},
"mercury" : { "type" : "number"},
"sulfur" : { "type" : "number"},
"crystal" : { "type" : "number"},
"gems" : { "type" : "number"}
} }
}, },
"connection" : "connection" :

View File

@@ -86,31 +86,17 @@
}, },
"cost" : { "cost" : {
"type" : "object", "type" : "object",
"additionalProperties" : false, "additionalProperties" : {
"description" : "Resources needed to build building", "type" : "number"
"properties" : { },
"gold" : { "type" : "number"}, "description" : "Resources needed to build building"
"wood" : { "type" : "number"},
"ore" : { "type" : "number"},
"mercury" : { "type" : "number"},
"sulfur" : { "type" : "number"},
"crystal" : { "type" : "number"},
"gems" : { "type" : "number"}
}
}, },
"produce" : { "produce" : {
"type" : "object", "type" : "object",
"additionalProperties" : false, "additionalProperties" : {
"description" : "Resources produced each day by this building", "type" : "number"
"properties" : { },
"gold" : { "type" : "number"}, "description" : "Resources produced each day by this building"
"wood" : { "type" : "number"},
"ore" : { "type" : "number"},
"mercury" : { "type" : "number"},
"sulfur" : { "type" : "number"},
"crystal" : { "type" : "number"},
"gems" : { "type" : "number"}
}
}, },
"warMachine" : { "warMachine" : {
"type" : "string", "type" : "string",

View File

@@ -14,7 +14,7 @@ Difficulty configuration is located in [config/difficulty.json](../../config/dif
"pawn": //parameters for specific difficulty "pawn": //parameters for specific difficulty
{ {
//starting resources //starting resources
"resources": { "wood" : 30, "mercury": 15, "ore": 30, "sulfur": 15, "crystal": 15, "gems": 15, "gold": 30000, "mithril": 0 }, "resources": { "wood" : 30, "mercury": 15, "ore": 30, "sulfur": 15, "crystal": 15, "gems": 15, "gold": 30000 },
//bonuses will be given to player globally //bonuses will be given to player globally
"globalBonuses": [], "globalBonuses": [],
//bonuses will be given to player every battle //bonuses will be given to player every battle

View File

@@ -0,0 +1,20 @@
# Resource Format
```json
// Internal field for H3 resources. Do not use for mods
"index" : "",
// displayed name of the resource
"name" : "",
// Resource icons of varying size
"images" : {
// 20x18 resource icon
"small" : "",
// 32x32 resource icon
"medium" : "",
// 82x93 resource icon
"large" : ""
}
```

View File

@@ -568,7 +568,6 @@ Deprecated, please use primarySkill instead
- resource.gems - resource.gems
- resource.gold - resource.gold
- resource.mercury - resource.mercury
- resource.mithril
- resource.ore - resource.ore
- resource.sulfur - resource.sulfur
- resource.wood - resource.wood

View File

@@ -31,7 +31,7 @@
// Type of mod, list of all possible values: // Type of mod, list of all possible values:
// "Translation", "Town", "Test", "Templates", "Spells", "Music", "Maps", "Sounds", "Skills", "Other", "Objects", // "Translation", "Town", "Test", "Templates", "Spells", "Music", "Maps", "Sounds", "Skills", "Other", "Objects",
// "Mechanics", "Interface", "Heroes", "Graphical", "Expansion", "Creatures", "Compatibility", "Campaigns", "Artifacts", "AI" // "Mechanics", "Interface", "Heroes", "Graphical", "Expansion", "Creatures", "Compatibility", "Campaigns", "Artifacts", "AI", "Resources"
// //
// Some mod types have additional effects on your mod: // Some mod types have additional effects on your mod:
// Translation: mod of this type is only active if player uses base language of this mod. See "language" property. // Translation: mod of this type is only active if player uses base language of this mod. See "language" property.

View File

@@ -41,10 +41,6 @@ Stack experience interface has been merged with regular creature window. Among o
VCMI offers native support for Commanders. Commanders are part of WoG mod for VCMI and require it to be enabled. However, once this is done, any new faction can use its own Commander, too. VCMI offers native support for Commanders. Commanders are part of WoG mod for VCMI and require it to be enabled. However, once this is done, any new faction can use its own Commander, too.
### Mithril module
VCMI natively supports Mithril resource known from WoG. However, it is not currently used by any mod.
### Stack Artifact module ### Stack Artifact module
In original WoG, there is one available Stack Artifact - Warlord's Banner, which is related directly to stack experience. VCMI natively supports any number of Stack Artifacts regardless if of Stack Experience module is enabled or not. However, currently no mods make use of this feature and it hasn't been tested for many years. In original WoG, there is one available Stack Artifact - Warlord's Banner, which is related directly to stack experience. VCMI natively supports any number of Stack Artifacts regardless if of Stack Experience module is enabled or not. However, currently no mods make use of this feature and it hasn't been tested for many years.

View File

@@ -0,0 +1,25 @@
/*
* ResourceType.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 "Entity.h"
VCMI_LIB_NAMESPACE_BEGIN
class GameResID;
class DLL_LINKAGE ResourceType : public EntityT<GameResID>
{
virtual int getPrice() const = 0;
};
VCMI_LIB_NAMESPACE_END

View File

@@ -1,5 +1,5 @@
/* /*
* CObjectHandler.h, part of VCMI engine * ResourceTypeService.h, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *
@@ -7,21 +7,19 @@
* Full text of license available in license.txt file, in main folder * Full text of license available in license.txt file, in main folder
* *
*/ */
#pragma once #pragma once
#include "../GameConstants.h" #include "EntityService.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
class CGObjectInstance; class GameResID;
class int3; class ResourceType;
class DLL_LINKAGE CObjectHandler class DLL_LINKAGE ResourceTypeService : public EntityServiceT<GameResID, ResourceType>
{ {
public: public:
std::vector<ui32> resVals; //default values of resources in gold
CObjectHandler();
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@@ -19,6 +19,7 @@ class CreatureService;
class FactionService; class FactionService;
class HeroClassService; class HeroClassService;
class HeroTypeService; class HeroTypeService;
class ResourceTypeService;
class SkillService; class SkillService;
class JsonNode; class JsonNode;
class BattleFieldService; class BattleFieldService;
@@ -52,6 +53,7 @@ public:
virtual const FactionService * factions() const = 0; virtual const FactionService * factions() const = 0;
virtual const HeroClassService * heroClasses() const = 0; virtual const HeroClassService * heroClasses() const = 0;
virtual const HeroTypeService * heroTypes() const = 0; virtual const HeroTypeService * heroTypes() const = 0;
virtual const ResourceTypeService * resources() const = 0;
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED
virtual const scripting::Service * scripts() const = 0; virtual const scripting::Service * scripts() const = 0;
#endif #endif

View File

@@ -54,6 +54,7 @@ QString ModStateItemModel::modTypeName(QString modTypeID) const
QT_TR_NOOP("Campaigns"), QT_TR_NOOP("Campaigns"),
QT_TR_NOOP("Artifacts"), QT_TR_NOOP("Artifacts"),
QT_TR_NOOP("AI"), QT_TR_NOOP("AI"),
QT_TR_NOOP("Resources"),
}; };
if (modTypes.contains(modTypeID)) if (modTypes.contains(modTypeID))

View File

@@ -568,7 +568,7 @@ std::vector<JsonNode> CCreatureHandler::loadLegacyData()
data["name"]["plural"].String() = parser.readString(); data["name"]["plural"].String() = parser.readString();
for(int v=0; v<7; ++v) for(int v=0; v<GameConstants::RESOURCE_QUANTITY; ++v)
data["cost"][GameConstants::RESOURCE_NAMES[v]].Float() = parser.readNumber(); data["cost"][GameConstants::RESOURCE_NAMES[v]].Float() = parser.readNumber();
data["fightValue"].Float() = parser.readNumber(); data["fightValue"].Float() = parser.readNumber();
@@ -623,7 +623,7 @@ std::shared_ptr<CCreature> CCreatureHandler::loadFromJson(const std::string & sc
JsonDeserializer handler(nullptr, node); JsonDeserializer handler(nullptr, node);
cre->serializeJson(handler); cre->serializeJson(handler);
cre->cost = ResourceSet(node["cost"]); cre->cost.resolveFromJson(node["cost"]);
LIBRARY->generaltexth->registerString(scope, cre->getNameSingularTextID(), node["name"]["singular"]); LIBRARY->generaltexth->registerString(scope, cre->getNameSingularTextID(), node["name"]["singular"]);
LIBRARY->generaltexth->registerString(scope, cre->getNamePluralTextID(), node["name"]["plural"]); LIBRARY->generaltexth->registerString(scope, cre->getNamePluralTextID(), node["name"]["plural"]);

View File

@@ -111,6 +111,7 @@ set(lib_MAIN_SRCS
entities/hero/CHeroClass.cpp entities/hero/CHeroClass.cpp
entities/hero/CHeroClassHandler.cpp entities/hero/CHeroClassHandler.cpp
entities/hero/CHeroHandler.cpp entities/hero/CHeroHandler.cpp
entities/ResourceTypeHandler.cpp
events/ApplyDamage.cpp events/ApplyDamage.cpp
events/GameResumed.cpp events/GameResumed.cpp
@@ -152,7 +153,6 @@ set(lib_MAIN_SRCS
mapObjects/CGResource.cpp mapObjects/CGResource.cpp
mapObjects/TownBuildingInstance.cpp mapObjects/TownBuildingInstance.cpp
mapObjects/CGTownInstance.cpp mapObjects/CGTownInstance.cpp
mapObjects/CObjectHandler.cpp
mapObjects/CQuest.cpp mapObjects/CQuest.cpp
mapObjects/CRewardableObject.cpp mapObjects/CRewardableObject.cpp
mapObjects/FlaggableMapObject.cpp mapObjects/FlaggableMapObject.cpp
@@ -428,6 +428,8 @@ set(lib_MAIN_HEADERS
../include/vcmi/HeroClassService.h ../include/vcmi/HeroClassService.h
../include/vcmi/HeroType.h ../include/vcmi/HeroType.h
../include/vcmi/HeroTypeService.h ../include/vcmi/HeroTypeService.h
../include/vcmi/ResourceType.h
../include/vcmi/ResourceTypeService.h
../include/vcmi/Metatype.h ../include/vcmi/Metatype.h
../include/vcmi/Player.h ../include/vcmi/Player.h
../include/vcmi/ServerCallback.h ../include/vcmi/ServerCallback.h
@@ -534,6 +536,7 @@ set(lib_MAIN_HEADERS
entities/hero/CHeroClassHandler.h entities/hero/CHeroClassHandler.h
entities/hero/CHeroHandler.h entities/hero/CHeroHandler.h
entities/hero/EHeroGender.h entities/hero/EHeroGender.h
entities/ResourceTypeHandler.h
events/ApplyDamage.h events/ApplyDamage.h
events/GameResumed.h events/GameResumed.h
@@ -581,7 +584,6 @@ set(lib_MAIN_HEADERS
mapObjects/TownBuildingInstance.h mapObjects/TownBuildingInstance.h
mapObjects/CGResource.h mapObjects/CGResource.h
mapObjects/CGTownInstance.h mapObjects/CGTownInstance.h
mapObjects/CObjectHandler.h
mapObjects/CQuest.h mapObjects/CQuest.h
mapObjects/CRewardableObject.h mapObjects/CRewardableObject.h
mapObjects/FlaggableMapObject.h mapObjects/FlaggableMapObject.h

View File

@@ -98,7 +98,7 @@ const IBonusBearer * PlayerState::getBonusBearer() const
int PlayerState::getResourceAmount(int type) const int PlayerState::getResourceAmount(int type) const
{ {
return vstd::atOrDefault(resources, static_cast<size_t>(type), 0); return resources[type];
} }
template<typename T> template<typename T>

View File

@@ -25,6 +25,7 @@
#include "entities/faction/CTownHandler.h" #include "entities/faction/CTownHandler.h"
#include "entities/hero/CHeroClassHandler.h" #include "entities/hero/CHeroClassHandler.h"
#include "entities/hero/CHeroHandler.h" #include "entities/hero/CHeroHandler.h"
#include "entities/ResourceTypeHandler.h"
#include "texts/CGeneralTextHandler.h" #include "texts/CGeneralTextHandler.h"
#include "campaign/CampaignRegionsHandler.h" #include "campaign/CampaignRegionsHandler.h"
#include "mapping/MapFormatSettings.h" #include "mapping/MapFormatSettings.h"
@@ -36,7 +37,6 @@
#include "filesystem/Filesystem.h" #include "filesystem/Filesystem.h"
#include "rmg/CRmgTemplateStorage.h" #include "rmg/CRmgTemplateStorage.h"
#include "mapObjectConstructors/CObjectClassesHandler.h" #include "mapObjectConstructors/CObjectClassesHandler.h"
#include "mapObjects/CObjectHandler.h"
#include "mapObjects/ObstacleSetHandler.h" #include "mapObjects/ObstacleSetHandler.h"
#include "mapping/CMapEditManager.h" #include "mapping/CMapEditManager.h"
#include "ScriptHandler.h" #include "ScriptHandler.h"
@@ -75,6 +75,11 @@ const HeroTypeService * GameLibrary::heroTypes() const
return heroh.get(); return heroh.get();
} }
const ResourceTypeService * GameLibrary::resources() const
{
return resourceTypeHandler.get();
}
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED
const scripting::Service * GameLibrary::scripts() const const scripting::Service * GameLibrary::scripts() const
{ {
@@ -171,6 +176,7 @@ void GameLibrary::initializeLibrary()
createHandler(generaltexth); createHandler(generaltexth);
createHandler(bth); createHandler(bth);
createHandler(resourceTypeHandler);
createHandler(roadTypeHandler); createHandler(roadTypeHandler);
createHandler(riverTypeHandler); createHandler(riverTypeHandler);
createHandler(terrainTypeHandler); createHandler(terrainTypeHandler);
@@ -180,7 +186,6 @@ void GameLibrary::initializeLibrary()
createHandler(creh); createHandler(creh);
createHandler(townh); createHandler(townh);
createHandler(biomeHandler); createHandler(biomeHandler);
createHandler(objh);
createHandler(objtypeh); createHandler(objtypeh);
createHandler(spellSchoolHandler); createHandler(spellSchoolHandler);
createHandler(spellh); createHandler(spellh);

View File

@@ -20,7 +20,6 @@ class CHeroClassHandler;
class CCreatureHandler; class CCreatureHandler;
class CSpellHandler; class CSpellHandler;
class CSkillHandler; class CSkillHandler;
class CObjectHandler;
class CObjectClassesHandler; class CObjectClassesHandler;
class ObstacleSetHandler; class ObstacleSetHandler;
class CTownHandler; class CTownHandler;
@@ -31,6 +30,7 @@ class BattleFieldHandler;
class IBonusTypeHandler; class IBonusTypeHandler;
class CBonusTypeHandler; class CBonusTypeHandler;
class TerrainTypeHandler; class TerrainTypeHandler;
class ResourceTypeHandler;
class RoadTypeHandler; class RoadTypeHandler;
class RiverTypeHandler; class RiverTypeHandler;
class ObstacleHandler; class ObstacleHandler;
@@ -60,6 +60,7 @@ public:
const FactionService * factions() const override; const FactionService * factions() const override;
const HeroClassService * heroClasses() const override; const HeroClassService * heroClasses() const override;
const HeroTypeService * heroTypes() const override; const HeroTypeService * heroTypes() const override;
const ResourceTypeService * resources() const override;
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED
const scripting::Service * scripts() const override; const scripting::Service * scripts() const override;
#endif #endif
@@ -83,13 +84,12 @@ public:
std::unique_ptr<CSpellHandler> spellh; std::unique_ptr<CSpellHandler> spellh;
std::unique_ptr<SpellSchoolHandler> spellSchoolHandler; std::unique_ptr<SpellSchoolHandler> spellSchoolHandler;
std::unique_ptr<CSkillHandler> skillh; std::unique_ptr<CSkillHandler> skillh;
// TODO: Remove ObjectHandler altogether?
std::unique_ptr<CObjectHandler> objh;
std::unique_ptr<CObjectClassesHandler> objtypeh; std::unique_ptr<CObjectClassesHandler> objtypeh;
std::unique_ptr<CTownHandler> townh; std::unique_ptr<CTownHandler> townh;
std::unique_ptr<CGeneralTextHandler> generaltexth; std::unique_ptr<CGeneralTextHandler> generaltexth;
std::unique_ptr<CModHandler> modh; std::unique_ptr<CModHandler> modh;
std::unique_ptr<TerrainTypeHandler> terrainTypeHandler; std::unique_ptr<TerrainTypeHandler> terrainTypeHandler;
std::unique_ptr<ResourceTypeHandler> resourceTypeHandler;
std::unique_ptr<RoadTypeHandler> roadTypeHandler; std::unique_ptr<RoadTypeHandler> roadTypeHandler;
std::unique_ptr<RiverTypeHandler> riverTypeHandler; std::unique_ptr<RiverTypeHandler> riverTypeHandler;
std::unique_ptr<CIdentifierStorage> identifiersHandler; std::unique_ptr<CIdentifierStorage> identifiersHandler;

View File

@@ -13,17 +13,34 @@
#include "ResourceSet.h" #include "ResourceSet.h"
#include "constants/StringConstants.h" #include "constants/StringConstants.h"
#include "serializer/JsonSerializeFormat.h" #include "serializer/JsonSerializeFormat.h"
#include "mapObjects/CObjectHandler.h" #include "entities/ResourceTypeHandler.h"
#include "GameLibrary.h" #include "GameLibrary.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
ResourceSet::ResourceSet() = default; ResourceSet::ResourceSet()
ResourceSet::ResourceSet(const JsonNode & node)
{ {
for(auto i = 0; i < GameConstants::RESOURCE_QUANTITY; i++) resizeContainer();
container[i] = static_cast<int>(node[GameConstants::RESOURCE_NAMES[i]].Float()); };
ResourceSet::ResourceSet(const ResourceSet& rhs)
: container(rhs.container) // vector copy constructor
{
resizeContainer();
}
void ResourceSet::resizeContainer()
{
container.resize(std::max(static_cast<int>(LIBRARY->resourceTypeHandler->getAllObjects().size()), GameConstants::RESOURCE_QUANTITY));
}
void ResourceSet::resolveFromJson(const JsonNode & node)
{
for(auto & n : node.Struct())
LIBRARY->identifiers()->requestIdentifier(n.second.getModScope(), "resource", n.first, [n, this](int32_t identifier)
{
(*this)[identifier] = static_cast<int>(n.second.Float());
});
} }
void ResourceSet::serializeJson(JsonSerializeFormat & handler, const std::string & fieldName) void ResourceSet::serializeJson(JsonSerializeFormat & handler, const std::string & fieldName)
@@ -32,9 +49,8 @@ void ResourceSet::serializeJson(JsonSerializeFormat & handler, const std::string
return; return;
auto s = handler.enterStruct(fieldName); auto s = handler.enterStruct(fieldName);
//TODO: add proper support for mithril to map format for(auto & idx : LIBRARY->resourceTypeHandler->getAllObjects())
for(int idx = 0; idx < GameConstants::RESOURCE_QUANTITY - 1; idx ++) handler.serializeInt(idx.toResource()->getJsonKey(), this->operator[](idx), 0);
handler.serializeInt(GameConstants::RESOURCE_NAMES[idx], this->operator[](idx), 0);
} }
bool ResourceSet::nonZero() const bool ResourceSet::nonZero() const
@@ -76,8 +92,7 @@ void ResourceSet::applyHandicap(int percentage)
static bool canAfford(const ResourceSet &res, const ResourceSet &price) static bool canAfford(const ResourceSet &res, const ResourceSet &price)
{ {
assert(res.size() == price.size() && price.size() == GameConstants::RESOURCE_QUANTITY); for(auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
for(int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++)
if(price[i] > res[i]) if(price[i] > res[i])
return false; return false;
@@ -97,8 +112,8 @@ bool ResourceSet::canAfford(const ResourceSet &price) const
TResourceCap ResourceSet::marketValue() const TResourceCap ResourceSet::marketValue() const
{ {
TResourceCap total = 0; TResourceCap total = 0;
for(int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++) for(auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
total += static_cast<TResourceCap>(LIBRARY->objh->resVals[i]) * static_cast<TResourceCap>(operator[](i)); total += static_cast<TResourceCap>(i.toResource()->getPrice()) * static_cast<TResourceCap>(operator[](i));
return total; return total;
} }
@@ -117,7 +132,7 @@ std::string ResourceSet::toString() const
bool ResourceSet::nziterator::valid() const bool ResourceSet::nziterator::valid() const
{ {
return cur.resType < GameResID::COUNT && cur.resVal; return static_cast<int>(cur.resType) < LIBRARY->resourceTypeHandler->getAllObjects().size() && cur.resVal;
} }
ResourceSet::nziterator ResourceSet::nziterator::operator++() ResourceSet::nziterator ResourceSet::nziterator::operator++()
@@ -148,9 +163,9 @@ void ResourceSet::nziterator::advance()
do do
{ {
++cur.resType; ++cur.resType;
} while(cur.resType < GameResID::COUNT && !(cur.resVal=rs[cur.resType])); } while(static_cast<int>(cur.resType) < LIBRARY->resourceTypeHandler->getAllObjects().size() && !(cur.resVal=rs[cur.resType]));
if(cur.resType >= GameResID::COUNT) if(static_cast<int>(cur.resType) >= LIBRARY->resourceTypeHandler->getAllObjects().size())
cur.resVal = -1; cur.resVal = -1;
} }

View File

@@ -26,16 +26,19 @@ class ResourceSet;
class ResourceSet class ResourceSet
{ {
private: private:
std::array<TResource, GameConstants::RESOURCE_QUANTITY> container = {}; std::vector<TResource> container = {};
DLL_LINKAGE void resizeContainer();
public: public:
// read resources set from json. Format example: { "gold": 500, "wood":5 }
DLL_LINKAGE ResourceSet(const JsonNode & node);
DLL_LINKAGE ResourceSet(); DLL_LINKAGE ResourceSet();
DLL_LINKAGE ResourceSet(const ResourceSet& rhs);
DLL_LINKAGE void resolveFromJson(const JsonNode & node);
#define scalarOperator(OPSIGN) \ #define scalarOperator(OPSIGN) \
ResourceSet& operator OPSIGN ## =(const TResource &rhs) \ ResourceSet& operator OPSIGN ## =(const TResource &rhs) \
{ \ { \
resizeContainer(); \
for(auto i = 0; i < container.size(); i++) \ for(auto i = 0; i < container.size(); i++) \
container.at(i) OPSIGN ## = rhs; \ container.at(i) OPSIGN ## = rhs; \
\ \
@@ -45,6 +48,7 @@ public:
#define vectorOperator(OPSIGN) \ #define vectorOperator(OPSIGN) \
ResourceSet& operator OPSIGN ## =(const ResourceSet &rhs) \ ResourceSet& operator OPSIGN ## =(const ResourceSet &rhs) \
{ \ { \
resizeContainer(); \
for(auto i = 0; i < container.size(); i++) \ for(auto i = 0; i < container.size(); i++) \
container.at(i) OPSIGN ## = rhs[i]; \ container.at(i) OPSIGN ## = rhs[i]; \
\ \
@@ -84,21 +88,31 @@ public:
// Array-like interface // Array-like interface
TResource & operator[](GameResID index) TResource & operator[](GameResID index)
{ {
resizeContainer();
return operator[](index.getNum()); return operator[](index.getNum());
} }
const TResource & operator[](GameResID index) const const TResource & operator[](GameResID index) const
{ {
if (index.getNum() >= container.size()) {
static const TResource defaultValue{};
return defaultValue;
}
return operator[](index.getNum()); return operator[](index.getNum());
} }
TResource & operator[](size_t index) TResource & operator[](size_t index)
{ {
resizeContainer();
return container.at(index); return container.at(index);
} }
const TResource & operator[](size_t index) const const TResource & operator[](size_t index) const
{ {
if (index >= container.size()) {
static const TResource defaultValue{};
return defaultValue;
}
return container.at(index); return container.at(index);
} }
@@ -176,6 +190,15 @@ public:
return *this; return *this;
} }
ResourceSet& operator=(const ResourceSet& rhs)
{
if (this != &rhs)
{
container = rhs.container;
}
return *this;
}
ResourceSet operator-() const ResourceSet operator-() const
{ {
ResourceSet ret; ResourceSet ret;

View File

@@ -21,6 +21,8 @@
#include <vcmi/HeroTypeService.h> #include <vcmi/HeroTypeService.h>
#include <vcmi/HeroClass.h> #include <vcmi/HeroClass.h>
#include <vcmi/HeroClassService.h> #include <vcmi/HeroClassService.h>
#include <vcmi/ResourceType.h>
#include <vcmi/ResourceTypeService.h>
#include <vcmi/Services.h> #include <vcmi/Services.h>
#include <vcmi/spells/Spell.h> #include <vcmi/spells/Spell.h>
@@ -37,6 +39,7 @@
#include "entities/faction/CFaction.h" #include "entities/faction/CFaction.h"
#include "entities/hero/CHero.h" #include "entities/hero/CHero.h"
#include "entities/hero/CHeroClass.h" #include "entities/hero/CHeroClass.h"
#include "entities/ResourceTypeHandler.h"
#include "mapObjectConstructors/AObjectTypeHandler.h" #include "mapObjectConstructors/AObjectTypeHandler.h"
#include "constants/StringConstants.h" #include "constants/StringConstants.h"
#include "texts/CGeneralTextHandler.h" #include "texts/CGeneralTextHandler.h"
@@ -398,6 +401,16 @@ const HeroType * HeroTypeID::toEntity(const Services * services) const
return services->heroTypes()->getByIndex(num); return services->heroTypes()->getByIndex(num);
} }
const Resource * GameResID::toResource() const
{
return dynamic_cast<const Resource*>(toEntity(LIBRARY));
}
const ResourceType * GameResID::toEntity(const Services * services) const
{
return services->resources()->getByIndex(num);
}
si32 SpellID::decode(const std::string & identifier) si32 SpellID::decode(const std::string & identifier)
{ {
if (identifier == "preset") if (identifier == "preset")
@@ -628,7 +641,7 @@ si32 GameResID::decode(const std::string & identifier)
std::string GameResID::encode(const si32 index) std::string GameResID::encode(const si32 index)
{ {
return GameConstants::RESOURCE_NAMES[index]; return GameResID(index).toResource()->getJsonKey();
} }
si32 BuildingTypeUniqueID::decode(const std::string & identifier) si32 BuildingTypeUniqueID::decode(const std::string & identifier)
@@ -676,21 +689,6 @@ const std::array<PrimarySkill, 4> & PrimarySkill::ALL_SKILLS()
return allSkills; return allSkills;
} }
const std::array<GameResID, 7> & GameResID::ALL_RESOURCES()
{
static const std::array allResources = {
GameResID(WOOD),
GameResID(MERCURY),
GameResID(ORE),
GameResID(SULFUR),
GameResID(CRYSTAL),
GameResID(GEMS),
GameResID(GOLD)
};
return allResources;
}
std::string SecondarySkill::entityType() std::string SecondarySkill::entityType()
{ {
return "secondarySkill"; return "secondarySkill";

View File

@@ -25,6 +25,9 @@ class CHero;
class CHeroClass; class CHeroClass;
class HeroClass; class HeroClass;
class HeroTypeService; class HeroTypeService;
class Resource;
class ResourceType;
class ResourceTypeService;
class CFaction; class CFaction;
class Faction; class Faction;
class Skill; class Skill;
@@ -1061,7 +1064,6 @@ public:
CRYSTAL, CRYSTAL,
GEMS, GEMS,
GOLD, GOLD,
MITHRIL,
COUNT, COUNT,
WOOD_AND_ORE = -4, // special case for town bonus resource WOOD_AND_ORE = -4, // special case for town bonus resource
@@ -1080,7 +1082,8 @@ public:
static std::string encode(const si32 index); static std::string encode(const si32 index);
static std::string entityType(); static std::string entityType();
static const std::array<GameResID, 7> & ALL_RESOURCES(); const Resource * toResource() const;
const ResourceType * toEntity(const Services * services) const;
}; };
class DLL_LINKAGE BuildingTypeUniqueID : public Identifier<BuildingTypeUniqueID> class DLL_LINKAGE BuildingTypeUniqueID : public Identifier<BuildingTypeUniqueID>

View File

@@ -37,7 +37,7 @@ namespace GameConstants
constexpr int SKILL_QUANTITY=28; constexpr int SKILL_QUANTITY=28;
constexpr int PRIMARY_SKILLS=4; constexpr int PRIMARY_SKILLS=4;
constexpr int RESOURCE_QUANTITY=8; constexpr int RESOURCE_QUANTITY=7;
constexpr int HEROES_PER_TYPE=8; //amount of heroes of each type constexpr int HEROES_PER_TYPE=8; //amount of heroes of each type
// amounts of OH3 objects. Can be changed by mods, should be used only during H3 loading phase // amounts of OH3 objects. Can be changed by mods, should be used only during H3 loading phase

View File

@@ -19,7 +19,7 @@ VCMI_LIB_NAMESPACE_BEGIN
namespace GameConstants namespace GameConstants
{ {
const std::string RESOURCE_NAMES [RESOURCE_QUANTITY] = { const std::string RESOURCE_NAMES [RESOURCE_QUANTITY] = {
"wood", "mercury", "ore", "sulfur", "crystal", "gems", "gold", "mithril" "wood", "mercury", "ore", "sulfur", "crystal", "gems", "gold"
}; };
const std::string PLAYER_COLOR_NAMES [PlayerColor::PLAYER_LIMIT_I] = { const std::string PLAYER_COLOR_NAMES [PlayerColor::PLAYER_LIMIT_I] = {

View File

@@ -0,0 +1,83 @@
/*
* ResourceTypeHandler.cpp, 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
*
*/
#include "StdInc.h"
#include "ResourceTypeHandler.h"
#include "../GameLibrary.h"
#include "../json/JsonNode.h"
#include "../texts/CGeneralTextHandler.h"
#include "../texts/TextIdentifier.h"
VCMI_LIB_NAMESPACE_BEGIN
std::string Resource::getNameTextID() const
{
if(id.getNum() < GameConstants::RESOURCE_QUANTITY) // OH3 resources
return TextIdentifier("core.restypes", id).get();
return TextIdentifier( "resources", modScope, identifier, "name" ).get();
}
std::string Resource::getNameTranslated() const
{
return LIBRARY->generaltexth->translate(getNameTextID());
}
void Resource::registerIcons(const IconRegistar & cb) const
{
cb(getIconIndex(), 0, "SMALRES", iconSmall);
cb(getIconIndex(), 0, "RESOURCE", iconMedium);
cb(getIconIndex(), 0, "RESOUR82", iconLarge);
}
std::vector<JsonNode> ResourceTypeHandler::loadLegacyData()
{
objects.resize(GameConstants::RESOURCE_QUANTITY);
return std::vector<JsonNode>(GameConstants::RESOURCE_QUANTITY, JsonNode(JsonMap()));
}
std::shared_ptr<Resource> ResourceTypeHandler::loadFromJson(const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index)
{
auto ret = std::make_shared<Resource>();
ret->id = GameResID(index);
ret->modScope = scope;
ret->identifier = identifier;
ret->price = json["price"].Integer();
ret->iconSmall = json["images"]["small"].String();
ret->iconMedium = json["images"]["medium"].String();
ret->iconLarge = json["images"]["large"].String();
if(ret->id.getNum() >= GameConstants::RESOURCE_QUANTITY) // not OH3 resources
LIBRARY->generaltexth->registerString(scope, ret->getNameTextID(), json["name"]);
return ret;
}
const std::vector<std::string> & ResourceTypeHandler::getTypeNames() const
{
static const std::vector<std::string> types = { "resource" };
return types;
}
std::vector<GameResID> ResourceTypeHandler::getAllObjects() const
{
std::vector<GameResID> result;
for (const auto & resource : objects)
if(resource)
result.push_back(resource->getId());
return result;
}
VCMI_LIB_NAMESPACE_END

View File

@@ -0,0 +1,66 @@
/*
* ResourceTypeHandler.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 <vcmi/EntityService.h>
#include <vcmi/Entity.h>
#include <vcmi/ResourceType.h>
#include <vcmi/ResourceTypeService.h>
#include "../constants/EntityIdentifiers.h"
#include "../IHandlerBase.h"
#include "../filesystem/ResourcePath.h"
VCMI_LIB_NAMESPACE_BEGIN
class ResourceTypeHandler;
class DLL_LINKAGE Resource : public ResourceType
{
friend class ResourceTypeHandler;
GameResID id; //backlink
int price;
std::string iconSmall;
std::string iconMedium;
std::string iconLarge;
std::string identifier;
std::string modScope;
public:
int getPrice() const override { return price; }
std::string getJsonKey() const override { return identifier; }
int32_t getIndex() const override { return id.getNum(); }
GameResID getId() const override { return id;}
int32_t getIconIndex() const override { return id.getNum(); }
std::string getModScope() const override { return modScope; };
void registerIcons(const IconRegistar & cb) const override;
std::string getNameTextID() const override;
std::string getNameTranslated() const override;
};
class DLL_LINKAGE ResourceTypeHandler : public CHandlerBase<GameResID, ResourceType, Resource, ResourceTypeService>
{
public:
std::shared_ptr<Resource> loadFromJson(const std::string & scope,
const JsonNode & json,
const std::string & identifier,
size_t index) override;
const std::vector<std::string> & getTypeNames() const override;
std::vector<JsonNode> loadLegacyData() override;
std::vector<GameResID> getAllObjects() const;
};
VCMI_LIB_NAMESPACE_END

View File

@@ -53,12 +53,9 @@ JsonNode readBuilding(CLegacyConfigParser & parser)
JsonNode ret; JsonNode ret;
JsonNode & cost = ret["cost"]; JsonNode & cost = ret["cost"];
//note: this code will try to parse mithril as well but wil always return 0 for it
for(const std::string & resID : GameConstants::RESOURCE_NAMES) for(const std::string & resID : GameConstants::RESOURCE_NAMES)
cost[resID].Float() = parser.readNumber(); cost[resID].Float() = parser.readNumber();
cost.Struct().erase("mithril"); // erase mithril to avoid confusing validator
parser.endLine(); parser.endLine();
return ret; return ret;
@@ -284,8 +281,8 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons
LIBRARY->generaltexth->registerString(source.getModScope(), ret->getDescriptionTextID(), source["description"]); LIBRARY->generaltexth->registerString(source.getModScope(), ret->getDescriptionTextID(), source["description"]);
ret->subId = vstd::find_or(MappedKeys::SPECIAL_BUILDINGS, source["type"].String(), BuildingSubID::NONE); ret->subId = vstd::find_or(MappedKeys::SPECIAL_BUILDINGS, source["type"].String(), BuildingSubID::NONE);
ret->resources = TResources(source["cost"]); ret->resources.resolveFromJson(source["cost"]);
ret->produce = TResources(source["produce"]); ret->produce.resolveFromJson(source["produce"]);
ret->manualHeroVisit = source["manualHeroVisit"].Bool(); ret->manualHeroVisit = source["manualHeroVisit"].Bool();
ret->upgradeReplacesBonuses = source["upgradeReplacesBonuses"].Bool(); ret->upgradeReplacesBonuses = source["upgradeReplacesBonuses"].Bool();

View File

@@ -397,7 +397,7 @@ void CGameState::initDifficulty()
auto setDifficulty = [this](PlayerState & state, const JsonNode & json) auto setDifficulty = [this](PlayerState & state, const JsonNode & json)
{ {
//set starting resources //set starting resources
state.resources = TResources(json["resources"]); state.resources.resolveFromJson(json["resources"]);
//handicap //handicap
const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(state.color); const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(state.color);

View File

@@ -24,6 +24,7 @@
#include "../entities/building/CBuilding.h" #include "../entities/building/CBuilding.h"
#include "../serializer/JsonDeserializer.h" #include "../serializer/JsonDeserializer.h"
#include "../serializer/JsonUpdater.h" #include "../serializer/JsonUpdater.h"
#include "../entities/ResourceTypeHandler.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -105,8 +106,8 @@ void StatisticDataSetEntry::serializeJson(JsonSerializeFormat & handler)
handler.serializeBool("hasGrail", hasGrail); handler.serializeBool("hasGrail", hasGrail);
{ {
auto zonesData = handler.enterStruct("numMines"); auto zonesData = handler.enterStruct("numMines");
for(TResource idx = 0; idx < (GameConstants::RESOURCE_QUANTITY - 1); idx++) for(auto & idx : LIBRARY->resourceTypeHandler->getAllObjects())
handler.serializeInt(GameConstants::RESOURCE_NAMES[idx], numMines[idx], 0); handler.serializeInt(idx.toResource()->getJsonKey(), numMines[idx], 0);
} }
handler.serializeInt("score", score); handler.serializeInt("score", score);
handler.serializeInt("maxHeroLevel", maxHeroLevel); handler.serializeInt("maxHeroLevel", maxHeroLevel);
@@ -158,7 +159,7 @@ std::string StatisticDataSet::toCsv(std::string sep) const
{ {
std::stringstream ss; std::stringstream ss;
auto resources = std::vector<EGameResID>{EGameResID::GOLD, EGameResID::WOOD, EGameResID::MERCURY, EGameResID::ORE, EGameResID::SULFUR, EGameResID::CRYSTAL, EGameResID::GEMS}; auto resources = std::vector<EGameResID>{EGameResID::GOLD, EGameResID::WOOD, EGameResID::MERCURY, EGameResID::ORE, EGameResID::SULFUR, EGameResID::CRYSTAL, EGameResID::GEMS}; //todo: configurable resource support
ss << "Map" << sep; ss << "Map" << sep;
ss << "Timestamp" << sep; ss << "Timestamp" << sep;
@@ -191,15 +192,15 @@ std::string StatisticDataSet::toCsv(std::string sep) const
ss << "EventDefeatedStrongestHero" << sep; ss << "EventDefeatedStrongestHero" << sep;
ss << "MovementPointsUsed"; ss << "MovementPointsUsed";
for(auto & resource : resources) for(auto & resource : resources)
ss << sep << GameConstants::RESOURCE_NAMES[resource]; ss << sep << resource.toResource()->getJsonKey();
for(auto & resource : resources) for(auto & resource : resources)
ss << sep << GameConstants::RESOURCE_NAMES[resource] + "Mines"; ss << sep << resource.toResource()->getJsonKey() + "Mines";
for(auto & resource : resources) for(auto & resource : resources)
ss << sep << GameConstants::RESOURCE_NAMES[resource] + "SpentResourcesForArmy"; ss << sep << resource.toResource()->getJsonKey() + "SpentResourcesForArmy";
for(auto & resource : resources) for(auto & resource : resources)
ss << sep << GameConstants::RESOURCE_NAMES[resource] + "SpentResourcesForBuildings"; ss << sep << resource.toResource()->getJsonKey() + "SpentResourcesForBuildings";
for(auto & resource : resources) for(auto & resource : resources)
ss << sep << GameConstants::RESOURCE_NAMES[resource] + "TradeVolume"; ss << sep << resource.toResource()->getJsonKey() + "TradeVolume";
ss << "\r\n"; ss << "\r\n";
for(auto & entry : data) for(auto & entry : data)
@@ -403,7 +404,7 @@ std::map<EGameResID, int> Statistic::getNumMines(const CGameState * gs, const Pl
{ {
std::map<EGameResID, int> tmp; std::map<EGameResID, int> tmp;
for(auto & res : EGameResID::ALL_RESOURCES()) for(auto & res : LIBRARY->resourceTypeHandler->getAllObjects())
tmp[res] = 0; tmp[res] = 0;
for(const auto * object : ps->getOwnedObjects()) for(const auto * object : ps->getOwnedObjects())

View File

@@ -28,6 +28,7 @@
#include "../entities/artifact/CArtHandler.h" #include "../entities/artifact/CArtHandler.h"
#include "../entities/hero/CHero.h" #include "../entities/hero/CHero.h"
#include "../entities/hero/CHeroClass.h" #include "../entities/hero/CHeroClass.h"
#include "../entities/ResourceTypeHandler.h"
#include "../gameState/CGameState.h" #include "../gameState/CGameState.h"
#include "../mapObjects/army/CStackBasicDescriptor.h" #include "../mapObjects/army/CStackBasicDescriptor.h"
#include "../mapObjects/IObjectInterface.h" #include "../mapObjects/IObjectInterface.h"
@@ -298,9 +299,9 @@ JsonRandom::JsonRandom(IGameInfoCallback * cb, IGameRandomizer & gameRandomizer)
return ret; return ret;
} }
for (size_t i=0; i<GameConstants::RESOURCE_QUANTITY; i++) for(auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
ret[i] = loadValue(value[GameConstants::RESOURCE_NAMES[i]], variables); ret[i] = loadValue(value[i.toResource()->getJsonKey()], variables);
} }
return ret; return ret;
} }
@@ -315,7 +316,7 @@ JsonRandom::JsonRandom(IGameInfoCallback * cb, IGameRandomizer & gameRandomizer)
GameResID::CRYSTAL, GameResID::CRYSTAL,
GameResID::GEMS, GameResID::GEMS,
GameResID::GOLD GameResID::GOLD
}; }; //todo: configurable resource support
std::set<GameResID> potentialPicks = filterKeys(value, defaultResources, variables); std::set<GameResID> potentialPicks = filterKeys(value, defaultResources, variables);
GameResID resourceID = *RandomGeneratorUtil::nextItem(potentialPicks, rng); GameResID resourceID = *RandomGeneratorUtil::nextItem(potentialPicks, rng);

View File

@@ -17,6 +17,7 @@
#include "../callback/IGameInfoCallback.h" #include "../callback/IGameInfoCallback.h"
#include "../entities/faction/CTownHandler.h" #include "../entities/faction/CTownHandler.h"
#include "../entities/hero/CHeroClass.h" #include "../entities/hero/CHeroClass.h"
#include "../entities/ResourceTypeHandler.h"
#include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CGHeroInstance.h"
#include "../mapObjects/CGTownInstance.h" #include "../mapObjects/CGTownInstance.h"
#include "../mapObjects/MiscObjects.h" #include "../mapObjects/MiscObjects.h"
@@ -60,7 +61,7 @@ bool ResourceInstanceConstructor::hasNameTextID() const
std::string ResourceInstanceConstructor::getNameTextID() const std::string ResourceInstanceConstructor::getNameTextID() const
{ {
return TextIdentifier("core", "restypes", resourceType.getNum()).get(); return resourceType.toResource()->getNameTextID();
} }
GameResID ResourceInstanceConstructor::getResourceType() const GameResID ResourceInstanceConstructor::getResourceType() const

View File

@@ -40,7 +40,7 @@ void FlaggableInstanceConstructor::initTypeData(const JsonNode & config)
} }
} }
dailyIncome = ResourceSet(config["dailyIncome"]); dailyIncome.resolveFromJson(config["dailyIncome"]);
} }
void FlaggableInstanceConstructor::initializeObject(FlaggableMapObject * flaggable) const void FlaggableInstanceConstructor::initializeObject(FlaggableMapObject * flaggable) const

View File

@@ -25,6 +25,7 @@
#include "../networkPacks/StackLocation.h" #include "../networkPacks/StackLocation.h"
#include "../serializer/JsonSerializeFormat.h" #include "../serializer/JsonSerializeFormat.h"
#include "../entities/faction/CTownHandler.h" #include "../entities/faction/CTownHandler.h"
#include "../entities/ResourceTypeHandler.h"
#include <vstd/RNG.h> #include <vstd/RNG.h>
@@ -630,7 +631,7 @@ void CGCreature::giveReward(IGameEventCallback & gameEvents, const CGHeroInstanc
if(!resources.empty()) if(!resources.empty())
{ {
gameEvents.giveResources(h->tempOwner, resources); gameEvents.giveResources(h->tempOwner, resources);
for(const auto & res : GameResID::ALL_RESOURCES()) for(const auto & res : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
if(resources[res] > 0) if(resources[res] > 0)
iw.components.emplace_back(ComponentType::RESOURCE, res, resources[res]); iw.components.emplace_back(ComponentType::RESOURCE, res, resources[res]);

View File

@@ -38,6 +38,7 @@
#include "../entities/faction/CTownHandler.h" #include "../entities/faction/CTownHandler.h"
#include "../entities/hero/CHeroHandler.h" #include "../entities/hero/CHeroHandler.h"
#include "../entities/hero/CHeroClass.h" #include "../entities/hero/CHeroClass.h"
#include "../entities/ResourceTypeHandler.h"
#include "../battle/CBattleInfoEssentials.h" #include "../battle/CBattleInfoEssentials.h"
#include "../campaign/CampaignState.h" #include "../campaign/CampaignState.h"
#include "../json/JsonBonus.h" #include "../json/JsonBonus.h"
@@ -1816,7 +1817,7 @@ ResourceSet CGHeroInstance::dailyIncome() const
{ {
ResourceSet income; ResourceSet income;
for (GameResID k : GameResID::ALL_RESOURCES()) for (GameResID k : LIBRARY->resourceTypeHandler->getAllObjects())
income[k] += valOfBonuses(BonusType::GENERATE_RESOURCE, BonusSubtypeID(k)); income[k] += valOfBonuses(BonusType::GENERATE_RESOURCE, BonusSubtypeID(k));
const auto & playerSettings = cb->getPlayerSettings(getOwner()); const auto & playerSettings = cb->getPlayerSettings(getOwner());

View File

@@ -1,5 +1,5 @@
/* /*
* CObjectHandler.cpp, part of VCMI engine * CGObjectInstance.cpp, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *

View File

@@ -21,6 +21,7 @@
#include "../gameState/CGameState.h" #include "../gameState/CGameState.h"
#include "../serializer/JsonSerializeFormat.h" #include "../serializer/JsonSerializeFormat.h"
#include "../CSoundBase.h" #include "../CSoundBase.h"
#include "../entities/ResourceTypeHandler.h"
#include <vstd/RNG.h> #include <vstd/RNG.h>
@@ -50,7 +51,7 @@ GameResID CGResource::resourceID() const
std::string CGResource::getHoverText(PlayerColor player) const std::string CGResource::getHoverText(PlayerColor player) const
{ {
return LIBRARY->generaltexth->restypes[resourceID().getNum()]; return resourceID().toResource()->getNameTranslated();
} }
void CGResource::pickRandomObject(IGameRandomizer & gameRandomizer) void CGResource::pickRandomObject(IGameRandomizer & gameRandomizer)
@@ -60,7 +61,7 @@ void CGResource::pickRandomObject(IGameRandomizer & gameRandomizer)
if (ID == Obj::RANDOM_RESOURCE) if (ID == Obj::RANDOM_RESOURCE)
{ {
ID = Obj::RESOURCE; ID = Obj::RESOURCE;
subID = gameRandomizer.getDefault().nextInt(EGameResID::WOOD, EGameResID::GOLD); subID = gameRandomizer.getDefault().nextInt(EGameResID::WOOD, EGameResID::GOLD); //todo: configurable resource support
setType(ID, subID); setType(ID, subID);
amount *= getAmountMultiplier(); amount *= getAmountMultiplier();

View File

@@ -32,6 +32,7 @@
#include "../callback/IGameRandomizer.h" #include "../callback/IGameRandomizer.h"
#include "../entities/building/CBuilding.h" #include "../entities/building/CBuilding.h"
#include "../entities/faction/CTownHandler.h" #include "../entities/faction/CTownHandler.h"
#include "../entities/ResourceTypeHandler.h"
#include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/AObjectTypeHandler.h"
#include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h"
#include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CGHeroInstance.h"
@@ -209,7 +210,7 @@ TResources CGTownInstance::dailyIncome() const
{ {
ResourceSet ret; ResourceSet ret;
for (GameResID k : GameResID::ALL_RESOURCES()) for (GameResID k : LIBRARY->resourceTypeHandler->getAllObjects())
ret[k] += valOfBonuses(BonusType::GENERATE_RESOURCE, BonusSubtypeID(k)); ret[k] += valOfBonuses(BonusType::GENERATE_RESOURCE, BonusSubtypeID(k));
for(const auto & p : getTown()->buildings) for(const auto & p : getTown()->buildings)

View File

@@ -1,31 +0,0 @@
/*
* CObjectHandler.cpp, 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
*
*/
#include "StdInc.h"
#include "CObjectHandler.h"
#include "CGObjectInstance.h"
#include "../filesystem/ResourcePath.h"
#include "../json/JsonNode.h"
VCMI_LIB_NAMESPACE_BEGIN
CObjectHandler::CObjectHandler()
{
logGlobal->trace("\t\tReading resources prices ");
const JsonNode config2(JsonPath::builtin("config/resources.json"));
for(const JsonNode &price : config2["resources_prices"].Vector())
{
resVals.push_back(static_cast<ui32>(price.Float()));
}
logGlobal->trace("\t\tDone loading resource prices!");
}
VCMI_LIB_NAMESPACE_END

View File

@@ -22,6 +22,7 @@
#include "../callback/IGameRandomizer.h" #include "../callback/IGameRandomizer.h"
#include "../entities/artifact/CArtifact.h" #include "../entities/artifact/CArtifact.h"
#include "../entities/hero/CHeroHandler.h" #include "../entities/hero/CHeroHandler.h"
#include "../entities/ResourceTypeHandler.h"
#include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h"
#include "../serializer/JsonSerializeFormat.h" #include "../serializer/JsonSerializeFormat.h"
#include "../GameConstants.h" #include "../GameConstants.h"
@@ -233,7 +234,7 @@ void CQuest::addTextReplacements(const IGameInfoCallback * cb, MetaString & text
if(mission.resources.nonZero()) if(mission.resources.nonZero())
{ {
MetaString loot; MetaString loot;
for(auto i : GameResID::ALL_RESOURCES()) for(auto i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
if(mission.resources[i]) if(mission.resources[i])
{ {
@@ -372,11 +373,9 @@ void CQuest::serializeJson(JsonSerializeFormat & handler, const std::string & fi
if(missionType == "Resources") if(missionType == "Resources")
{ {
auto r = handler.enterStruct("resources"); auto r = handler.enterStruct("resources");
for(size_t idx = 0; idx < (GameConstants::RESOURCE_QUANTITY - 1); idx++) for(auto & idx : LIBRARY->resourceTypeHandler->getAllObjects())
{ handler.serializeInt(idx.toResource()->getJsonKey(), mission.resources[idx], 0);
handler.serializeInt(GameConstants::RESOURCE_NAMES[idx], mission.resources[idx], 0);
}
} }
if(missionType == "Hero") if(missionType == "Hero")

View File

@@ -13,10 +13,10 @@
#include "CCreatureHandler.h" #include "CCreatureHandler.h"
#include "CGObjectInstance.h" #include "CGObjectInstance.h"
#include "CObjectHandler.h"
#include "../GameLibrary.h" #include "../GameLibrary.h"
#include "../entities/artifact/CArtHandler.h" #include "../entities/artifact/CArtHandler.h"
#include "../entities/ResourceTypeHandler.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -33,8 +33,8 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode)
{ {
double effectiveness = std::min((getMarketEfficiency() + 1.0) / 20.0, 0.5); double effectiveness = std::min((getMarketEfficiency() + 1.0) / 20.0, 0.5);
double r = LIBRARY->objh->resVals[id1]; //value of given resource double r = GameResID(id1).toResource()->getPrice(); //value of given resource
double g = LIBRARY->objh->resVals[id2] / effectiveness; //value of wanted resource double g = GameResID(id2).toResource()->getPrice() / effectiveness; //value of wanted resource
if(r>g) //if given resource is more expensive than wanted if(r>g) //if given resource is more expensive than wanted
{ {
@@ -54,7 +54,7 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode)
double effectiveness = effectivenessArray[std::min(getMarketEfficiency(), 8)]; double effectiveness = effectivenessArray[std::min(getMarketEfficiency(), 8)];
double r = LIBRARY->creatures()->getByIndex(id1)->getRecruitCost(EGameResID::GOLD); //value of given creature in gold double r = LIBRARY->creatures()->getByIndex(id1)->getRecruitCost(EGameResID::GOLD); //value of given creature in gold
double g = LIBRARY->objh->resVals[id2] / effectiveness; //value of wanted resource double g = GameResID(id2).toResource()->getPrice() / effectiveness; //value of wanted resource
if(r>g) //if given resource is more expensive than wanted if(r>g) //if given resource is more expensive than wanted
{ {
@@ -75,7 +75,7 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode)
case EMarketMode::RESOURCE_ARTIFACT: case EMarketMode::RESOURCE_ARTIFACT:
{ {
double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6); double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
double r = LIBRARY->objh->resVals[id1]; //value of offered resource double r = GameResID(id1).toResource()->getPrice(); //value of offered resource
double g = LIBRARY->artifacts()->getByIndex(id2)->getPrice() / effectiveness; //value of bought artifact in gold double g = LIBRARY->artifacts()->getByIndex(id2)->getPrice() / effectiveness; //value of bought artifact in gold
if(id1 != 6) //non-gold prices are doubled if(id1 != 6) //non-gold prices are doubled
@@ -89,7 +89,7 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode)
{ {
double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6); double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
double r = LIBRARY->artifacts()->getByIndex(id1)->getPrice() * effectiveness; double r = LIBRARY->artifacts()->getByIndex(id1)->getPrice() * effectiveness;
double g = LIBRARY->objh->resVals[id2]; double g = GameResID(id2).toResource()->getPrice();
// if(id2 != 6) //non-gold prices are doubled // if(id2 != 6) //non-gold prices are doubled
// r /= 2; // r /= 2;
@@ -163,7 +163,7 @@ std::vector<TradeItemBuy> IMarket::availableItemsIds(const EMarketMode mode) con
case EMarketMode::RESOURCE_RESOURCE: case EMarketMode::RESOURCE_RESOURCE:
case EMarketMode::ARTIFACT_RESOURCE: case EMarketMode::ARTIFACT_RESOURCE:
case EMarketMode::CREATURE_RESOURCE: case EMarketMode::CREATURE_RESOURCE:
for(const auto & res : GameResID::ALL_RESOURCES()) for(const auto & res : LIBRARY->resourceTypeHandler->getAllObjects())
ret.push_back(res); ret.push_back(res);
} }
return ret; return ret;

View File

@@ -10,8 +10,6 @@
#pragma once #pragma once
// Helper header that includes all map objects, similar to old CObjectHandler.h // Helper header that includes all map objects, similar to old CObjectHandler.h
// Possible TODO - remove this header after CObjectHandler.cpp will be fully split into smaller files
#include "CObjectHandler.h"
#include "CGDwelling.h" #include "CGDwelling.h"
#include "CGHeroInstance.h" #include "CGHeroInstance.h"

View File

@@ -18,6 +18,7 @@
#include "../constants/StringConstants.h" #include "../constants/StringConstants.h"
#include "../entities/artifact/ArtifactUtils.h" #include "../entities/artifact/ArtifactUtils.h"
#include "../entities/artifact/CArtifact.h" #include "../entities/artifact/CArtifact.h"
#include "../entities/ResourceTypeHandler.h"
#include "../CConfigHandler.h" #include "../CConfigHandler.h"
#include "../texts/CGeneralTextHandler.h" #include "../texts/CGeneralTextHandler.h"
#include "../CSkillHandler.h" #include "../CSkillHandler.h"
@@ -143,7 +144,7 @@ ResourceSet CGMine::dailyIncome() const
{ {
ResourceSet result; ResourceSet result;
for (GameResID k : GameResID::ALL_RESOURCES()) for (GameResID k : LIBRARY->resourceTypeHandler->getAllObjects())
result[k] += valOfBonuses(BonusType::GENERATE_RESOURCE, BonusSubtypeID(k)); result[k] += valOfBonuses(BonusType::GENERATE_RESOURCE, BonusSubtypeID(k));
result[producedResource] += defaultResProduction(); result[producedResource] += defaultResProduction();
@@ -164,7 +165,7 @@ std::string CGMine::getHoverText(PlayerColor player) const
std::string hoverName = CArmedInstance::getHoverText(player); std::string hoverName = CArmedInstance::getHoverText(player);
if (tempOwner != PlayerColor::NEUTRAL) if (tempOwner != PlayerColor::NEUTRAL)
hoverName += "\n(" + LIBRARY->generaltexth->restypes[producedResource.getNum()] + ")"; hoverName += "\n(" + producedResource.toResource()->getNameTranslated() + ")";
if(stacksCount()) if(stacksCount())
{ {
@@ -238,7 +239,7 @@ void CGMine::serializeJsonOptions(JsonSerializeFormat & handler)
{ {
JsonNode node; JsonNode node;
for(const auto & resID : abandonedMineResources) for(const auto & resID : abandonedMineResources)
node.Vector().emplace_back(GameConstants::RESOURCE_NAMES[resID.getNum()]); node.Vector().emplace_back(resID.toResource()->getJsonKey());
handler.serializeRaw("possibleResources", node, std::nullopt); handler.serializeRaw("possibleResources", node, std::nullopt);
} }
@@ -251,7 +252,10 @@ void CGMine::serializeJsonOptions(JsonSerializeFormat & handler)
for(const std::string & s : names) for(const std::string & s : names)
{ {
int raw_res = vstd::find_pos(GameConstants::RESOURCE_NAMES, s); std::vector<std::string> resNames;
for(auto & res : LIBRARY->resourceTypeHandler->getAllObjects())
resNames.push_back(res.toResource()->getJsonKey());
int raw_res = vstd::find_pos(resNames, s);
if(raw_res < 0) if(raw_res < 0)
logGlobal->error("Invalid resource name: %s", s); logGlobal->error("Invalid resource name: %s", s);
else else
@@ -872,7 +876,7 @@ const IOwnableObject * CGGarrison::asOwnable() const
ResourceSet CGGarrison::dailyIncome() const ResourceSet CGGarrison::dailyIncome() const
{ {
ResourceSet result; ResourceSet result;
for (GameResID k : GameResID::ALL_RESOURCES()) for (GameResID k : LIBRARY->resourceTypeHandler->getAllObjects())
result[k] += valOfBonuses(BonusType::GENERATE_RESOURCE, BonusSubtypeID(k)); result[k] += valOfBonuses(BonusType::GENERATE_RESOURCE, BonusSubtypeID(k));
return result; return result;

View File

@@ -23,6 +23,7 @@
#include "../entities/faction/CTownHandler.h" #include "../entities/faction/CTownHandler.h"
#include "../entities/hero/CHeroClassHandler.h" #include "../entities/hero/CHeroClassHandler.h"
#include "../entities/hero/CHeroHandler.h" #include "../entities/hero/CHeroHandler.h"
#include "../entities/ResourceTypeHandler.h"
#include "../texts/CGeneralTextHandler.h" #include "../texts/CGeneralTextHandler.h"
#include "../CBonusTypeHandler.h" #include "../CBonusTypeHandler.h"
#include "../CSkillHandler.h" #include "../CSkillHandler.h"
@@ -263,6 +264,7 @@ void CContentHandler::init()
handlers.insert(std::make_pair("roads", ContentTypeHandler(LIBRARY->roadTypeHandler.get(), "road"))); handlers.insert(std::make_pair("roads", ContentTypeHandler(LIBRARY->roadTypeHandler.get(), "road")));
handlers.insert(std::make_pair("obstacles", ContentTypeHandler(LIBRARY->obstacleHandler.get(), "obstacle"))); handlers.insert(std::make_pair("obstacles", ContentTypeHandler(LIBRARY->obstacleHandler.get(), "obstacle")));
handlers.insert(std::make_pair("biomes", ContentTypeHandler(LIBRARY->biomeHandler.get(), "biome"))); handlers.insert(std::make_pair("biomes", ContentTypeHandler(LIBRARY->biomeHandler.get(), "biome")));
handlers.insert(std::make_pair("resources", ContentTypeHandler(LIBRARY->resourceTypeHandler.get(), "resources")));
} }
bool CContentHandler::preloadData(const ModDescription & mod, bool validate) bool CContentHandler::preloadData(const ModDescription & mod, bool validate)

View File

@@ -22,6 +22,7 @@
#include "../mapObjects/IObjectInterface.h" #include "../mapObjects/IObjectInterface.h"
#include "../modding/IdentifierStorage.h" #include "../modding/IdentifierStorage.h"
#include "../texts/CGeneralTextHandler.h" #include "../texts/CGeneralTextHandler.h"
#include "../entities/ResourceTypeHandler.h"
#include <vstd/RNG.h> #include <vstd/RNG.h>
@@ -296,7 +297,7 @@ void Rewardable::Info::replaceTextPlaceholders(MetaString & target, const Variab
MetaString loot; MetaString loot;
for (GameResID it : GameResID::ALL_RESOURCES()) for (GameResID it : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
if (info.reward.resources[it] != 0) if (info.reward.resources[it] != 0)
{ {

View File

@@ -18,6 +18,7 @@
#include "../GameLibrary.h" #include "../GameLibrary.h"
#include "../constants/StringConstants.h" #include "../constants/StringConstants.h"
#include "../entities/faction/CTownHandler.h" #include "../entities/faction/CTownHandler.h"
#include "../entities/ResourceTypeHandler.h"
#include "../modding/ModScope.h" #include "../modding/ModScope.h"
#include "../serializer/JsonSerializeFormat.h" #include "../serializer/JsonSerializeFormat.h"
@@ -258,12 +259,12 @@ std::set<FactionID> ZoneOptions::getMonsterTypes() const
return vstd::difference(monsterTypes, bannedMonsters); return vstd::difference(monsterTypes, bannedMonsters);
} }
void ZoneOptions::setMinesInfo(const std::map<TResource, ui16> & value) void ZoneOptions::setMinesInfo(const std::map<GameResID, ui16> & value)
{ {
mines = value; mines = value;
} }
std::map<TResource, ui16> ZoneOptions::getMinesInfo() const std::map<GameResID, ui16> ZoneOptions::getMinesInfo() const
{ {
return mines; return mines;
} }
@@ -532,12 +533,7 @@ void ZoneOptions::serializeJson(JsonSerializeFormat & handler)
if((minesLikeZone == NO_ZONE) && (!handler.saving || !mines.empty())) if((minesLikeZone == NO_ZONE) && (!handler.saving || !mines.empty()))
{ {
auto minesData = handler.enterStruct("mines"); handler.serializeIdMap<GameResID, ui16>("mines", mines);
for(TResource idx = 0; idx < (GameConstants::RESOURCE_QUANTITY - 1); idx++)
{
handler.serializeInt(GameConstants::RESOURCE_NAMES[idx], mines[idx], 0);
}
} }
handler.serializeStruct("customObjects", objectConfig); handler.serializeStruct("customObjects", objectConfig);

View File

@@ -209,8 +209,8 @@ public:
void setMonsterTypes(const std::set<FactionID> & value); void setMonsterTypes(const std::set<FactionID> & value);
void setMinesInfo(const std::map<TResource, ui16> & value); void setMinesInfo(const std::map<GameResID, ui16> & value);
std::map<TResource, ui16> getMinesInfo() const; std::map<GameResID, ui16> getMinesInfo() const;
void setTreasureInfo(const std::vector<CTreasureInfo> & value); void setTreasureInfo(const std::vector<CTreasureInfo> & value);
void addTreasureInfo(const CTreasureInfo & value); void addTreasureInfo(const CTreasureInfo & value);
@@ -277,7 +277,7 @@ protected:
std::set<FactionID> monsterTypes; std::set<FactionID> monsterTypes;
std::set<FactionID> bannedMonsters; std::set<FactionID> bannedMonsters;
std::map<TResource, ui16> mines; //obligatory mines to spawn in this zone std::map<GameResID, ui16> mines; //obligatory mines to spawn in this zone
std::vector<CTreasureInfo> treasureInfo; std::vector<CTreasureInfo> treasureInfo;
@@ -373,7 +373,7 @@ private:
std::set<HeroTypeID> bannedHeroes; std::set<HeroTypeID> bannedHeroes;
std::set<TerrainId> inheritTerrainType(std::shared_ptr<rmg::ZoneOptions> zone, uint32_t iteration = 0); std::set<TerrainId> inheritTerrainType(std::shared_ptr<rmg::ZoneOptions> zone, uint32_t iteration = 0);
std::map<TResource, ui16> inheritMineTypes(std::shared_ptr<rmg::ZoneOptions> zone, uint32_t iteration = 0); std::map<GameResID, ui16> inheritMineTypes(std::shared_ptr<rmg::ZoneOptions> zone, uint32_t iteration = 0);
std::vector<CTreasureInfo> inheritTreasureInfo(std::shared_ptr<rmg::ZoneOptions> zone, uint32_t iteration = 0); std::vector<CTreasureInfo> inheritTreasureInfo(std::shared_ptr<rmg::ZoneOptions> zone, uint32_t iteration = 0);
void inheritTownProperties(std::shared_ptr<rmg::ZoneOptions> zone, uint32_t iteration = 0); void inheritTownProperties(std::shared_ptr<rmg::ZoneOptions> zone, uint32_t iteration = 0);

View File

@@ -119,6 +119,16 @@ void JsonDeserializer::serializeInternal(const std::string & fieldName, std::vec
} }
} }
void JsonDeserializer::serializeInternal(const std::string & fieldName, std::map<std::string, uint16_t> & value)
{
const JsonMap & data = currentObject->operator[](fieldName).Struct();
value.clear();
for(const auto & [id, elem] : data)
value[id] = elem.Integer();
}
void JsonDeserializer::serializeInternal(std::string & value) void JsonDeserializer::serializeInternal(std::string & value)
{ {
value = currentObject->String(); value = currentObject->String();

View File

@@ -32,6 +32,7 @@ protected:
void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override; void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override;
void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override; void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override;
void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) override; void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) override;
void serializeInternal(const std::string & fieldName, std::map<std::string, uint16_t> & value) override;
void serializeInternal(std::string & value) override; void serializeInternal(std::string & value) override;
void serializeInternal(int64_t & value) override; void serializeInternal(int64_t & value) override;

View File

@@ -331,6 +331,33 @@ public:
} }
} }
/// si32-convertible identifier map <-> Json object of {key: string}
template <typename Key, typename T, typename E = T>
void serializeIdMap(const std::string & fieldName, std::map<Key, T> & value)
{
if (saving)
{
std::map<std::string, T> fieldValue;
for (const auto & [key, val] : value)
fieldValue[Key::encode(key.getNum())] = val;
serializeInternal(fieldName, fieldValue);
}
else
{
const JsonNode & node = getCurrent()[fieldName];
for (const auto & [keyStr, jsonVal] : node.Struct())
{
Key key = Key::decode(keyStr);
LIBRARY->identifiers()->requestIdentifier(node.getModScope(), Key::entityType(), keyStr, [&value, key](int32_t index) {
value[key] = T(index);
});
}
}
}
///si32-convertible identifier vector <-> Json array of string ///si32-convertible identifier vector <-> Json array of string
template <typename T, typename E = T> template <typename T, typename E = T>
void serializeIdArray(const std::string & fieldName, std::vector<T> & value) void serializeIdArray(const std::string & fieldName, std::vector<T> & value)
@@ -443,6 +470,9 @@ protected:
///String vector <-> Json string vector ///String vector <-> Json string vector
virtual void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) = 0; virtual void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) = 0;
///String map <-> Json map of int
virtual void serializeInternal(const std::string & fieldName, std::map<std::string, uint16_t> & value) = 0;
virtual void pop() = 0; virtual void pop() = 0;
virtual void pushStruct(const std::string & fieldName) = 0; virtual void pushStruct(const std::string & fieldName) = 0;
virtual void pushArray(const std::string & fieldName) = 0; virtual void pushArray(const std::string & fieldName) = 0;

View File

@@ -75,6 +75,17 @@ void JsonSerializer::serializeInternal(const std::string & fieldName, std::vecto
data.emplace_back(rawId); data.emplace_back(rawId);
} }
void JsonSerializer::serializeInternal(const std::string & fieldName, std::map<std::string, uint16_t> & value)
{
if(value.empty())
return;
JsonMap & data = currentObject->operator[](fieldName).Struct();
for(const auto & [rawId, val] : value)
data[rawId].Integer() = val;
}
void JsonSerializer::serializeInternal(std::string & value) void JsonSerializer::serializeInternal(std::string & value)
{ {
currentObject->String() = value; currentObject->String() = value;

View File

@@ -32,6 +32,7 @@ protected:
void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override; void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override;
void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override; void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override;
void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) override; void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) override;
void serializeInternal(const std::string & fieldName, std::map<std::string, uint16_t> & value) override;
void serializeInternal(std::string & value) override; void serializeInternal(std::string & value) override;
void serializeInternal(int64_t & value) override; void serializeInternal(int64_t & value) override;

View File

@@ -65,6 +65,11 @@ void JsonUpdater::serializeInternal(const std::string & fieldName, std::vector<s
// TODO // TODO
} }
void JsonUpdater::serializeInternal(const std::string & fieldName, std::map<std::string, uint16_t> & value)
{
// TODO
}
void JsonUpdater::serializeInternal(const std::string & fieldName, double & value, const std::optional<double> & defaultValue) void JsonUpdater::serializeInternal(const std::string & fieldName, double & value, const std::optional<double> & defaultValue)
{ {
const JsonNode & data = currentObject->operator[](fieldName); const JsonNode & data = currentObject->operator[](fieldName);

View File

@@ -36,6 +36,7 @@ protected:
void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override; void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override;
void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override; void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override;
void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) override; void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) override;
void serializeInternal(const std::string & fieldName, std::map<std::string, uint16_t> & value) override;
void serializeInternal(std::string & value) override; void serializeInternal(std::string & value) override;
void serializeInternal(int64_t & value) override; void serializeInternal(int64_t & value) override;

View File

@@ -14,6 +14,7 @@
#include "entities/artifact/CArtifact.h" #include "entities/artifact/CArtifact.h"
#include "entities/faction/CFaction.h" #include "entities/faction/CFaction.h"
#include "entities/hero/CHero.h" #include "entities/hero/CHero.h"
#include "entities/ResourceTypeHandler.h"
#include "texts/CGeneralTextHandler.h" #include "texts/CGeneralTextHandler.h"
#include "CSkillHandler.h" #include "CSkillHandler.h"
#include "GameConstants.h" #include "GameConstants.h"
@@ -378,7 +379,7 @@ void MetaString::appendName(const CreatureID & id, TQuantity count)
void MetaString::appendName(const GameResID& id) void MetaString::appendName(const GameResID& id)
{ {
appendTextID(TextIdentifier("core.restypes", id.getNum()).get()); appendTextID(id.toResource()->getNameTextID());
} }
void MetaString::appendNameSingular(const CreatureID & id) void MetaString::appendNameSingular(const CreatureID & id)
@@ -423,7 +424,7 @@ void MetaString::replaceName(const SpellID & id)
void MetaString::replaceName(const GameResID& id) void MetaString::replaceName(const GameResID& id)
{ {
replaceTextID(TextIdentifier("core.restypes", id.getNum()).get()); replaceTextID(id.toResource()->getNameTextID());
} }
void MetaString::replaceNameSingular(const CreatureID & id) void MetaString::replaceNameSingular(const CreatureID & id)

View File

@@ -19,6 +19,7 @@
#include <vcmi/HeroTypeService.h> #include <vcmi/HeroTypeService.h>
#include <vcmi/SkillService.h> #include <vcmi/SkillService.h>
#include <vcmi/spells/Service.h> #include <vcmi/spells/Service.h>
#include <vcmi/ResourceTypeService.h>
#include "../lib/filesystem/Filesystem.h" #include "../lib/filesystem/Filesystem.h"
#include "../lib/filesystem/CBinaryReader.h" #include "../lib/filesystem/CBinaryReader.h"
@@ -342,4 +343,5 @@ void Graphics::initializeImageLists()
addImageListEntries(LIBRARY->factions()); addImageListEntries(LIBRARY->factions());
addImageListEntries(LIBRARY->spells()); addImageListEntries(LIBRARY->spells());
addImageListEntries(LIBRARY->skills()); addImageListEntries(LIBRARY->skills());
addImageListEntries(LIBRARY->resources());
} }

View File

@@ -17,6 +17,7 @@
#include "../lib/CCreatureHandler.h" #include "../lib/CCreatureHandler.h"
#include "../lib/constants/StringConstants.h" #include "../lib/constants/StringConstants.h"
#include "../lib/entities/artifact/CArtHandler.h" #include "../lib/entities/artifact/CArtHandler.h"
#include "../lib/entities/ResourceTypeHandler.h"
#include "../lib/mapping/CMap.h" #include "../lib/mapping/CMap.h"
#include "../lib/mapObjects/CGHeroInstance.h" #include "../lib/mapObjects/CGHeroInstance.h"
#include "../lib/mapObjects/CGCreature.h" #include "../lib/mapObjects/CGCreature.h"
@@ -40,13 +41,13 @@ QuestWidget::QuestWidget(MapController & _controller, CQuest & _sh, QWidget *par
ui->lDayOfWeek->addItem(tr("Day %1").arg(i)); ui->lDayOfWeek->addItem(tr("Day %1").arg(i));
//fill resources //fill resources
ui->lResources->setRowCount(GameConstants::RESOURCE_QUANTITY - 1); ui->lResources->setRowCount(LIBRARY->resourceTypeHandler->getAllObjects().size() - 1);
for(int i = 0; i < GameConstants::RESOURCE_QUANTITY - 1; ++i) for(auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
MetaString str; MetaString str;
str.appendName(GameResID(i)); str.appendName(GameResID(i));
auto * item = new QTableWidgetItem(QString::fromStdString(str.toString())); auto * item = new QTableWidgetItem(QString::fromStdString(str.toString()));
item->setData(Qt::UserRole, QVariant::fromValue(i)); item->setData(Qt::UserRole, QVariant::fromValue(i.getNum()));
ui->lResources->setItem(i, 0, item); ui->lResources->setItem(i, 0, item);
auto * spinBox = new QSpinBox; auto * spinBox = new QSpinBox;
spinBox->setMaximum(i == GameResID::GOLD ? 999999 : 999); spinBox->setMaximum(i == GameResID::GOLD ? 999999 : 999);
@@ -455,8 +456,6 @@ void QuestDelegate::updateModelData(QAbstractItemModel * model, const QModelInde
QStringList resourcesList; QStringList resourcesList;
for(GameResID resource = GameResID::WOOD; resource < GameResID::COUNT ; resource++) for(GameResID resource = GameResID::WOOD; resource < GameResID::COUNT ; resource++)
{ {
if(resource == GameResID::MITHRIL)
continue;
if(quest.mission.resources[resource] == 0) if(quest.mission.resources[resource] == 0)
continue; continue;
MetaString str; MetaString str;

View File

@@ -17,6 +17,7 @@
#include "../lib/CCreatureHandler.h" #include "../lib/CCreatureHandler.h"
#include "../lib/constants/StringConstants.h" #include "../lib/constants/StringConstants.h"
#include "../lib/entities/artifact/CArtifact.h" #include "../lib/entities/artifact/CArtifact.h"
#include "../lib/entities/ResourceTypeHandler.h"
#include "../lib/mapping/CMap.h" #include "../lib/mapping/CMap.h"
#include "../lib/modding/IdentifierStorage.h" #include "../lib/modding/IdentifierStorage.h"
#include "../lib/modding/ModScope.h" #include "../lib/modding/ModScope.h"
@@ -55,16 +56,16 @@ RewardsWidget::RewardsWidget(CMap & m, CRewardableObject & p, QWidget *parent) :
ui->lDayOfWeek->addItem(tr("Day %1").arg(i)); ui->lDayOfWeek->addItem(tr("Day %1").arg(i));
//fill resources //fill resources
ui->rResources->setRowCount(GameConstants::RESOURCE_QUANTITY - 1); ui->rResources->setRowCount(LIBRARY->resourceTypeHandler->getAllObjects().size() - 1);
ui->lResources->setRowCount(GameConstants::RESOURCE_QUANTITY - 1); ui->lResources->setRowCount(LIBRARY->resourceTypeHandler->getAllObjects().size() - 1);
for(int i = 0; i < GameConstants::RESOURCE_QUANTITY - 1; ++i) for(auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
MetaString str; MetaString str;
str.appendName(GameResID(i)); str.appendName(GameResID(i));
for(auto * w : {ui->rResources, ui->lResources}) for(auto * w : {ui->rResources, ui->lResources})
{ {
auto * item = new QTableWidgetItem(QString::fromStdString(str.toString())); auto * item = new QTableWidgetItem(QString::fromStdString(str.toString()));
item->setData(Qt::UserRole, QVariant::fromValue(i)); item->setData(Qt::UserRole, QVariant::fromValue(i.getNum()));
w->setItem(i, 0, item); w->setItem(i, 0, item);
auto * spinBox = new QSpinBox; auto * spinBox = new QSpinBox;
spinBox->setMaximum(i == GameResID::GOLD ? 999999 : 999); spinBox->setMaximum(i == GameResID::GOLD ? 999999 : 999);
@@ -779,8 +780,6 @@ void RewardsDelegate::updateModelData(QAbstractItemModel * model, const QModelIn
QStringList resourcesList; QStringList resourcesList;
for(GameResID resource = GameResID::WOOD; resource < GameResID::COUNT ; resource++) for(GameResID resource = GameResID::WOOD; resource < GameResID::COUNT ; resource++)
{ {
if(resource == GameResID::MITHRIL)
continue; // translated as "Abandoned"?
if(vinfo.reward.resources[resource] == 0) if(vinfo.reward.resources[resource] == 0)
continue; continue;
MetaString str; MetaString str;

View File

@@ -18,6 +18,8 @@
#include "../../lib/entities/faction/CTownHandler.h" #include "../../lib/entities/faction/CTownHandler.h"
#include "../../lib/constants/NumericConstants.h" #include "../../lib/constants/NumericConstants.h"
#include "../../lib/constants/StringConstants.h" #include "../../lib/constants/StringConstants.h"
#include "../../lib/GameLibrary.h"
#include "../../lib/entities/ResourceTypeHandler.h"
static const int FIRST_DAY_FOR_EVENT = 1; static const int FIRST_DAY_FOR_EVENT = 1;
static const int LAST_DAY_FOR_EVENT = 999; static const int LAST_DAY_FOR_EVENT = 999;
@@ -79,9 +81,9 @@ void TownEventDialog::initPlayers()
void TownEventDialog::initResources() void TownEventDialog::initResources()
{ {
ui->resourcesTable->setRowCount(GameConstants::RESOURCE_QUANTITY); ui->resourcesTable->setRowCount(LIBRARY->resourceTypeHandler->getAllObjects().size());
auto resourcesMap = params.value("resources").toMap(); auto resourcesMap = params.value("resources").toMap();
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i) for(auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
MetaString str; MetaString str;
str.appendName(GameResID(i)); str.appendName(GameResID(i));
@@ -91,7 +93,7 @@ void TownEventDialog::initResources()
item->setText(name); item->setText(name);
ui->resourcesTable->setItem(i, 0, item); ui->resourcesTable->setItem(i, 0, item);
int val = resourcesMap.value(QString::fromStdString(GameConstants::RESOURCE_NAMES[i])).toInt(); int val = resourcesMap.value(QString::fromStdString(i.toResource()->getJsonKey())).toInt();
auto * edit = new QSpinBox(ui->resourcesTable); auto * edit = new QSpinBox(ui->resourcesTable);
edit->setMaximum(i == GameResID::GOLD ? MAXIMUM_GOLD_CHANGE : MAXIMUM_RESOURCE_CHANGE); edit->setMaximum(i == GameResID::GOLD ? MAXIMUM_GOLD_CHANGE : MAXIMUM_RESOURCE_CHANGE);
edit->setMinimum(i == GameResID::GOLD ? -MAXIMUM_GOLD_CHANGE : -MAXIMUM_RESOURCE_CHANGE); edit->setMinimum(i == GameResID::GOLD ? -MAXIMUM_GOLD_CHANGE : -MAXIMUM_RESOURCE_CHANGE);
@@ -228,9 +230,9 @@ QVariant TownEventDialog::playersToVariant()
QVariantMap TownEventDialog::resourcesToVariant() QVariantMap TownEventDialog::resourcesToVariant()
{ {
auto res = params.value("resources").toMap(); auto res = params.value("resources").toMap();
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i) for(auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
auto itemType = QString::fromStdString(GameConstants::RESOURCE_NAMES[i]); auto itemType = QString::fromStdString(i.toResource()->getJsonKey());
auto * itemQty = static_cast<QSpinBox *> (ui->resourcesTable->cellWidget(i, 1)); auto * itemQty = static_cast<QSpinBox *> (ui->resourcesTable->cellWidget(i, 1));
res[itemType] = QVariant::fromValue(itemQty->value()); res[itemType] = QVariant::fromValue(itemQty->value());

View File

@@ -14,6 +14,8 @@
#include "../mapcontroller.h" #include "../mapcontroller.h"
#include "../../lib/constants/NumericConstants.h" #include "../../lib/constants/NumericConstants.h"
#include "../../lib/constants/StringConstants.h" #include "../../lib/constants/StringConstants.h"
#include "../../lib/GameLibrary.h"
#include "../../lib/entities/ResourceTypeHandler.h"
QString toQString(const PlayerColor & player) QString toQString(const PlayerColor & player)
{ {
@@ -41,8 +43,8 @@ std::set<PlayerColor> playersFromVariant(const QVariant & v)
QVariant toVariant(const TResources & resources) QVariant toVariant(const TResources & resources)
{ {
QVariantMap result; QVariantMap result;
for(int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i) for(auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
result[QString::fromStdString(GameConstants::RESOURCE_NAMES[i])] = QVariant::fromValue(resources[i]); result[QString::fromStdString(i.toResource()->getJsonKey())] = QVariant::fromValue(resources[i]);
return result; return result;
} }
@@ -51,7 +53,9 @@ TResources resourcesFromVariant(const QVariant & v)
JsonNode vJson; JsonNode vJson;
for(auto r : v.toMap().keys()) for(auto r : v.toMap().keys())
vJson[r.toStdString()].Integer() = v.toMap().value(r).toInt(); vJson[r.toStdString()].Integer() = v.toMap().value(r).toInt();
return TResources(vJson); ResourceSet res;
res.resolveFromJson(vJson);
return res;
} }
QVariant toVariant(std::vector<ObjectInstanceID> objects) QVariant toVariant(std::vector<ObjectInstanceID> objects)

View File

@@ -14,6 +14,8 @@
#include "../mapeditorroles.h" #include "../mapeditorroles.h"
#include "../../lib/constants/EntityIdentifiers.h" #include "../../lib/constants/EntityIdentifiers.h"
#include "../../lib/constants/StringConstants.h" #include "../../lib/constants/StringConstants.h"
#include "../../lib/GameLibrary.h"
#include "../../lib/entities/ResourceTypeHandler.h"
TimedEvent::TimedEvent(MapController & c, QListWidgetItem * t, QWidget *parent) : TimedEvent::TimedEvent(MapController & c, QListWidgetItem * t, QWidget *parent) :
controller(c), controller(c),
@@ -45,13 +47,13 @@ TimedEvent::TimedEvent(MapController & c, QListWidgetItem * t, QWidget *parent)
ui->playersAffected->addItem(item); ui->playersAffected->addItem(item);
} }
ui->resources->setRowCount(GameConstants::RESOURCE_QUANTITY); ui->resources->setRowCount(LIBRARY->resourceTypeHandler->getAllObjects().size());
for(int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i) for(auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
MetaString str; MetaString str;
str.appendName(GameResID(i)); str.appendName(GameResID(i));
auto name = QString::fromStdString(str.toString()); auto name = QString::fromStdString(str.toString());
int val = params.value("resources").toMap().value(QString::fromStdString(GameConstants::RESOURCE_NAMES[i])).toInt(); int val = params.value("resources").toMap().value(QString::fromStdString(i.toResource()->getJsonKey())).toInt();
ui->resources->setItem(i, 0, new QTableWidgetItem(name)); ui->resources->setItem(i, 0, new QTableWidgetItem(name));
auto nval = new QTableWidgetItem(QString::number(val)); auto nval = new QTableWidgetItem(QString::number(val));
nval->setFlags(nval->flags() | Qt::ItemIsEditable); nval->setFlags(nval->flags() | Qt::ItemIsEditable);
@@ -94,9 +96,9 @@ void TimedEvent::on_TimedEvent_finished(int result)
descriptor["players"] = QVariant::fromValue(players); descriptor["players"] = QVariant::fromValue(players);
auto res = target->data(Qt::UserRole).toMap().value("resources").toMap(); auto res = target->data(Qt::UserRole).toMap().value("resources").toMap();
for(int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i) for(auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
auto itemType = QString::fromStdString(GameConstants::RESOURCE_NAMES[i]); auto itemType = QString::fromStdString(i.toResource()->getJsonKey());
auto * itemQty = ui->resources->item(i, 1); auto * itemQty = ui->resources->item(i, 1);
res[itemType] = QVariant::fromValue(itemQty->text().toInt()); res[itemType] = QVariant::fromValue(itemQty->text().toInt());
} }

View File

@@ -12,9 +12,11 @@
#include "ui_victoryconditions.h" #include "ui_victoryconditions.h"
#include "../mapcontroller.h" #include "../mapcontroller.h"
#include "../../lib/GameLibrary.h"
#include "../../lib/constants/StringConstants.h" #include "../../lib/constants/StringConstants.h"
#include "../../lib/entities/artifact/CArtHandler.h" #include "../../lib/entities/artifact/CArtHandler.h"
#include "../../lib/entities/faction/CTownHandler.h" #include "../../lib/entities/faction/CTownHandler.h"
#include "../../lib/entities/ResourceTypeHandler.h"
#include "../../lib/mapObjects/CGCreature.h" #include "../../lib/mapObjects/CGCreature.h"
#include "../../lib/texts/CGeneralTextHandler.h" #include "../../lib/texts/CGeneralTextHandler.h"
@@ -406,12 +408,12 @@ void VictoryConditions::on_victoryComboBox_currentIndexChanged(int index)
victoryTypeWidget = new QComboBox; victoryTypeWidget = new QComboBox;
ui->victoryParamsLayout->addWidget(victoryTypeWidget); ui->victoryParamsLayout->addWidget(victoryTypeWidget);
{ {
for(int resType = 0; resType < GameConstants::RESOURCE_QUANTITY; ++resType) for(auto & resType : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
MetaString str; MetaString str;
str.appendName(GameResID(resType)); str.appendName(GameResID(resType));
auto resName = QString::fromStdString(str.toString()); auto resName = QString::fromStdString(str.toString());
victoryTypeWidget->addItem(resName, QVariant::fromValue(resType)); victoryTypeWidget->addItem(resName, QVariant::fromValue(resType.getNum()));
} }
} }

View File

@@ -16,6 +16,8 @@
#include "../../../lib/constants/EntityIdentifiers.h" #include "../../../lib/constants/EntityIdentifiers.h"
#include "../../../lib/constants/StringConstants.h" #include "../../../lib/constants/StringConstants.h"
#include "../../../lib/rmg/CRmgTemplate.h" #include "../../../lib/rmg/CRmgTemplate.h"
#include "../../../lib/GameLibrary.h"
#include "../../../lib/entities/ResourceTypeHandler.h"
QDomElement CardItem::getElementById(const QDomDocument& doc, const QString& id) QDomElement CardItem::getElementById(const QDomDocument& doc, const QString& id)
{ {
@@ -149,11 +151,11 @@ int CardItem::getId()
void CardItem::setResAmount(GameResID res, int val) void CardItem::setResAmount(GameResID res, int val)
{ {
auto textElem = getElementById(doc, "text" + QString::fromStdString(GameConstants::RESOURCE_NAMES[res])); auto textElem = getElementById(doc, "text" + QString::fromStdString(res.toResource()->getJsonKey()));
textElem.setAttribute("style", textElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:" + QColor(useBlackText ? Qt::black : Qt::white).name() + ";")); textElem.setAttribute("style", textElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:" + QColor(useBlackText ? Qt::black : Qt::white).name() + ";"));
textElem.firstChild().setNodeValue(val ? QString::number(val) : ""); textElem.firstChild().setNodeValue(val ? QString::number(val) : "");
auto iconElem = getElementById(doc, "icon" + QString::fromStdString(GameConstants::RESOURCE_NAMES[res])); auto iconElem = getElementById(doc, "icon" + QString::fromStdString(res.toResource()->getJsonKey()));
iconElem.setAttribute("opacity", val ? "1.0" : "0.1"); iconElem.setAttribute("opacity", val ? "1.0" : "0.1");
} }

View File

@@ -15,10 +15,12 @@
#include "../../lib/GameLibrary.h" #include "../../lib/GameLibrary.h"
#include "../../lib/texts/CGeneralTextHandler.h" #include "../../lib/texts/CGeneralTextHandler.h"
#include "../../lib/texts/MetaString.h"
#include "../../lib/entities/ResourceTypeHandler.h"
auto resources = std::vector<EGameResID>{EGameResID::GOLD, EGameResID::WOOD, EGameResID::MERCURY, EGameResID::ORE, EGameResID::SULFUR, EGameResID::CRYSTAL, EGameResID::GEMS}; auto resourcesToShow = std::vector<EGameResID>{EGameResID::GOLD, EGameResID::WOOD, EGameResID::MERCURY, EGameResID::ORE, EGameResID::SULFUR, EGameResID::CRYSTAL, EGameResID::GEMS}; //todo: configurable resource support
MineSelector::MineSelector(std::map<TResource, ui16> & mines) : MineSelector::MineSelector(std::map<GameResID, ui16> & mines) :
ui(new Ui::MineSelector), ui(new Ui::MineSelector),
minesSelected(mines) minesSelected(mines)
{ {
@@ -29,18 +31,18 @@ MineSelector::MineSelector(std::map<TResource, ui16> & mines) :
setWindowModality(Qt::ApplicationModal); setWindowModality(Qt::ApplicationModal);
ui->tableWidgetMines->setColumnCount(2); ui->tableWidgetMines->setColumnCount(2);
ui->tableWidgetMines->setRowCount(resources.size()); ui->tableWidgetMines->setRowCount(resourcesToShow.size());
ui->tableWidgetMines->setHorizontalHeaderLabels({tr("Resource"), tr("Mines")}); ui->tableWidgetMines->setHorizontalHeaderLabels({tr("Resource"), tr("Mines")});
for (int row = 0; row < resources.size(); ++row) for (int row = 0; row < resourcesToShow.size(); ++row)
{ {
auto name = LIBRARY->generaltexth->translate(TextIdentifier("core.restypes", resources[row].getNum()).get()); auto name = resourcesToShow[row].toResource()->getNameTranslated();
auto label = new QLabel(QString::fromStdString(name)); auto label = new QLabel(QString::fromStdString(name));
label->setAlignment(Qt::AlignCenter); label->setAlignment(Qt::AlignCenter);
ui->tableWidgetMines->setCellWidget(row, 0, label); ui->tableWidgetMines->setCellWidget(row, 0, label);
auto spinBox = new QSpinBox(); auto spinBox = new QSpinBox();
spinBox->setRange(0, 100); spinBox->setRange(0, 100);
spinBox->setValue(mines[resources[row]]); spinBox->setValue(mines[resourcesToShow[row]]);
ui->tableWidgetMines->setCellWidget(row, 1, spinBox); ui->tableWidgetMines->setCellWidget(row, 1, spinBox);
} }
ui->tableWidgetMines->resizeColumnsToContents(); ui->tableWidgetMines->resizeColumnsToContents();
@@ -48,7 +50,7 @@ MineSelector::MineSelector(std::map<TResource, ui16> & mines) :
show(); show();
} }
void MineSelector::showMineSelector(std::map<TResource, ui16> & mines) void MineSelector::showMineSelector(std::map<GameResID, ui16> & mines)
{ {
auto * dialog = new MineSelector(mines); auto * dialog = new MineSelector(mines);
dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setAttribute(Qt::WA_DeleteOnClose);
@@ -57,8 +59,8 @@ void MineSelector::showMineSelector(std::map<TResource, ui16> & mines)
void MineSelector::on_buttonBoxResult_accepted() void MineSelector::on_buttonBoxResult_accepted()
{ {
for (int row = 0; row < resources.size(); ++row) for (int row = 0; row < resourcesToShow.size(); ++row)
minesSelected[resources[row]] = static_cast<QSpinBox *>(ui->tableWidgetMines->cellWidget(row, 1))->value(); minesSelected[resourcesToShow[row]] = static_cast<QSpinBox *>(ui->tableWidgetMines->cellWidget(row, 1))->value();
close(); close();
} }

View File

@@ -22,9 +22,9 @@ class MineSelector : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit MineSelector(std::map<TResource, ui16> & mines); explicit MineSelector(std::map<GameResID, ui16> & mines);
static void showMineSelector(std::map<TResource, ui16> & mines); static void showMineSelector(std::map<GameResID, ui16> & mines);
private slots: private slots:
void on_buttonBoxResult_accepted(); void on_buttonBoxResult_accepted();
@@ -33,5 +33,5 @@ private slots:
private: private:
Ui::MineSelector *ui; Ui::MineSelector *ui;
std::map<TResource, ui16> & minesSelected; std::map<GameResID, ui16> & minesSelected;
}; };

View File

@@ -14,8 +14,6 @@
#include "../LuaWrapper.h" #include "../LuaWrapper.h"
#include "../../../lib/mapObjects/CObjectHandler.h"
namespace scripting namespace scripting
{ {
namespace api namespace api

View File

@@ -82,7 +82,7 @@ int SetResourcesProxy::getAmount(lua_State * L)
S.clear(); S.clear();
const TQuantity amount = vstd::atOrDefault(object->res, static_cast<size_t>(type), 0); const TQuantity amount = object->res[type];
S.push(amount); S.push(amount);
return 1; return 1;
} }

View File

@@ -8,7 +8,7 @@ local Bonus = require("Bonus")
local BonusBearer = require("BonusBearer") local BonusBearer = require("BonusBearer")
local BonusList = require("BonusList") local BonusList = require("BonusList")
local RES = {[0] = "wood", [1] = "mercury", [2] = "ore", [3] = "sulfur", [4] = "crystal", [5] = "gems", [6] = "gold", [7] = "mithril"} local RES = {[0] = "wood", [1] = "mercury", [2] = "ore", [3] = "sulfur", [4] = "crystal", [5] = "gems", [6] = "gold"}
local SERVICES = SERVICES local SERVICES = SERVICES
local creatures = SERVICES:creatures() local creatures = SERVICES:creatures()

View File

@@ -2293,7 +2293,8 @@ bool CGameHandler::spellResearch(ObjectInstanceID tid, SpellID spellAtSlot, bool
return true; return true;
} }
auto costBase = TResources(gameInfo().getSettings().getValue(EGameSettings::TOWNS_SPELL_RESEARCH_COST).Vector()[level]); ResourceSet costBase;
costBase.resolveFromJson(gameInfo().getSettings().getValue(EGameSettings::TOWNS_SPELL_RESEARCH_COST).Vector()[level]);
auto costExponent = gameInfo().getSettings().getValue(EGameSettings::TOWNS_SPELL_RESEARCH_COST_EXPONENT_PER_RESEARCH).Vector()[level].Float(); auto costExponent = gameInfo().getSettings().getValue(EGameSettings::TOWNS_SPELL_RESEARCH_COST_EXPONENT_PER_RESEARCH).Vector()[level].Float();
auto cost = costBase * std::pow(t->spellResearchAcceptedCounter + 1, costExponent); auto cost = costBase * std::pow(t->spellResearchAcceptedCounter + 1, costExponent);

View File

@@ -20,6 +20,7 @@
#include "../lib/campaign/CampaignState.h" #include "../lib/campaign/CampaignState.h"
#include "../lib/entities/hero/CHeroHandler.h" #include "../lib/entities/hero/CHeroHandler.h"
#include "../lib/entities/hero/CHeroClass.h" #include "../lib/entities/hero/CHeroClass.h"
#include "../lib/entities/ResourceTypeHandler.h"
#include "../lib/gameState/CGameState.h" #include "../lib/gameState/CGameState.h"
#include "../lib/mapping/CMapInfo.h" #include "../lib/mapping/CMapInfo.h"
#include "../lib/mapping/CMapHeader.h" #include "../lib/mapping/CMapHeader.h"
@@ -709,7 +710,7 @@ void CVCMIServer::setPlayerHandicap(PlayerColor color, Handicap handicap)
return; return;
} }
for(auto & res : EGameResID::ALL_RESOURCES()) for(auto & res : LIBRARY->resourceTypeHandler->getAllObjects())
if(handicap.startBonus[res] != 0) if(handicap.startBonus[res] != 0)
{ {
str.appendRawString(" "); str.appendRawString(" ");
@@ -1008,7 +1009,7 @@ void CVCMIServer::multiplayerWelcomeMessage()
str.appendRawString(" "); str.appendRawString(" ");
str.appendName(pi.first); str.appendName(pi.first);
str.appendRawString(":"); str.appendRawString(":");
for(auto & res : EGameResID::ALL_RESOURCES()) for(auto & res : LIBRARY->resourceTypeHandler->getAllObjects())
if(pi.second.handicap.startBonus[res] != 0) if(pi.second.handicap.startBonus[res] != 0)
{ {
str.appendRawString(" "); str.appendRawString(" ");

View File

@@ -21,6 +21,7 @@
#include "../../lib/constants/StringConstants.h" #include "../../lib/constants/StringConstants.h"
#include "../../lib/entities/building/CBuilding.h" #include "../../lib/entities/building/CBuilding.h"
#include "../../lib/entities/faction/CTownHandler.h" #include "../../lib/entities/faction/CTownHandler.h"
#include "../../lib/entities/ResourceTypeHandler.h"
#include "../../lib/gameState/CGameState.h" #include "../../lib/gameState/CGameState.h"
#include "../../lib/gameState/SThievesGuildInfo.h" #include "../../lib/gameState/SThievesGuildInfo.h"
#include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGHeroInstance.h"
@@ -58,7 +59,7 @@ void NewTurnProcessor::handleTimeEvents(PlayerColor color)
if (!event.resources.empty()) if (!event.resources.empty())
{ {
gameHandler->giveResources(color, event.resources); gameHandler->giveResources(color, event.resources);
for (GameResID i : GameResID::ALL_RESOURCES()) for (GameResID i : LIBRARY->resourceTypeHandler->getAllObjects())
if (event.resources[i]) if (event.resources[i])
iw.components.emplace_back(ComponentType::RESOURCE, i, event.resources[i]); iw.components.emplace_back(ComponentType::RESOURCE, i, event.resources[i]);
} }
@@ -94,7 +95,7 @@ void NewTurnProcessor::handleTownEvents(const CGTownInstance * town)
{ {
gameHandler->giveResources(player, event.resources); gameHandler->giveResources(player, event.resources);
for (GameResID i : GameResID::ALL_RESOURCES()) for (GameResID i : LIBRARY->resourceTypeHandler->getAllObjects())
if (event.resources[i]) if (event.resources[i])
iw.components.emplace_back(ComponentType::RESOURCE, i, event.resources[i]); iw.components.emplace_back(ComponentType::RESOURCE, i, event.resources[i]);
} }
@@ -256,9 +257,9 @@ ResourceSet NewTurnProcessor::generatePlayerIncome(PlayerColor playerID, bool ne
const JsonNode & difficultyConfig = weeklyBonusesConfig[difficultyName]; const JsonNode & difficultyConfig = weeklyBonusesConfig[difficultyName];
// Distribute weekly bonuses over 7 days, depending on the current day of the week // Distribute weekly bonuses over 7 days, depending on the current day of the week
for (GameResID i : GameResID::ALL_RESOURCES()) for (GameResID i : LIBRARY->resourceTypeHandler->getAllObjects())
{ {
const std::string & name = GameConstants::RESOURCE_NAMES[i.getNum()]; const std::string & name = i.toResource()->getJsonKey();
int64_t weeklyBonus = difficultyConfig[name].Integer(); int64_t weeklyBonus = difficultyConfig[name].Integer();
int64_t dayOfWeek = gameHandler->gameState().getDate(Date::DAY_OF_WEEK); int64_t dayOfWeek = gameHandler->gameState().getDate(Date::DAY_OF_WEEK);
int64_t dailyIncome = incomeHandicapped[i]; int64_t dailyIncome = incomeHandicapped[i];

View File

@@ -23,6 +23,7 @@
#include "../../lib/entities/artifact/CArtHandler.h" #include "../../lib/entities/artifact/CArtHandler.h"
#include "../../lib/entities/building/CBuilding.h" #include "../../lib/entities/building/CBuilding.h"
#include "../../lib/entities/hero/CHeroHandler.h" #include "../../lib/entities/hero/CHeroHandler.h"
#include "../../lib/entities/ResourceTypeHandler.h"
#include "../../lib/gameState/CGameState.h" #include "../../lib/gameState/CGameState.h"
#include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/mapObjects/CGTownInstance.h"
#include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGHeroInstance.h"
@@ -593,7 +594,7 @@ void PlayerMessageProcessor::cheatResources(PlayerColor player, std::vector<std:
TResources resources; TResources resources;
resources[EGameResID::GOLD] = baseResourceAmount * 1000; resources[EGameResID::GOLD] = baseResourceAmount * 1000;
for (GameResID i = EGameResID::WOOD; i < EGameResID::GOLD; ++i) for (auto & i : LIBRARY->resourceTypeHandler->getAllObjects())
resources[i] = baseResourceAmount; resources[i] = baseResourceAmount;
gameHandler->giveResources(player, resources); gameHandler->giveResources(player, resources);

View File

@@ -13,8 +13,6 @@
#include "../scripting/ScriptFixture.h" #include "../scripting/ScriptFixture.h"
#include "../../lib/mapObjects/CObjectHandler.h"
namespace test namespace test
{ {
namespace scripting namespace scripting

View File

@@ -21,6 +21,7 @@ public:
MOCK_CONST_METHOD0(factions, const FactionService *()); MOCK_CONST_METHOD0(factions, const FactionService *());
MOCK_CONST_METHOD0(heroClasses, const HeroClassService *()); MOCK_CONST_METHOD0(heroClasses, const HeroClassService *());
MOCK_CONST_METHOD0(heroTypes, const HeroTypeService *()); MOCK_CONST_METHOD0(heroTypes, const HeroTypeService *());
MOCK_CONST_METHOD0(resources, const ResourceTypeService *());
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED
MOCK_CONST_METHOD0(scripts, const scripting::Service *()); MOCK_CONST_METHOD0(scripts, const scripting::Service *());
#endif #endif

View File

@@ -214,7 +214,6 @@ TEST_F(ResourceManagerTest, freeResources)
ASSERT_GE(res[EGameResID::CRYSTAL], 0); ASSERT_GE(res[EGameResID::CRYSTAL], 0);
ASSERT_GE(res[EGameResID::GEMS], 0); ASSERT_GE(res[EGameResID::GEMS], 0);
ASSERT_GE(res[EGameResID::GOLD], 0); ASSERT_GE(res[EGameResID::GOLD], 0);
ASSERT_GE(res[EGameResID::MITHRIL], 0);
} }
TEST_F(ResourceManagerTest, freeResourcesWithManyGoals) TEST_F(ResourceManagerTest, freeResourcesWithManyGoals)