1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00

Merge pull request #4544 from IvanSavenko/map_settings

Per-map game settings
This commit is contained in:
Ivan Savenko 2024-09-10 00:03:10 +03:00 committed by GitHub
commit ce4548718c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
73 changed files with 469 additions and 295 deletions

View File

@ -18,7 +18,7 @@
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/CHeroHandler.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/gameState/CGameState.h"
#include "../../lib/serializer/CTypeList.h"
#include "../../lib/networkPacks/PacksForClient.h"

View File

@ -18,7 +18,7 @@
#include "../../lib/mapObjects/MapObjects.h"
#include "../../lib/mapping/CMapDefines.h"
#include "../../lib/gameState/QuestInfo.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include <vcmi/CreatureService.h>

View File

@ -12,7 +12,7 @@
#include "../Engine/Nullkiller.h"
#include "../../../lib/mapObjects/MapObjects.h"
#include "../../../lib/CHeroHandler.h"
#include "../../../lib/GameSettings.h"
#include "../../../lib/IGameSettings.h"
namespace NKAI
{
@ -196,8 +196,8 @@ bool HeroManager::heroCapReached() const
return heroCount >= ALLOWED_ROAMING_HEROES
|| heroCount >= ai->settings->getMaxRoamingHeroes()
|| heroCount >= VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP)
|| heroCount >= VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP);
|| heroCount >= cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP)
|| heroCount >= cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP);
}
float HeroManager::getFightingStrengthCached(const CGHeroInstance * hero) const

View File

