mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Renamed & reorganized all game mechanics settings names
This commit is contained in:
@@ -1072,7 +1072,7 @@ bool AIGateway::canRecruitAnyHero(const CGTownInstance * t) const
|
||||
return false;
|
||||
if(cb->getHeroesInfo().size() >= ALLOWED_ROAMING_HEROES)
|
||||
return false;
|
||||
if(cb->getHeroesInfo().size() >= VLC->settings()->getInteger(EGameSettings::INT_MAX_HEROES_ON_MAP_PER_PLAYER))
|
||||
if(cb->getHeroesInfo().size() >= VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
|
||||
return false;
|
||||
if(!cb->getAvailableHeroes(t).size())
|
||||
return false;
|
||||
|
@@ -445,7 +445,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
|
||||
case Obj::MAGIC_WELL:
|
||||
return h->mana < h->manaLimit();
|
||||
case Obj::PRISON:
|
||||
return ai->cb->getHeroesInfo().size() < VLC->settings()->getInteger(EGameSettings::INT_MAX_HEROES_ON_MAP_PER_PLAYER);
|
||||
return ai->cb->getHeroesInfo().size() < VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP);
|
||||
case Obj::TAVERN:
|
||||
case Obj::EYE_OF_MAGI:
|
||||
case Obj::BOAT:
|
||||
|
@@ -1318,7 +1318,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::INT_MAX_HEROES_ON_MAP_PER_PLAYER))
|
||||
if(cb->getHeroesInfo().size() >= VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
|
||||
return false;
|
||||
if(!cb->getAvailableHeroes(t).size())
|
||||
return false;
|
||||
@@ -2851,12 +2851,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::INT_MAX_HEROES_ON_MAP_PER_PLAYER);
|
||||
return ai->myCb->getHeroesInfo().size() < VLC->settings()->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::INT_MAX_HEROES_ON_MAP_PER_PLAYER))
|
||||
if(ai->myCb->getHeroesInfo().size() >= VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
|
||||
return false;
|
||||
else if(ai->ah->freeGold() < GameConstants::HERO_GOLD_COST)
|
||||
return false;
|
||||
|
@@ -284,7 +284,7 @@ std::shared_ptr<CIntObject> CTownList::CTownItem::genSelection()
|
||||
|
||||
void CTownList::CTownItem::update()
|
||||
{
|
||||
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::INT_MAX_BUILDING_PER_TURN)];
|
||||
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
||||
|
||||
picture->setFrame(iconIndex + 2);
|
||||
redraw();
|
||||
|
@@ -329,7 +329,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::INT_MAX_BUILDING_PER_TURN)];
|
||||
size_t iconIndex = town.tType->clientInfo.icons[town.fortLevel > 0][town.built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
||||
|
||||
build = std::make_shared<CAnimImage>("itpt", iconIndex, 0, 3, 2);
|
||||
|
||||
|
@@ -408,7 +408,7 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState)
|
||||
bool allow = true;
|
||||
if(upg) //moving hero out of town - check if it is allowed
|
||||
{
|
||||
if(!hero && LOCPLINT->cb->howManyHeroes(false) >= CGI->settings()->getInteger(EGameSettings::INT_MAX_HEROES_ON_MAP_PER_PLAYER))
|
||||
if(!hero && LOCPLINT->cb->howManyHeroes(false) >= CGI->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
|
||||
{
|
||||
std::string tmp = CGI->generaltexth->allTexts[18]; //You already have %d adventuring heroes under your command.
|
||||
boost::algorithm::replace_first(tmp,"%d",std::to_string(LOCPLINT->cb->howManyHeroes(false)));
|
||||
@@ -1270,7 +1270,7 @@ void CCastleInterface::removeBuilding(BuildingID bid)
|
||||
void CCastleInterface::recreateIcons()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::INT_MAX_BUILDING_PER_TURN)];
|
||||
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
||||
|
||||
icon->setFrame(iconIndex);
|
||||
TResources townIncome = town->dailyIncome();
|
||||
|
@@ -779,7 +779,7 @@ CTownItem::CTownItem(const CGTownInstance * Town)
|
||||
garr = std::make_shared<CGarrisonInt>(313, 3, 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, true);
|
||||
heroes = std::make_shared<HeroSlots>(town, Point(244,6), Point(475,6), garr, false);
|
||||
|
||||
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::INT_MAX_BUILDING_PER_TURN)];
|
||||
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
||||
|
||||
picture = std::make_shared<CAnimImage>("ITPT", iconIndex, 0, 5, 6);
|
||||
openTown = std::make_shared<LRClickableAreaOpenTown>(Rect(5, 6, 58, 64), town);
|
||||
|
@@ -468,13 +468,13 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj)
|
||||
recruit->addHoverText(CButton::NORMAL, CGI->generaltexth->tavernInfo[0]); //Cannot afford a Hero
|
||||
recruit->block(true);
|
||||
}
|
||||
else if(LOCPLINT->cb->howManyHeroes(true) >= CGI->settings()->getInteger(EGameSettings::INT_MAX_HEROES_AVAILABLE_PER_PLAYER))
|
||||
else if(LOCPLINT->cb->howManyHeroes(true) >= CGI->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP))
|
||||
{
|
||||
//Cannot recruit. You already have %d Heroes.
|
||||
recruit->addHoverText(CButton::NORMAL, boost::str(boost::format(CGI->generaltexth->tavernInfo[1]) % LOCPLINT->cb->howManyHeroes(true)));
|
||||
recruit->block(true);
|
||||
}
|
||||
else if(LOCPLINT->cb->howManyHeroes(false) >= CGI->settings()->getInteger(EGameSettings::INT_MAX_HEROES_ON_MAP_PER_PLAYER))
|
||||
else if(LOCPLINT->cb->howManyHeroes(false) >= CGI->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
|
||||
{
|
||||
//Cannot recruit. You already have %d Heroes.
|
||||
recruit->addHoverText(CButton::NORMAL, boost::str(boost::format(CGI->generaltexth->tavernInfo[1]) % LOCPLINT->cb->howManyHeroes(false)));
|
||||
|
@@ -108,6 +108,7 @@
|
||||
|
||||
"settings":
|
||||
{
|
||||
// Number of entries of each type to load from Heroes III text files
|
||||
"textData" :
|
||||
{
|
||||
"heroClass" : 18,
|
||||
@@ -123,33 +124,79 @@
|
||||
"mapVersion" : 28 // max supported version, SoD
|
||||
},
|
||||
|
||||
"hardcodedFeatures" :
|
||||
"heroes" :
|
||||
{
|
||||
"CREEP_SIZE": 4000,
|
||||
"WEEKLY_GROWTH_PERCENT" : 10,
|
||||
"NEUTRAL_STACK_EXP_DAILY" : 500,
|
||||
"MAX_BUILDING_PER_TURN" : 1,
|
||||
"DWELLINGS_ACCUMULATE_CREATURES" : false,
|
||||
"ALL_CREATURES_GET_DOUBLE_MONTHS" : false,
|
||||
"NEGATIVE_LUCK" : false,
|
||||
"MAX_HEROES_AVAILABLE_PER_PLAYER" : 16,
|
||||
"MAX_HEROES_ON_MAP_PER_PLAYER" : 8,
|
||||
"WINNING_HERO_WITH_NO_TROOPS_RETREATS": true,
|
||||
"BLACK_MARKET_MONTHLY_ARTIFACTS_CHANGE": true,
|
||||
"NO_RANDOM_SPECIAL_WEEKS_AND_MONTHS": false,
|
||||
"ATTACK_POINT_DMG_MULTIPLIER": 0.05, //every 1 attack point damage influence in battle when attack points > defense points during creature attack
|
||||
"ATTACK_POINTS_DMG_MULTIPLIER_CAP": 4.0, //limit of damage increase that can be achieved by overpowering attack points
|
||||
"DEFENSE_POINT_DMG_MULTIPLIER": 0.025, //every 1 defense point damage influence in battle when defense points > attack points during creature attack
|
||||
"DEFENSE_POINTS_DMG_MULTIPLIER_CAP": 0.7, //limit of damage reduction that can be achieved by overpowering defense points
|
||||
//chances for new hero units count - technically random number 1-100, first element in list below generated number sets count, if none then result is number of elements + 1
|
||||
"HERO_STARTING_ARMY_STACKS_COUNT_CHANCES": [10, 80], //example: [10,80] gives 10% chance for 1 stack, 70% for 2, 20% for 3. Additionally you can add -1 as last special value to start counting from 0 and allowing empty armies
|
||||
"DEFAULT_BUILDING_SET_DWELLING_CHANCES": [100, 50] //percent chance for dwellings to appear - for example [30,10,0,100] means 30% chance for 1st level dwelling, 10% for 2nd, 0% for 3rd, and guaranteed 4th level, no 5th, no 6th, no 7th
|
||||
// number of heroes that player can have active on map at the same time
|
||||
"perPlayerOnMapCap" : 8,
|
||||
// number of heroes that player can have in total, including garrisoned
|
||||
"perPlayerTotalCap" : 16,
|
||||
// if hero wins a battle without any non-summoned troops left, he will retreat and become available in tavern instead of being lost
|
||||
"retreatOnWinWithoutTroops" : true,
|
||||
// Chances for a hero with default army to receive corresponding stack out of his predefined starting troops
|
||||
"startingStackChances": [ 100, 88, 25]
|
||||
},
|
||||
|
||||
"towns":
|
||||
{
|
||||
// How many new building can be built in a town per day
|
||||
"buildingsPerTurnCap" : 1,
|
||||
// Chances for a town with default buildings to receive corresponding dwelling level built in start
|
||||
"startingDwellingChances": [100, 50]
|
||||
},
|
||||
|
||||
"combat":
|
||||
{
|
||||
//defines dice size of a morale roll, based on creature's morale
|
||||
"goodMoraleDice" : [ 24, 12, 8 ],
|
||||
"badMoraleDice" : [ 12, 6, 4],
|
||||
|
||||
//defines dice size of a luck roll, based on creature's luck
|
||||
"goodLuckDice" : [ 24, 12, 8 ],
|
||||
"badLuckDice" : [],
|
||||
|
||||
//every 1 attack point damage influence in battle when attack points > defense points during creature attack
|
||||
"attackPointDamageFactor": 0.05,
|
||||
//limit of damage increase that can be achieved by overpowering attack points
|
||||
"attackPointDamageFactorCap": 4.0,
|
||||
//every 1 defense point damage influence in battle when defense points > attack points during creature attack
|
||||
"defensePointDamageFactor": 0.025,
|
||||
//limit of damage reduction that can be achieved by overpowering defense points
|
||||
"defensePointDamageFactorCap": 0.7
|
||||
},
|
||||
|
||||
"creatures":
|
||||
{
|
||||
// creatures on map will grow by specific percentage each week
|
||||
"weeklyGrowthPercent" : 10,
|
||||
// creatures on map will not grow if their quantity is greater than this value
|
||||
"weeklyGrowthCap" : 4000,
|
||||
// if stack experience is on, creatures on map will get specified amount of experience daily
|
||||
"dailyStackExperience" : 100,
|
||||
// if set to true, double growth, plague and creature weeks can happen randomly. Has no effect on "Deity of Fire"
|
||||
"allowRandomSpecialWeeks" : true,
|
||||
// if set to true, every creature can get double growth month, ignoring predefined list
|
||||
"allowAllForDoubleMonth" : false,
|
||||
},
|
||||
|
||||
"dwellings" :
|
||||
{
|
||||
// If true, neutral dwellings will accumulate creatures
|
||||
"accumulateWhenNeutral" : false,
|
||||
// If true, dwellings owned by players will accumulate creatures
|
||||
"accumulateWhenOwned" : false
|
||||
},
|
||||
|
||||
"markets" :
|
||||
{
|
||||
// period between restocking of "Black Market" object found on adventure map
|
||||
"blackMarketRestockPeriod" : 0,
|
||||
},
|
||||
|
||||
"modules":
|
||||
{
|
||||
"STACK_EXPERIENCE": false,
|
||||
"STACK_ARTIFACTS": false,
|
||||
"COMMANDERS": false
|
||||
"stackExperience": false,
|
||||
"stackArtifact": false,
|
||||
"commanders": false
|
||||
},
|
||||
|
||||
"bonuses" :
|
||||
@@ -158,18 +205,18 @@
|
||||
{
|
||||
"spellDamage" :
|
||||
{
|
||||
"type" : "SPELL_DAMAGE", //Default spell damage
|
||||
"type" : "SPELL_DAMAGE",
|
||||
"val" : 100,
|
||||
"valueType" : "BASE_NUMBER"
|
||||
},
|
||||
"wisdomBase" :
|
||||
"wisdom" :
|
||||
{
|
||||
"type" : "MAX_LEARNABLE_SPELL_LEVEL", //Hero can always learn level 1 and 2 spells
|
||||
"val" : 2,
|
||||
"valueType" : "BASE_NUMBER"
|
||||
}
|
||||
},
|
||||
"heroes":
|
||||
"perHero":
|
||||
{
|
||||
"manaRegeneration" :
|
||||
{
|
||||
@@ -191,7 +238,7 @@
|
||||
},
|
||||
"manaPerKnowledge" :
|
||||
{
|
||||
"type" : "MANA_PER_KNOWLEDGE", //10 knowledge to 100 mana is default
|
||||
"type" : "MANA_PER_KNOWLEDGE", //10 mana per knowledge
|
||||
"val" : 10,
|
||||
"valueType" : "BASE_NUMBER"
|
||||
},
|
||||
|
@@ -604,7 +604,7 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow
|
||||
if (!t->genBuildingRequirements(ID).test(buildTest))
|
||||
return EBuildingState::PREREQUIRES;
|
||||
|
||||
if(t->builded >= VLC->settings()->getInteger(EGameSettings::INT_MAX_BUILDING_PER_TURN))
|
||||
if(t->builded >= VLC->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP))
|
||||
return EBuildingState::CANT_BUILD_TODAY; //building limit
|
||||
|
||||
//checking resources
|
||||
|
@@ -949,7 +949,7 @@ void CGameState::checkMapChecksum()
|
||||
|
||||
void CGameState::initGlobalBonuses()
|
||||
{
|
||||
const JsonNode & baseBonuses = VLC->settings()->getValue(EGameSettings::BONUSES_LIST_GLOBAL);
|
||||
const JsonNode & baseBonuses = VLC->settings()->getValue(EGameSettings::BONUSES_GLOBAL);
|
||||
logGlobal->debug("\tLoading global bonuses");
|
||||
for(const auto & b : baseBonuses.Struct())
|
||||
{
|
||||
@@ -1748,7 +1748,7 @@ void CGameState::initTowns()
|
||||
if(vti->tempOwner != PlayerColor::NEUTRAL)
|
||||
vti->builtBuildings.insert(BuildingID::TAVERN);
|
||||
|
||||
auto definesBuildingsChances = VLC->settings()->getValue(EGameSettings::VECTOR_DEFAULT_BUILDING_SET_DWELLING_CHANCES).convertTo<std::vector<int32_t>>();
|
||||
auto definesBuildingsChances = VLC->settings()->getVector(EGameSettings::TOWNS_STARTING_DWELLING_CHANCES);
|
||||
|
||||
BuildingID basicDwellings[] = { BuildingID::DWELL_FIRST, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3, BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7 };
|
||||
|
||||
|
@@ -9,7 +9,6 @@
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "GameSettings.h"
|
||||
|
||||
#include "JsonNode.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
@@ -29,61 +28,72 @@ double IGameSettings::getDouble(EGameSettings option) const
|
||||
return getValue(option).Float();
|
||||
}
|
||||
|
||||
GameSettings::GameSettings():
|
||||
gameSettings(static_cast<size_t>(EGameSettings::OPTIONS_COUNT))
|
||||
std::vector<int> IGameSettings::getVector(EGameSettings option) const
|
||||
{
|
||||
return getValue(option).convertTo<std::vector<int>>();
|
||||
}
|
||||
|
||||
GameSettings::GameSettings()
|
||||
: gameSettings(static_cast<size_t>(EGameSettings::OPTIONS_COUNT))
|
||||
{
|
||||
}
|
||||
|
||||
void GameSettings::load(const JsonNode & input)
|
||||
{
|
||||
static std::array<std::array<std::string, 2>, 34> optionPath =
|
||||
{ {
|
||||
{"textData", "heroClass"},
|
||||
{"textData", "artifact"},
|
||||
{"textData", "creature"},
|
||||
{"textData", "faction"},
|
||||
{"textData", "hero"},
|
||||
{"textData", "spell"},
|
||||
{"textData", "object"},
|
||||
{"textData", "terrain"},
|
||||
{"textData", "river"},
|
||||
{"textData", "road"},
|
||||
{"textData", "mapVersion"},
|
||||
{"modules", "STACK_EXPERIENCE"},
|
||||
{"modules", "STACK_ARTIFACTS"},
|
||||
{"modules", "COMMANDERS"},
|
||||
{"hardcodedFeatures", "DWELLINGS_ACCUMULATE_CREATURES"},
|
||||
{"hardcodedFeatures", "NO_RANDOM_SPECIAL_WEEKS_AND_MONTHS"},
|
||||
{"hardcodedFeatures", "BLACK_MARKET_MONTHLY_ARTIFACTS_CHANGE"},
|
||||
{"hardcodedFeatures", "WINNING_HERO_WITH_NO_TROOPS_RETREATS"},
|
||||
{"hardcodedFeatures", "ALL_CREATURES_GET_DOUBLE_MONTHS"},
|
||||
{"hardcodedFeatures", "NEGATIVE_LUCK"},
|
||||
{"hardcodedFeatures", "CREEP_SIZE"},
|
||||
{"hardcodedFeatures", "WEEKLY_GROWTH"},
|
||||
{"hardcodedFeatures", "NEUTRAL_STACK_EXP"},
|
||||
{"hardcodedFeatures", "MAX_BUILDING_PER_TURN"},
|
||||
{"hardcodedFeatures", "MAX_HEROES_AVAILABLE_PER_PLAYER"},
|
||||
{"hardcodedFeatures", "MAX_HEROES_ON_MAP_PER_PLAYER"},
|
||||
{"hardcodedFeatures", "ATTACK_POINT_DMG_MULTIPLIER"},
|
||||
{"hardcodedFeatures", "ATTACK_POINTS_DMG_MULTIPLIER_CAP"},
|
||||
{"hardcodedFeatures", "DEFENSE_POINT_DMG_MULTIPLIER"},
|
||||
{"hardcodedFeatures", "DEFENSE_POINTS_DMG_MULTIPLIER_CAP"},
|
||||
{"hardcodedFeatures", "HERO_STARTING_ARMY_STACKS_COUNT_CHANCES"},
|
||||
{"hardcodedFeatures", "DEFAULT_BUILDING_SET_DWELLING_CHANCES"},
|
||||
{"bonuses", "global"},
|
||||
{"bonuses", "heroes"},
|
||||
} };
|
||||
static_assert(static_cast<size_t>(EGameSettings::OPTIONS_COUNT) == optionPath.size(), "Missing option path");
|
||||
|
||||
for (size_t i = 0; i < optionPath.size(); ++i)
|
||||
struct SettingOption
|
||||
{
|
||||
const std::string & group = optionPath[i][0];
|
||||
const std::string & key = optionPath[i][1];
|
||||
EGameSettings setting;
|
||||
std::string group;
|
||||
std::string key;
|
||||
};
|
||||
|
||||
const JsonNode & optionValue = input[group][key];
|
||||
static const std::vector<SettingOption> optionPath = {
|
||||
{EGameSettings::BONUSES_GLOBAL, "bonuses", "global" },
|
||||
{EGameSettings::BONUSES_PER_HERO, "bonuses", "perHero" },
|
||||
{EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR, "combat", "attackPointDamageFactor" },
|
||||
{EGameSettings::COMBAT_ATTACK_POINT_DAMAGE_FACTOR_CAP, "combat", "attackPointDamageFactorCap" },
|
||||
{EGameSettings::COMBAT_BAD_LUCK_DICE, "combat", "badLuckDice" },
|
||||
{EGameSettings::COMBAT_BAD_MORALE_DICE, "combat", "badMoraleDice" },
|
||||
{EGameSettings::COMBAT_DEFENSE_POINT_DAMAGE_FACTOR, "combat", "defensePointDamageFactor" },
|
||||
{EGameSettings::COMBAT_DEFENSE_POINT_DAMAGE_FACTOR_CAP, "combat", "defensePointDamageFactorCap"},
|
||||
{EGameSettings::COMBAT_GOOD_LUCK_DICE, "combat", "goodLuckDice" },
|
||||
{EGameSettings::COMBAT_GOOD_MORALE_DICE, "combat", "goodMoraleDice" },
|
||||
{EGameSettings::CREATURES_ALLOW_ALL_FOR_DOUBLE_MONTH, "creatures", "allowAllForDoubleMonth" },
|
||||
{EGameSettings::CREATURES_ALLOW_RANDOM_SPECIAL_WEEKS, "creatures", "allowRandomSpecialWeeks" },
|
||||
{EGameSettings::CREATURES_DAILY_STACK_EXPERIENCE, "creatures", "dailyStackExperience" },
|
||||
{EGameSettings::CREATURES_WEEKLY_GROWTH_CAP, "creatures", "weeklyGrowthCap" },
|
||||
{EGameSettings::CREATURES_WEEKLY_GROWTH_PERCENT, "creatures", "weeklyGrowthPercent" },
|
||||
{EGameSettings::DWELLINGS_ACCUMULATE_WHEN_NEUTRAL, "dwellings", "accumulateWhenNeutral" },
|
||||
{EGameSettings::DWELLINGS_ACCUMULATE_WHEN_OWNED, "dwellings", "accumulateWhenOwned" },
|
||||
{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::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::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_MAP_VERSION, "textData", "mapVersion" },
|
||||
{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" },
|
||||
};
|
||||
|
||||
if (!optionValue.isNull())
|
||||
gameSettings[i] = optionValue;
|
||||
for(const auto & option : optionPath)
|
||||
{
|
||||
const JsonNode & optionValue = input[option.group][option.key];
|
||||
|
||||
if(!optionValue.isNull())
|
||||
gameSettings[static_cast<size_t>(option.setting)] = optionValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,8 +102,8 @@ const JsonNode & GameSettings::getValue(EGameSettings option) const
|
||||
assert(option < EGameSettings::OPTIONS_COUNT);
|
||||
auto index = static_cast<size_t>(option);
|
||||
|
||||
assert(!gameSettings[index].isNull());
|
||||
return gameSettings[index];
|
||||
}
|
||||
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@@ -15,44 +15,44 @@ class JsonNode;
|
||||
|
||||
enum class EGameSettings
|
||||
{
|
||||
TEXTS_HERO_CLASS,
|
||||
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,
|
||||
HEROES_PER_PLAYER_ON_MAP_CAP,
|
||||
HEROES_PER_PLAYER_TOTAL_CAP,
|
||||
HEROES_RETREAT_ON_WIN_WITHOUT_TROOPS,
|
||||
HEROES_STARTING_STACKS_CHANCES,
|
||||
MARKETS_BLACK_MARKET_RESTOCK_PERIOD,
|
||||
MODULE_COMMANDERS,
|
||||
MODULE_STACK_ARTIFACT,
|
||||
MODULE_STACK_EXPERIENCE,
|
||||
TEXTS_ARTIFACT,
|
||||
TEXTS_CREATURE,
|
||||
TEXTS_FACTION,
|
||||
TEXTS_HERO,
|
||||
TEXTS_SPELL,
|
||||
TEXTS_HERO_CLASS,
|
||||
TEXTS_MAP_VERSION,
|
||||
TEXTS_OBJECT,
|
||||
TEXTS_TERRAIN,
|
||||
TEXTS_RIVER,
|
||||
TEXTS_ROAD,
|
||||
TEXTS_MAP_VERSION,
|
||||
|
||||
MODULE_STACK_EXPERIENCE,
|
||||
MODULE_STACK_ARTIFACT,
|
||||
MODULE_COMMANDERS,
|
||||
|
||||
BOOL_WINNING_HERO_WITH_NO_TROOPS_RETREATS,
|
||||
BOOL_BLACK_MARKET_MONTHLY_ARTIFACTS_CHANGE,
|
||||
BOOL_NO_RANDOM_SPECIAL_WEEKS_AND_MONTHS,
|
||||
BOOL_DWELLINGS_ACCUMULATE_CREATURES,
|
||||
BOOL_ALL_CREATURES_GET_DOUBLE_MONTHS,
|
||||
BOOL_NEGATIVE_LUCK,
|
||||
|
||||
INT_CREEP_SIZE,
|
||||
INT_WEEKLY_GROWTH,
|
||||
INT_NEUTRAL_STACK_EXP,
|
||||
INT_MAX_BUILDING_PER_TURN,
|
||||
INT_MAX_HEROES_AVAILABLE_PER_PLAYER,
|
||||
INT_MAX_HEROES_ON_MAP_PER_PLAYER,
|
||||
DOUBLE_ATTACK_POINT_DMG_MULTIPLIER,
|
||||
DOUBLE_ATTACK_POINTS_DMG_MULTIPLIER_CAP,
|
||||
DOUBLE_DEFENSE_POINT_DMG_MULTIPLIER,
|
||||
DOUBLE_DEFENSE_POINTS_DMG_MULTIPLIER_CAP,
|
||||
VECTOR_HERO_STARTING_ARMY_STACKS_COUNT_CHANCES,
|
||||
VECTOR_DEFAULT_BUILDING_SET_DWELLING_CHANCES,
|
||||
|
||||
BONUSES_LIST_GLOBAL,
|
||||
BONUSES_LIST_HERO,
|
||||
TEXTS_SPELL,
|
||||
TEXTS_TERRAIN,
|
||||
TOWNS_BUILDINGS_PER_TURN_CAP,
|
||||
TOWNS_STARTING_DWELLING_CHANCES,
|
||||
|
||||
OPTIONS_COUNT
|
||||
};
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
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
|
||||
@@ -73,9 +74,7 @@ class DLL_LINKAGE GameSettings final : public IGameSettings
|
||||
|
||||
public:
|
||||
GameSettings();
|
||||
|
||||
void load(const JsonNode & input);
|
||||
|
||||
const JsonNode & getValue(EGameSettings option) const override;
|
||||
|
||||
template<typename Handler>
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include "CGameState.h"
|
||||
#include "mapping/CMap.h"
|
||||
#include "CPlayerState.h"
|
||||
#include "GameSettings.h"
|
||||
#include "ScriptHandler.h"
|
||||
#include "RoadHandler.h"
|
||||
#include "RiverHandler.h"
|
||||
|
@@ -128,6 +128,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
h & settingsHandler;
|
||||
h & heroh;
|
||||
h & arth;
|
||||
h & creh;
|
||||
|
@@ -183,8 +183,8 @@ double DamageCalculator::getAttackSkillFactor() const
|
||||
|
||||
if(attackAdvantage > 0)
|
||||
{
|
||||
const double attackMultiplier = VLC->settings()->getDouble(EGameSettings::DOUBLE_ATTACK_POINT_DMG_MULTIPLIER);
|
||||
const double attackMultiplierCap = VLC->settings()->getDouble(EGameSettings::DOUBLE_ATTACK_POINTS_DMG_MULTIPLIER_CAP);
|
||||
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);
|
||||
const double attackFactor = std::min(attackMultiplier * attackAdvantage, attackMultiplierCap);
|
||||
|
||||
return attackFactor;
|
||||
@@ -269,8 +269,8 @@ double DamageCalculator::getDefenseSkillFactor() const
|
||||
//bonus from attack/defense skills
|
||||
if(defenseAdvantage > 0) //decreasing dmg
|
||||
{
|
||||
const double defenseMultiplier = VLC->settings()->getDouble(EGameSettings::DOUBLE_DEFENSE_POINT_DMG_MULTIPLIER);
|
||||
const double defenseMultiplierCap = VLC->settings()->getDouble(EGameSettings::DOUBLE_DEFENSE_POINTS_DMG_MULTIPLIER_CAP);
|
||||
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);
|
||||
|
||||
const double dec = std::min(defenseMultiplier * defenseAdvantage, defenseMultiplierCap);
|
||||
return dec;
|
||||
|
@@ -313,7 +313,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
|
||||
// are not attached to global bonus node but need access to some global bonuses
|
||||
// e.g. MANA_PER_KNOWLEDGE 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_LIST_HERO);
|
||||
const JsonNode & baseBonuses = VLC->settings()->getValue(EGameSettings::BONUSES_PER_HERO);
|
||||
for(const auto & b : baseBonuses.Struct())
|
||||
{
|
||||
auto bonus = JsonUtils::parseBonus(b.second);
|
||||
@@ -341,27 +341,16 @@ void CGHeroInstance::initArmy(CRandomGenerator & rand, IArmyDescriptor * dst)
|
||||
|
||||
int warMachinesGiven = 0;
|
||||
|
||||
auto stacksCountChances = VLC->settings()->getValue(EGameSettings::VECTOR_HERO_STARTING_ARMY_STACKS_COUNT_CHANCES).convertTo<std::vector<int32_t>>();
|
||||
|
||||
const int zeroStacksAllowingValue = -1;
|
||||
bool allowZeroStacksArmy = !stacksCountChances.empty() && stacksCountChances.back() == zeroStacksAllowingValue;
|
||||
if(allowZeroStacksArmy)
|
||||
stacksCountChances.pop_back();
|
||||
|
||||
auto stacksCountChances = VLC->settings()->getVector(EGameSettings::HEROES_STARTING_STACKS_CHANCES);
|
||||
int stacksCountInitRandomNumber = rand.nextInt(1, 100);
|
||||
|
||||
auto stacksCountElementIndex = vstd::find_pos_if(stacksCountChances, [stacksCountInitRandomNumber](int element){ return stacksCountInitRandomNumber < element; });
|
||||
if(stacksCountElementIndex == -1)
|
||||
stacksCountElementIndex = stacksCountChances.size();
|
||||
size_t maxStacksCount = std::min(stacksCountChances.size(), type->initialArmy.size());
|
||||
|
||||
int howManyStacks = stacksCountElementIndex;
|
||||
if(!allowZeroStacksArmy)
|
||||
howManyStacks++;
|
||||
|
||||
vstd::amin(howManyStacks, type->initialArmy.size());
|
||||
|
||||
for(int stackNo=0; stackNo < howManyStacks; stackNo++)
|
||||
for(int stackNo=0; stackNo < maxStacksCount; stackNo++)
|
||||
{
|
||||
if (stacksCountInitRandomNumber > stacksCountChances[stackNo])
|
||||
continue;
|
||||
|
||||
auto & stack = type->initialArmy[stackNo];
|
||||
|
||||
int count = rand.nextInt(stack.minAmount, stack.maxAmount);
|
||||
@@ -438,7 +427,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
|
||||
{
|
||||
int txt_id;
|
||||
|
||||
if (cb->getHeroCount(h->tempOwner, false) < VLC->settings()->getInteger(EGameSettings::INT_MAX_HEROES_ON_MAP_PER_PLAYER))//free hero slot
|
||||
if (cb->getHeroCount(h->tempOwner, false) < VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))//free hero slot
|
||||
{
|
||||
//update hero parameters
|
||||
SetMovePoints smp;
|
||||
|
@@ -277,10 +277,12 @@ std::vector<int> CGBlackMarket::availableItemsIds(EMarketMode::EMarketMode mode)
|
||||
|
||||
void CGBlackMarket::newTurn(CRandomGenerator & rand) const
|
||||
{
|
||||
if(!VLC->settings()->getBoolean(EGameSettings::BOOL_BLACK_MARKET_MONTHLY_ARTIFACTS_CHANGE)) //check if feature changing OH3 behavior is enabled
|
||||
int resetPeriod = VLC->settings()->getInteger(EGameSettings::MARKETS_BLACK_MARKET_RESTOCK_PERIOD);
|
||||
|
||||
if(resetPeriod == 0) //check if feature changing OH3 behavior is enabled
|
||||
return;
|
||||
|
||||
if(cb->getDate(Date::DAY_OF_MONTH) != 1) //new month
|
||||
if (((cb->getDate(Date::DAY)-1) % resetPeriod) != 0)
|
||||
return;
|
||||
|
||||
SetAvailableArtifacts saa;
|
||||
|
@@ -255,9 +255,16 @@ void CGDwelling::newTurn(CRandomGenerator & rand) const
|
||||
{
|
||||
if(!creatures[i].second.empty())
|
||||
{
|
||||
bool creaturesAccumulate = false;
|
||||
|
||||
if (tempOwner.isValidPlayer())
|
||||
creaturesAccumulate = VLC->settings()->getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_OWNED);
|
||||
else
|
||||
creaturesAccumulate = VLC->settings()->getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_NEUTRAL);
|
||||
|
||||
CCreature *cre = VLC->creh->objects[creatures[i].second[0]];
|
||||
TQuantity amount = cre->growth * (1 + cre->valOfBonuses(Bonus::CREATURE_GROWTH_PERCENT)/100) + cre->valOfBonuses(Bonus::CREATURE_GROWTH);
|
||||
if (VLC->settings()->getBoolean(EGameSettings::BOOL_DWELLINGS_ACCUMULATE_CREATURES) && ID != Obj::REFUGEE_CAMP) //camp should not try to accumulate different kinds of creatures
|
||||
if (creaturesAccumulate && ID != Obj::REFUGEE_CAMP) //camp should not try to accumulate different kinds of creatures
|
||||
sac.creatures[i].first += amount;
|
||||
else
|
||||
sac.creatures[i].first = amount;
|
||||
|
@@ -233,15 +233,15 @@ void CGCreature::newTurn(CRandomGenerator & 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::INT_CREEP_SIZE) && cb->getDate(Date::DAY_OF_WEEK) == 1 && cb->getDate(Date::DAY) > 1)
|
||||
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)
|
||||
{
|
||||
ui32 power = static_cast<ui32>(temppower * (100 + VLC->settings()->getInteger(EGameSettings::INT_WEEKLY_GROWTH)) / 100);
|
||||
cb->setObjProperty(id, ObjProperty::MONSTER_COUNT, std::min<uint32_t>(power / 1000, VLC->settings()->getInteger(EGameSettings::INT_CREEP_SIZE))); //set new amount
|
||||
ui32 power = static_cast<ui32>(temppower * (100 + VLC->settings()->getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_PERCENT)) / 100);
|
||||
cb->setObjProperty(id, ObjProperty::MONSTER_COUNT, std::min<uint32_t>(power / 1000, VLC->settings()->getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_PERCENT))); //set new amount
|
||||
cb->setObjProperty(id, ObjProperty::MONSTER_POWER, power); //increase temppower
|
||||
}
|
||||
}
|
||||
if (VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
|
||||
cb->setObjProperty(id, ObjProperty::MONSTER_EXP, VLC->settings()->getInteger(EGameSettings::INT_NEUTRAL_STACK_EXP)); //for testing purpose
|
||||
cb->setObjProperty(id, ObjProperty::MONSTER_EXP, VLC->settings()->getInteger(EGameSettings::CREATURES_DAILY_STACK_EXPERIENCE)); //for testing purpose
|
||||
}
|
||||
void CGCreature::setPropertyDer(ui8 what, ui32 val)
|
||||
{
|
||||
|
@@ -14,8 +14,8 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
const ui32 SERIALIZATION_VERSION = 819;
|
||||
const ui32 MINIMAL_SERIALIZATION_VERSION = 819;
|
||||
const ui32 SERIALIZATION_VERSION = 820;
|
||||
const ui32 MINIMAL_SERIALIZATION_VERSION = 820;
|
||||
const std::string SAVEGAME_MAGIC = "VCMISVG";
|
||||
|
||||
class CHero;
|
||||
|
@@ -988,7 +988,7 @@ void CGameHandler::battleAfterLevelUp(const BattleResult &result)
|
||||
RemoveObject ro(finishingBattle->winnerHero->id);
|
||||
sendAndApply(&ro);
|
||||
|
||||
if (VLC->settings()->getBoolean(EGameSettings::BOOL_WINNING_HERO_WITH_NO_TROOPS_RETREATS))
|
||||
if (VLC->settings()->getBoolean(EGameSettings::HEROES_RETREAT_ON_WIN_WITHOUT_TROOPS))
|
||||
{
|
||||
SetAvailableHeroes sah;
|
||||
sah.player = finishingBattle->victor;
|
||||
@@ -1026,17 +1026,22 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
|
||||
|
||||
const int attackerLuck = attacker->LuckVal();
|
||||
|
||||
if (attackerLuck > 0 && getRandomGenerator().nextInt(23) < attackerLuck)
|
||||
if(attackerLuck > 0)
|
||||
{
|
||||
bat.flags |= BattleAttack::LUCKY;
|
||||
auto diceSize = VLC->settings()->getVector(EGameSettings::COMBAT_GOOD_LUCK_DICE);
|
||||
size_t diceIndex = std::min<size_t>(diceSize.size() - 1, attackerLuck);
|
||||
|
||||
if(diceSize.size() > 0 && getRandomGenerator().nextInt(1, diceSize[diceIndex]) == 1)
|
||||
bat.flags |= BattleAttack::LUCKY;
|
||||
}
|
||||
|
||||
if (VLC->settings()->getBoolean(EGameSettings::BOOL_NEGATIVE_LUCK)) // negative luck enabled
|
||||
if(attackerLuck < 0)
|
||||
{
|
||||
if (attackerLuck < 0 && getRandomGenerator().nextInt(23) < abs(attackerLuck))
|
||||
{
|
||||
auto diceSize = VLC->settings()->getVector(EGameSettings::COMBAT_BAD_LUCK_DICE);
|
||||
size_t diceIndex = std::min<size_t>(diceSize.size() - 1, -attackerLuck);
|
||||
|
||||
if(diceSize.size() > 0 && getRandomGenerator().nextInt(1, diceSize[diceIndex]) == 1)
|
||||
bat.flags |= BattleAttack::UNLUCKY;
|
||||
}
|
||||
}
|
||||
|
||||
if (getRandomGenerator().nextInt(99) < attacker->valOfBonuses(Bonus::DOUBLE_DAMAGE_CHANCE))
|
||||
@@ -1779,7 +1784,7 @@ void CGameHandler::newTurn()
|
||||
n.specialWeek = NewTurn::DEITYOFFIRE;
|
||||
n.creatureid = CreatureID::IMP;
|
||||
}
|
||||
else if(!VLC->settings()->getBoolean(EGameSettings::BOOL_NO_RANDOM_SPECIAL_WEEKS_AND_MONTHS))
|
||||
else if(!VLC->settings()->getBoolean(EGameSettings::CREATURES_ALLOW_RANDOM_SPECIAL_WEEKS))
|
||||
{
|
||||
int monthType = getRandomGenerator().nextInt(99);
|
||||
if (newMonth) //new month
|
||||
@@ -1787,15 +1792,13 @@ void CGameHandler::newTurn()
|
||||
if (monthType < 40) //double growth
|
||||
{
|
||||
n.specialWeek = NewTurn::DOUBLE_GROWTH;
|
||||
if (VLC->settings()->getBoolean(EGameSettings::BOOL_ALL_CREATURES_GET_DOUBLE_MONTHS))
|
||||
if (VLC->settings()->getBoolean(EGameSettings::CREATURES_ALLOW_ALL_FOR_DOUBLE_MONTH))
|
||||
{
|
||||
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster(getRandomGenerator()));
|
||||
n.creatureid = newMonster.second;
|
||||
n.creatureid = VLC->creh->pickRandomMonster(getRandomGenerator());
|
||||
}
|
||||
else if (VLC->creh->doubledCreatures.size())
|
||||
{
|
||||
const std::vector<CreatureID> doubledCreatures (VLC->creh->doubledCreatures.begin(), VLC->creh->doubledCreatures.end());
|
||||
n.creatureid = *RandomGeneratorUtil::nextItem(doubledCreatures, getRandomGenerator());
|
||||
n.creatureid = *RandomGeneratorUtil::nextItem(VLC->creh->doubledCreatures, getRandomGenerator());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3962,7 +3965,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat
|
||||
if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->getId(), dst.slot))
|
||||
giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
|
||||
}
|
||||
catch (boost::bad_get const &)
|
||||
catch(const boost::bad_get &)
|
||||
{
|
||||
// object other than hero received an art - ignore
|
||||
}
|
||||
@@ -4366,8 +4369,8 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, PlayerColor pl
|
||||
// if ((p->resources.at(Res::GOLD)<GOLD_NEEDED && complain("Not enough gold for buying hero!"))
|
||||
// || (getHeroCount(player, false) >= GameConstants::MAX_HEROES_PER_PLAYER && complain("Cannot hire hero, only 8 wandering heroes are allowed!")))
|
||||
if ((p->resources.at(Res::GOLD) < GameConstants::HERO_GOLD_COST && complain("Not enough gold for buying hero!"))
|
||||
|| ((getHeroCount(player, false) >= VLC->settings()->getInteger(EGameSettings::INT_MAX_HEROES_ON_MAP_PER_PLAYER) && complain("Cannot hire hero, too many wandering heroes already!")))
|
||||
|| ((getHeroCount(player, true) >= VLC->settings()->getInteger(EGameSettings::INT_MAX_HEROES_AVAILABLE_PER_PLAYER) && complain("Cannot hire hero, too many heroes garrizoned and wandering already!"))))
|
||||
|| ((getHeroCount(player, false) >= VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP) && complain("Cannot hire hero, too many wandering heroes already!")))
|
||||
|| ((getHeroCount(player, true) >= VLC->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP) && complain("Cannot hire hero, too many heroes garrizoned and wandering already!"))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -6570,7 +6573,10 @@ void CGameHandler::runBattle()
|
||||
int nextStackMorale = next->MoraleVal();
|
||||
if (nextStackMorale < 0)
|
||||
{
|
||||
if (getRandomGenerator().nextInt(23) < -2 * nextStackMorale)
|
||||
auto diceSize = VLC->settings()->getVector(EGameSettings::COMBAT_BAD_MORALE_DICE);
|
||||
size_t diceIndex = std::min<size_t>(diceSize.size()-1, -nextStackMorale);
|
||||
|
||||
if(diceSize.size() > 0 && getRandomGenerator().nextInt(1, diceSize[diceIndex]) == 1)
|
||||
{
|
||||
//unit loses its turn - empty freeze action
|
||||
BattleAction ba;
|
||||
@@ -6758,7 +6764,10 @@ void CGameHandler::runBattle()
|
||||
&& next->alive()
|
||||
&& nextStackMorale > 0)
|
||||
{
|
||||
if(getRandomGenerator().nextInt(23) < nextStackMorale) //this stack hasn't got morale this turn
|
||||
auto diceSize = VLC->settings()->getVector(EGameSettings::COMBAT_GOOD_MORALE_DICE);
|
||||
size_t diceIndex = std::min<size_t>(diceSize.size()-1, nextStackMorale);
|
||||
|
||||
if(diceSize.size() > 0 && getRandomGenerator().nextInt(1, diceSize[diceIndex]) == 1)
|
||||
{
|
||||
BattleTriggerEffect bte;
|
||||
bte.stackID = next->ID;
|
||||
|
Reference in New Issue
Block a user