diff --git a/AI/Nullkiller/Analyzers/ArmyManager.cpp b/AI/Nullkiller/Analyzers/ArmyManager.cpp index e5356d368..d1c39980d 100644 --- a/AI/Nullkiller/Analyzers/ArmyManager.cpp +++ b/AI/Nullkiller/Analyzers/ArmyManager.cpp @@ -182,7 +182,7 @@ std::vector ArmyManager::getBestArmy(const IBonusBearer * armyCarrier, { auto weakest = getWeakestCreature(resultingArmy); - if(weakest->count == 1) + if(weakest != resultingArmy.end() && weakest->count == 1) //we check iterator validity for playing with settings that allow 0 stacks armies { resultingArmy.erase(weakest); } diff --git a/config/defaultMods.json b/config/defaultMods.json index bfced4e84..60448d347 100644 --- a/config/defaultMods.json +++ b/config/defaultMods.json @@ -33,7 +33,10 @@ "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 + "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 }, "modules": { diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index aa1414628..c1dc7edee 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -1722,10 +1722,16 @@ void CGameState::initTowns() if(vti->tempOwner != PlayerColor::NEUTRAL) vti->builtBuildings.insert(BuildingID::TAVERN); - vti->builtBuildings.insert(BuildingID::DWELL_FIRST); - if(getRandomGenerator().nextInt(1) == 1) + auto definesBuildingsChances = VLC->modh->settings.DEFAULT_BUILDING_SET_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 }; + + for(int i = 0; i < definesBuildingsChances.size(); i++) { - vti->builtBuildings.insert(BuildingID::DWELL_LVL_2); + if((getRandomGenerator().nextInt(1,100) <= definesBuildingsChances[i])) + { + vti->builtBuildings.insert(basicDwellings[i]); + } } } diff --git a/lib/CModHandler.cpp b/lib/CModHandler.cpp index 9e2ed6677..e516f9c24 100644 --- a/lib/CModHandler.cpp +++ b/lib/CModHandler.cpp @@ -767,6 +767,14 @@ void CModHandler::loadConfigFromFile (std::string name) settings.DEFENSE_POINTS_DMG_MULTIPLIER_CAP = hardcodedFeatures["DEFENSE_POINTS_DMG_MULTIPLIER_CAP"].Float(); logMod->debug("\tDEFENSE_POINTS_DMG_MULTIPLIER_CAP\t%f", settings.DEFENSE_POINTS_DMG_MULTIPLIER_CAP); + settings.HERO_STARTING_ARMY_STACKS_COUNT_CHANCES = hardcodedFeatures["HERO_STARTING_ARMY_STACKS_COUNT_CHANCES"].convertTo>(); + for (auto const & entry : settings.HERO_STARTING_ARMY_STACKS_COUNT_CHANCES) + logMod->debug("\tHERO_STARTING_ARMY_STACKS_COUNT_CHANCES\t%d", entry); + + settings.DEFAULT_BUILDING_SET_DWELLING_CHANCES = hardcodedFeatures["DEFAULT_BUILDING_SET_DWELLING_CHANCES"].convertTo>(); + for (auto const & entry : settings.DEFAULT_BUILDING_SET_DWELLING_CHANCES) + logMod->debug("\tDEFAULT_BUILDING_SET_DWELLING_CHANCES\t%d", entry); + const JsonNode & gameModules = settings.data["modules"]; modules.STACK_EXP = gameModules["STACK_EXPERIENCE"].Bool(); logMod->debug("\tSTACK_EXP\t%d", static_cast(modules.STACK_EXP)); diff --git a/lib/CModHandler.h b/lib/CModHandler.h index beb5e0baf..77fe51547 100644 --- a/lib/CModHandler.h +++ b/lib/CModHandler.h @@ -363,6 +363,8 @@ public: double ATTACK_POINTS_DMG_MULTIPLIER_CAP; double DEFENSE_POINT_DMG_MULTIPLIER; double DEFENSE_POINTS_DMG_MULTIPLIER_CAP; + std::vector HERO_STARTING_ARMY_STACKS_COUNT_CHANCES; + std::vector DEFAULT_BUILDING_SET_DWELLING_CHANCES; template void serialize(Handler &h, const int version) { @@ -382,6 +384,11 @@ public: h & ATTACK_POINTS_DMG_MULTIPLIER_CAP; h & DEFENSE_POINT_DMG_MULTIPLIER; h & DEFENSE_POINTS_DMG_MULTIPLIER_CAP; + if(version >= 815) + { + h & HERO_STARTING_ARMY_STACKS_COUNT_CHANCES; + h & DEFAULT_BUILDING_SET_DWELLING_CHANCES; + } } } settings; diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 304b4dc05..74f072dc9 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -345,16 +345,24 @@ void CGHeroInstance::initArmy(CRandomGenerator & rand, IArmyDescriptor * dst) if(!dst) dst = this; - int howManyStacks = 0; //how many stacks will hero receives <1 - 3> - int pom = rand.nextInt(99); int warMachinesGiven = 0; - if(pom < 9) - howManyStacks = 1; - else if(pom < 79) - howManyStacks = 2; - else - howManyStacks = 3; + std::vector stacksCountChances = VLC->modh->settings.HERO_STARTING_ARMY_STACKS_COUNT_CHANCES; + + const int zeroStacksAllowingValue = -1; + bool allowZeroStacksArmy = !stacksCountChances.empty() && stacksCountChances.back() == zeroStacksAllowingValue; + if(allowZeroStacksArmy) + stacksCountChances.pop_back(); + + 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(); + + int howManyStacks = stacksCountElementIndex; + if(!allowZeroStacksArmy) + howManyStacks++; vstd::amin(howManyStacks, type->initialArmy.size()); diff --git a/lib/serializer/CSerializer.h b/lib/serializer/CSerializer.h index b7ed4c89e..12223598f 100644 --- a/lib/serializer/CSerializer.h +++ b/lib/serializer/CSerializer.h @@ -14,7 +14,7 @@ VCMI_LIB_NAMESPACE_BEGIN -const ui32 SERIALIZATION_VERSION = 814; +const ui32 SERIALIZATION_VERSION = 815; const ui32 MINIMAL_SERIALIZATION_VERSION = 813; const std::string SAVEGAME_MAGIC = "VCMISVG";