windownewmap.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /*
  2. * windownewmap.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "../lib/mapping/CMap.h"
  12. #include "../lib/rmg/CRmgTemplateStorage.h"
  13. #include "../lib/rmg/CRmgTemplate.h"
  14. #include "../lib/rmg/CMapGenerator.h"
  15. #include "../lib/VCMI_Lib.h"
  16. #include "../lib/mapping/CMapEditManager.h"
  17. #include "../lib/mapping/MapFormat.h"
  18. #include "../lib/CGeneralTextHandler.h"
  19. #include "../lib/serializer/JsonSerializer.h"
  20. #include "../lib/serializer/JsonDeserializer.h"
  21. #include "jsonutils.h"
  22. #include "windownewmap.h"
  23. #include "ui_windownewmap.h"
  24. #include "mainwindow.h"
  25. #include "generatorprogress.h"
  26. WindowNewMap::WindowNewMap(QWidget *parent) :
  27. QDialog(parent),
  28. ui(new Ui::WindowNewMap)
  29. {
  30. ui->setupUi(this);
  31. setAttribute(Qt::WA_DeleteOnClose);
  32. setWindowModality(Qt::ApplicationModal);
  33. for(auto * combo : {ui->humanCombo, ui->cpuCombo, ui->humanTeamsCombo, ui->cpuTeamsCombo})
  34. combo->clear();
  35. //prepare human players combo box
  36. for(int i = 0; i <= PlayerColor::PLAYER_LIMIT_I; ++i)
  37. {
  38. ui->humanCombo->addItem(!i ? randomString : QString::number(players.at(i)));
  39. ui->humanCombo->setItemData(i, QVariant(players.at(i)));
  40. ui->cpuCombo->addItem(!i ? randomString : QString::number(cpuPlayers.at(i)));
  41. ui->cpuCombo->setItemData(i, QVariant(cpuPlayers.at(i)));
  42. ui->humanTeamsCombo->addItem(!i ? randomString : QString::number(cpuPlayers.at(i)));
  43. ui->humanTeamsCombo->setItemData(i, QVariant(cpuPlayers.at(i)));
  44. ui->cpuTeamsCombo->addItem(!i ? randomString : QString::number(cpuPlayers.at(i)));
  45. ui->cpuTeamsCombo->setItemData(i, QVariant(cpuPlayers.at(i)));
  46. }
  47. bool useLoaded = loadUserSettings();
  48. if (!useLoaded)
  49. {
  50. for(auto * combo : {ui->humanCombo, ui->cpuCombo, ui->humanTeamsCombo, ui->cpuTeamsCombo})
  51. combo->setCurrentIndex(0);
  52. }
  53. show();
  54. if (!useLoaded)
  55. {
  56. //setup initial parameters
  57. int width = ui->widthTxt->text().toInt();
  58. int height = ui->heightTxt->text().toInt();
  59. mapGenOptions.setWidth(width ? width : 1);
  60. mapGenOptions.setHeight(height ? height : 1);
  61. bool twoLevel = ui->twoLevelCheck->isChecked();
  62. mapGenOptions.setHasTwoLevels(twoLevel);
  63. updateTemplateList();
  64. }
  65. }
  66. WindowNewMap::~WindowNewMap()
  67. {
  68. delete ui;
  69. }
  70. bool WindowNewMap::loadUserSettings()
  71. {
  72. bool ret = false;
  73. CRmgTemplate * templ = nullptr;
  74. QSettings s(Ui::teamName, Ui::appName);
  75. auto generateRandom = s.value(newMapGenerateRandom);
  76. if (generateRandom.isValid())
  77. {
  78. ui->randomMapCheck->setChecked(generateRandom.toBool());
  79. }
  80. auto settings = s.value(newMapWindow);
  81. if (settings.isValid())
  82. {
  83. auto node = JsonUtils::toJson(settings);
  84. JsonDeserializer handler(nullptr, node);
  85. handler.serializeStruct("lastSettings", mapGenOptions);
  86. templ = const_cast<CRmgTemplate*>(mapGenOptions.getMapTemplate()); // Remember for later
  87. ui->widthTxt->setText(QString::number(mapGenOptions.getWidth()));
  88. ui->heightTxt->setText(QString::number(mapGenOptions.getHeight()));
  89. for(auto & sz : mapSizes)
  90. {
  91. if(sz.second.first == mapGenOptions.getWidth() &&
  92. sz.second.second == mapGenOptions.getHeight())
  93. {
  94. ui->sizeCombo->setCurrentIndex(sz.first);
  95. break;
  96. }
  97. }
  98. ui->twoLevelCheck->setChecked(mapGenOptions.getHasTwoLevels());
  99. ui->humanCombo->setCurrentIndex(mapGenOptions.getHumanOrCpuPlayerCount());
  100. ui->cpuCombo->setCurrentIndex(mapGenOptions.getCompOnlyPlayerCount());
  101. ui->humanTeamsCombo->setCurrentIndex(mapGenOptions.getTeamCount());
  102. ui->cpuTeamsCombo->setCurrentIndex(mapGenOptions.getCompOnlyTeamCount());
  103. switch (mapGenOptions.getWaterContent())
  104. {
  105. case EWaterContent::RANDOM:
  106. ui->waterOpt1->setChecked(true); break;
  107. case EWaterContent::NONE:
  108. ui->waterOpt2->setChecked(true); break;
  109. case EWaterContent::NORMAL:
  110. ui->waterOpt3->setChecked(true); break;
  111. case EWaterContent::ISLANDS:
  112. ui->waterOpt4->setChecked(true); break;
  113. }
  114. switch (mapGenOptions.getMonsterStrength())
  115. {
  116. case EMonsterStrength::RANDOM:
  117. ui->monsterOpt1->setChecked(true); break;
  118. case EMonsterStrength::GLOBAL_WEAK:
  119. ui->monsterOpt2->setChecked(true); break;
  120. case EMonsterStrength::GLOBAL_NORMAL:
  121. ui->monsterOpt3->setChecked(true); break;
  122. case EMonsterStrength::GLOBAL_STRONG:
  123. ui->monsterOpt4->setChecked(true); break;
  124. }
  125. ret = true;
  126. }
  127. updateTemplateList();
  128. mapGenOptions.setMapTemplate(templ); // Can be null
  129. if (templ)
  130. {
  131. std::string name = templ->getName();
  132. for (size_t i = 0; i < ui->templateCombo->count(); i++)
  133. {
  134. if (ui->templateCombo->itemText(i).toStdString() == name)
  135. {
  136. ui->templateCombo->setCurrentIndex(i);
  137. break;
  138. }
  139. }
  140. ret = true;
  141. }
  142. return ret;
  143. }
  144. void WindowNewMap::saveUserSettings()
  145. {
  146. QSettings s(Ui::teamName, Ui::appName);
  147. JsonNode data;
  148. JsonSerializer ser(nullptr, data);
  149. ser.serializeStruct("lastSettings", mapGenOptions);
  150. auto variant = JsonUtils::toVariant(data);
  151. s.setValue(newMapWindow, variant);
  152. s.setValue(newMapGenerateRandom, ui->randomMapCheck->isChecked());
  153. }
  154. void WindowNewMap::on_cancelButton_clicked()
  155. {
  156. saveUserSettings();
  157. close();
  158. }
  159. void generateRandomMap(CMapGenerator & gen, MainWindow * window)
  160. {
  161. window->controller.setMap(gen.generate());
  162. }
  163. std::unique_ptr<CMap> generateEmptyMap(CMapGenOptions & options)
  164. {
  165. auto map = std::make_unique<CMap>(nullptr);
  166. map->version = EMapFormat::VCMI;
  167. map->width = options.getWidth();
  168. map->height = options.getHeight();
  169. map->twoLevel = options.getHasTwoLevels();
  170. map->initTerrain();
  171. map->getEditManager()->clearTerrain(&CRandomGenerator::getDefault());
  172. return map;
  173. }
  174. void WindowNewMap::on_okButton_clicked()
  175. {
  176. EWaterContent::EWaterContent water = EWaterContent::RANDOM;
  177. EMonsterStrength::EMonsterStrength monster = EMonsterStrength::RANDOM;
  178. if(ui->waterOpt1->isChecked())
  179. water = EWaterContent::RANDOM;
  180. if(ui->waterOpt2->isChecked())
  181. water = EWaterContent::NONE;
  182. if(ui->waterOpt3->isChecked())
  183. water = EWaterContent::NORMAL;
  184. if(ui->waterOpt4->isChecked())
  185. water = EWaterContent::ISLANDS;
  186. if(ui->monsterOpt1->isChecked())
  187. monster = EMonsterStrength::RANDOM;
  188. if(ui->monsterOpt2->isChecked())
  189. monster = EMonsterStrength::GLOBAL_WEAK;
  190. if(ui->monsterOpt3->isChecked())
  191. monster = EMonsterStrength::GLOBAL_NORMAL;
  192. if(ui->monsterOpt4->isChecked())
  193. monster = EMonsterStrength::GLOBAL_STRONG;
  194. mapGenOptions.setWaterContent(water);
  195. mapGenOptions.setMonsterStrength(monster);
  196. saveUserSettings();
  197. std::unique_ptr<CMap> nmap;
  198. if(ui->randomMapCheck->isChecked())
  199. {
  200. //verify map template
  201. if(mapGenOptions.getPossibleTemplates().empty())
  202. {
  203. QMessageBox::warning(this, tr("No template"), tr("No template for parameters scecified. Random map cannot be generated."));
  204. return;
  205. }
  206. int seed = std::time(nullptr);
  207. if(ui->checkSeed->isChecked() && !ui->lineSeed->text().isEmpty())
  208. seed = ui->lineSeed->text().toInt();
  209. CMapGenerator generator(mapGenOptions, nullptr, seed);
  210. auto progressBarWnd = new GeneratorProgress(generator, this);
  211. progressBarWnd->show();
  212. try
  213. {
  214. auto f = std::async(std::launch::async, &CMapGenerator::generate, &generator);
  215. progressBarWnd->update();
  216. nmap = f.get();
  217. }
  218. catch(const std::exception & e)
  219. {
  220. QMessageBox::critical(this, tr("RMG failure"), e.what());
  221. }
  222. }
  223. else
  224. {
  225. auto f = std::async(std::launch::async, &::generateEmptyMap, std::ref(mapGenOptions));
  226. nmap = f.get();
  227. }
  228. nmap->mods = MapController::modAssessmentAll();
  229. static_cast<MainWindow*>(parent())->controller.setMap(std::move(nmap));
  230. static_cast<MainWindow*>(parent())->initializeMap(true);
  231. close();
  232. }
  233. void WindowNewMap::on_sizeCombo_activated(int index)
  234. {
  235. ui->widthTxt->setText(QString::number(mapSizes.at(index).first));
  236. ui->heightTxt->setText(QString::number(mapSizes.at(index).second));
  237. }
  238. void WindowNewMap::on_twoLevelCheck_stateChanged(int arg1)
  239. {
  240. bool twoLevel = ui->twoLevelCheck->isChecked();
  241. mapGenOptions.setHasTwoLevels(twoLevel);
  242. updateTemplateList();
  243. }
  244. void WindowNewMap::on_humanCombo_activated(int index)
  245. {
  246. int humans = ui->humanCombo->currentData().toInt();
  247. if(humans > PlayerColor::PLAYER_LIMIT_I)
  248. {
  249. humans = PlayerColor::PLAYER_LIMIT_I;
  250. ui->humanCombo->setCurrentIndex(humans);
  251. }
  252. mapGenOptions.setHumanOrCpuPlayerCount(humans);
  253. int teams = mapGenOptions.getTeamCount();
  254. if(teams > humans - 1)
  255. {
  256. teams = humans > 0 ? humans - 1 : CMapGenOptions::RANDOM_SIZE;
  257. ui->humanTeamsCombo->setCurrentIndex(teams + 1); //skip one element because first is random
  258. }
  259. int cpu = mapGenOptions.getCompOnlyPlayerCount();
  260. if(cpu > PlayerColor::PLAYER_LIMIT_I - humans)
  261. {
  262. cpu = PlayerColor::PLAYER_LIMIT_I - humans;
  263. ui->cpuCombo->setCurrentIndex(cpu + 1); //skip one element because first is random
  264. }
  265. int cpuTeams = mapGenOptions.getCompOnlyTeamCount(); //comp only players - 1
  266. if(cpuTeams > cpu - 1)
  267. {
  268. cpuTeams = cpu > 0 ? cpu - 1 : CMapGenOptions::RANDOM_SIZE;
  269. ui->cpuTeamsCombo->setCurrentIndex(cpuTeams + 1); //skip one element because first is random
  270. }
  271. updateTemplateList();
  272. }
  273. void WindowNewMap::on_cpuCombo_activated(int index)
  274. {
  275. int humans = mapGenOptions.getHumanOrCpuPlayerCount();
  276. int cpu = ui->cpuCombo->currentData().toInt();
  277. // FIXME: Use mapGenOption method only to calculate actual number of players for current template
  278. if(cpu > PlayerColor::PLAYER_LIMIT_I - humans)
  279. {
  280. cpu = PlayerColor::PLAYER_LIMIT_I - humans;
  281. ui->cpuCombo->setCurrentIndex(cpu + 1); //skip one element because first is random
  282. }
  283. mapGenOptions.setCompOnlyPlayerCount(cpu);
  284. int cpuTeams = mapGenOptions.getCompOnlyTeamCount(); //comp only players - 1
  285. if(cpuTeams > cpu - 1)
  286. {
  287. cpuTeams = cpu > 0 ? cpu - 1 : CMapGenOptions::RANDOM_SIZE;
  288. ui->cpuTeamsCombo->setCurrentIndex(cpuTeams + 1); //skip one element because first is random
  289. }
  290. updateTemplateList();
  291. }
  292. void WindowNewMap::on_randomMapCheck_stateChanged(int arg1)
  293. {
  294. randomMap = ui->randomMapCheck->isChecked();
  295. ui->templateCombo->setEnabled(randomMap);
  296. updateTemplateList();
  297. }
  298. void WindowNewMap::on_templateCombo_activated(int index)
  299. {
  300. if(index == 0)
  301. {
  302. mapGenOptions.setMapTemplate(nullptr);
  303. return;
  304. }
  305. auto * templ = data_cast<const CRmgTemplate>(ui->templateCombo->currentData().toLongLong());
  306. mapGenOptions.setMapTemplate(templ);
  307. }
  308. void WindowNewMap::on_widthTxt_textChanged(const QString &arg1)
  309. {
  310. int sz = arg1.toInt();
  311. if(sz > 1)
  312. {
  313. mapGenOptions.setWidth(arg1.toInt());
  314. updateTemplateList();
  315. }
  316. }
  317. void WindowNewMap::on_heightTxt_textChanged(const QString &arg1)
  318. {
  319. int sz = arg1.toInt();
  320. if(sz > 1)
  321. {
  322. mapGenOptions.setHeight(arg1.toInt());
  323. updateTemplateList();
  324. }
  325. }
  326. void WindowNewMap::updateTemplateList()
  327. {
  328. ui->templateCombo->clear();
  329. ui->templateCombo->setCurrentIndex(-1);
  330. if(!randomMap)
  331. return;
  332. mapGenOptions.setMapTemplate(nullptr);
  333. auto templates = mapGenOptions.getPossibleTemplates();
  334. if(templates.empty())
  335. return;
  336. ui->templateCombo->addItem("[default]", 0);
  337. for(auto * templ : templates)
  338. {
  339. ui->templateCombo->addItem(QString::fromStdString(templ->getName()), data_cast(templ));
  340. }
  341. ui->templateCombo->setCurrentIndex(0);
  342. }
  343. void WindowNewMap::on_checkSeed_toggled(bool checked)
  344. {
  345. ui->lineSeed->setEnabled(checked);
  346. }
  347. void WindowNewMap::on_humanTeamsCombo_activated(int index)
  348. {
  349. int humans = mapGenOptions.getHumanOrCpuPlayerCount();
  350. int teams = ui->humanTeamsCombo->currentData().toInt();
  351. if(teams >= humans)
  352. {
  353. teams = humans > 0 ? humans - 1 : CMapGenOptions::RANDOM_SIZE;
  354. ui->humanTeamsCombo->setCurrentIndex(teams + 1); //skip one element because first is random
  355. }
  356. mapGenOptions.setTeamCount(teams);
  357. updateTemplateList();
  358. }
  359. void WindowNewMap::on_cpuTeamsCombo_activated(int index)
  360. {
  361. int cpu = mapGenOptions.getCompOnlyPlayerCount();
  362. int cpuTeams = ui->cpuTeamsCombo->currentData().toInt();
  363. if(cpuTeams >= cpu)
  364. {
  365. cpuTeams = cpu > 0 ? cpu - 1 : CMapGenOptions::RANDOM_SIZE;
  366. ui->cpuTeamsCombo->setCurrentIndex(cpuTeams + 1); //skip one element because first is random
  367. }
  368. mapGenOptions.setCompOnlyTeamCount(cpuTeams);
  369. updateTemplateList();
  370. }