@ -44,7 +44,7 @@ namespace AIPathfinding
Nullkiller * ai,
std::shared_ptr<AINodeStorage> nodeStorage,
bool allowBypassObjects)
:PathfinderConfig(nodeStorage, makeRuleset(cb, ai, nodeStorage, allowBypassObjects)), aiNodeStorage(nodeStorage)
:PathfinderConfig(nodeStorage, cb, makeRuleset(cb, ai, nodeStorage, allowBypassObjects)), aiNodeStorage(nodeStorage)
{
options.canUseCast = true;
options.allowLayerTransitioningAfterBattle = true;

View File

@ -39,7 +39,7 @@ namespace AIPathfinding
CPlayerSpecificInfoCallback * cb,
VCAI * ai,
std::shared_ptr<AINodeStorage> nodeStorage)
:PathfinderConfig(nodeStorage, makeRuleset(cb, ai, nodeStorage)), hero(nodeStorage->getHero())
:PathfinderConfig(nodeStorage, cb, makeRuleset(cb, ai, nodeStorage)), hero(nodeStorage->getHero())
{
options.ignoreGuards = false;
options.useEmbarkAndDisembark = true;

View File

@ -21,7 +21,7 @@
#include "../../lib/mapObjects/ObjectTemplate.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/CHeroHandler.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/gameState/CGameState.h"
#include "../../lib/bonuses/Limiters.h"
#include "../../lib/bonuses/Updaters.h"
@ -1317,7 +1317,7 @@ bool VCAI::canRecruitAnyHero(const CGTownInstance * t) const
return false;
if(cb->getHeroesInfo().size() >= ALLOWED_ROAMING_HEROES)
return false;
if(cb->getHeroesInfo().size() >= VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
if(cb->getHeroesInfo().size() >= cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
return false;
if(!cb->getAvailableHeroes(t).size())
return false;
@ -2852,12 +2852,12 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
case Obj::MAGIC_WELL:
return h->mana < h->manaLimit();
case Obj::PRISON:
return ai->myCb->getHeroesInfo().size() < VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP);
return ai->myCb->getHeroesInfo().size() < cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP);
case Obj::TAVERN:
{
//TODO: make AI actually recruit heroes
//TODO: only on request
if(ai->myCb->getHeroesInfo().size() >= VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
if(ai->myCb->getHeroesInfo().size() >= cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
return false;
else if(ai->ah->freeGold() < GameConstants::HERO_GOLD_COST)
return false;

View File

@ -92,9 +92,9 @@ const ObstacleService * CGameInfo::obstacles() const
return globalServices->obstacles();
}
const IGameSettings * CGameInfo::settings() const
const IGameSettings * CGameInfo::engineSettings() const
{
return globalServices->settings();
return globalServices->engineSettings();
}
spells::effects::Registry * CGameInfo::spellEffects()

View File

@ -70,7 +70,7 @@ public:
const SkillService * skills() const override;
const BattleFieldService * battlefields() const override;
const ObstacleService * obstacles() const override;
const IGameSettings * settings() const override;
const IGameSettings * engineSettings() const override;
const spells::effects::Registry * spellEffects() const override;
spells::effects::Registry * spellEffects() override;

View File

@ -39,7 +39,7 @@
#include "../CPlayerInterface.h"
#include "../../CCallback.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/StartInfo.h"
#include "../../lib/texts/CGeneralTextHandler.h"
#include "../../lib/spells/CSpellHandler.h"
@ -617,7 +617,7 @@ void AdventureMapInterface::onTileHovered(const int3 &targetPosition)
case SpellID::DIMENSION_DOOR:
if(isValidAdventureSpellTarget(targetPosition))
{
if(VLC->settings()->getBoolean(EGameSettings::DIMENSION_DOOR_TRIGGERS_GUARDS) && LOCPLINT->cb->isTileGuardedUnchecked(targetPosition))
if(LOCPLINT->cb->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_TRIGGERS_GUARDS) && LOCPLINT->cb->isTileGuardedUnchecked(targetPosition))
CCS->curh->set(Cursor::Map::T1_ATTACK);
else
CCS->curh->set(Cursor::Map::TELEPORT);

View File

@ -30,7 +30,7 @@
#include "../../lib/texts/CGeneralTextHandler.h"
#include "../../lib/CHeroHandler.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/CGTownInstance.h"
@ -432,7 +432,7 @@ std::shared_ptr<CIntObject> CTownList::CTownItem::genSelection()
void CTownList::CTownItem::update()
{
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
picture->setFrame(iconIndex + 2);
redraw();

View File

@ -36,7 +36,7 @@
#include "../../CCallback.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/filesystem/Filesystem.h"
#include "../../lib/campaign/CampaignState.h"
#include "../../lib/mapping/CMapInfo.h"
@ -782,19 +782,19 @@ bool SelectionTab::isMapSupported(const CMapInfo & info)
switch (info.mapHeader->version)
{
case EMapFormat::ROE:
return CGI->settings()->getValue(EGameSettings::MAP_FORMAT_RESTORATION_OF_ERATHIA)["supported"].Bool();
return CGI->engineSettings()->getValue(EGameSettings::MAP_FORMAT_RESTORATION_OF_ERATHIA)["supported"].Bool();
case EMapFormat::AB:
return CGI->settings()->getValue(EGameSettings::MAP_FORMAT_ARMAGEDDONS_BLADE)["supported"].Bool();
return CGI->engineSettings()->getValue(EGameSettings::MAP_FORMAT_ARMAGEDDONS_BLADE)["supported"].Bool();
case EMapFormat::SOD:
return CGI->settings()->getValue(EGameSettings::MAP_FORMAT_SHADOW_OF_DEATH)["supported"].Bool();
return CGI->engineSettings()->getValue(EGameSettings::MAP_FORMAT_SHADOW_OF_DEATH)["supported"].Bool();
case EMapFormat::CHR:
return CGI->settings()->getValue(EGameSettings::MAP_FORMAT_CHRONICLES)["supported"].Bool();
return CGI->engineSettings()->getValue(EGameSettings::MAP_FORMAT_CHRONICLES)["supported"].Bool();
case EMapFormat::WOG:
return CGI->settings()->getValue(EGameSettings::MAP_FORMAT_IN_THE_WAKE_OF_GODS)["supported"].Bool();
return CGI->engineSettings()->getValue(EGameSettings::MAP_FORMAT_IN_THE_WAKE_OF_GODS)["supported"].Bool();
case EMapFormat::HOTA:
return CGI->settings()->getValue(EGameSettings::MAP_FORMAT_HORN_OF_THE_ABYSS)["supported"].Bool();
return CGI->engineSettings()->getValue(EGameSettings::MAP_FORMAT_HORN_OF_THE_ABYSS)["supported"].Bool();
case EMapFormat::VCMI:
return CGI->settings()->getValue(EGameSettings::MAP_FORMAT_JSON_VCMI)["supported"].Bool();
return CGI->engineSettings()->getValue(EGameSettings::MAP_FORMAT_JSON_VCMI)["supported"].Bool();
}
return false;
}

View File

@ -13,7 +13,7 @@
#include "../gui/CGuiHandler.h"
#include "Images.h"
#include "GameSettings.h"
#include "IGameSettings.h"
#include "ObjectLists.h"
#include "../CPlayerInterface.h"
@ -34,7 +34,7 @@ CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(size_t slotsColumnsMax, size_
CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack()
: CArtifactsOfHeroBackpack(8, 8)
{
const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP);
const auto backpackCap = LOCPLINT->cb->getSettings().getInteger(EGameSettings::HEROES_BACKPACK_CAP);
auto visibleCapacityMax = slotsRowsMax * slotsColumnsMax;
if(backpackCap >= 0)
visibleCapacityMax = visibleCapacityMax > backpackCap ? backpackCap : visibleCapacityMax;
@ -204,4 +204,4 @@ void CArtifactsOfHeroQuickBackpack::swapSelected()
}
if(backpackLoc.slot != ArtifactPosition::PRE_FIRST && filterBySlot != ArtifactPosition::PRE_FIRST && curHero)
LOCPLINT->cb->swapArtifacts(backpackLoc, ArtifactLocation(curHero->id, filterBySlot));
}
}

View File

@ -32,7 +32,7 @@
#include "../../CCallback.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/entities/faction/CTownHandler.h"
#include "../../lib/gameState/InfoAboutArmy.h"
#include "../../lib/mapObjects/CGCreature.h"
@ -388,7 +388,7 @@ void CTownTooltip::init(const InfoAboutTown & town)
assert(town.tType);
size_t iconIndex = town.tType->clientInfo.icons[town.fortLevel > 0][town.built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
size_t iconIndex = town.tType->clientInfo.icons[town.fortLevel > 0][town.built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
build = std::make_shared<CAnimImage>(AnimationPath::builtin("itpt"), iconIndex, 0, 3, 2);
@ -487,7 +487,7 @@ void CInteractableTownTooltip::init(const CGTownInstance * town)
assert(townInfo.tType);
size_t iconIndex = townInfo.tType->clientInfo.icons[townInfo.fortLevel > 0][townInfo.built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
size_t iconIndex = townInfo.tType->clientInfo.icons[townInfo.fortLevel > 0][townInfo.built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
build = std::make_shared<CAnimImage>(AnimationPath::builtin("itpt"), iconIndex, 0, 3, 2);
title = std::make_shared<CLabel>(66, 2, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, townInfo.name);

View File

@ -46,7 +46,7 @@
#include "../../lib/CSoundBase.h"
#include "../../lib/CCreatureHandler.h"
#include "../../lib/texts/CGeneralTextHandler.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/spells/CSpellHandler.h"
#include "../../lib/GameConstants.h"
#include "../../lib/StartInfo.h"
@ -527,7 +527,7 @@ void HeroSlots::swapArmies()
//moving hero out of town - check if it is allowed
if (town->garrisonHero)
{
if (!town->visitingHero && LOCPLINT->cb->howManyHeroes(false) >= CGI->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
if (!town->visitingHero && LOCPLINT->cb->howManyHeroes(false) >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
{
std::string text = CGI->generaltexth->translate("core.genrltxt.18"); //You already have %d adventuring heroes under your command.
boost::algorithm::replace_first(text,"%d",std::to_string(LOCPLINT->cb->howManyHeroes(false)));
@ -1388,7 +1388,7 @@ void CCastleInterface::removeBuilding(BuildingID bid)
void CCastleInterface::recreateIcons()
{
OBJECT_CONSTRUCTION;
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
icon->setFrame(iconIndex);
TResources townIncome = town->dailyIncome();

View File

@ -30,7 +30,7 @@
#include "../../lib/ArtifactUtils.h"
#include "../../lib/CStack.h"
#include "../../lib/CBonusTypeHandler.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/CHeroHandler.h"
#include "../../lib/gameState/CGameState.h"
#include "../../lib/networkPacks/ArtifactLocation.h"
@ -801,8 +801,8 @@ void CStackWindow::initSections()
{
OBJECT_CONSTRUCTION;
bool showArt = CGI->settings()->getBoolean(EGameSettings::MODULE_STACK_ARTIFACT) && info->commander == nullptr && info->stackNode;
bool showExp = (CGI->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE) || info->commander != nullptr) && info->stackNode;
bool showArt = LOCPLINT->cb->getSettings().getBoolean(EGameSettings::MODULE_STACK_ARTIFACT) && info->commander == nullptr && info->stackNode;
bool showExp = (LOCPLINT->cb->getSettings().getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE) || info->commander != nullptr) && info->stackNode;
mainSection = std::make_shared<MainSection>(this, pos.h, showExp, showArt);

View File

@ -10,7 +10,9 @@
#include "StdInc.h"
#include "CHeroOverview.h"
#include "../CCallback.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../gui/CGuiHandler.h"
#include "../render/Canvas.h"
#include "../render/Colors.h"
@ -21,7 +23,7 @@
#include "../widgets/TextControls.h"
#include "../widgets/GraphicalPrimitiveCanvas.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/texts/CGeneralTextHandler.h"
#include "../../lib/CCreatureHandler.h"
#include "../../lib/CHeroHandler.h"
@ -123,7 +125,7 @@ void CHeroOverview::genControls()
r = Rect(302, 3 * borderOffset + yOffset + 62, 292, 32);
backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
auto stacksCountChances = CGI->settings()->getVector(EGameSettings::HEROES_STARTING_STACKS_CHANCES);
auto stacksCountChances = LOCPLINT->cb->getSettings().getVector(EGameSettings::HEROES_STARTING_STACKS_CHANCES);
// army
int space = (260 - 7 * 32) / 6;

View File

@ -35,7 +35,7 @@
#include "../../lib/CCreatureHandler.h"
#include "../../lib/texts/CGeneralTextHandler.h"
#include "../../lib/CHeroHandler.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/CSkillHandler.h"
#include "../../lib/StartInfo.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
@ -800,7 +800,7 @@ CTownItem::CTownItem(const CGTownInstance * Town)
garr = std::make_shared<CGarrisonInt>(Point(313, 3), 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS);
heroes = std::make_shared<HeroSlots>(town, Point(244,6), Point(475,6), garr, false);
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
picture = std::make_shared<CAnimImage>(AnimationPath::builtin("ITPT"), iconIndex, 0, 5, 6);
openTown = std::make_shared<LRClickableAreaOpenTown>(Rect(5, 6, 58, 64), town);

View File

@ -53,7 +53,7 @@
#include "../lib/gameState/TavernHeroesPool.h"
#include "../lib/texts/CGeneralTextHandler.h"
#include "../lib/CHeroHandler.h"
#include "../lib/GameSettings.h"
#include "../lib/IGameSettings.h"
#include "ConditionalWait.h"
#include "../lib/CRandomGenerator.h"
#include "../lib/CSkillHandler.h"
@ -153,7 +153,7 @@ void CRecruitmentWindow::buy()
if(!dstslot.validSlot() && (selected->creature->warMachine == ArtifactID::NONE)) //no available slot
{
std::pair<SlotID, SlotID> toMerge;
bool allowMerge = CGI->settings()->getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_OWNED);
bool allowMerge = LOCPLINT->cb->getSettings().getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_OWNED);
if (allowMerge && dst->mergeableStacks(toMerge))
{
@ -491,7 +491,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func
recruit->addHoverText(EButtonState::NORMAL, CGI->generaltexth->tavernInfo[0]); //Cannot afford a Hero
recruit->block(true);
}
else if(LOCPLINT->cb->howManyHeroes(true) >= CGI->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP))
else if(LOCPLINT->cb->howManyHeroes(true) >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP))
{
MetaString message;
message.appendTextID("core.tvrninfo.1");
@ -501,7 +501,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func
recruit->addHoverText(EButtonState::NORMAL, message.toString());
recruit->block(true);
}
else if(LOCPLINT->cb->howManyHeroes(false) >= CGI->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
else if(LOCPLINT->cb->howManyHeroes(false) >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
{
MetaString message;
message.appendTextID("core.tvrninfo.1");
@ -534,7 +534,7 @@ void CTavernWindow::addInvite()
{
OBJECT_CONSTRUCTION;
if(!VLC->settings()->getBoolean(EGameSettings::HEROES_TAVERN_INVITE))
if(!LOCPLINT->cb->getSettings().getBoolean(EGameSettings::HEROES_TAVERN_INVITE))
return;
const auto & heroesPool = CSH->client->gameState()->heroesPool;

View File

@ -354,6 +354,7 @@
// if stack experience is on, creatures on map will get specified amount of experience daily
"dailyStackExperience" : 100,
// if enabled, double growth, plague and creature weeks can happen randomly. Has no effect on weeks by "Deity of Fire"
// NOTE: on HotA maps, this setting has no effect. Value provided in map will be used instead.
"allowRandomSpecialWeeks" : true,
// if enabled, every creature can get double growth month, ignoring predefined list
"allowAllForDoubleMonth" : false

View File

@ -131,6 +131,13 @@
"description" : "Maximal size of the map, e.g. 'm+u' or '120x120x1",
"type": "string"
},
"settings" : {
"description" : "List of changed game settings by template",
"type" : "object",
"additionalProperties" : {
"type" : "object"
}
},
"name" : {
"description" : "Optional name - useful to have several template variations with same name",
"type": "string"

View File

@ -25,6 +25,15 @@
///Optional parameter allowing to prohibit some water modes. All modes are allowed if parameter is not specified
"allowedWaterContent" : ["none", "normal", "islands"]
/// List of game settings that were overriden by this template. See config/gameConfig.json in vcmi install directory for possible values
/// Settings defined here will always override any settings from vcmi or from mods
"settings" : {
"heroes" : {
"perPlayerOnMapCap" : 1
}
}
},
/// List of named zones, see below for format description
"zones" :

View File

@ -59,7 +59,7 @@ public:
virtual const SkillService * skills() const = 0;
virtual const BattleFieldService * battlefields() const = 0;
virtual const ObstacleService * obstacles() const = 0;
virtual const IGameSettings * settings() const = 0;
virtual const IGameSettings * engineSettings() const = 0;
virtual const spells::effects::Registry * spellEffects() const = 0;
virtual spells::effects::Registry * spellEffects() = 0;

View File

@ -11,7 +11,7 @@
#include "ArtifactUtils.h"
#include "CArtHandler.h"
#include "GameSettings.h"
#include "IGameSettings.h"
#include "spells/CSpellHandler.h"
#include "mapObjects/CGHeroInstance.h"
@ -184,7 +184,7 @@ DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target,
{
if(target->bearerType() == ArtBearer::HERO)
{
const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP);
const auto backpackCap = VLC->engineSettings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP);
if(backpackCap < 0)
return true;
else

View File

@ -12,7 +12,7 @@
#include "VCMI_Lib.h"
#include "GameConstants.h"
#include "GameSettings.h"
#include "IGameSettings.h"
#include "bonuses/BonusList.h"
#include "bonuses/Bonus.h"
#include "bonuses/IBonusBearer.h"
@ -86,14 +86,14 @@ int AFactionMember::getPrimSkillLevel(PrimarySkill id) const
static const std::string keyAllSkills = "type_PRIMARY_SKILL";
auto allSkills = getBonusBearer()->getBonuses(selectorAllSkills, keyAllSkills);
auto ret = allSkills->valOfBonuses(Selector::subtype()(BonusSubtypeID(id)));
auto minSkillValue = VLC->settings()->getVector(EGameSettings::HEROES_MINIMAL_PRIMARY_SKILLS)[id.getNum()];
auto minSkillValue = VLC->engineSettings()->getVector(EGameSettings::HEROES_MINIMAL_PRIMARY_SKILLS)[id.getNum()];
return std::max(ret, minSkillValue); //otherwise, some artifacts may cause negative skill value effect, sp=0 works in old saves
}
int AFactionMember::moraleValAndBonusList(TConstBonusListPtr & bonusList) const
{
int32_t maxGoodMorale = VLC->settings()->getVector(EGameSettings::COMBAT_GOOD_MORALE_DICE).size();
int32_t maxBadMorale = - (int32_t) VLC->settings()->getVector(EGameSettings::COMBAT_BAD_MORALE_DICE).size();
int32_t maxGoodMorale = VLC->engineSettings()->getVector(EGameSettings::COMBAT_GOOD_MORALE_DICE).size();
int32_t maxBadMorale = - (int32_t) VLC->engineSettings()->getVector(EGameSettings::COMBAT_BAD_MORALE_DICE).size();
if(getBonusBearer()->hasBonusOfType(BonusType::MAX_MORALE))
{
@ -123,8 +123,8 @@ int AFactionMember::moraleValAndBonusList(TConstBonusListPtr & bonusList) const
int AFactionMember::luckValAndBonusList(TConstBonusListPtr & bonusList) const
{
int32_t maxGoodLuck = VLC->settings()->getVector(EGameSettings::COMBAT_GOOD_LUCK_DICE).size();
int32_t maxBadLuck = - (int32_t) VLC->settings()->getVector(EGameSettings::COMBAT_BAD_LUCK_DICE).size();
int32_t maxGoodLuck = VLC->engineSettings()->getVector(EGameSettings::COMBAT_GOOD_LUCK_DICE).size();
int32_t maxBadLuck = - (int32_t) VLC->engineSettings()->getVector(EGameSettings::COMBAT_BAD_LUCK_DICE).size();
if(getBonusBearer()->hasBonusOfType(BonusType::MAX_LUCK))
{

View File

@ -12,7 +12,7 @@
#include "ArtifactUtils.h"
#include "ExceptionsCommon.h"
#include "GameSettings.h"
#include "IGameSettings.h"
#include "mapObjects/MapObjects.h"
#include "constants/StringConstants.h"
#include "json/JsonBonus.h"
@ -327,7 +327,7 @@ CArtHandler::~CArtHandler() = default;
std::vector<JsonNode> CArtHandler::loadLegacyData()
{
size_t dataSize = VLC->settings()->getInteger(EGameSettings::TEXTS_ARTIFACT);
size_t dataSize = VLC->engineSettings()->getInteger(EGameSettings::TEXTS_ARTIFACT);
objects.resize(dataSize);
std::vector<JsonNode> h3Data;
@ -656,10 +656,10 @@ bool CArtHandler::legalArtifact(const ArtifactID & id) const
if(art->possibleSlots.count(ArtBearer::HERO) && !art->possibleSlots.at(ArtBearer::HERO).empty())
return true;
if(art->possibleSlots.count(ArtBearer::CREATURE) && !art->possibleSlots.at(ArtBearer::CREATURE).empty() && VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_ARTIFACT))
if(art->possibleSlots.count(ArtBearer::CREATURE) && !art->possibleSlots.at(ArtBearer::CREATURE).empty() && VLC->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_ARTIFACT))
return true;
if(art->possibleSlots.count(ArtBearer::COMMANDER) && !art->possibleSlots.at(ArtBearer::COMMANDER).empty() && VLC->settings()->getBoolean(EGameSettings::MODULE_COMMANDERS))
if(art->possibleSlots.count(ArtBearer::COMMANDER) && !art->possibleSlots.at(ArtBearer::COMMANDER).empty() && VLC->engineSettings()->getBoolean(EGameSettings::MODULE_COMMANDERS))
return true;
return false;

View File

@ -15,7 +15,7 @@
#include "entities/faction/CTownHandler.h"
#include "filesystem/Filesystem.h"
#include "VCMI_Lib.h"
#include "GameSettings.h"
#include "IGameSettings.h"
#include "constants/StringConstants.h"
#include "bonuses/Limiters.h"
#include "bonuses/Updaters.h"
@ -519,7 +519,7 @@ void CCreatureHandler::loadBonuses(JsonNode & creature, std::string bonuses) con
std::vector<JsonNode> CCreatureHandler::loadLegacyData()
{
size_t dataSize = VLC->settings()->getInteger(EGameSettings::TEXTS_CREATURE);
size_t dataSize = VLC->engineSettings()->getInteger(EGameSettings::TEXTS_CREATURE);
objects.resize(dataSize);
std::vector<JsonNode> h3Data;
@ -704,7 +704,7 @@ const std::vector<std::string> & CCreatureHandler::getTypeNames() const
void CCreatureHandler::loadCrExpMod()
{
if (VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE)) //reading default stack experience values
if (VLC->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE)) //reading default stack experience values
{
//Calculate rank exp values, formula appears complicated bu no parsing needed
expRanks.resize(8);
@ -754,7 +754,7 @@ void CCreatureHandler::loadCrExpMod()
void CCreatureHandler::loadCrExpBon(CBonusSystemNode & globalEffects)
{
if (VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE)) //reading default stack experience bonuses
if (VLC->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE)) //reading default stack experience bonuses
{
logGlobal->debug("\tLoading stack experience bonuses");
auto addBonusForAllCreatures = [&](std::shared_ptr<Bonus> b) {
@ -833,7 +833,7 @@ void CCreatureHandler::loadAnimationInfo(std::vector<JsonNode> &h3Data) const
parser.endLine(); // header
parser.endLine();
for(int dd = 0; dd < VLC->settings()->getInteger(EGameSettings::TEXTS_CREATURE); ++dd)
for(int dd = 0; dd < VLC->engineSettings()->getInteger(EGameSettings::TEXTS_CREATURE); ++dd)
{
while (parser.isNextEntryEmpty() && parser.endLine()) // skip empty lines
;

View File

@ -14,7 +14,7 @@
#include "CConfigHandler.h"
#include "CCreatureHandler.h"
#include "VCMI_Lib.h"
#include "GameSettings.h"
#include "IGameSettings.h"
#include "mapObjects/CGHeroInstance.h"
#include "modding/ModScope.h"
#include "IGameCallback.h"
@ -424,7 +424,7 @@ void CCreatureSet::setStackCount(const SlotID & slot, TQuantity count)
{
assert(hasStackAtSlot(slot));
assert(stacks[slot]->count + count > 0);
if (VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE) && count > stacks[slot]->count)
if (count > stacks[slot]->count)
stacks[slot]->experience = static_cast<TExpType>(stacks[slot]->experience * (count / static_cast<double>(stacks[slot]->count)));
stacks[slot]->count = count;
armyChanged();
@ -705,7 +705,7 @@ CCreature::CreatureQuantityId CStackInstance::getQuantityID() const
int CStackInstance::getExpRank() const
{
if (!VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
if (!VLC->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
return 0;
int tier = type->getLevel();
if (vstd::iswithin(tier, 1, 7))
@ -759,7 +759,7 @@ void CStackInstance::setType(const CCreature *c)
if(type)
{
detachFromSource(*type);
if (type->isMyUpgrade(c) && VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
if (type->isMyUpgrade(c) && VLC->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
experience = static_cast<TExpType>(experience * VLC->creh->expAfterUpgrade / 100.0);
}

View File

@ -23,7 +23,7 @@
#include "texts/CGeneralTextHandler.h"
#include "StartInfo.h" // for StartInfo
#include "battle/BattleInfo.h" // for BattleInfo
#include "GameSettings.h"
#include "IGameSettings.h"
#include "TerrainHandler.h"
#include "spells/CSpellHandler.h"
#include "mapping/CMap.h"
@ -274,6 +274,11 @@ bool CGameInfoCallback::getTownInfo(const CGObjectInstance * town, InfoAboutTown
return true;
}
const IGameSettings & CGameInfoCallback::getSettings() const
{
return gs->getSettings();
}
int3 CGameInfoCallback::guardingCreaturePosition (int3 pos) const //FIXME: redundant?
{
ERROR_RET_VAL_IF(!isVisible(pos), "Tile is not visible!", int3(-1,-1,-1));
@ -626,7 +631,7 @@ EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, Bu
if (!t->genBuildingRequirements(ID).test(buildTest))
return EBuildingState::PREREQUIRES;
if(t->built >= VLC->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP))
if(t->built >= getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP))
return EBuildingState::CANT_BUILD_TODAY; //building limit
//checking resources

View File

@ -18,6 +18,7 @@ VCMI_LIB_NAMESPACE_BEGIN
class Player;
class Team;
class IGameSettings;
struct InfoWindow;
struct PlayerSettings;
@ -148,6 +149,7 @@ public:
bool isAllowed(SpellID id) const override;
bool isAllowed(ArtifactID id) const override;
bool isAllowed(SecondarySkill id) const override;
const IGameSettings & getSettings() const;
//player
std::optional<PlayerColor> getPlayerID() const override;

View File

@ -15,7 +15,7 @@
#include "constants/StringConstants.h"
#include "battle/BattleHex.h"
#include "CCreatureHandler.h"
#include "GameSettings.h"
#include "IGameSettings.h"
#include "CSkillHandler.h"
#include "BattleFieldHandler.h"
#include "bonuses/Limiters.h"
@ -240,7 +240,7 @@ void CHeroClassHandler::fillPrimarySkillData(const JsonNode & node, CHeroClass *
{
const auto & skillName = NPrimarySkill::names[pSkill.getNum()];
auto currentPrimarySkillValue = static_cast<int>(node["primarySkills"][skillName].Integer());
int primarySkillLegalMinimum = VLC->settings()->getVector(EGameSettings::HEROES_MINIMAL_PRIMARY_SKILLS)[pSkill.getNum()];
int primarySkillLegalMinimum = VLC->engineSettings()->getVector(EGameSettings::HEROES_MINIMAL_PRIMARY_SKILLS)[pSkill.getNum()];
if(currentPrimarySkillValue < primarySkillLegalMinimum)
{
@ -350,7 +350,7 @@ std::shared_ptr<CHeroClass> CHeroClassHandler::loadFromJson(const std::string &
std::vector<JsonNode> CHeroClassHandler::loadLegacyData()
{
size_t dataSize = VLC->settings()->getInteger(EGameSettings::TEXTS_HERO_CLASS);
size_t dataSize = VLC->engineSettings()->getInteger(EGameSettings::TEXTS_HERO_CLASS);
objects.resize(dataSize);
std::vector<JsonNode> h3Data;
@ -717,7 +717,7 @@ static std::string genRefName(std::string input)
std::vector<JsonNode> CHeroHandler::loadLegacyData()
{
size_t dataSize = VLC->settings()->getInteger(EGameSettings::TEXTS_HERO);
size_t dataSize = VLC->engineSettings()->getInteger(EGameSettings::TEXTS_HERO);
objects.resize(dataSize);
std::vector<JsonNode> h3Data;

View File

@ -694,6 +694,7 @@ set(lib_MAIN_HEADERS
IBonusTypeHandler.h
IGameCallback.h
IGameEventsReceiver.h
IGameSettings.h
IHandlerBase.h
int3.h
LoadProgress.h

View File

@ -33,23 +33,10 @@ std::vector<int> IGameSettings::getVector(EGameSettings option) const
return getValue(option).convertTo<std::vector<int>>();
}
GameSettings::GameSettings() = default;
GameSettings::~GameSettings() = default;
GameSettings::GameSettings()
: gameSettings(static_cast<size_t>(EGameSettings::OPTIONS_COUNT))
{
}
void GameSettings::load(const JsonNode & input)
{
struct SettingOption
{
EGameSettings setting;
std::string group;
std::string key;
};
static const std::vector<SettingOption> optionPath = {
const std::vector<GameSettings::SettingOption> GameSettings::settingProperties = {
{EGameSettings::BONUSES_GLOBAL, "bonuses", "global" },
{EGameSettings::BONUSES_PER_HERO, "bonuses", "perHero" },
{EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR, "combat", "attackPointDamageFactor" },
@ -114,7 +101,9 @@ void GameSettings::load(const JsonNode & input)
{EGameSettings::TOWNS_STARTING_DWELLING_CHANCES, "towns", "startingDwellingChances" },
};
for(const auto & option : optionPath)
void GameSettings::loadBase(const JsonNode & input)
{
for(const auto & option : settingProperties)
{
const JsonNode & optionValue = input[option.group][option.key];
size_t index = static_cast<size_t>(option.setting);
@ -122,16 +111,59 @@ void GameSettings::load(const JsonNode & input)
if(optionValue.isNull())
continue;
JsonUtils::mergeCopy(gameSettings[index], optionValue);
JsonUtils::mergeCopy(baseSettings[index], optionValue);
}
actualSettings = baseSettings;
}
void GameSettings::loadOverrides(const JsonNode & input)
{
for(const auto & option : settingProperties)
{
const JsonNode & optionValue = input[option.group][option.key];
if (!optionValue.isNull())
addOverride(option.setting, optionValue);
}
}
void GameSettings::addOverride(EGameSettings option, const JsonNode & input)
{
size_t index = static_cast<size_t>(option);
overridenSettings[index] = input;
JsonNode newValue = baseSettings[index];
JsonUtils::mergeCopy(newValue, input);
actualSettings[index] = newValue;
}
const JsonNode & GameSettings::getValue(EGameSettings option) const
{
auto index = static_cast<size_t>(option);
assert(!gameSettings.at(index).isNull());
return gameSettings.at(index);
assert(!actualSettings.at(index).isNull());
return actualSettings.at(index);
}
JsonNode GameSettings::getFullConfig() const
{
JsonNode result;
for(const auto & option : settingProperties)
result[option.group][option.key] = getValue(option.setting);
return result;
}
JsonNode GameSettings::getAllOverrides() const
{
JsonNode result;
for(const auto & option : settingProperties)
{
const JsonNode & value = overridenSettings[static_cast<int32_t>(option.setting)];
if (!value.isNull())
result[option.group][option.key] = value;
}
return result;
}
VCMI_LIB_NAMESPACE_END

View File

@ -9,105 +9,65 @@
*/
#pragma once
#include "IGameSettings.h"
#include "json/JsonNode.h"
VCMI_LIB_NAMESPACE_BEGIN
class JsonNode;
enum class EGameSettings
{
BONUSES_GLOBAL,
BONUSES_PER_HERO,
COMBAT_ATTACK_POINT_DAMAGE_FACTOR,
COMBAT_ATTACK_POINT_DAMAGE_FACTOR_CAP,
COMBAT_BAD_LUCK_DICE,
COMBAT_BAD_MORALE_DICE,
COMBAT_DEFENSE_POINT_DAMAGE_FACTOR,
COMBAT_DEFENSE_POINT_DAMAGE_FACTOR_CAP,
COMBAT_GOOD_LUCK_DICE,
COMBAT_GOOD_MORALE_DICE,
CREATURES_ALLOW_ALL_FOR_DOUBLE_MONTH,
CREATURES_ALLOW_RANDOM_SPECIAL_WEEKS,
CREATURES_DAILY_STACK_EXPERIENCE,
CREATURES_WEEKLY_GROWTH_CAP,
CREATURES_WEEKLY_GROWTH_PERCENT,
DWELLINGS_ACCUMULATE_WHEN_NEUTRAL,
DWELLINGS_ACCUMULATE_WHEN_OWNED,
DWELLINGS_MERGE_ON_RECRUIT,
HEROES_PER_PLAYER_ON_MAP_CAP,
HEROES_PER_PLAYER_TOTAL_CAP,
HEROES_RETREAT_ON_WIN_WITHOUT_TROOPS,
HEROES_STARTING_STACKS_CHANCES,
HEROES_BACKPACK_CAP,
HEROES_TAVERN_INVITE,
HEROES_MINIMAL_PRIMARY_SKILLS,
MARKETS_BLACK_MARKET_RESTOCK_PERIOD,
BANKS_SHOW_GUARDS_COMPOSITION,
MODULE_COMMANDERS,
MODULE_STACK_ARTIFACT,
MODULE_STACK_EXPERIENCE,
TEXTS_ARTIFACT,
TEXTS_CREATURE,
TEXTS_FACTION,
TEXTS_HERO,
TEXTS_HERO_CLASS,
TEXTS_OBJECT,
TEXTS_RIVER,
TEXTS_ROAD,
TEXTS_SPELL,
TEXTS_TERRAIN,
MAP_FORMAT_RESTORATION_OF_ERATHIA,
MAP_FORMAT_ARMAGEDDONS_BLADE,
MAP_FORMAT_SHADOW_OF_DEATH,
MAP_FORMAT_CHRONICLES,
MAP_FORMAT_HORN_OF_THE_ABYSS,
MAP_FORMAT_JSON_VCMI,
MAP_FORMAT_IN_THE_WAKE_OF_GODS,
PATHFINDER_USE_BOAT,
PATHFINDER_IGNORE_GUARDS,
PATHFINDER_USE_MONOLITH_TWO_WAY,
PATHFINDER_USE_MONOLITH_ONE_WAY_UNIQUE,
PATHFINDER_USE_MONOLITH_ONE_WAY_RANDOM,
PATHFINDER_USE_WHIRLPOOL,
PATHFINDER_ORIGINAL_FLY_RULES,
TOWNS_BUILDINGS_PER_TURN_CAP,
TOWNS_STARTING_DWELLING_CHANCES,
COMBAT_ONE_HEX_TRIGGERS_OBSTACLES,
DIMENSION_DOOR_ONLY_TO_UNCOVERED_TILES,
DIMENSION_DOOR_EXPOSES_TERRAIN_TYPE,
DIMENSION_DOOR_FAILURE_SPENDS_POINTS,
DIMENSION_DOOR_TRIGGERS_GUARDS,
DIMENSION_DOOR_TOURNAMENT_RULES_LIMIT,
OPTIONS_COUNT
};
class DLL_LINKAGE IGameSettings
{
public:
virtual const JsonNode & getValue(EGameSettings option) const = 0;
virtual ~IGameSettings() = default;
bool getBoolean(EGameSettings option) const;
int64_t getInteger(EGameSettings option) const;
double getDouble(EGameSettings option) const;
std::vector<int> getVector(EGameSettings option) const;
};
class DLL_LINKAGE GameSettings final : public IGameSettings, boost::noncopyable
{
std::vector<JsonNode> gameSettings;
struct SettingOption
{
EGameSettings setting;
std::string group;
std::string key;
};
static constexpr int32_t OPTIONS_COUNT = static_cast<int32_t>(EGameSettings::OPTIONS_COUNT);
static const std::vector<SettingOption> settingProperties;
// contains base settings, like those defined in base game or mods
std::array<JsonNode, OPTIONS_COUNT> baseSettings;
// contains settings that were overriden, in map or in random map template
std::array<JsonNode, OPTIONS_COUNT> overridenSettings;
// for convenience / performance, contains actual settings - combined version of base and override settings
std::array<JsonNode, OPTIONS_COUNT> actualSettings;
// converts all existing overrides into a single json node for serialization
JsonNode getAllOverrides() const;
public:
GameSettings();
~GameSettings();
void load(const JsonNode & input);
/// Loads settings as 'base settings' that can be overriden
/// For settings defined in vcmi or in mods
void loadBase(const JsonNode & input);
/// Loads setting as an override, for use in maps or rmg templates
/// undefined behavior if setting was already overriden (TODO: decide which approach is better - replace or append)
void addOverride(EGameSettings option, const JsonNode & input);
// loads all overrides from provided json node, for deserialization
void loadOverrides(const JsonNode &);
JsonNode getFullConfig() const override;
const JsonNode & getValue(EGameSettings option) const override;
template<typename Handler>
void serialize(Handler & h)
{
h & gameSettings;
if (h.saving)
{
JsonNode overrides = getAllOverrides();
h & overrides;
}
else
{
JsonNode overrides;
h & overrides;
loadOverrides(overrides);
}
}
};

98
lib/IGameSettings.h Normal file
View File

@ -0,0 +1,98 @@
/*
* IIGameSettings.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
VCMI_LIB_NAMESPACE_BEGIN
class JsonNode;
enum class EGameSettings
{
BONUSES_GLOBAL,
BONUSES_PER_HERO,
COMBAT_ATTACK_POINT_DAMAGE_FACTOR,
COMBAT_ATTACK_POINT_DAMAGE_FACTOR_CAP,
COMBAT_BAD_LUCK_DICE,
COMBAT_BAD_MORALE_DICE,
COMBAT_DEFENSE_POINT_DAMAGE_FACTOR,
COMBAT_DEFENSE_POINT_DAMAGE_FACTOR_CAP,
COMBAT_GOOD_LUCK_DICE,
COMBAT_GOOD_MORALE_DICE,
CREATURES_ALLOW_ALL_FOR_DOUBLE_MONTH,
CREATURES_ALLOW_RANDOM_SPECIAL_WEEKS,
CREATURES_DAILY_STACK_EXPERIENCE,
CREATURES_WEEKLY_GROWTH_CAP,
CREATURES_WEEKLY_GROWTH_PERCENT,
DWELLINGS_ACCUMULATE_WHEN_NEUTRAL,
DWELLINGS_ACCUMULATE_WHEN_OWNED,
DWELLINGS_MERGE_ON_RECRUIT,
HEROES_PER_PLAYER_ON_MAP_CAP,
HEROES_PER_PLAYER_TOTAL_CAP,
HEROES_RETREAT_ON_WIN_WITHOUT_TROOPS,
HEROES_STARTING_STACKS_CHANCES,
HEROES_BACKPACK_CAP,
HEROES_TAVERN_INVITE,
HEROES_MINIMAL_PRIMARY_SKILLS,
MARKETS_BLACK_MARKET_RESTOCK_PERIOD,
BANKS_SHOW_GUARDS_COMPOSITION,
MODULE_COMMANDERS,
MODULE_STACK_ARTIFACT,
MODULE_STACK_EXPERIENCE,
TEXTS_ARTIFACT,
TEXTS_CREATURE,
TEXTS_FACTION,
TEXTS_HERO,
TEXTS_HERO_CLASS,
TEXTS_OBJECT,
TEXTS_RIVER,
TEXTS_ROAD,
TEXTS_SPELL,
TEXTS_TERRAIN,
MAP_FORMAT_RESTORATION_OF_ERATHIA,
MAP_FORMAT_ARMAGEDDONS_BLADE,
MAP_FORMAT_SHADOW_OF_DEATH,
MAP_FORMAT_CHRONICLES,
MAP_FORMAT_HORN_OF_THE_ABYSS,
MAP_FORMAT_JSON_VCMI,
MAP_FORMAT_IN_THE_WAKE_OF_GODS,
PATHFINDER_USE_BOAT,
PATHFINDER_IGNORE_GUARDS,
PATHFINDER_USE_MONOLITH_TWO_WAY,
PATHFINDER_USE_MONOLITH_ONE_WAY_UNIQUE,
PATHFINDER_USE_MONOLITH_ONE_WAY_RANDOM,
PATHFINDER_USE_WHIRLPOOL,
PATHFINDER_ORIGINAL_FLY_RULES,
TOWNS_BUILDINGS_PER_TURN_CAP,
TOWNS_STARTING_DWELLING_CHANCES,
COMBAT_ONE_HEX_TRIGGERS_OBSTACLES,
DIMENSION_DOOR_ONLY_TO_UNCOVERED_TILES,
DIMENSION_DOOR_EXPOSES_TERRAIN_TYPE,
DIMENSION_DOOR_FAILURE_SPENDS_POINTS,
DIMENSION_DOOR_TRIGGERS_GUARDS,
DIMENSION_DOOR_TOURNAMENT_RULES_LIMIT,
OPTIONS_COUNT,
OPTIONS_BEGIN = BONUSES_GLOBAL
};
class DLL_LINKAGE IGameSettings
{
public:
virtual JsonNode getFullConfig() const = 0;
virtual const JsonNode & getValue(EGameSettings option) const = 0;
virtual ~IGameSettings() = default;
bool getBoolean(EGameSettings option) const;
int64_t getInteger(EGameSettings option) const;
double getDouble(EGameSettings option) const;
std::vector<int> getVector(EGameSettings option) const;
};
VCMI_LIB_NAMESPACE_END

View File

@ -11,7 +11,7 @@
#include "StdInc.h"
#include "RiverHandler.h"
#include "texts/CGeneralTextHandler.h"
#include "GameSettings.h"
#include "IGameSettings.h"
#include "json/JsonNode.h"
#include "VCMI_Lib.h"
@ -63,7 +63,7 @@ const std::vector<std::string> & RiverTypeHandler::getTypeNames() const
std::vector<JsonNode> RiverTypeHandler::loadLegacyData()
{
size_t dataSize = VLC->settings()->getInteger(EGameSettings::TEXTS_RIVER);
size_t dataSize = VLC->engineSettings()->getInteger(EGameSettings::TEXTS_RIVER);
objects.resize(dataSize);
return {};

View File

@ -11,7 +11,7 @@
#include "StdInc.h"
#include "RoadHandler.h"
#include "texts/CGeneralTextHandler.h"
#include "GameSettings.h"
#include "IGameSettings.h"
#include "json/JsonNode.h"
#include "VCMI_Lib.h"
@ -54,7 +54,7 @@ const std::vector<std::string> & RoadTypeHandler::getTypeNames() const
std::vector<JsonNode> RoadTypeHandler::loadLegacyData()
{
size_t dataSize = VLC->settings()->getInteger(EGameSettings::TEXTS_ROAD);
size_t dataSize = VLC->engineSettings()->getInteger(EGameSettings::TEXTS_ROAD);
objects.resize(dataSize);
return {};

View File

@ -10,7 +10,7 @@
#include "StdInc.h"
#include "TerrainHandler.h"
#include "GameSettings.h"
#include "IGameSettings.h"
#include "json/JsonNode.h"
#include "modding/IdentifierStorage.h"
#include "texts/CGeneralTextHandler.h"
@ -133,7 +133,7 @@ const std::vector<std::string> & TerrainTypeHandler::getTypeNames() const
std::vector<JsonNode> TerrainTypeHandler::loadLegacyData()
{
size_t dataSize = VLC->settings()->getInteger(EGameSettings::TEXTS_TERRAIN);
size_t dataSize = VLC->engineSettings()->getInteger(EGameSettings::TEXTS_TERRAIN);
objects.resize(dataSize);

View File

@ -135,7 +135,7 @@ const ObstacleService * LibClasses::obstacles() const
return obstacleHandler.get();
}
const IGameSettings * LibClasses::settings() const
const IGameSettings * LibClasses::engineSettings() const
{
return settingsHandler.get();
}

View File

@ -69,7 +69,7 @@ public:
const SkillService * skills() const override;
const BattleFieldService * battlefields() const override;
const ObstacleService * obstacles() const override;
const IGameSettings * settings() const override;
const IGameSettings * engineSettings() const override;
const spells::effects::Registry * spellEffects() const override;
spells::effects::Registry * spellEffects() override;

View File

@ -17,7 +17,7 @@
#include "../bonuses/Bonus.h"
#include "../mapObjects/CGTownInstance.h"
#include "../spells/CSpellHandler.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../VCMI_Lib.h"
@ -212,8 +212,9 @@ double DamageCalculator::getAttackSkillFactor() const
if(attackAdvantage > 0)
{
const double attackMultiplier = VLC->settings()->getDouble(EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR);
const double attackMultiplierCap = VLC->settings()->getDouble(EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR_CAP);
// FIXME: use cb to acquire these settings
const double attackMultiplier = VLC->engineSettings()->getDouble(EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR);
const double attackMultiplierCap = VLC->engineSettings()->getDouble(EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR_CAP);
const double attackFactor = std::min(attackMultiplier * attackAdvantage, attackMultiplierCap);
return attackFactor;
@ -312,8 +313,9 @@ double DamageCalculator::getDefenseSkillFactor() const
//bonus from attack/defense skills
if(defenseAdvantage > 0) //decreasing dmg
{
const double defenseMultiplier = VLC->settings()->getDouble(EGameSettings::COMBAT_DEFENSE_POINT_DAMAGE_FACTOR);
const double defenseMultiplierCap = VLC->settings()->getDouble(EGameSettings::COMBAT_DEFENSE_POINT_DAMAGE_FACTOR_CAP);
// FIXME: use cb to acquire these settings
const double defenseMultiplier = VLC->engineSettings()->getDouble(EGameSettings::COMBAT_DEFENSE_POINT_DAMAGE_FACTOR);
const double defenseMultiplierCap = VLC->engineSettings()->getDouble(EGameSettings::COMBAT_DEFENSE_POINT_DAMAGE_FACTOR_CAP);
const double dec = std::min(defenseMultiplier * defenseAdvantage, defenseMultiplierCap);
return dec;

View File

@ -16,7 +16,7 @@
#include "../../CCreatureHandler.h"
#include "../../CHeroHandler.h"
#include "../../GameSettings.h"
#include "../../IGameSettings.h"
#include "../../TerrainHandler.h"
#include "../../VCMI_Lib.h"
@ -76,7 +76,7 @@ const TPropagatorPtr & CTownHandler::emptyPropagator()
std::vector<JsonNode> CTownHandler::loadLegacyData()
{
size_t dataSize = VLC->settings()->getInteger(EGameSettings::TEXTS_FACTION);
size_t dataSize = VLC->engineSettings()->getInteger(EGameSettings::TEXTS_FACTION);
std::vector<JsonNode> dest(dataSize);
objects.resize(dataSize);

View File

@ -21,7 +21,7 @@
#include "../CHeroHandler.h"
#include "../CPlayerState.h"
#include "../CStopWatch.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../StartInfo.h"
#include "../TerrainHandler.h"
#include "../VCMIDirs.h"
@ -153,6 +153,11 @@ CGameState::~CGameState()
initialOpts.dellNull();
}
const IGameSettings & CGameState::getSettings() const
{
return map->getSettings();
}
void CGameState::preInit(Services * newServices, IGameCallback * newCallback)
{
services = newServices;
@ -356,7 +361,7 @@ void CGameState::generateOwnedObjectsAfterDeserialize()
void CGameState::initGlobalBonuses()
{
const JsonNode & baseBonuses = VLC->settings()->getValue(EGameSettings::BONUSES_GLOBAL);
const JsonNode & baseBonuses = getSettings().getValue(EGameSettings::BONUSES_GLOBAL);
logGlobal->debug("\tLoading global bonuses");
for(const auto & b : baseBonuses.Struct())
{
@ -807,7 +812,7 @@ void CGameState::initTowns()
if(vti->tempOwner != PlayerColor::NEUTRAL)
vti->addBuilding(BuildingID::TAVERN);
auto definesBuildingsChances = VLC->settings()->getVector(EGameSettings::TOWNS_STARTING_DWELLING_CHANCES);
auto definesBuildingsChances = getSettings().getVector(EGameSettings::TOWNS_STARTING_DWELLING_CHANCES);
for(int i = 0; i < definesBuildingsChances.size(); i++)
{

View File

@ -37,6 +37,7 @@ class CGameStateCampaign;
class TavernHeroesPool;
struct SThievesGuildInfo;
class CRandomGenerator;
class GameSettings;
struct UpgradeInfo
{
@ -53,7 +54,6 @@ DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EVictoryLossCheck
class DLL_LINKAGE CGameState : public CNonConstInfoCallback, public Serializeable
{
friend class CGameStateCampaign;
public:
/// Stores number of times each artifact was placed on map via randomization
std::map<ArtifactID, int> allocatedArtifacts;
@ -130,6 +130,7 @@ public:
bool checkForStandardLoss(const PlayerColor & player) const; //checks if given player lost the game
void obtainPlayersStats(SThievesGuildInfo & tgi, int level); //fills tgi with info about other players that is available at given level of thieves' guild
const IGameSettings & getSettings() const;
bool isVisible(int3 pos, const std::optional<PlayerColor> & player) const override;
bool isVisible(const CGObjectInstance * obj, const std::optional<PlayerColor> & player) const override;

View File

@ -16,7 +16,7 @@
#include "../VCMI_Lib.h"
#include "../GameConstants.h"
#include "../constants/StringConstants.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../CSoundBase.h"
#include "../mapObjectConstructors/CBankInstanceConstructor.h"
@ -103,7 +103,7 @@ CObjectClassesHandler::~CObjectClassesHandler() = default;
std::vector<JsonNode> CObjectClassesHandler::loadLegacyData()
{
size_t dataSize = VLC->settings()->getInteger(EGameSettings::TEXTS_OBJECT);
size_t dataSize = VLC->engineSettings()->getInteger(EGameSettings::TEXTS_OBJECT);
CLegacyConfigParser parser(TextPath::builtin("Data/Objects.txt"));
auto totalNumber = static_cast<size_t>(parser.readNumber()); // first line contains number of objects to read and nothing else

View File

@ -16,7 +16,7 @@
#include "../texts/CGeneralTextHandler.h"
#include "../CSoundBase.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../CPlayerState.h"
#include "../mapObjectConstructors/CObjectClassesHandler.h"
#include "../mapObjectConstructors/CBankInstanceConstructor.h"
@ -68,7 +68,7 @@ std::vector<Component> CBank::getPopupComponents(PlayerColor player) const
if (!wasVisited(player))
return {};
if (!VLC->settings()->getBoolean(EGameSettings::BANKS_SHOW_GUARDS_COMPOSITION))
if (!cb->getSettings().getBoolean(EGameSettings::BANKS_SHOW_GUARDS_COMPOSITION))
return {};
if (bankConfig == nullptr)

View File

@ -14,7 +14,7 @@
#include "../texts/CGeneralTextHandler.h"
#include "../CConfigHandler.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../IGameCallback.h"
#include "../gameState/CGameState.h"
#include "../mapObjectConstructors/CObjectClassesHandler.h"
@ -280,15 +280,15 @@ void CGCreature::newTurn(vstd::RNG & rand) const
{//Works only for stacks of single type of size up to 2 millions
if (!notGrowingTeam)
{
if (stacks.begin()->second->count < VLC->settings()->getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_CAP) && cb->getDate(Date::DAY_OF_WEEK) == 1 && cb->getDate(Date::DAY) > 1)
if (stacks.begin()->second->count < cb->getSettings().getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_CAP) && cb->getDate(Date::DAY_OF_WEEK) == 1 && cb->getDate(Date::DAY) > 1)
{
ui32 power = static_cast<ui32>(temppower * (100 + VLC->settings()->getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_PERCENT)) / 100);
cb->setObjPropertyValue(id, ObjProperty::MONSTER_COUNT, std::min<uint32_t>(power / 1000, VLC->settings()->getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_CAP))); //set new amount
ui32 power = static_cast<ui32>(temppower * (100 + cb->getSettings().getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_PERCENT)) / 100);
cb->setObjPropertyValue(id, ObjProperty::MONSTER_COUNT, std::min<uint32_t>(power / 1000, cb->getSettings().getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_CAP))); //set new amount
cb->setObjPropertyValue(id, ObjProperty::MONSTER_POWER, power); //increase temppower
}
}
if (VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
cb->setObjPropertyValue(id, ObjProperty::MONSTER_EXP, VLC->settings()->getInteger(EGameSettings::CREATURES_DAILY_STACK_EXPERIENCE)); //for testing purpose
if (cb->getSettings().getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
cb->setObjPropertyValue(id, ObjProperty::MONSTER_EXP, cb->getSettings().getInteger(EGameSettings::CREATURES_DAILY_STACK_EXPERIENCE)); //for testing purpose
}
void CGCreature::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{

View File

@ -24,7 +24,7 @@
#include "../IGameCallback.h"
#include "../gameState/CGameState.h"
#include "../CPlayerState.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../CConfigHandler.h"
#include <vstd/RNG.h>
@ -309,9 +309,9 @@ void CGDwelling::newTurn(vstd::RNG & rand) const
bool creaturesAccumulate = false;
if (tempOwner.isValidPlayer())
creaturesAccumulate = VLC->settings()->getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_OWNED);
creaturesAccumulate = cb->getSettings().getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_OWNED);
else
creaturesAccumulate = VLC->settings()->getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_NEUTRAL);
creaturesAccumulate = cb->getSettings().getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_NEUTRAL);
const CCreature * cre =creatures[i].second[0].toCreature();
TQuantity amount = cre->getGrowth() * (1 + cre->valOfBonuses(BonusType::CREATURE_GROWTH_PERCENT)/100) + cre->valOfBonuses(BonusType::CREATURE_GROWTH, BonusCustomSubtype::creatureLevel(cre->getLevel()));
@ -418,7 +418,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
if(count) //there are available creatures
{
if (VLC->settings()->getBoolean(EGameSettings::DWELLINGS_MERGE_ON_RECRUIT))
if (cb->getSettings().getBoolean(EGameSettings::DWELLINGS_MERGE_ON_RECRUIT))
{
SlotID testSlot = h->getSlotFor(crid);
if(!testSlot.validSlot()) //no available slot - try merging army of visiting hero

View File

@ -20,7 +20,7 @@
#include "../CHeroHandler.h"
#include "../TerrainHandler.h"
#include "../RoadHandler.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../CSoundBase.h"
#include "../spells/CSpellHandler.h"
#include "../CSkillHandler.h"
@ -393,7 +393,7 @@ void CGHeroInstance::initHero(vstd::RNG & rand)
// are not attached to global bonus node but need access to some global bonuses
// e.g. MANA_PER_KNOWLEDGE_PERCENTAGE for correct preview and initial state after recruit for(const auto & ob : VLC->modh->heroBaseBonuses)
// or MOVEMENT to compute initial movement before recruiting is finished
const JsonNode & baseBonuses = VLC->settings()->getValue(EGameSettings::BONUSES_PER_HERO);
const JsonNode & baseBonuses = cb->getSettings().getValue(EGameSettings::BONUSES_PER_HERO);
for(const auto & b : baseBonuses.Struct())
{
auto bonus = JsonUtils::parseBonus(b.second);
@ -403,7 +403,7 @@ void CGHeroInstance::initHero(vstd::RNG & rand)
addNewBonus(bonus);
}
if (VLC->settings()->getBoolean(EGameSettings::MODULE_COMMANDERS) && !commander && type->heroClass->commander.hasValue())
if (cb->getSettings().getBoolean(EGameSettings::MODULE_COMMANDERS) && !commander && type->heroClass->commander.hasValue())
{
commander = new CCommanderInstance(type->heroClass->commander);
commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders
@ -430,7 +430,7 @@ void CGHeroInstance::initArmy(vstd::RNG & rand, IArmyDescriptor * dst)
int warMachinesGiven = 0;
auto stacksCountChances = VLC->settings()->getVector(EGameSettings::HEROES_STARTING_STACKS_CHANCES);
auto stacksCountChances = cb->getSettings().getVector(EGameSettings::HEROES_STARTING_STACKS_CHANCES);
int stacksCountInitRandomNumber = rand.nextInt(1, 100);
size_t maxStacksCount = std::min(stacksCountChances.size(), type->initialArmy.size());
@ -517,7 +517,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
}
else if(ID == Obj::PRISON)
{
if (cb->getHeroCount(h->tempOwner, false) < VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))//free hero slot
if (cb->getHeroCount(h->tempOwner, false) < cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))//free hero slot
{
//update hero parameters
SetMovePoints smp;

View File

@ -15,7 +15,7 @@
#include "../IGameCallback.h"
#include "../CCreatureHandler.h"
#include "CGTownInstance.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../CSkillHandler.h"
#include "../mapObjectConstructors/AObjectTypeHandler.h"
#include "../mapObjectConstructors/CObjectClassesHandler.h"
@ -82,7 +82,7 @@ std::vector<TradeItemBuy> CGBlackMarket::availableItemsIds(EMarketMode mode) con
void CGBlackMarket::newTurn(vstd::RNG & rand) const
{
int resetPeriod = VLC->settings()->getInteger(EGameSettings::MARKETS_BLACK_MARKET_RESTOCK_PERIOD);
int resetPeriod = cb->getSettings().getInteger(EGameSettings::MARKETS_BLACK_MARKET_RESTOCK_PERIOD);
bool isFirstDay = cb->getDate(Date::DAY) == 1;
bool regularResetTriggered = resetPeriod != 0 && ((cb->getDate(Date::DAY)-1) % resetPeriod) == 0;

View File

@ -14,6 +14,7 @@
#include "../VCMI_Lib.h"
#include "../CCreatureHandler.h"
#include "../CHeroHandler.h"
#include "../GameSettings.h"
#include "../RiverHandler.h"
#include "../RoadHandler.h"
#include "../TerrainHandler.h"
@ -208,6 +209,9 @@ CMap::CMap(IGameCallback * cb)
allowedAbilities = VLC->skillh->getDefaultAllowed();
allowedArtifact = VLC->arth->getDefaultAllowed();
allowedSpells = VLC->spellh->getDefaultAllowed();
gameSettings = std::make_unique<GameSettings>();
gameSettings->loadBase(VLC->settingsHandler->getFullConfig());
}
CMap::~CMap()
@ -781,4 +785,19 @@ void CMap::reindexObjects()
}
}
const IGameSettings & CMap::getSettings() const
{
return *gameSettings;
}
void CMap::overrideGameSetting(EGameSettings option, const JsonNode & input)
{
return gameSettings->addOverride(option, input);
}
void CMap::overrideGameSettings(const JsonNode & input)
{
return gameSettings->loadOverrides(input);
}
VCMI_LIB_NAMESPACE_END

View File

@ -32,7 +32,10 @@ class IQuestObject;
class CInputStream;
class CMapEditManager;
class JsonSerializeFormat;
class IGameSettings;
class GameSettings;
struct TeleportChannel;
enum class EGameSettings;
/// The rumor struct consists of a rumor name and text.
struct DLL_LINKAGE Rumor
@ -76,6 +79,7 @@ struct DLL_LINKAGE DisposedHero
/// The map contains the map header, the tiles of the terrain, objects, heroes, towns, rumors...
class DLL_LINKAGE CMap : public CMapHeader, public GameCallbackHolder
{
std::unique_ptr<GameSettings> gameSettings;
public:
explicit CMap(IGameCallback *cb);
~CMap();
@ -176,6 +180,10 @@ public:
std::vector<const CArtifact *> townMerchantArtifacts;
std::vector<TradeItemBuy> townUniversitySkills;
void overrideGameSettings(const JsonNode & input);
void overrideGameSetting(EGameSettings option, const JsonNode & input);
const IGameSettings & getSettings() const;
private:
/// a 3-dimensional array of terrain tiles, access is as follows: x, y, level. where level=1 is underground
boost::multi_array<TerrainTile, 3> terrain;
@ -215,6 +223,9 @@ public:
h & townUniversitySkills;
h & instanceNames;
if (h.version >= Handler::Version::PER_MAP_GAME_SETTINGS)
h & *gameSettings;
}
};

View File

@ -24,7 +24,7 @@
#include "../texts/CGeneralTextHandler.h"
#include "../texts/TextOperations.h"
#include "../CCreatureHandler.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../CHeroHandler.h"
#include "../CConfigHandler.h"
@ -167,19 +167,19 @@ int CMapInfo::getMapSizeFormatIconId() const
switch(mapHeader->version)
{
case EMapFormat::ROE:
return VLC->settings()->getValue(EGameSettings::MAP_FORMAT_RESTORATION_OF_ERATHIA)["iconIndex"].Integer();
return VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_RESTORATION_OF_ERATHIA)["iconIndex"].Integer();
case EMapFormat::AB:
return VLC->settings()->getValue(EGameSettings::MAP_FORMAT_ARMAGEDDONS_BLADE)["iconIndex"].Integer();
return VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_ARMAGEDDONS_BLADE)["iconIndex"].Integer();
case EMapFormat::SOD:
return VLC->settings()->getValue(EGameSettings::MAP_FORMAT_SHADOW_OF_DEATH)["iconIndex"].Integer();
return VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_SHADOW_OF_DEATH)["iconIndex"].Integer();
case EMapFormat::CHR:
return VLC->settings()->getValue(EGameSettings::MAP_FORMAT_CHRONICLES)["iconIndex"].Integer();
return VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_CHRONICLES)["iconIndex"].Integer();
case EMapFormat::WOG:
return VLC->settings()->getValue(EGameSettings::MAP_FORMAT_IN_THE_WAKE_OF_GODS)["iconIndex"].Integer();
return VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_IN_THE_WAKE_OF_GODS)["iconIndex"].Integer();
case EMapFormat::HOTA:
return VLC->settings()->getValue(EGameSettings::MAP_FORMAT_HORN_OF_THE_ABYSS)["iconIndex"].Integer();
return VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_HORN_OF_THE_ABYSS)["iconIndex"].Integer();
case EMapFormat::VCMI:
return VLC->settings()->getValue(EGameSettings::MAP_FORMAT_JSON_VCMI)["iconIndex"].Integer();
return VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_JSON_VCMI)["iconIndex"].Integer();
}
return 0;
}

View File

@ -21,7 +21,7 @@
#include "../CHeroHandler.h"
#include "../CSkillHandler.h"
#include "../CStopWatch.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../RiverHandler.h"
#include "../RoadHandler.h"
#include "../TerrainHandler.h"
@ -130,17 +130,17 @@ static MapIdentifiersH3M generateMapping(EMapFormat format)
MapIdentifiersH3M identifierMapper;
if(features.levelROE)
identifierMapper.loadMapping(VLC->settings()->getValue(EGameSettings::MAP_FORMAT_RESTORATION_OF_ERATHIA));
identifierMapper.loadMapping(VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_RESTORATION_OF_ERATHIA));
if(features.levelAB)
identifierMapper.loadMapping(VLC->settings()->getValue(EGameSettings::MAP_FORMAT_ARMAGEDDONS_BLADE));
identifierMapper.loadMapping(VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_ARMAGEDDONS_BLADE));
if(features.levelSOD)
identifierMapper.loadMapping(VLC->settings()->getValue(EGameSettings::MAP_FORMAT_SHADOW_OF_DEATH));
identifierMapper.loadMapping(VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_SHADOW_OF_DEATH));
if(features.levelCHR)
identifierMapper.loadMapping(VLC->settings()->getValue(EGameSettings::MAP_FORMAT_CHRONICLES));
identifierMapper.loadMapping(VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_CHRONICLES));
if(features.levelWOG)
identifierMapper.loadMapping(VLC->settings()->getValue(EGameSettings::MAP_FORMAT_IN_THE_WAKE_OF_GODS));
identifierMapper.loadMapping(VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_IN_THE_WAKE_OF_GODS));
if(features.levelHOTA0)
identifierMapper.loadMapping(VLC->settings()->getValue(EGameSettings::MAP_FORMAT_HORN_OF_THE_ABYSS));
identifierMapper.loadMapping(VLC->engineSettings()->getValue(EGameSettings::MAP_FORMAT_HORN_OF_THE_ABYSS));
return identifierMapper;
}
@ -737,8 +737,7 @@ void CMapLoaderH3M::readMapOptions()
{
//TODO: HotA
bool allowSpecialMonths = reader->readBool();
if(!allowSpecialMonths)
logGlobal->warn("Map '%s': Option 'allow special months' is not implemented!", mapName);
map->overrideGameSetting(EGameSettings::CREATURES_ALLOW_RANDOM_SPECIAL_WEEKS, JsonNode(allowSpecialMonths));
reader->skipZero(3);
}

View File

@ -384,13 +384,13 @@ std::set<TModID> CModHandler::getModDependencies(const TModID & modId, bool & is
void CModHandler::initializeConfig()
{
VLC->settingsHandler->load(coreMod->config["settings"]);
VLC->settingsHandler->loadBase(coreMod->config["settings"]);
for(const TModID & modName : activeMods)
{
const auto & mod = allMods[modName];
if (!mod.config["settings"].isNull())
VLC->settingsHandler->load(mod.config["settings"]);
VLC->settingsHandler->loadBase(mod.config["settings"]);
}
}

View File

@ -22,7 +22,7 @@
#include "../CHeroHandler.h"
#include "../CSkillHandler.h"
#include "../CStopWatch.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../IHandlerBase.h"
#include "../ObstacleHandler.h"
#include "../mapObjects/ObstacleSetHandler.h"

View File

@ -44,7 +44,7 @@
#include "mapObjectConstructors/AObjectTypeHandler.h"
#include "mapObjectConstructors/CObjectClassesHandler.h"
#include "campaign/CampaignState.h"
#include "GameSettings.h"
#include "IGameSettings.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -1580,7 +1580,7 @@ void RebalanceStacks::applyGs(CGameState *gs)
const CCreature * srcType = src.army->getCreature(src.slot);
TQuantity srcCount = src.army->getStackCount(src.slot);
bool stackExp = VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE);
bool stackExp = gs->getSettings().getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE);
if(srcCount == count) //moving whole stack
{
@ -2109,7 +2109,7 @@ void BattleResultAccepted::applyGs(CGameState *gs)
}
}
if(VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
if(gs->getSettings().getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
{
if(heroResult[BattleSide::ATTACKER].army)
heroResult[BattleSide::ATTACKER].army->giveStackExp(heroResult[BattleSide::ATTACKER].exp);

View File

@ -10,7 +10,8 @@
#include "StdInc.h"
#include "PathfinderOptions.h"
#include "../GameSettings.h"
#include "../gameState/CGameState.h"
#include "../IGameSettings.h"
#include "../VCMI_Lib.h"
#include "NodeStorage.h"
#include "PathfindingRules.h"
@ -18,16 +19,16 @@
VCMI_LIB_NAMESPACE_BEGIN
PathfinderOptions::PathfinderOptions()
PathfinderOptions::PathfinderOptions(const CGameInfoCallback * cb)
: useFlying(true)
, useWaterWalking(true)
, ignoreGuards(VLC->settings()->getBoolean(EGameSettings::PATHFINDER_IGNORE_GUARDS))
, useEmbarkAndDisembark(VLC->settings()->getBoolean(EGameSettings::PATHFINDER_USE_BOAT))
, useTeleportTwoWay(VLC->settings()->getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_TWO_WAY))
, useTeleportOneWay(VLC->settings()->getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_UNIQUE))
, useTeleportOneWayRandom(VLC->settings()->getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_RANDOM))
, useTeleportWhirlpool(VLC->settings()->getBoolean(EGameSettings::PATHFINDER_USE_WHIRLPOOL))
, originalFlyRules(VLC->settings()->getBoolean(EGameSettings::PATHFINDER_ORIGINAL_FLY_RULES))
, ignoreGuards(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_IGNORE_GUARDS))
, useEmbarkAndDisembark(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_USE_BOAT))
, useTeleportTwoWay(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_TWO_WAY))
, useTeleportOneWay(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_UNIQUE))
, useTeleportOneWayRandom(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_RANDOM))
, useTeleportWhirlpool(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_USE_WHIRLPOOL))
, originalFlyRules(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_ORIGINAL_FLY_RULES))
, useCastleGate(false)
, lightweightFlyingMode(false)
, oneTurnSpecialLayersLimit(true)
@ -38,9 +39,10 @@ PathfinderOptions::PathfinderOptions()
{
}
PathfinderConfig::PathfinderConfig(std::shared_ptr<INodeStorage> nodeStorage, std::vector<std::shared_ptr<IPathfindingRule>> rules):
PathfinderConfig::PathfinderConfig(std::shared_ptr<INodeStorage> nodeStorage, const CGameInfoCallback * callback, std::vector<std::shared_ptr<IPathfindingRule>> rules):
nodeStorage(std::move(nodeStorage)),
rules(std::move(rules))
rules(std::move(rules)),
options(callback)
{
}
@ -58,7 +60,7 @@ std::vector<std::shared_ptr<IPathfindingRule>> SingleHeroPathfinderConfig::build
SingleHeroPathfinderConfig::~SingleHeroPathfinderConfig() = default;
SingleHeroPathfinderConfig::SingleHeroPathfinderConfig(CPathsInfo & out, CGameState * gs, const CGHeroInstance * hero)
: PathfinderConfig(std::make_shared<NodeStorage>(out, hero), buildRuleSet())
: PathfinderConfig(std::make_shared<NodeStorage>(out, hero), gs, buildRuleSet())
{
pathfinderHelper = std::make_unique<CPathfinderHelper>(gs, hero, options);
}

View File

@ -16,7 +16,7 @@ class IPathfindingRule;
class CPathfinderHelper;
class CGameState;
class CGHeroInstance;
class CGameInfoCallback;
struct PathNodeInfo;
struct CPathsInfo;
@ -85,7 +85,7 @@ struct DLL_LINKAGE PathfinderOptions
/// </summary>
bool allowLayerTransitioningAfterBattle;
PathfinderOptions();
PathfinderOptions(const CGameInfoCallback * callback);
};
class DLL_LINKAGE PathfinderConfig
@ -97,6 +97,7 @@ public:
PathfinderConfig(
std::shared_ptr<INodeStorage> nodeStorage,
const CGameInfoCallback * callback,
std::vector<std::shared_ptr<IPathfindingRule>> rules);
virtual ~PathfinderConfig() = default;

View File

@ -455,6 +455,7 @@ void CMapGenerator::addHeaderInfo()
addPlayerInfo();
m.waterMap = (mapGenOptions.getWaterContent() != EWaterContent::EWaterContent::NONE);
m.banWaterContent();
m.overrideGameSettings(mapGenOptions.getMapTemplate()->getMapSettings());
}
int CMapGenerator::getNextMonlithIndex()

View File

@ -501,9 +501,12 @@ void ZoneConnection::serializeJson(JsonSerializeFormat & handler)
using namespace rmg;//todo: remove
CRmgTemplate::~CRmgTemplate() = default;
CRmgTemplate::CRmgTemplate()
: minSize(72, 72, 2),
maxSize(72, 72, 2)
maxSize(72, 72, 2),
mapSettings(std::make_unique<JsonNode>())
{
}
@ -694,6 +697,8 @@ void CRmgTemplate::serializeJson(JsonSerializeFormat & handler)
serializePlayers(handler, players, "players");
serializePlayers(handler, humanPlayers, "humans"); // TODO: Rename this parameter
*mapSettings = handler.getCurrent()["settings"];
{
auto connectionsData = handler.enterArray("connections");
connectionsData.serializeStruct(connectedZoneIds);
@ -749,6 +754,11 @@ void CRmgTemplate::serializeJson(JsonSerializeFormat & handler)
}
}
const JsonNode & CRmgTemplate::getMapSettings() const
{
return *mapSettings;
}
std::set<TerrainId> CRmgTemplate::inheritTerrainType(std::shared_ptr<ZoneOptions> zone, uint32_t iteration /* = 0 */)
{
if (iteration >= 50)

View File

@ -216,7 +216,7 @@ protected:
}
/// The CRmgTemplate describes a random map template.
class DLL_LINKAGE CRmgTemplate
class DLL_LINKAGE CRmgTemplate : boost::noncopyable
{
public:
using Zones = std::map<TRmgTemplateZoneId, std::shared_ptr<rmg::ZoneOptions>>;
@ -240,6 +240,7 @@ public:
};
CRmgTemplate();
~CRmgTemplate();
bool matchesSize(const int3 & value) const;
bool isWaterContentAllowed(EWaterContent::EWaterContent waterContent) const;
@ -255,6 +256,7 @@ public:
const CPlayerCountRange & getHumanPlayers() const;
std::pair<int3, int3> getMapSizes() const;
const Zones & getZones() const;
const JsonNode & getMapSettings() const;
const std::vector<rmg::ZoneConnection> & getConnectedZoneIds() const;
void validate() const; /// Tests template on validity and throws exception on failure
@ -273,6 +275,7 @@ private:
Zones zones;
std::vector<rmg::ZoneConnection> connectedZoneIds;
std::set<EWaterContent::EWaterContent> allowedWaterContent;
std::unique_ptr<JsonNode> mapSettings;
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);

View File

@ -57,6 +57,7 @@ enum class ESerializationVersion : int32_t
PLAYER_STATE_OWNED_OBJECTS, // 858 - player state stores all owned objects in a single list
SAVE_COMPATIBILITY_FIXES, // 859 - implementation of previoulsy postponed changes to serialization
CHRONICLES_SUPPORT, // 860 - support for heroes chronicles
PER_MAP_GAME_SETTINGS, // 861 - game settings are now stored per-map
CURRENT = CHRONICLES_SUPPORT
CURRENT = PER_MAP_GAME_SETTINGS
};

View File

@ -12,9 +12,6 @@
#include "../CHeroHandler.h"
#include "../CPlayerState.h"
#include "../CStack.h"
#include "../RiverHandler.h"
#include "../RoadHandler.h"
#include "../TerrainHandler.h"
#include "../battle/BattleInfo.h"
#include "../battle/CObstacleInstance.h"
#include "../bonuses/Limiters.h"
@ -31,17 +28,14 @@
#include "../mapObjects/CGTownInstance.h"
#include "../mapObjects/CQuest.h"
#include "../mapObjects/MiscObjects.h"
#include "../mapObjects/ObjectTemplate.h"
#include "../mapObjects/TownBuildingInstance.h"
#include "../mapping/CMap.h"
#include "../mapping/CMapInfo.h"
#include "../networkPacks/PacksForClient.h"
#include "../networkPacks/PacksForClientBattle.h"
#include "../networkPacks/PacksForLobby.h"
#include "../networkPacks/PacksForServer.h"
#include "../networkPacks/SetRewardableConfiguration.h"
#include "../networkPacks/SetStackEffect.h"
#include "../rmg/CMapGenOptions.h"
VCMI_LIB_NAMESPACE_BEGIN

View File

@ -15,6 +15,14 @@
#include "RegisterTypes.h"
#include "../GameSettings.h"
#include "../RiverHandler.h"
#include "../RoadHandler.h"
#include "../TerrainHandler.h"
#include "../mapObjects/ObjectTemplate.h"
#include "../mapping/CMapInfo.h"
#include "../rmg/CMapGenOptions.h"
VCMI_LIB_NAMESPACE_BEGIN
template<typename Type>

View File

@ -17,7 +17,7 @@
#include "../CGameInfoCallback.h"
#include "../CPlayerState.h"
#include "../GameSettings.h"
#include "../IGameSettings.h"
#include "../mapObjects/CGHeroInstance.h"
#include "../mapObjects/CGTownInstance.h"
#include "../mapObjects/MiscObjects.h"
@ -320,7 +320,7 @@ bool DimensionDoorMechanics::canBeCastImpl(spells::Problem & problem, const CGam
int castsAlreadyPerformedThisTurn = caster->getHeroCaster()->getBonuses(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(owner->id)), Selector::all, cachingStr.str())->size();
int castsLimit = owner->getLevelPower(schoolLevel);
bool isTournamentRulesLimitEnabled = VLC->settings()->getBoolean(EGameSettings::DIMENSION_DOOR_TOURNAMENT_RULES_LIMIT);
bool isTournamentRulesLimitEnabled = cb->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_TOURNAMENT_RULES_LIMIT);
if(isTournamentRulesLimitEnabled)
{
int3 mapSize = cb->getMapSize();
@ -347,7 +347,7 @@ bool DimensionDoorMechanics::canBeCastAtImpl(spells::Problem & problem, const CG
if(!cb->isInTheMap(pos))
return false;
if(VLC->settings()->getBoolean(EGameSettings::DIMENSION_DOOR_ONLY_TO_UNCOVERED_TILES))
if(cb->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_ONLY_TO_UNCOVERED_TILES))
{
if(!cb->isVisible(pos, caster->getCasterOwner()))
return false;
@ -367,7 +367,7 @@ bool DimensionDoorMechanics::canBeCastAtImpl(spells::Problem & problem, const CG
if(!isInScreenRange(casterPosition, pos))
return false;
if(VLC->settings()->getBoolean(EGameSettings::DIMENSION_DOOR_EXPOSES_TERRAIN_TYPE))
if(cb->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_EXPOSES_TERRAIN_TYPE))
{
if(!dest->isClear(curr))
return false;
@ -396,7 +396,7 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
iw.player = parameters.caster->getCasterOwner();
// tile is either blocked or not possible to move (e.g. water <-> land)
if(VLC->settings()->getBoolean(EGameSettings::DIMENSION_DOOR_FAILURE_SPENDS_POINTS))
if(env->getCb()->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_FAILURE_SPENDS_POINTS))
{
// SOD: DD to such "wrong" terrain results in mana and move points spending, but fails to move hero
iw.text = MetaString::createFromTextID("core.genrltxt.70"); // Dimension Door failed!

View File

@ -12,7 +12,7 @@
#include "CLegacyConfigParser.h"
#include "CConfigHandler.h"
#include "GameSettings.h"
#include "IGameSettings.h"
#include "Languages.h"
#include "../filesystem/Filesystem.h"
#include "../mapObjects/CQuest.h"
@ -303,7 +303,7 @@ CGeneralTextHandler::CGeneralTextHandler():
scenariosCountPerCampaign.push_back(region);
}
}
if (VLC->settings()->getBoolean(EGameSettings::MODULE_COMMANDERS))
if (VLC->engineSettings()->getBoolean(EGameSettings::MODULE_COMMANDERS))
{
if(CResourceHandler::get()->existsResource(TextPath::builtin("DATA/ZNPC00.TXT")))
readToVector("vcmi.znpc00", "DATA/ZNPC00.TXT" );

View File

@ -36,7 +36,7 @@
#include "../lib/CThreadHelper.h"
#include "../lib/GameConstants.h"
#include "../lib/UnlockGuard.h"
#include "../lib/GameSettings.h"
#include "../lib/IGameSettings.h"
#include "../lib/ScriptHandler.h"
#include "../lib/StartInfo.h"
#include "../lib/TerrainHandler.h"
@ -823,7 +823,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
tmh.movePoints = h->movementPointsRemaining();
//check if destination tile is available
auto pathfinderHelper = std::make_unique<CPathfinderHelper>(gs, h, PathfinderOptions());
auto pathfinderHelper = std::make_unique<CPathfinderHelper>(gs, h, PathfinderOptions(this));
auto ti = pathfinderHelper->getTurnInfo();
const bool canFly = pathfinderHelper->hasBonusOfType(BonusType::FLYING_MOVEMENT) || (h->boat && h->boat->layer == EPathfindingLayer::AIR);
@ -966,7 +966,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
if (blockingVisit()) // e.g. hero on the other side of teleporter
return true;
EGuardLook guardsCheck = (VLC->settings()->getBoolean(EGameSettings::DIMENSION_DOOR_TRIGGERS_GUARDS) && movementMode == EMovementMode::DIMENSION_DOOR)
EGuardLook guardsCheck = (getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_TRIGGERS_GUARDS) && movementMode == EMovementMode::DIMENSION_DOOR)
? CHECK_FOR_GUARDS
: IGNORE_GUARDS;
@ -2427,7 +2427,7 @@ bool CGameHandler::garrisonSwap(ObjectInstanceID tid)
}
else if (town->garrisonHero && !town->visitingHero) //move hero out of the garrison
{
int mapCap = VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP);
int mapCap = getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP);
//check if moving hero out of town will break wandering heroes limit
if (getHeroCount(town->garrisonHero->tempOwner,false) >= mapCap)
{
@ -2718,7 +2718,7 @@ bool CGameHandler::switchArtifactsCostume(const PlayerColor & player, const Obje
estimateBackpackSize++;
}
const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP);
const auto backpackCap = getSettings().getInteger(EGameSettings::HEROES_BACKPACK_CAP);
if((backpackCap < 0 || estimateBackpackSize <= backpackCap) && !bma.artsPack0.empty())
sendAndApply(&bma);
}

View File

@ -16,7 +16,7 @@
#include "../../lib/texts/CGeneralTextHandler.h"
#include "../../lib/CStack.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/battle/CBattleInfoCallback.h"
#include "../../lib/battle/CObstacleInstance.h"
#include "../../lib/battle/IBattleState.h"
@ -891,7 +891,7 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
}
}
//handle last hex separately for deviation
if (VLC->settings()->getBoolean(EGameSettings::COMBAT_ONE_HEX_TRIGGERS_OBSTACLES))
if (gameHandler->getSettings().getBoolean(EGameSettings::COMBAT_ONE_HEX_TRIGGERS_OBSTACLES))
{
if (dest == battle::Unit::occupiedHex(start, curStack->doubleWide(), curStack->unitSide())
|| start == battle::Unit::occupiedHex(dest, curStack->doubleWide(), curStack->unitSide()))
@ -930,7 +930,7 @@ void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const
if(attackerLuck > 0)
{
auto diceSize = VLC->settings()->getVector(EGameSettings::COMBAT_GOOD_LUCK_DICE);
auto diceSize = gameHandler->getSettings().getVector(EGameSettings::COMBAT_GOOD_LUCK_DICE);
size_t diceIndex = std::min<size_t>(diceSize.size(), attackerLuck) - 1; // array index, so 0-indexed
if(diceSize.size() > 0 && gameHandler->getRandomGenerator().nextInt(1, diceSize[diceIndex]) == 1)
@ -939,7 +939,7 @@ void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const
if(attackerLuck < 0)
{
auto diceSize = VLC->settings()->getVector(EGameSettings::COMBAT_BAD_LUCK_DICE);
auto diceSize = gameHandler->getSettings().getVector(EGameSettings::COMBAT_BAD_LUCK_DICE);
size_t diceIndex = std::min<size_t>(diceSize.size(), -attackerLuck) - 1; // array index, so 0-indexed
if(diceSize.size() > 0 && gameHandler->getRandomGenerator().nextInt(1, diceSize[diceIndex]) == 1)

View File

@ -16,7 +16,7 @@
#include "../TurnTimerHandler.h"
#include "../../lib/CStack.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/battle/CBattleInfoCallback.h"
#include "../../lib/battle/IBattleState.h"
#include "../../lib/entities/building/TownFortifications.h"
@ -347,7 +347,7 @@ bool BattleFlowProcessor::tryMakeAutomaticAction(const CBattleInfoCallback & bat
int nextStackMorale = next->moraleVal();
if(!next->hadMorale && !next->waited() && nextStackMorale < 0)
{
auto diceSize = VLC->settings()->getVector(EGameSettings::COMBAT_BAD_MORALE_DICE);
auto diceSize = gameHandler->getSettings().getVector(EGameSettings::COMBAT_BAD_MORALE_DICE);
size_t diceIndex = std::min<size_t>(diceSize.size(), -nextStackMorale) - 1; // array index, so 0-indexed
if(diceSize.size() > 0 && gameHandler->getRandomGenerator().nextInt(1, diceSize[diceIndex]) == 1)
@ -526,7 +526,7 @@ bool BattleFlowProcessor::rollGoodMorale(const CBattleInfoCallback & battle, con
&& next->canMove()
&& nextStackMorale > 0)
{
auto diceSize = VLC->settings()->getVector(EGameSettings::COMBAT_GOOD_MORALE_DICE);
auto diceSize = gameHandler->getSettings().getVector(EGameSettings::COMBAT_GOOD_MORALE_DICE);
size_t diceIndex = std::min<size_t>(diceSize.size(), nextStackMorale) - 1; // array index, so 0-indexed
if(diceSize.size() > 0 && gameHandler->getRandomGenerator().nextInt(1, diceSize[diceIndex]) == 1)

View File

@ -19,7 +19,7 @@
#include "../../lib/ArtifactUtils.h"
#include "../../lib/CStack.h"
#include "../../lib/CPlayerState.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/battle/CBattleInfoCallback.h"
#include "../../lib/battle/IBattleState.h"
#include "../../lib/battle/SideInBattle.h"
@ -592,7 +592,7 @@ void BattleResultProcessor::battleAfterLevelUp(const BattleID & battleID, const
RemoveObject ro(finishingBattle->winnerHero->id, finishingBattle->winnerHero->getOwner());
gameHandler->sendAndApply(&ro);
if (VLC->settings()->getBoolean(EGameSettings::HEROES_RETREAT_ON_WIN_WITHOUT_TROOPS))
if (gameHandler->getSettings().getBoolean(EGameSettings::HEROES_RETREAT_ON_WIN_WITHOUT_TROOPS))
gameHandler->heroPool->onHeroEscaped(finishingBattle->victor, finishingBattle->winnerHero);
}

View File

@ -16,7 +16,7 @@
#include "../../lib/CRandomGenerator.h"
#include "../../lib/CHeroHandler.h"
#include "../../lib/CPlayerState.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/StartInfo.h"
#include "../../lib/mapObjects/CGTownInstance.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
@ -24,7 +24,7 @@
#include "../../lib/gameState/CGameState.h"
#include "../../lib/gameState/TavernHeroesPool.h"
#include "../../lib/gameState/TavernSlot.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
HeroPoolProcessor::HeroPoolProcessor(CGameHandler * gameHandler)
: gameHandler(gameHandler)
@ -158,15 +158,15 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy
if (playerState->resources[EGameResID::GOLD] < GameConstants::HERO_GOLD_COST && gameHandler->complain("Not enough gold for buying hero!"))
return false;
if (gameHandler->getHeroCount(player, false) >= VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP) && gameHandler->complain("Cannot hire hero, too many wandering heroes already!"))
if (gameHandler->getHeroCount(player, false) >= gameHandler->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP) && gameHandler->complain("Cannot hire hero, too many wandering heroes already!"))
return false;
if (gameHandler->getHeroCount(player, true) >= VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP) && gameHandler->complain("Cannot hire hero, too many heroes garrizoned and wandering already!"))
if (gameHandler->getHeroCount(player, true) >= gameHandler->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP) && gameHandler->complain("Cannot hire hero, too many heroes garrizoned and wandering already!"))
return false;
if (nextHero != HeroTypeID::NONE) // player attempts to invite next hero
{
if(!VLC->settings()->getBoolean(EGameSettings::HEROES_TAVERN_INVITE) && gameHandler->complain("Inviting heroes not allowed!"))
if(!gameHandler->getSettings().getBoolean(EGameSettings::HEROES_TAVERN_INVITE) && gameHandler->complain("Inviting heroes not allowed!"))
return false;
if(!heroesPool->unusedHeroesFromPool().count(nextHero) && gameHandler->complain("Cannot invite specified hero!"))

View File

@ -15,7 +15,7 @@
#include "../CGameHandler.h"
#include "../../lib/CPlayerState.h"
#include "../../lib/GameSettings.h"
#include "../../lib/IGameSettings.h"
#include "../../lib/StartInfo.h"
#include "../../lib/TerrainHandler.h"
#include "../../lib/entities/building/CBuilding.h"
@ -479,7 +479,7 @@ std::tuple<EWeekType, CreatureID> NewTurnProcessor::pickWeekType(bool newMonth)
return { EWeekType::DEITYOFFIRE, CreatureID::IMP };
}
if(!VLC->settings()->getBoolean(EGameSettings::CREATURES_ALLOW_RANDOM_SPECIAL_WEEKS))
if(!gameHandler->getSettings().getBoolean(EGameSettings::CREATURES_ALLOW_RANDOM_SPECIAL_WEEKS))
return { EWeekType::NORMAL, CreatureID::NONE};
int monthType = gameHandler->getRandomGenerator().nextInt(99);
@ -487,7 +487,7 @@ std::tuple<EWeekType, CreatureID> NewTurnProcessor::pickWeekType(bool newMonth)
{
if (monthType < 40) //double growth
{
if (VLC->settings()->getBoolean(EGameSettings::CREATURES_ALLOW_ALL_FOR_DOUBLE_MONTH))
if (gameHandler->getSettings().getBoolean(EGameSettings::CREATURES_ALLOW_ALL_FOR_DOUBLE_MONTH))
{
CreatureID creatureID = VLC->creh->pickRandomMonster(gameHandler->getRandomGenerator());
return { EWeekType::DOUBLE_GROWTH, creatureID};

View File

@ -28,7 +28,7 @@ public:
MOCK_CONST_METHOD0(skills, const SkillService * ());
MOCK_CONST_METHOD0(battlefields, const BattleFieldService *());
MOCK_CONST_METHOD0(obstacles, const ObstacleService *());
MOCK_CONST_METHOD0(settings, const IGameSettings *());
MOCK_CONST_METHOD0(engineSettings, const IGameSettings *());
MOCK_METHOD3(updateEntity, void(Metatype, int32_t, const JsonNode &));