Skip to content

Commit c26e38e

Browse files
committed
Added premade config presets
1 parent db97ae6 commit c26e38e

10 files changed

Lines changed: 164 additions & 10 deletions

File tree

CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ include(ext/mernel/mernel.cmake)
4545
# source
4646
set(sourceRoot ${CMAKE_CURRENT_SOURCE_DIR}/src)
4747
set(pluginRootBin ${CMAKE_CURRENT_BINARY_DIR}/plugins)
48+
set(presetsRootBin ${CMAKE_CURRENT_BINARY_DIR}/presets)
4849

4950
AddTarget(TYPE shared NAME ModgenCore
5051
SOURCE_DIR ${sourceRoot}/CoreLib
@@ -63,6 +64,15 @@ foreach(filename ${resourceFiles})
6364
target_sources(ModgenCore PRIVATE ${pluginRootBin}/${filename})
6465
endforeach()
6566

67+
file(GLOB_RECURSE presetFiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/presets
68+
${CMAKE_CURRENT_SOURCE_DIR}/presets/*.json ${CMAKE_CURRENT_SOURCE_DIR}/presets/*.txt)
69+
foreach(filename ${presetFiles})
70+
add_custom_command(OUTPUT ${presetsRootBin}/${filename}
71+
COMMAND ${CMAKE_COMMAND} ARGS -E copy ${CMAKE_CURRENT_SOURCE_DIR}/presets/${filename} ${presetsRootBin}/${filename}
72+
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/presets/${filename})
73+
target_sources(ModgenCore PRIVATE ${presetsRootBin}/${filename})
74+
endforeach()
75+
6676
# ConsoleApp
6777
AddTarget( TYPE app_console NAME modgen_console
6878
SOURCE_DIR ${sourceRoot}/ConsoleApp
@@ -112,6 +122,7 @@ AddResourceCustomTarget("all_resources" Translations breeze)
112122

113123
install(TARGETS modgen ModgenCore RUNTIME DESTINATION bin)
114124
install(DIRECTORY ${pluginRootBin} DESTINATION bin PATTERN *.ilk EXCLUDE PATTERN *.pdb EXCLUDE)
125+
install(DIRECTORY ${presetsRootBin} DESTINATION bin PATTERN *.ilk EXCLUDE PATTERN *.pdb EXCLUDE)
115126
foreach(th IN ITEMS dark light)
116127
install(FILES theme/${th}.conf DESTINATION bin/theme)
117128
configure_file(theme/${th}.conf ${CMAKE_CURRENT_BINARY_DIR}/theme/${th}.conf COPYONLY)

presets/basic.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"character":{"addCube":true,"idTome":true,"manaPots":true},"character_enabled":true,"density":{"hellPacks":true},"density_enabled":true,"drop_filter":{"compact_pots":true,"compact_scrolls":true,"hide_ammo":true,"hide_junks":true,"hide_lowq":true,"hide_stam":true},"drop_filter_enabled":true,"item_drops":{"boss_quest_drops":true,"chance_highlevel":2,"chance_rare":2,"chance_set":10,"chance_uni":20,"equal_uniques":true,"gold_percent":5,"high_elite_drops":true,"junk_percent":5},"item_drops_enabled":true,"qol":{"disableExpPenalty":true,"showItemLevel":true,"tomeSize":true,"uniqueCharmLimit":true,"weakenTownSkills":true,"weakenTownSkillsExt":true},"qol_enabled":true,"testConfig":{"addKeys":false},"testConfig_enabled":true}

presets/friendly_chaos.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"challenge":{"hell_minus_res":250,"nightmare_minus_res":100},"challenge_enabled":true,"character":{"addCube":true,"idTome":true,"manaPots":true},"character_enabled":true,"cube":null,"cube_enabled":false,"density":{"hellPacks":true},"density_enabled":true,"drop_filter":{"compact_pots":true,"compact_scrolls":true,"hide_ammo":true,"hide_junks":true,"hide_lowq":true,"hide_stam":true},"drop_filter_enabled":true,"gambling":null,"gambling_enabled":false,"item_drops":{"boss_quest_drops":true,"chance_highlevel":2,"chance_rare":2,"chance_set":10,"chance_uni":20,"equal_uniques":true,"gold_percent":5,"high_elite_drops":true,"junk_percent":5},"item_drops_enabled":true,"mergePostgen":null,"mergePostgen_enabled":false,"mergePregen":null,"mergePregen_enabled":false,"monRandomizer":null,"monRandomizer_enabled":true,"monster_stats":{"mon_hp":300,"mon_xp":300},"monster_stats_enabled":true,"perfect_rolls":{"gem_power":500,"uniques_power_l1":150,"uniques_power_l50":500},"perfect_rolls_enabled":true,"qol":{"disableExpPenalty":true,"showItemLevel":true,"tomeSize":true,"uniqueCharmLimit":true,"weakenTownSkills":true,"weakenTownSkillsExt":true},"qol_enabled":true,"randomizer":{"gemsRandom":true,"itemFitPercent":50,"keepOriginalPercent":100,"relativeCountMax":300,"relativeCountMin":300,"repeat_sets":2,"replaceCharges":true,"replaceSkills":true,"setRelativeCountMin":1000},"randomizer_enabled":true,"requirements":null,"requirements_enabled":false,"rune_drops":null,"rune_drops_enabled":false,"skillRandomizer":null,"skillRandomizer_enabled":false,"testConfig":{"addKeys":false},"testConfig_enabled":true}

presets/magic_rando.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"challenge":null,"challenge_enabled":false,"character":{"addCube":true,"idTome":true,"manaPots":true},"character_enabled":true,"cube":null,"cube_enabled":false,"density":{"hellPacks":true},"density_enabled":true,"drop_filter":{"compact_pots":true,"compact_scrolls":true,"hide_ammo":true,"hide_junks":true,"hide_lowq":true,"hide_stam":true},"drop_filter_enabled":true,"gambling":null,"gambling_enabled":false,"item_drops":{"boss_quest_drops":true,"chance_highlevel":2,"chance_rare":2,"chance_set":10,"chance_uni":20,"equal_uniques":true,"gold_percent":5,"high_elite_drops":true,"junk_percent":5},"item_drops_enabled":true,"mergePostgen":null,"mergePostgen_enabled":false,"mergePregen":null,"mergePregen_enabled":false,"monRandomizer":{"hellResistances":true,"randomizeResistances":true,"randomizeSpawns":false},"monRandomizer_enabled":true,"monster_stats":{"mon_hp":300,"mon_xp":200},"monster_stats_enabled":true,"perfect_rolls":null,"perfect_rolls_enabled":false,"qol":{"disableExpPenalty":true,"showItemLevel":true,"tomeSize":true,"uniqueCharmLimit":true,"weakenTownSkills":true,"weakenTownSkillsExt":true},"qol_enabled":true,"randomizer":{"affixRandom":false,"crazyLevel":8,"itemFitPercent":75,"keepOriginalPercent":50,"relativeCountMax":150,"relativeCountMin":150,"repeat_sets":2,"replaceCharges":true,"replaceSkills":true,"setRelativeCountMax":150,"setRelativeCountMin":150},"randomizer_enabled":true,"requirements":null,"requirements_enabled":false,"rune_drops":null,"rune_drops_enabled":false,"skillRandomizer":{"skillTree":false},"skillRandomizer_enabled":true,"testConfig":{"addKeys":false},"testConfig_enabled":true}

presets/oh_no.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"challenge":{"hell_minus_res":200,"nightmare_minus_res":80},"challenge_enabled":true,"character":{"addCube":true,"idTome":true,"manaPots":true,"skillPointLimit":5,"statPerLevel":1},"character_enabled":true,"cube":null,"cube_enabled":false,"density":{"density":2,"hellPacks":true},"density_enabled":true,"drop_filter":{"compact_pots":true,"compact_scrolls":true,"hide_ammo":true,"hide_junks":true,"hide_lowq":true,"hide_stam":true},"drop_filter_enabled":true,"gambling":null,"gambling_enabled":false,"item_drops":{"boss_quest_drops":true,"chance_highlevel":2,"chance_rare":2,"chance_set":10,"chance_uni":20,"equal_uniques":true,"gold_percent":5,"high_elite_drops":true,"junk_percent":5},"item_drops_enabled":true,"mergePostgen":null,"mergePostgen_enabled":false,"mergePregen":null,"mergePregen_enabled":false,"monRandomizer":{"hellResistances":true,"randomizeResistances":true},"monRandomizer_enabled":true,"monster_stats":{"max_resist":90,"mon_dam":150,"mon_hp":200,"resist_apply_magic":true,"resist_apply_physical":true},"monster_stats_enabled":true,"perfect_rolls":null,"perfect_rolls_enabled":false,"qol":{"disableExpPenalty":true,"showItemLevel":true,"tomeSize":true,"uniqueCharmLimit":true,"weakenTownSkills":true,"weakenTownSkillsExt":true},"qol_enabled":true,"randomizer":{"affixRandom":false,"crazyLevel":8,"itemFitPercent":80,"keepOriginalPercent":0,"relativeCountMax":100,"repeat_sets":2,"setRelativeCountMax":100},"randomizer_enabled":true,"requirements":{"reqStr":60},"requirements_enabled":true,"rune_drops":null,"rune_drops_enabled":false,"skillRandomizer":null,"skillRandomizer_enabled":false,"testConfig":{"addKeys":false},"testConfig_enabled":true}

presets/readme.txt

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
### General changes for all presets:
2+
QOL:
3+
- show item level in title;
4+
- increase tome scroll size to 60;
5+
- compacted potion like !MP5 for mana potion where (!) is blue;
6+
- starting Horadric cube;
7+
- starting tome of ID;
8+
- starting mana pots instead of health;
9+
10+
Drops:
11+
- 20x increase of Uniques;
12+
- 10x increase of sets;
13+
- 4x more items from pack bosses, 2x more from champions;
14+
- almost no gold and junk (keys/bolts/rancid/etc) drops;
15+
16+
Density:
17+
- Boss packs have same frequency on normal and nightmare as on hell difficulty. Basically to have items in Normal faster.
18+
19+
20+
### Preset 'friendly_chaos':
21+
Recommended characters: zeal paladin, barbarian, spear zon. With casters it will be too easy.
22+
23+
Item rando:
24+
- relatively unbalanced affix level difference (up to 20 levels);
25+
- random affixes are 50% chance to fit in the item (like have weapon-like affix on weapon). Example - having Enchance Damage not on weapon.
26+
- 100% original properties of item are kept;
27+
- unique/magic/rare items have 300% of affixes (100% original + 200% randomized);
28+
- set items have 1000% affixes (so almost always max amount);
29+
- magic and rare items randomized too, as well as gems;
30+
- have 2 different incompatible sets. You will have 'Sigons Steel' and 'Sigons Steel 2' sets.
31+
32+
Monster rando:
33+
- you will have up to 5 different types in one area (not 3 as in base game)
34+
- overall monster pool is 25 monster types. Got unlucky with Oblivion + dolls + Horadrims in Cold plains normal? reroll! (blood moor is unaffected just to start)
35+
Note: bosses unaffected, Ancients unaffected, also fixed spawns are the same (shaman packs and catapults).
36+
Note: monsters in normal scaled accordingly, so you won't get oneshot by level 30 monster; still can be challenging in rare occasions.
37+
38+
Monster stats:
39+
- 300% base HP and 300% base XP (similar to Players5 experience but without dmg/defence boost). If you use P8 in game it will give you something like P24 with 1350% HP.
40+
41+
Item power tuning:
42+
note: item power is basically multiplying affix rolls to percent with some exceptions (for +all skills it multiply for lower value for example, so 500% power will give just 200% increase)
43+
- All items will always have perfect (max) rolls;
44+
- Unique items will have additional item power, raizing crazy high for high levels
45+
- Gems/runes will have 500% item power. (In rando you usually don't value much white socketed items)
46+
47+
Challenge:
48+
- Nightmare resitance penalty -100% instead of -40%
49+
- Hell resitance penalty -250% instead of -100%
50+
It is very easy to overstack resistances with those settings, like have +400 all res, so don't be afraid. Also you probably get +ton of Life too.
51+
52+
### Preset 'magic_rando'
53+
Recomended characters: elemental bowazon, bone necro, fire druid, fire/lightning (not nova) sorc, choose class with magic damage but not blizzard (it still OP every time)
54+
55+
Item rando:
56+
- relatively balanced affix level difference (up to 8 levels);
57+
- random affixes are 75% chance to fit in the item;
58+
- All items will have 50% of original properties (so one time you get SoJ +1 skill, other time not);
59+
- Uniques and sets have 150% of original property count (50% kept original, 100% extra is randomized. if item have 4 properties, 2 of 4 will be kept, 4 extra added).
60+
- have 2 different incompatible sets
61+
- gems, rare and magic items are unchanged
62+
63+
Monster rando:
64+
- monster spawns in areas are original;
65+
- mosnters have random resistances (magic and phys res are considered more rare);
66+
- monsters will have same resistances in normal and nightmare as in Hell (so basically all monster is immune to something).
67+
Keep in mind - many monsters have 'secondary' high resistance - and that is randomized too. So Zombie is immune to cold and hires to phys; it can be changed to fire+cold.
68+
69+
Skill rando:
70+
- Many skills with elemental damage will do different type of damage (unfortunately I have no luck with 'explosion' skills, like fireball or explosive arrow. so for Amazon it's like only 3 skills randomized, Exploding/Freezing arrow are the same);
71+
72+
Monster stats:
73+
- 300% base HP and 200% base XP. (hp like p5 and xp gain like p3).
74+
75+
Item power tuning:
76+
- No extra tuning;
77+
78+
Challenge:
79+
- Disabled, res are normal;
80+
81+
### Preset 'oh_no'
82+
Recomended characters: some op builds like trapsin, hammerdin, blizzard sorc etc.
83+
You have only 1 stat point on level up!
84+
85+
Item rando:
86+
- relatively balanced affix level difference (up to 8 levels);
87+
- random affixes are 80% chance to fit in the item;
88+
- All items will have 0% of original properties;
89+
- Uniques and sets have 100% of original property count - you have same amount of affixes but they all differ from original;
90+
- have 2 different incompatible sets
91+
- gems, rare and magic items are unchanged
92+
93+
Monster rando:
94+
- you will have up to 5 different types in one area
95+
- overall monster pool is 25 monster types;
96+
- monsters will have same resistances in normal and nightmare as in Hell and they randomized;
97+
98+
Skill rando:
99+
- Disabled;
100+
101+
Monster stats:
102+
- 200% base HP
103+
- 100% base XP
104+
- 150% base damage (so they hit like on P8)
105+
- double normal density (for regular spawns, packs kept same as basic preset)
106+
- monster will have 90% max resistance, so no immunities for normal monsters.
107+
However that means, that any monster can have all enchantements on boss; and that can give very high res overall.
108+
Example: skelly with poison + lightning immunity become 90% lightning and 90% poison. boss having magic+cold enchantement gives cold immunity.
109+
Practically this monster is immune to 3 damage types without extra pierce.
110+
And yes, only way to figure high res after randomization is by attacking them.
111+
112+
Challenge:
113+
- Nightmare resitance penalty -80% instead of -40%
114+
- Hell resitance penalty -200% instead of -100%
115+
- (!!!!) Only 1 stat point per level (and you better to put it in Strength)
116+
- Maximum 5 hard points per skill
117+
118+
Requirements:
119+
- 60% of basic strength requirement for items. (with 1 stat point is hard to equip items in first place)

src/CoreLib/ConfigHandler.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,16 @@ ConfigHandler::ConfigHandler(const std::string& pluginsRoot)
6262
m_modules[std::string(IModule::Key::testConfig)].m_enabled = true;
6363
}
6464

65-
bool ConfigHandler::loadConfig(const std::string& filename)
65+
bool ConfigHandler::loadConfig(const std::string& filename, bool resetMain)
6666
{
6767
Logger() << "Load:" << filename;
6868
std::string buffer;
6969
Mernel::PropertyTree doc;
7070
if (!Mernel::readFileIntoBufferNoexcept(string2path(filename), buffer) || !readJsonFromBufferNoexcept(buffer, doc)) {
71-
loadConfig(Mernel::PropertyTree{});
71+
loadConfig(Mernel::PropertyTree{}, resetMain);
7272
return false;
7373
}
74-
return loadConfig(doc);
74+
return loadConfig(doc, resetMain);
7575
}
7676

7777
bool ConfigHandler::saveConfig(const std::string& filename) const
@@ -85,7 +85,7 @@ bool ConfigHandler::saveConfig(const std::string& filename) const
8585
return Mernel::writeFileFromBufferNoexcept(string2path(filename), buffer);
8686
}
8787

88-
bool ConfigHandler::loadConfig(const Mernel::PropertyTree& data)
88+
bool ConfigHandler::loadConfig(const Mernel::PropertyTree& data, bool resetMain)
8989
{
9090
for (auto& p : m_modules) {
9191
p.second.m_enabled = data.value(p.first + "_enabled", Mernel::PropertyTreeScalar(false)).toBool();
@@ -95,9 +95,11 @@ bool ConfigHandler::loadConfig(const Mernel::PropertyTree& data)
9595
p.second.m_currentConfig = data[p.first];
9696
}
9797
m_modules[std::string(IModule::Key::testConfig)].m_enabled = true;
98-
m_currentMainConfig = {};
99-
if (data.contains(std::string(IModule::Key::main)))
100-
m_currentMainConfig = data[std::string(IModule::Key::main)];
98+
if (resetMain) {
99+
m_currentMainConfig = {};
100+
if (data.contains(std::string(IModule::Key::main)))
101+
m_currentMainConfig = data[std::string(IModule::Key::main)];
102+
}
101103
return true;
102104
}
103105

src/CoreLib/ConfigHandler.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ class MODGENCORE_EXPORT ConfigHandler {
1818
ConfigHandler(const ConfigHandler&) = delete;
1919
~ConfigHandler();
2020

21-
bool loadConfig(const std::string& filename);
21+
bool loadConfig(const std::string& filename, bool resetMain = true);
2222
bool saveConfig(const std::string& filename) const;
2323

24-
bool loadConfig(const Mernel::PropertyTree& data);
24+
bool loadConfig(const Mernel::PropertyTree& data, bool resetMain = true);
2525
bool saveConfig(Mernel::PropertyTree& data) const;
2626

2727
bool isConfigEnabled(const std::string& key) const;

src/QtApp/MainWindow.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ MainWindow::MainWindow(ConfigHandler& configHandler)
8888
{
8989
setWindowTitle("Diablo II Resurrected mod generator by mapron");
9090

91-
const auto appData = ensureTrailingSlash(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
91+
const auto appData = ensureTrailingSlash(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
92+
QString binDir = QApplication::applicationDirPath();
93+
QFileInfoList presetList = QDir(binDir + "/presets").entryInfoList({ "*.json" });
9294

9395
m_delayTimer = new DelayedTimer(
9496
1000, [this] { pushUndoCurrent(); }, this);
@@ -266,6 +268,7 @@ MainWindow::MainWindow(ConfigHandler& configHandler)
266268
QAction* saveConfigAction = fileMenu->addAction(tr("Save config..."));
267269
QAction* loadConfigAction = fileMenu->addAction(tr("Load config..."));
268270
QAction* clearConfig = fileMenu->addAction(tr("Clear config"));
271+
QMenu* presetMenu = fileMenu->addMenu(tr("Config from preset"));
269272
QAction* browseToSettings = fileMenu->addAction(tr("Browse to settings folder"));
270273
fileMenu->addSeparator();
271274
QAction* quitNoSaveAction = fileMenu->addAction(tr("Quit without saving"));
@@ -287,6 +290,13 @@ MainWindow::MainWindow(ConfigHandler& configHandler)
287290
m_undoAction->setShortcut(QKeySequence::Undo);
288291
generateMod->setShortcut(QKeySequence(Qt::Key_F9));
289292

293+
for (const auto& entry : presetList) {
294+
QString basename = entry.baseName();
295+
QString absPath = entry.absoluteFilePath();
296+
QAction* presetAct = presetMenu->addAction(basename);
297+
connect(presetAct, &QAction::triggered, this, [absPath, this](bool) { loadPresetConfig(absPath); });
298+
}
299+
290300
auto updateMenuState = [themeActionLight, themeActionDark, langActionEn, langActionRu]() {
291301
auto appSettings = getAppSettings();
292302
const bool themeLight = appSettings.m_themeId == "light";
@@ -435,6 +445,13 @@ bool MainWindow::loadConfig(const Mernel::PropertyTree& data)
435445
return result;
436446
}
437447

448+
bool MainWindow::loadPresetConfig(const QString& filename)
449+
{
450+
const auto result = m_configHandler.loadConfig(filename.toStdString(), false);
451+
updateUIFromSettings();
452+
return result;
453+
}
454+
438455
MainWindow::AppSettings MainWindow::getAppSettings()
439456
{
440457
auto ini = makeAppSettings();

src/QtApp/MainWindow.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class MainWindow : public QMainWindow {
5050
bool saveConfig(const QString& filename) const;
5151
bool loadConfig(const QString& filename);
5252
bool loadConfig(const Mernel::PropertyTree& data);
53+
bool loadPresetConfig(const QString& filename);
5354

5455
struct AppSettings {
5556
QString m_langId;

0 commit comments

Comments
 (0)