scenarioproperties.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. /*
  2. * scenarioproperties.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 "scenarioproperties.h"
  12. #include "ui_scenarioproperties.h"
  13. #include "startingbonus.h"
  14. #include "campaigneditor.h"
  15. #include "callback/EditorCallback.h"
  16. #include "../../lib/GameLibrary.h"
  17. #include "../../lib/CCreatureHandler.h"
  18. #include "../../lib/texts/CGeneralTextHandler.h"
  19. #include "../../lib/entities/artifact/CArtHandler.h"
  20. #include "../../lib/entities/hero/CHeroHandler.h"
  21. #include "../../lib/campaign/CampaignState.h"
  22. #include "../../lib/mapping/CMap.h"
  23. #include "../../lib/constants/StringConstants.h"
  24. ScenarioProperties::ScenarioProperties(std::shared_ptr<CampaignState> campaignState, CampaignScenarioID scenario, EditorCallback * cb):
  25. ui(new Ui::ScenarioProperties),
  26. campaignState(campaignState),
  27. map(campaignState->getMap(scenario, cb)),
  28. scenario(scenario),
  29. cb(cb)
  30. {
  31. ui->setupUi(this);
  32. setWindowTitle(tr("Scenario Properties"));
  33. setWindowModality(Qt::ApplicationModal);
  34. ui->lineEditRegionName->setText(QString::fromStdString(campaignState->getRegions().regions.at(scenario).infix));
  35. ui->plainTextEditRightClickText->setPlainText(QString::fromStdString(campaignState->scenarios.at(scenario).regionText.toString()));
  36. for(int i = 0, index = 0; i < PlayerColor::PLAYER_LIMIT_I; ++i)
  37. {
  38. MetaString str;
  39. str.appendName(PlayerColor(i));
  40. ui->comboBoxRegionColor->addItem(QString::fromStdString(str.toString()), QVariant(i));
  41. if(i == campaignState->scenarios.at(scenario).regionColor)
  42. ui->comboBoxRegionColor->setCurrentIndex(index);
  43. ++index;
  44. }
  45. for(int i = 0, index = 0; i < 5; ++i)
  46. {
  47. ui->comboBoxDefaultDifficulty->addItem(QString::fromStdString(LIBRARY->generaltexth->arraytxt[142 + i]), QVariant(i));
  48. if(i == campaignState->scenarios.at(scenario).difficulty)
  49. ui->comboBoxDefaultDifficulty->setCurrentIndex(index);
  50. ++index;
  51. }
  52. for(int i = 0; i < campaignState->scenarios.size(); ++i)
  53. {
  54. auto tmpScenario = CampaignScenarioID(i);
  55. auto * item = new QListWidgetItem(QString::fromStdString(campaignState->getRegions().regions.at(i).infix) + " - " + QString::fromStdString(campaignState->scenarios.at(tmpScenario).mapName));
  56. item->setData(Qt::UserRole, QVariant::fromValue(i));
  57. item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
  58. item->setCheckState(campaignState->scenarios.at(scenario).preconditionRegions.count(tmpScenario) ? Qt::Checked : Qt::Unchecked);
  59. ui->listWidgetPrerequisites->addItem(item);
  60. }
  61. ui->checkBoxPrologueEnabled->setChecked(campaignState->scenarios.at(scenario).prolog.hasPrologEpilog);
  62. ui->lineEditPrologueVideo->setText(QString::fromStdString(campaignState->scenarios.at(scenario).prolog.prologVideo.first.getName()));
  63. ui->lineEditPrologueVideoLoop->setText(QString::fromStdString(campaignState->scenarios.at(scenario).prolog.prologVideo.second.getName()));
  64. ui->lineEditPrologueMusic->setText(QString::fromStdString(campaignState->scenarios.at(scenario).prolog.prologMusic.getName()));
  65. ui->lineEditPrologueVoice->setText(QString::fromStdString(campaignState->scenarios.at(scenario).prolog.prologVoice.getName()));
  66. ui->plainTextEditPrologueText->setPlainText(QString::fromStdString(campaignState->scenarios.at(scenario).prolog.prologText.toString()));
  67. ui->checkBoxEpilogueEnabled->setChecked(campaignState->scenarios.at(scenario).epilog.hasPrologEpilog);
  68. ui->lineEditEpilogueVideo->setText(QString::fromStdString(campaignState->scenarios.at(scenario).epilog.prologVideo.first.getName()));
  69. ui->lineEditEpilogueVideoLoop->setText(QString::fromStdString(campaignState->scenarios.at(scenario).epilog.prologVideo.second.getName()));
  70. ui->lineEditEpilogueMusic->setText(QString::fromStdString(campaignState->scenarios.at(scenario).epilog.prologMusic.getName()));
  71. ui->lineEditEpilogueVoice->setText(QString::fromStdString(campaignState->scenarios.at(scenario).epilog.prologVoice.getName()));
  72. ui->plainTextEditEpilogueText->setPlainText(QString::fromStdString(campaignState->scenarios.at(scenario).epilog.prologText.toString()));
  73. ui->checkBoxCrossoverExperience->setChecked(campaignState->scenarios.at(scenario).travelOptions.whatHeroKeeps.experience);
  74. ui->checkBoxCrossoverPrimarySkills->setChecked(campaignState->scenarios.at(scenario).travelOptions.whatHeroKeeps.primarySkills);
  75. ui->checkBoxCrossoverSecondarySkills->setChecked(campaignState->scenarios.at(scenario).travelOptions.whatHeroKeeps.secondarySkills);
  76. ui->checkBoxCrossoverSpells->setChecked(campaignState->scenarios.at(scenario).travelOptions.whatHeroKeeps.spells);
  77. ui->checkBoxCrossoverArtifacts->setChecked(campaignState->scenarios.at(scenario).travelOptions.whatHeroKeeps.artifacts);
  78. auto campaignStartOption = campaignState->scenarios.at(scenario).travelOptions.startOptions;
  79. ui->radioButtonStartingOptionBonus->setChecked(campaignStartOption == CampaignStartOptions::START_BONUS || campaignStartOption == CampaignStartOptions::NONE);
  80. ui->radioButtonStartingOptionHeroCrossover->setChecked(campaignStartOption == CampaignStartOptions::HERO_CROSSOVER);
  81. ui->radioButtonStartingOptionStartingHero->setChecked(campaignStartOption == CampaignStartOptions::HERO_OPTIONS);
  82. for(auto const & objectPtr : LIBRARY->arth->objects)
  83. {
  84. auto * item = new QListWidgetItem(QString::fromStdString(objectPtr->getNameTranslated()));
  85. item->setData(Qt::UserRole, QVariant::fromValue(objectPtr->getIndex()));
  86. item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
  87. item->setCheckState(campaignState->scenarios.at(scenario).travelOptions.artifactsKeptByHero.count(objectPtr->getId()) ? Qt::Checked : Qt::Unchecked);
  88. ui->listWidgetCrossoverArtifacts->addItem(item);
  89. }
  90. for(auto const & objectPtr : LIBRARY->creh->objects)
  91. {
  92. auto * item = new QListWidgetItem(QString::fromStdString(objectPtr->getNameSingularTranslated()));
  93. item->setData(Qt::UserRole, QVariant::fromValue(objectPtr->getIndex()));
  94. item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
  95. item->setCheckState(campaignState->scenarios.at(scenario).travelOptions.monstersKeptByHero.count(objectPtr->getId()) ? Qt::Checked : Qt::Unchecked);
  96. ui->listWidgetCrossoverCreatures->addItem(item);
  97. }
  98. ui->tabWidgetStartOptions->tabBar()->hide();
  99. ui->tabWidgetStartOptions->setStyleSheet("QTabWidget::pane { border: 0; }");
  100. ui->tableWidgetStartingCrossover->setColumnCount(2);
  101. LIBRARY->heroTypes()->forEach([this](const HeroType * hero, bool &)
  102. {
  103. heroSelection.emplace(hero->getId().getNum(), hero->getNameTranslated());
  104. });
  105. heroSelection.emplace(HeroTypeID::CAMP_STRONGEST, tr("Strongest").toStdString());
  106. heroSelection.emplace(HeroTypeID::CAMP_GENERATED, tr("Generated").toStdString());
  107. heroSelection.emplace(HeroTypeID::CAMP_RANDOM, tr("Random").toStdString());
  108. reloadMapRelatedUi();
  109. show();
  110. }
  111. ScenarioProperties::~ScenarioProperties()
  112. {
  113. delete ui;
  114. }
  115. void ScenarioProperties::reloadMapRelatedUi()
  116. {
  117. map = campaignState->getMap(scenario, cb);
  118. ui->lineEditMapFile->setText(QString::fromStdString(campaignState->scenarios.at(scenario).mapName));
  119. ui->lineEditScenarioName->setText(map ? QString::fromStdString(map->name.toString()) : tr("No map"));
  120. if(!map)
  121. ui->lineEditScenarioName->setStyleSheet("background-color: red;");
  122. else
  123. ui->lineEditScenarioName->setStyleSheet("");
  124. ui->pushButtonExport->setEnabled(map != nullptr);
  125. ui->pushButtonRemove->setEnabled(map != nullptr);
  126. ui->radioButtonStartingOptionHeroCrossover->setEnabled(scenario.getNum() > 0);
  127. bool allowSelectingStartHero = false;
  128. if(map != nullptr)
  129. for(auto & player : map->players)
  130. if(player.generateHeroAtMainTown)
  131. allowSelectingStartHero = true;
  132. ui->radioButtonStartingOptionStartingHero->setEnabled(allowSelectingStartHero);
  133. ui->tabPrologueEpilogue->setEnabled(map != nullptr);
  134. ui->tabCrossover->setEnabled(map != nullptr);
  135. ui->tabStarting->setEnabled(map != nullptr);
  136. ui->comboBoxDefaultDifficulty->setEnabled(map != nullptr);
  137. ui->listWidgetPrerequisites->setEnabled(map != nullptr);
  138. ui->plainTextEditRightClickText->setEnabled(map != nullptr);
  139. ui->tableWidgetStartingCrossover->clearContents();
  140. ui->tableWidgetStartingCrossover->setRowCount(0);
  141. ui->listWidgetStartingBonusOption->clear();
  142. if(map != nullptr)
  143. {
  144. std::vector<PlayerColor> selectableColors;
  145. for(int i = 0; i < map->players.size(); i++)
  146. if(map->players[i].canHumanPlay)
  147. selectableColors.push_back(PlayerColor(i));
  148. ui->comboBoxStartingBonusPlayerPosition->clear();
  149. for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; ++i)
  150. {
  151. if(!vstd::contains(selectableColors, PlayerColor(i)))
  152. continue;
  153. MetaString str;
  154. str.appendRawString((tr("Player") + " ").toStdString());
  155. str.appendNumber(i + 1);
  156. str.appendRawString(" (");
  157. str.appendName(PlayerColor(i));
  158. str.appendRawString(")");
  159. ui->comboBoxStartingBonusPlayerPosition->addItem(QString::fromStdString(str.toString()), QVariant(i));
  160. }
  161. int index = ui->comboBoxStartingBonusPlayerPosition->findData(campaignState->scenarios.at(scenario).travelOptions.playerColor.getNum());
  162. if(index != -1)
  163. ui->comboBoxStartingBonusPlayerPosition->setCurrentIndex(index);
  164. }
  165. if(campaignState->scenarios.at(scenario).travelOptions.startOptions == CampaignStartOptions::HERO_CROSSOVER || campaignState->scenarios.at(scenario).travelOptions.startOptions == CampaignStartOptions::HERO_OPTIONS)
  166. {
  167. if(campaignState->scenarios.at(scenario).travelOptions.startOptions == CampaignStartOptions::HERO_OPTIONS)
  168. on_radioButtonStartingOptionStartingHero_toggled();
  169. else
  170. on_radioButtonStartingOptionHeroCrossover_toggled();
  171. for(int i = 0; i < campaignState->scenarios.at(scenario).travelOptions.bonusesToChoose.size(); i++)
  172. {
  173. auto bonus = campaignState->scenarios.at(scenario).travelOptions.bonusesToChoose[i];
  174. ui->tableWidgetStartingCrossover->insertRow(i);
  175. QComboBox* comboBoxOption = new QComboBox();
  176. if(campaignState->scenarios.at(scenario).travelOptions.startOptions == CampaignStartOptions::HERO_OPTIONS)
  177. {
  178. for(auto & hero : heroSelection)
  179. comboBoxOption->addItem(QString::fromStdString(hero.second), hero.first);
  180. }
  181. else
  182. {
  183. for(int j = 0; j < scenario.getNum(); ++j)
  184. {
  185. auto tmpScenario = CampaignScenarioID(j);
  186. auto text = QString::fromStdString(campaignState->getRegions().regions.at(j).infix) + " - " + QString::fromStdString(campaignState->scenarios.at(tmpScenario).mapName);
  187. comboBoxOption->addItem(text, j);
  188. }
  189. }
  190. QComboBox* comboBoxPlayer = new QComboBox();
  191. for(int i = 0; i < ui->comboBoxStartingBonusPlayerPosition->count(); ++i) // copy from player dropdown
  192. comboBoxPlayer->addItem(ui->comboBoxStartingBonusPlayerPosition->itemText(i), ui->comboBoxStartingBonusPlayerPosition->itemData(i));
  193. const auto & bonusValue = bonus.getValue<CampaignBonusHeroesFromScenario>();
  194. // set selected
  195. int index = comboBoxPlayer->findData(bonusValue.startingPlayer.getNum());
  196. if(index != -1)
  197. comboBoxPlayer->setCurrentIndex(index);
  198. index = comboBoxOption->findData(bonusValue.scenario.getNum());
  199. if(index != -1)
  200. comboBoxOption->setCurrentIndex(index);
  201. ui->tableWidgetStartingCrossover->setCellWidget(i, 0, comboBoxOption);
  202. ui->tableWidgetStartingCrossover->setCellWidget(i, 1, comboBoxPlayer);
  203. }
  204. ui->tableWidgetStartingCrossover->resizeColumnsToContents();
  205. }
  206. else if(campaignState->scenarios.at(scenario).travelOptions.startOptions == CampaignStartOptions::START_BONUS)
  207. {
  208. ui->listWidgetStartingBonusOption->clear();
  209. for(auto & bonus : campaignState->scenarios.at(scenario).travelOptions.bonusesToChoose)
  210. {
  211. QListWidgetItem * item = new QListWidgetItem(StartingBonus::getBonusListTitle(bonus, map));
  212. item->setData(Qt::UserRole, QVariant::fromValue(bonus));
  213. ui->listWidgetStartingBonusOption->addItem(item);
  214. }
  215. }
  216. reloadEnableState();
  217. }
  218. void ScenarioProperties::reloadEnableState()
  219. {
  220. ui->pushButtonStartingAdd->setEnabled(ui->tableWidgetStartingCrossover->rowCount() < 3 && ui->listWidgetStartingBonusOption->count() < 3);
  221. ui->pushButtonStartingRemove->setEnabled(ui->tableWidgetStartingCrossover->rowCount() > 0 || ui->listWidgetStartingBonusOption->count() > 0);
  222. }
  223. bool ScenarioProperties::showScenarioProperties(std::shared_ptr<CampaignState> campaignState, CampaignScenarioID scenario, EditorCallback * cb)
  224. {
  225. if(!campaignState || scenario == CampaignScenarioID::NONE)
  226. return false;
  227. auto * dialog = new ScenarioProperties(campaignState, scenario, cb);
  228. dialog->setAttribute(Qt::WA_DeleteOnClose);
  229. return dialog->exec() == QDialog::Accepted;
  230. }
  231. void ScenarioProperties::on_buttonBox_clicked(QAbstractButton * button)
  232. {
  233. if(button == ui->buttonBox->button(QDialogButtonBox::Ok))
  234. {
  235. campaignState->scenarios.at(scenario).regionText = MetaString::createFromRawString(ui->plainTextEditRightClickText->toPlainText().toStdString());
  236. campaignState->scenarios.at(scenario).regionColor = ui->comboBoxRegionColor->currentData().toInt();
  237. campaignState->scenarios.at(scenario).difficulty = ui->comboBoxDefaultDifficulty->currentData().toInt();
  238. campaignState->scenarios.at(scenario).prolog.hasPrologEpilog = ui->checkBoxPrologueEnabled->isChecked();
  239. campaignState->scenarios.at(scenario).prolog.prologVideo.first = VideoPath::builtin(ui->lineEditPrologueVideo->text().toStdString());
  240. campaignState->scenarios.at(scenario).prolog.prologVideo.second = VideoPath::builtin(ui->lineEditPrologueVideoLoop->text().toStdString());
  241. campaignState->scenarios.at(scenario).prolog.prologMusic = AudioPath::builtin(ui->lineEditPrologueMusic->text().toStdString());
  242. campaignState->scenarios.at(scenario).prolog.prologVoice = AudioPath::builtin(ui->lineEditPrologueVoice->text().toStdString());
  243. campaignState->scenarios.at(scenario).prolog.prologText = MetaString::createFromRawString(ui->plainTextEditPrologueText->toPlainText().toStdString());
  244. campaignState->scenarios.at(scenario).epilog.hasPrologEpilog = ui->checkBoxEpilogueEnabled->isChecked();
  245. campaignState->scenarios.at(scenario).epilog.prologVideo.first = VideoPath::builtin(ui->lineEditEpilogueVideo->text().toStdString());
  246. campaignState->scenarios.at(scenario).epilog.prologVideo.second = VideoPath::builtin(ui->lineEditEpilogueVideoLoop->text().toStdString());
  247. campaignState->scenarios.at(scenario).epilog.prologMusic = AudioPath::builtin(ui->lineEditEpilogueMusic->text().toStdString());
  248. campaignState->scenarios.at(scenario).epilog.prologVoice = AudioPath::builtin(ui->lineEditEpilogueVoice->text().toStdString());
  249. campaignState->scenarios.at(scenario).epilog.prologText = MetaString::createFromRawString(ui->plainTextEditEpilogueText->toPlainText().toStdString());
  250. campaignState->scenarios.at(scenario).travelOptions.whatHeroKeeps.experience = ui->checkBoxCrossoverExperience->isChecked();
  251. campaignState->scenarios.at(scenario).travelOptions.whatHeroKeeps.primarySkills = ui->checkBoxCrossoverPrimarySkills->isChecked();
  252. campaignState->scenarios.at(scenario).travelOptions.whatHeroKeeps.secondarySkills = ui->checkBoxCrossoverSecondarySkills->isChecked();
  253. campaignState->scenarios.at(scenario).travelOptions.whatHeroKeeps.spells = ui->checkBoxCrossoverSpells->isChecked();
  254. campaignState->scenarios.at(scenario).travelOptions.whatHeroKeeps.artifacts = ui->checkBoxCrossoverArtifacts->isChecked();
  255. CampaignStartOptions startOption = CampaignStartOptions::NONE;
  256. if(ui->radioButtonStartingOptionBonus->isChecked())
  257. startOption = CampaignStartOptions::START_BONUS;
  258. else if(ui->radioButtonStartingOptionHeroCrossover->isChecked())
  259. startOption = CampaignStartOptions::HERO_CROSSOVER;
  260. else if(ui->radioButtonStartingOptionStartingHero->isChecked())
  261. startOption = CampaignStartOptions::HERO_OPTIONS;
  262. campaignState->scenarios.at(scenario).travelOptions.startOptions = startOption;
  263. campaignState->scenarios.at(scenario).travelOptions.artifactsKeptByHero.clear();
  264. for(int i = 0; i < ui->listWidgetCrossoverArtifacts->count(); ++i)
  265. {
  266. auto * item = ui->listWidgetCrossoverArtifacts->item(i);
  267. if(item->checkState() == Qt::Checked)
  268. campaignState->scenarios.at(scenario).travelOptions.artifactsKeptByHero.emplace(i);
  269. }
  270. campaignState->scenarios.at(scenario).travelOptions.monstersKeptByHero.clear();
  271. for(int i = 0; i < ui->listWidgetCrossoverCreatures->count(); ++i)
  272. {
  273. auto * item = ui->listWidgetCrossoverCreatures->item(i);
  274. if(item->checkState() == Qt::Checked)
  275. campaignState->scenarios.at(scenario).travelOptions.monstersKeptByHero.emplace(i);
  276. }
  277. campaignState->scenarios.at(scenario).preconditionRegions.clear();
  278. for(int i = 0; i < ui->listWidgetPrerequisites->count(); ++i)
  279. {
  280. auto * item = ui->listWidgetPrerequisites->item(i);
  281. if(item->checkState() == Qt::Checked)
  282. campaignState->scenarios.at(scenario).preconditionRegions.emplace(i);
  283. }
  284. campaignState->scenarios.at(scenario).travelOptions.bonusesToChoose.clear();
  285. if(ui->radioButtonStartingOptionBonus->isChecked())
  286. {
  287. campaignState->scenarios.at(scenario).travelOptions.playerColor = PlayerColor(ui->comboBoxStartingBonusPlayerPosition->currentData().toInt());
  288. campaignState->scenarios.at(scenario).travelOptions.bonusesToChoose.clear();
  289. for (int i = 0; i < ui->listWidgetStartingBonusOption->count(); ++i) {
  290. QListWidgetItem *item = ui->listWidgetStartingBonusOption->item(i);
  291. campaignState->scenarios.at(scenario).travelOptions.bonusesToChoose.push_back(item->data(Qt::UserRole).value<CampaignBonus>());
  292. }
  293. }
  294. else if(ui->radioButtonStartingOptionHeroCrossover->isChecked() || ui->radioButtonStartingOptionStartingHero->isChecked())
  295. {
  296. for (int i = 0; i < ui->tableWidgetStartingCrossover->rowCount(); ++i)
  297. {
  298. QComboBox* comboBoxOption = qobject_cast<QComboBox*>(ui->tableWidgetStartingCrossover->cellWidget(i, 0));
  299. QComboBox* comboBoxPlayer = qobject_cast<QComboBox*>(ui->tableWidgetStartingCrossover->cellWidget(i, 1));
  300. CampaignBonus bonus;
  301. if (ui->radioButtonStartingOptionHeroCrossover->isChecked())
  302. {
  303. bonus = CampaignBonusHeroesFromScenario{
  304. PlayerColor(comboBoxPlayer->currentData().toInt()),
  305. CampaignScenarioID(comboBoxOption->currentData().toInt())
  306. };
  307. }
  308. else
  309. {
  310. bonus = CampaignBonusStartingHero{
  311. PlayerColor(comboBoxPlayer->currentData().toInt()),
  312. HeroTypeID(comboBoxOption->currentData().toInt())
  313. };
  314. }
  315. campaignState->scenarios.at(scenario).travelOptions.bonusesToChoose.push_back(bonus);
  316. }
  317. }
  318. accept();
  319. }
  320. close();
  321. }
  322. void ScenarioProperties::on_pushButtonCreatureTypeAll_clicked()
  323. {
  324. for(int i = 0; i < ui->listWidgetCrossoverCreatures->count(); ++i)
  325. ui->listWidgetCrossoverCreatures->item(i)->setCheckState(Qt::CheckState::Checked);
  326. }
  327. void ScenarioProperties::on_pushButtonCreatureTypeNone_clicked()
  328. {
  329. for(int i = 0; i < ui->listWidgetCrossoverCreatures->count(); ++i)
  330. ui->listWidgetCrossoverCreatures->item(i)->setCheckState(Qt::CheckState::Unchecked);
  331. }
  332. void ScenarioProperties::on_pushButtonImport_clicked()
  333. {
  334. auto filename = QFileDialog::getOpenFileName(this, tr("Open map"), "", tr("All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m)"));
  335. if(filename.isEmpty())
  336. return;
  337. QFile file(filename);
  338. if (!file.open(QIODevice::ReadOnly)) {
  339. QMessageBox::critical(nullptr, tr("Error"), tr("Could not open the file."));
  340. return;
  341. }
  342. QByteArray fileData = file.readAll();
  343. std::vector<uint8_t> byteArray(fileData.begin(), fileData.end());
  344. campaignState->mapPieces[scenario] = byteArray;
  345. QFileInfo fileInfo(filename);
  346. QString baseName = fileInfo.fileName();
  347. campaignState->scenarios.at(scenario).mapName = baseName.toStdString();
  348. if(!CampaignEditor::tryToOpenMap(this, campaignState, scenario, cb))
  349. {
  350. campaignState->mapPieces.erase(scenario);
  351. campaignState->scenarios.at(scenario) = CampaignScenario();
  352. return;
  353. }
  354. reloadMapRelatedUi();
  355. }
  356. void ScenarioProperties::on_pushButtonExport_clicked()
  357. {
  358. auto mapName = QString::fromStdString(campaignState->scenarios.at(scenario).mapName);
  359. bool isVmap = mapName.toLower().endsWith(".vmap");
  360. QString fileName = QFileDialog::getSaveFileName(nullptr, tr("Save map"), mapName, isVmap ? tr("VCMI maps (*.vmap);") : tr("HoMM3 maps (*.h3m);"));
  361. if (fileName.isEmpty())
  362. return;
  363. QFile file(fileName);
  364. if (!file.open(QIODevice::WriteOnly)) {
  365. QMessageBox::critical(nullptr, tr("Error"), tr("Could not open the file."));
  366. return;
  367. }
  368. auto byteArray = campaignState->mapPieces[scenario];
  369. QByteArray fileData(reinterpret_cast<const char*>(byteArray.data()), byteArray.size());
  370. file.write(fileData);
  371. }
  372. void ScenarioProperties::on_pushButtonRemove_clicked()
  373. {
  374. campaignState->mapPieces.erase(scenario);
  375. campaignState->scenarios.at(scenario) = CampaignScenario();
  376. reloadMapRelatedUi();
  377. }
  378. void ScenarioProperties::on_radioButtonStartingOptionBonus_toggled()
  379. {
  380. ui->tabWidgetStartOptions->setCurrentIndex(0);
  381. ui->listWidgetStartingBonusOption->clear();
  382. ui->pushButtonStartingEdit->setEnabled(true);
  383. }
  384. void ScenarioProperties::on_radioButtonStartingOptionHeroCrossover_toggled()
  385. {
  386. ui->tabWidgetStartOptions->setCurrentIndex(1);
  387. ui->tableWidgetStartingCrossover->clearContents();
  388. ui->tableWidgetStartingCrossover->setRowCount(0);
  389. ui->tableWidgetStartingCrossover->setHorizontalHeaderLabels({tr("Source scenario"), tr("Player position")});
  390. ui->tableWidgetStartingCrossover->resizeColumnsToContents();
  391. ui->pushButtonStartingEdit->setEnabled(false);
  392. }
  393. void ScenarioProperties::on_radioButtonStartingOptionStartingHero_toggled()
  394. {
  395. ui->tabWidgetStartOptions->setCurrentIndex(1);
  396. ui->tableWidgetStartingCrossover->clearContents();
  397. ui->tableWidgetStartingCrossover->setRowCount(0);
  398. ui->tableWidgetStartingCrossover->setHorizontalHeaderLabels({tr("Hero"), tr("Player position")});
  399. ui->tableWidgetStartingCrossover->resizeColumnsToContents();
  400. ui->pushButtonStartingEdit->setEnabled(false);
  401. }
  402. void ScenarioProperties::on_pushButtonStartingAdd_clicked()
  403. {
  404. if(ui->radioButtonStartingOptionHeroCrossover->isChecked() || ui->radioButtonStartingOptionStartingHero->isChecked())
  405. {
  406. int row = ui->tableWidgetStartingCrossover->rowCount();
  407. ui->tableWidgetStartingCrossover->insertRow(row);
  408. QComboBox* comboBoxOption = new QComboBox();
  409. if(ui->radioButtonStartingOptionStartingHero->isChecked())
  410. {
  411. for(auto & hero : heroSelection)
  412. comboBoxOption->addItem(QString::fromStdString(hero.second), hero.first);
  413. }
  414. else
  415. {
  416. for(int i = 0; i < scenario.getNum(); ++i)
  417. {
  418. auto tmpScenario = CampaignScenarioID(i);
  419. auto text = QString::fromStdString(campaignState->getRegions().regions.at(i).infix) + " - " + QString::fromStdString(campaignState->scenarios.at(tmpScenario).mapName);
  420. comboBoxOption->addItem(text, i);
  421. }
  422. }
  423. QComboBox* comboBoxPlayer = new QComboBox();
  424. for(int i = 0; i < ui->comboBoxStartingBonusPlayerPosition->count(); ++i) // copy from player dropdown
  425. comboBoxPlayer->addItem(ui->comboBoxStartingBonusPlayerPosition->itemText(i), ui->comboBoxStartingBonusPlayerPosition->itemData(i));
  426. ui->tableWidgetStartingCrossover->setCellWidget(row, 0, comboBoxOption);
  427. ui->tableWidgetStartingCrossover->setCellWidget(row, 1, comboBoxPlayer);
  428. ui->tableWidgetStartingCrossover->resizeColumnsToContents();
  429. }
  430. else
  431. {
  432. CampaignBonus bonus = CampaignBonusSpell{ HeroTypeID(), SpellID() };
  433. if(StartingBonus::showStartingBonus(PlayerColor(ui->comboBoxStartingBonusPlayerPosition->currentData().toInt()), map, bonus))
  434. {
  435. QListWidgetItem * item = new QListWidgetItem(StartingBonus::getBonusListTitle(bonus, map));
  436. item->setData(Qt::UserRole, QVariant::fromValue(bonus));
  437. ui->listWidgetStartingBonusOption->addItem(item);
  438. }
  439. }
  440. reloadEnableState();
  441. }
  442. void ScenarioProperties::on_pushButtonStartingEdit_clicked()
  443. {
  444. if(ui->radioButtonStartingOptionBonus->isChecked())
  445. {
  446. QList<QListWidgetItem *> selectedItems = ui->listWidgetStartingBonusOption->selectedItems();
  447. QListWidgetItem * item = selectedItems.takeFirst();
  448. CampaignBonus bonus = item->data(Qt::UserRole).value<CampaignBonus>();
  449. if(StartingBonus::showStartingBonus(PlayerColor(ui->comboBoxStartingBonusPlayerPosition->currentData().toInt()), map, bonus))
  450. {
  451. item->setText(StartingBonus::getBonusListTitle(bonus, map));
  452. item->setData(Qt::UserRole, QVariant::fromValue(bonus));
  453. }
  454. }
  455. }
  456. void ScenarioProperties::on_pushButtonStartingRemove_clicked()
  457. {
  458. if(ui->radioButtonStartingOptionHeroCrossover->isChecked() || ui->radioButtonStartingOptionStartingHero->isChecked())
  459. {
  460. int rows = ui->tableWidgetStartingCrossover->rowCount() - 1;
  461. ui->tableWidgetStartingCrossover->removeRow(rows);
  462. ui->tableWidgetStartingCrossover->setRowCount(rows);
  463. ui->tableWidgetStartingCrossover->resizeColumnsToContents();
  464. }
  465. else if(ui->radioButtonStartingOptionBonus->isChecked())
  466. {
  467. QList<QListWidgetItem *> selectedItems = ui->listWidgetStartingBonusOption->selectedItems();
  468. for (QListWidgetItem *item : selectedItems)
  469. delete ui->listWidgetStartingBonusOption->takeItem(ui->listWidgetStartingBonusOption->row(item));
  470. }
  471. reloadEnableState();
  472. }