| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 | /* * GameSettings.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 "GameSettings.h"#include "json/JsonUtils.h"VCMI_LIB_NAMESPACE_BEGINbool IGameSettings::getBoolean(EGameSettings option) const{	return getValue(option).Bool();}int64_t IGameSettings::getInteger(EGameSettings option) const{	return getValue(option).Integer();}double IGameSettings::getDouble(EGameSettings option) const{	return getValue(option).Float();}std::vector<int> IGameSettings::getVector(EGameSettings option) const{	return getValue(option).convertTo<std::vector<int>>();}int IGameSettings::getVectorValue(EGameSettings option, size_t index) const{	return getValue(option)[index].Integer();}GameSettings::GameSettings() = default;GameSettings::~GameSettings() = default;const std::vector<GameSettings::SettingOption> GameSettings::settingProperties = {		{EGameSettings::BANKS_SHOW_GUARDS_COMPOSITION,                    "banks",     "showGuardsComposition"                },		{EGameSettings::BONUSES_GLOBAL,                                   "bonuses",   "global"                               },		{EGameSettings::BONUSES_PER_HERO,                                 "bonuses",   "perHero"                              },		{EGameSettings::COMBAT_ABILITY_BIAS,                              "combat",    "abilityBias"                          },		{EGameSettings::COMBAT_AREA_SHOT_CAN_TARGET_EMPTY_HEX,            "combat",    "areaShotCanTargetEmptyHex"            },		{EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR,                "combat",    "attackPointDamageFactor"              },		{EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR_CAP,            "combat",    "attackPointDamageFactorCap"           },		{EGameSettings::COMBAT_DEFENSE_POINT_DAMAGE_FACTOR,               "combat",    "defensePointDamageFactor"             },		{EGameSettings::COMBAT_DEFENSE_POINT_DAMAGE_FACTOR_CAP,           "combat",    "defensePointDamageFactorCap"          },		{EGameSettings::COMBAT_GOOD_MORALE_CHANCE,                        "combat",    "goodMoraleChance"                     },		{EGameSettings::COMBAT_BAD_MORALE_CHANCE,                         "combat",    "badMoraleChance"                      },		{EGameSettings::COMBAT_MORALE_DICE_SIZE,                          "combat",    "moraleDiceSize"                       },		{EGameSettings::COMBAT_MORALE_BIAS,                               "combat",    "moraleBias"                           },		{EGameSettings::COMBAT_GOOD_LUCK_CHANCE,                          "combat",    "goodLuckChance"                       },		{EGameSettings::COMBAT_BAD_LUCK_CHANCE,                           "combat",    "badLuckChance"                        },		{EGameSettings::COMBAT_LUCK_DICE_SIZE,                            "combat",    "luckDiceSize"                         },		{EGameSettings::COMBAT_LUCK_BIAS,                                 "combat",    "luckBias"                             },		{EGameSettings::COMBAT_LAYOUTS,                                   "combat",    "layouts"                              },		{EGameSettings::COMBAT_ONE_HEX_TRIGGERS_OBSTACLES,                "combat",    "oneHexTriggersObstacles"              },		{EGameSettings::CREATURES_ALLOW_ALL_FOR_DOUBLE_MONTH,             "creatures", "allowAllForDoubleMonth"               },		{EGameSettings::CREATURES_ALLOW_JOINING_FOR_FREE,                 "creatures", "allowJoiningForFree"                  },		{EGameSettings::CREATURES_ALLOW_RANDOM_SPECIAL_WEEKS,             "creatures", "allowRandomSpecialWeeks"              },		{EGameSettings::CREATURES_DAILY_STACK_EXPERIENCE,                 "creatures", "dailyStackExperience"                 },		{EGameSettings::CREATURES_JOINING_PERCENTAGE,                     "creatures", "joiningPercentage"                    },		{EGameSettings::CREATURES_WEEKLY_GROWTH_CAP,                      "creatures", "weeklyGrowthCap"                      },		{EGameSettings::CREATURES_WEEKLY_GROWTH_PERCENT,                  "creatures", "weeklyGrowthPercent"                  },		{EGameSettings::DIMENSION_DOOR_EXPOSES_TERRAIN_TYPE,              "spells",    "dimensionDoorExposesTerrainType"      },		{EGameSettings::DIMENSION_DOOR_FAILURE_SPENDS_POINTS,             "spells",    "dimensionDoorFailureSpendsPoints"     },		{EGameSettings::DIMENSION_DOOR_ONLY_TO_UNCOVERED_TILES,           "spells",    "dimensionDoorOnlyToUncoveredTiles"    },		{EGameSettings::DIMENSION_DOOR_TOURNAMENT_RULES_LIMIT,            "spells",    "dimensionDoorTournamentRulesLimit"    },		{EGameSettings::DIMENSION_DOOR_TRIGGERS_GUARDS,                   "spells",    "dimensionDoorTriggersGuards"          },		{EGameSettings::DWELLINGS_ACCUMULATE_WHEN_NEUTRAL,                "dwellings", "accumulateWhenNeutral"                },		{EGameSettings::DWELLINGS_ACCUMULATE_WHEN_OWNED,                  "dwellings", "accumulateWhenOwned"                  },		{EGameSettings::DWELLINGS_MERGE_ON_RECRUIT,                       "dwellings", "mergeOnRecruit"                       },		{EGameSettings::HEROES_BACKPACK_CAP,                              "heroes",    "backpackSize"                         },		{EGameSettings::HEROES_MINIMAL_PRIMARY_SKILLS,                    "heroes",    "minimalPrimarySkills"                 },		{EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP,                     "heroes",    "perPlayerOnMapCap"                    },		{EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP,                      "heroes",    "perPlayerTotalCap"                    },		{EGameSettings::HEROES_RETREAT_ON_WIN_WITHOUT_TROOPS,             "heroes",    "retreatOnWinWithoutTroops"            },		{EGameSettings::HEROES_STARTING_STACKS_CHANCES,                   "heroes",    "startingStackChances"                 },		{EGameSettings::HEROES_TAVERN_INVITE,                             "heroes",    "tavernInvite"                         },		{EGameSettings::HEROES_MOVEMENT_COST_BASE,                        "heroes",    "movementCostBase"                     },		{EGameSettings::HEROES_MOVEMENT_POINTS_LAND,                      "heroes",    "movementPointsLand"                   },		{EGameSettings::HEROES_MOVEMENT_POINTS_SEA,                       "heroes",    "movementPointsSea"                    },		{EGameSettings::MAP_FORMAT_ARMAGEDDONS_BLADE,                     "mapFormat", "armageddonsBlade"                     },		{EGameSettings::MAP_FORMAT_CHRONICLES,                            "mapFormat", "chronicles"                           },		{EGameSettings::MAP_FORMAT_HORN_OF_THE_ABYSS,                     "mapFormat", "hornOfTheAbyss"                       },		{EGameSettings::MAP_FORMAT_IN_THE_WAKE_OF_GODS,                   "mapFormat", "inTheWakeOfGods"                      },		{EGameSettings::MAP_FORMAT_JSON_VCMI,                             "mapFormat", "jsonVCMI"                             },		{EGameSettings::MAP_FORMAT_RESTORATION_OF_ERATHIA,                "mapFormat", "restorationOfErathia"                 },		{EGameSettings::MAP_FORMAT_SHADOW_OF_DEATH,                       "mapFormat", "shadowOfDeath"                        },		{EGameSettings::MAP_OBJECTS_H3_BUG_QUEST_TAKES_ENTIRE_ARMY,       "mapObjects","h3BugQuestTakesEntireArmy"            },		{EGameSettings::MARKETS_BLACK_MARKET_RESTOCK_PERIOD,              "markets",   "blackMarketRestockPeriod"             },		{EGameSettings::MODULE_COMMANDERS,                                "modules",   "commanders"                           },		{EGameSettings::MODULE_STACK_ARTIFACT,                            "modules",   "stackArtifact"                        },		{EGameSettings::MODULE_STACK_EXPERIENCE,                          "modules",   "stackExperience"                      },		{EGameSettings::PATHFINDER_IGNORE_GUARDS,                         "pathfinder", "ignoreGuards"                        },		{EGameSettings::PATHFINDER_ORIGINAL_FLY_RULES,                    "pathfinder", "originalFlyRules"                    },		{EGameSettings::PATHFINDER_USE_BOAT,                              "pathfinder", "useBoat"                             },		{EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_RANDOM,           "pathfinder", "useMonolithOneWayRandom"             },		{EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_UNIQUE,           "pathfinder", "useMonolithOneWayUnique"             },		{EGameSettings::PATHFINDER_USE_MONOLITH_TWO_WAY,                  "pathfinder", "useMonolithTwoWay"                   },		{EGameSettings::PATHFINDER_USE_WHIRLPOOL,                         "pathfinder", "useWhirlpool"                        },		{EGameSettings::RESOURCES_WEEKLY_BONUSES_AI,                      "resources", "weeklyBonusesAI"                      },		{EGameSettings::TEXTS_ARTIFACT,                                   "textData",  "artifact"                             },		{EGameSettings::TEXTS_CREATURE,                                   "textData",  "creature"                             },		{EGameSettings::TEXTS_FACTION,                                    "textData",  "faction"                              },		{EGameSettings::TEXTS_HERO,                                       "textData",  "hero"                                 },		{EGameSettings::TEXTS_HERO_CLASS,                                 "textData",  "heroClass"                            },		{EGameSettings::TEXTS_OBJECT,                                     "textData",  "object"                               },		{EGameSettings::TEXTS_RIVER,                                      "textData",  "river"                                },		{EGameSettings::TEXTS_ROAD,                                       "textData",  "road"                                 },		{EGameSettings::TEXTS_SPELL,                                      "textData",  "spell"                                },		{EGameSettings::TEXTS_TERRAIN,                                    "textData",  "terrain"                              },		{EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP,                     "towns",     "buildingsPerTurnCap"                  },		{EGameSettings::TOWNS_STARTING_DWELLING_CHANCES,                  "towns",     "startingDwellingChances"              },		{EGameSettings::TOWNS_SPELL_RESEARCH,                             "towns",     "spellResearch"                        },		{EGameSettings::TOWNS_SPELL_RESEARCH_COST,                        "towns",     "spellResearchCost"                    },		{EGameSettings::TOWNS_SPELL_RESEARCH_PER_DAY,                     "towns",     "spellResearchPerDay"                  },		{EGameSettings::TOWNS_SPELL_RESEARCH_COST_EXPONENT_PER_RESEARCH,  "towns",     "spellResearchCostExponentPerResearch" },		{EGameSettings::INTERFACE_PLAYER_COLORED_BACKGROUND,              "interface", "playerColoredBackground"              },	};void GameSettings::loadBase(const JsonNode & input){	JsonUtils::validate(input, "vcmi:gameSettings", input.getModScope());	for(const auto & option : settingProperties)	{		const JsonNode & optionValue = input[option.group][option.key];		size_t index = static_cast<size_t>(option.setting);		if(optionValue.isNull())			continue;		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(!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
 |