startingbonus.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. * startingbonus.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 "startingbonus.h"
  12. #include "ui_startingbonus.h"
  13. #include "../../lib/mapObjects/CGHeroInstance.h"
  14. #include "../../lib/mapObjects/CGTownInstance.h"
  15. #include "../../lib/campaign/CampaignState.h"
  16. #include "../../lib/entities/building/CBuilding.h"
  17. #include "../../lib/entities/hero/CHero.h"
  18. #include "../../lib/mapping/CMap.h"
  19. #include "../../lib/CArtHandler.h"
  20. #include "../../lib/CSkillHandler.h"
  21. #include "../../lib/CCreatureHandler.h"
  22. #include "../../lib/spells/CSpellHandler.h"
  23. #include "../../lib/texts/CGeneralTextHandler.h"
  24. StartingBonus::StartingBonus(PlayerColor color, std::shared_ptr<CMap> map, CampaignBonus bonus):
  25. ui(new Ui::StartingBonus),
  26. bonus(bonus),
  27. map(map),
  28. color(color)
  29. {
  30. ui->setupUi(this);
  31. setWindowTitle(tr("Edit Starting Bonus"));
  32. setWindowModality(Qt::ApplicationModal);
  33. ui->tabWidget->tabBar()->hide();
  34. ui->tabWidget->setStyleSheet("QTabWidget::pane { border: 0; }");
  35. initControls();
  36. loadBonus();
  37. show();
  38. }
  39. StartingBonus::~StartingBonus()
  40. {
  41. delete ui;
  42. }
  43. void StartingBonus::initControls()
  44. {
  45. std::map<int, std::string> heroSelection;
  46. for(auto & hero : map->heroesOnMap)
  47. if(hero->getOwner() == color || color == PlayerColor::CANNOT_DETERMINE)
  48. heroSelection.emplace(hero->getHeroTypeID(), hero->getNameTranslated());
  49. heroSelection.emplace(HeroTypeID::CAMP_STRONGEST, tr("Strongest").toStdString());
  50. heroSelection.emplace(HeroTypeID::CAMP_GENERATED, tr("Generated").toStdString());
  51. heroSelection.emplace(HeroTypeID::CAMP_RANDOM, tr("Random").toStdString());
  52. for(auto & hero : heroSelection)
  53. {
  54. ui->comboBoxSpellRecipient->addItem(QString::fromStdString(hero.second), QVariant(hero.first));
  55. ui->comboBoxCreatureRecipient->addItem(QString::fromStdString(hero.second), QVariant(hero.first));
  56. ui->comboBoxArtifactRecipient->addItem(QString::fromStdString(hero.second), QVariant(hero.first));
  57. ui->comboBoxSpellScrollRecipient->addItem(QString::fromStdString(hero.second), QVariant(hero.first));
  58. ui->comboBoxPrimarySkillRecipient->addItem(QString::fromStdString(hero.second), QVariant(hero.first));
  59. ui->comboBoxSecondarySkillRecipient->addItem(QString::fromStdString(hero.second), QVariant(hero.first));
  60. }
  61. for(auto const & objectPtr : LIBRARY->spellh->objects)
  62. {
  63. ui->comboBoxSpellSpell->addItem(QString::fromStdString(objectPtr->getNameTranslated()), QVariant(objectPtr->getId()));
  64. ui->comboBoxSpellScrollSpell->addItem(QString::fromStdString(objectPtr->getNameTranslated()), QVariant(objectPtr->getId()));
  65. }
  66. for(auto const & objectPtr : LIBRARY->creh->objects)
  67. ui->comboBoxCreatureCreatureType->addItem(QString::fromStdString(objectPtr->getNameSingularTranslated()), QVariant(objectPtr->getId()));
  68. if(map->players[color].hasMainTown)
  69. for(auto & town : map->towns)
  70. if(town->pos == map->players[color].posOfMainTown)
  71. {
  72. for(auto & building : town->getTown()->buildings)
  73. ui->comboBoxBuildingBuilding->addItem(QString::fromStdString(building.second->getNameTranslated()), QVariant(building.first.getNum()));
  74. break;
  75. }
  76. for(auto const & objectPtr : LIBRARY->arth->objects)
  77. if(!vstd::contains(std::vector<ArtifactID>({
  78. ArtifactID::SPELL_SCROLL,
  79. ArtifactID::SPELLBOOK,
  80. ArtifactID::GRAIL,
  81. ArtifactID::AMMO_CART,
  82. ArtifactID::BALLISTA,
  83. ArtifactID::CATAPULT,
  84. ArtifactID::FIRST_AID_TENT,
  85. }), objectPtr->getId()))
  86. ui->comboBoxArtifactArtifact->addItem(QString::fromStdString(objectPtr->getNameTranslated()), QVariant(objectPtr->getId()));
  87. for(auto const & objectPtr : LIBRARY->skillh->objects)
  88. ui->comboBoxSecondarySkillSecondarySkill->addItem(QString::fromStdString(objectPtr->getNameTranslated()), QVariant(objectPtr->getId()));
  89. for(int i = 0; i < 3; i++) // Basic, Advanced, Expert
  90. ui->comboBoxSecondarySkillMastery->addItem(QString::fromStdString(LIBRARY->generaltexth->translate("core.skilllev", i)), QVariant(i));
  91. for(auto & res : std::vector<EGameResID>({EGameResID::WOOD, EGameResID::MERCURY, EGameResID::ORE, EGameResID::SULFUR, EGameResID::CRYSTAL, EGameResID::GEMS, EGameResID::GOLD}))
  92. ui->comboBoxResourceResourceType->addItem(QString::fromStdString(MetaString::createFromName(res).toString()), QVariant(res));
  93. ui->comboBoxResourceResourceType->addItem(
  94. tr("Common (%1 and %2)")
  95. .arg(QString::fromStdString(MetaString::createFromName(EGameResID::WOOD).toString()))
  96. .arg(QString::fromStdString(MetaString::createFromName(EGameResID::ORE).toString()))
  97. , QVariant(EGameResID::COMMON));
  98. ui->comboBoxResourceResourceType->addItem(
  99. tr("Rare (%1, %2, %3, %4)")
  100. .arg(QString::fromStdString(MetaString::createFromName(EGameResID::MERCURY).toString()))
  101. .arg(QString::fromStdString(MetaString::createFromName(EGameResID::SULFUR).toString()))
  102. .arg(QString::fromStdString(MetaString::createFromName(EGameResID::CRYSTAL).toString()))
  103. .arg(QString::fromStdString(MetaString::createFromName(EGameResID::GEMS).toString()))
  104. , QVariant(EGameResID::RARE));
  105. }
  106. void StartingBonus::loadBonus()
  107. {
  108. auto setComboBoxValue = [](QComboBox * comboBox, QVariant data){
  109. int index = comboBox->findData(data);
  110. if(index != -1)
  111. comboBox->setCurrentIndex(index);
  112. };
  113. switch (bonus.type)
  114. {
  115. case CampaignBonusType::SPELL:
  116. ui->radioButtonSpell->setChecked(true);
  117. on_radioButtonSpell_toggled();
  118. setComboBoxValue(ui->comboBoxSpellRecipient, bonus.info1);
  119. setComboBoxValue(ui->comboBoxSpellSpell, bonus.info2);
  120. break;
  121. case CampaignBonusType::MONSTER:
  122. ui->radioButtonCreature->setChecked(true);
  123. on_radioButtonCreature_toggled();
  124. setComboBoxValue(ui->comboBoxCreatureRecipient, bonus.info1);
  125. setComboBoxValue(ui->comboBoxCreatureCreatureType, bonus.info2);
  126. ui->spinBoxCreatureQuantity->setValue(bonus.info3);
  127. break;
  128. case CampaignBonusType::BUILDING:
  129. ui->radioButtonBuilding->setChecked(true);
  130. on_radioButtonBuilding_toggled();
  131. setComboBoxValue(ui->comboBoxBuildingBuilding, bonus.info1);
  132. break;
  133. case CampaignBonusType::ARTIFACT:
  134. ui->radioButtonArtifact->setChecked(true);
  135. on_radioButtonArtifact_toggled();
  136. setComboBoxValue(ui->comboBoxArtifactRecipient, bonus.info1);
  137. setComboBoxValue(ui->comboBoxArtifactArtifact, bonus.info2);
  138. break;
  139. case CampaignBonusType::SPELL_SCROLL:
  140. ui->radioButtonSpellScroll->setChecked(true);
  141. on_radioButtonSpellScroll_toggled();
  142. setComboBoxValue(ui->comboBoxSpellScrollRecipient, bonus.info1);
  143. setComboBoxValue(ui->comboBoxSpellScrollSpell, bonus.info2);
  144. break;
  145. case CampaignBonusType::PRIMARY_SKILL:
  146. ui->radioButtonPrimarySkill->setChecked(true);
  147. on_radioButtonPrimarySkill_toggled();
  148. setComboBoxValue(ui->comboBoxPrimarySkillRecipient, bonus.info1);
  149. ui->spinBoxPrimarySkillAttack->setValue((bonus.info2 >> 0) & 0xff);
  150. ui->spinBoxPrimarySkillDefense->setValue((bonus.info2 >> 8) & 0xff);
  151. ui->spinBoxPrimarySkillSpell->setValue((bonus.info2 >> 16) & 0xff);
  152. ui->spinBoxPrimarySkillKnowledge->setValue((bonus.info2 >> 24) & 0xff);
  153. break;
  154. case CampaignBonusType::SECONDARY_SKILL:
  155. ui->radioButtonSecondarySkill->setChecked(true);
  156. on_radioButtonSecondarySkill_toggled();
  157. setComboBoxValue(ui->comboBoxSecondarySkillRecipient, bonus.info1);
  158. setComboBoxValue(ui->comboBoxSecondarySkillSecondarySkill, bonus.info2);
  159. setComboBoxValue(ui->comboBoxSecondarySkillMastery, bonus.info3);
  160. break;
  161. case CampaignBonusType::RESOURCE:
  162. ui->radioButtonResource->setChecked(true);
  163. on_radioButtonResource_toggled();
  164. setComboBoxValue(ui->comboBoxResourceResourceType, bonus.info1);
  165. ui->spinBoxResourceQuantity->setValue(bonus.info2);
  166. break;
  167. default:
  168. break;
  169. }
  170. }
  171. void StartingBonus::saveBonus()
  172. {
  173. if(ui->radioButtonSpell->isChecked())
  174. bonus.type = CampaignBonusType::SPELL;
  175. else if(ui->radioButtonCreature->isChecked())
  176. bonus.type = CampaignBonusType::MONSTER;
  177. else if(ui->radioButtonBuilding->isChecked())
  178. bonus.type = CampaignBonusType::BUILDING;
  179. else if(ui->radioButtonArtifact->isChecked())
  180. bonus.type = CampaignBonusType::ARTIFACT;
  181. else if(ui->radioButtonSpellScroll->isChecked())
  182. bonus.type = CampaignBonusType::SPELL_SCROLL;
  183. else if(ui->radioButtonPrimarySkill->isChecked())
  184. bonus.type = CampaignBonusType::PRIMARY_SKILL;
  185. else if(ui->radioButtonSecondarySkill->isChecked())
  186. bonus.type = CampaignBonusType::SECONDARY_SKILL;
  187. else if(ui->radioButtonResource->isChecked())
  188. bonus.type = CampaignBonusType::RESOURCE;
  189. bonus.info1 = 0;
  190. bonus.info2 = 0;
  191. bonus.info3 = 0;
  192. switch (bonus.type)
  193. {
  194. case CampaignBonusType::SPELL:
  195. bonus.info1 = ui->comboBoxSpellRecipient->currentData().toInt();
  196. bonus.info2 = ui->comboBoxSpellSpell->currentData().toInt();
  197. break;
  198. case CampaignBonusType::MONSTER:
  199. bonus.info1 = ui->comboBoxCreatureRecipient->currentData().toInt();
  200. bonus.info2 = ui->comboBoxCreatureCreatureType->currentData().toInt();
  201. bonus.info3 = ui->spinBoxCreatureQuantity->value();
  202. break;
  203. case CampaignBonusType::BUILDING:
  204. bonus.info1 = ui->comboBoxBuildingBuilding->currentData().toInt();
  205. break;
  206. case CampaignBonusType::ARTIFACT:
  207. bonus.info1 = ui->comboBoxArtifactRecipient->currentData().toInt();
  208. bonus.info2 = ui->comboBoxArtifactArtifact->currentData().toInt();
  209. break;
  210. case CampaignBonusType::SPELL_SCROLL:
  211. bonus.info1 = ui->comboBoxSpellScrollRecipient->currentData().toInt();
  212. bonus.info2 = ui->comboBoxSpellScrollSpell->currentData().toInt();
  213. break;
  214. case CampaignBonusType::PRIMARY_SKILL:
  215. bonus.info1 = ui->comboBoxPrimarySkillRecipient->currentData().toInt();
  216. bonus.info2 |= ui->spinBoxPrimarySkillAttack->value() << 0;
  217. bonus.info2 |= ui->spinBoxPrimarySkillDefense->value() << 8;
  218. bonus.info2 |= ui->spinBoxPrimarySkillSpell->value() << 16;
  219. bonus.info2 |= ui->spinBoxPrimarySkillKnowledge->value() << 24;
  220. break;
  221. case CampaignBonusType::SECONDARY_SKILL:
  222. bonus.info1 = ui->comboBoxSecondarySkillRecipient->currentData().toInt();
  223. bonus.info2 = ui->comboBoxSecondarySkillSecondarySkill->currentData().toInt();
  224. bonus.info3 = ui->comboBoxSecondarySkillMastery->currentData().toInt();
  225. break;
  226. case CampaignBonusType::RESOURCE:
  227. bonus.info1 = ui->comboBoxResourceResourceType->currentData().toInt();
  228. bonus.info2 = ui->spinBoxResourceQuantity->value();
  229. break;
  230. default:
  231. break;
  232. }
  233. }
  234. void StartingBonus::on_buttonBox_clicked(QAbstractButton * button)
  235. {
  236. if(button == ui->buttonBox->button(QDialogButtonBox::Ok))
  237. {
  238. saveBonus();
  239. accept();
  240. }
  241. close();
  242. }
  243. bool StartingBonus::showStartingBonus(PlayerColor color, std::shared_ptr<CMap> map, CampaignBonus & bonus)
  244. {
  245. auto * dialog = new StartingBonus(color, map, bonus);
  246. dialog->setAttribute(Qt::WA_DeleteOnClose);
  247. auto result = dialog->exec();
  248. if(result == QDialog::Accepted)
  249. bonus = dialog->bonus;
  250. return result == QDialog::Accepted;
  251. }
  252. QString StartingBonus::getBonusListTitle(CampaignBonus bonus, std::shared_ptr<CMap> map)
  253. {
  254. auto getHeroName = [map](int id){
  255. MetaString tmp;
  256. if(id == HeroTypeID::CAMP_STRONGEST)
  257. tmp.appendRawString(tr("strongest hero").toStdString());
  258. else if(id == HeroTypeID::CAMP_GENERATED)
  259. tmp.appendRawString(tr("generated hero").toStdString());
  260. else if(id == HeroTypeID::CAMP_RANDOM)
  261. tmp.appendRawString(tr("random hero").toStdString());
  262. else
  263. {
  264. for(auto o : map->objects)
  265. if(auto * ins = dynamic_cast<CGHeroInstance *>(o.get()))
  266. if(ins->getHeroTypeID().getNum() == id)
  267. tmp.appendTextID(ins->getNameTextID());
  268. }
  269. return QString::fromStdString(tmp.toString());
  270. };
  271. auto getSpellName = [](int id){
  272. MetaString tmp;
  273. tmp.appendName(SpellID(id));
  274. return QString::fromStdString(tmp.toString());
  275. };
  276. auto getMonsterName = [](int id, int amount){
  277. MetaString tmp;
  278. tmp.appendName(CreatureID(id), amount);
  279. return QString::fromStdString(tmp.toString());
  280. };
  281. auto getArtifactName = [](int id){
  282. MetaString tmp;
  283. tmp.appendName(ArtifactID(id));
  284. return QString::fromStdString(tmp.toString());
  285. };
  286. switch (bonus.type)
  287. {
  288. case CampaignBonusType::SPELL:
  289. return tr("%1 spell for %2").arg(getSpellName(bonus.info2)).arg(getHeroName(bonus.info1));
  290. case CampaignBonusType::MONSTER:
  291. return tr("%1 %2 for %3").arg(bonus.info3).arg(getMonsterName(bonus.info2, bonus.info3)).arg(getHeroName(bonus.info1));
  292. case CampaignBonusType::BUILDING:
  293. return tr("Building");
  294. case CampaignBonusType::ARTIFACT:
  295. return tr("%1 artifact for %2").arg(getArtifactName(bonus.info2)).arg(getHeroName(bonus.info1));
  296. case CampaignBonusType::SPELL_SCROLL:
  297. return tr("%1 spell scroll for %2").arg(getSpellName(bonus.info2)).arg(getHeroName(bonus.info1));
  298. case CampaignBonusType::PRIMARY_SKILL:
  299. return tr("Primary skill (Attack: %1, Defense: %2, Spell: %3, Knowledge: %4) for %5").arg((bonus.info2 >> 0) & 0xff).arg((bonus.info2 >> 8) & 0xff).arg((bonus.info2 >> 16) & 0xff).arg((bonus.info2 >> 24) & 0xff).arg(getHeroName(bonus.info1));
  300. case CampaignBonusType::SECONDARY_SKILL:
  301. return tr("Secondary skill");
  302. case CampaignBonusType::RESOURCE:
  303. return tr("Resource");
  304. }
  305. return {};
  306. }
  307. void StartingBonus::on_radioButtonSpell_toggled()
  308. {
  309. ui->tabWidget->setCurrentIndex(0);
  310. }
  311. void StartingBonus::on_radioButtonCreature_toggled()
  312. {
  313. ui->tabWidget->setCurrentIndex(1);
  314. }
  315. void StartingBonus::on_radioButtonBuilding_toggled()
  316. {
  317. ui->tabWidget->setCurrentIndex(2);
  318. }
  319. void StartingBonus::on_radioButtonArtifact_toggled()
  320. {
  321. ui->tabWidget->setCurrentIndex(3);
  322. }
  323. void StartingBonus::on_radioButtonSpellScroll_toggled()
  324. {
  325. ui->tabWidget->setCurrentIndex(4);
  326. }
  327. void StartingBonus::on_radioButtonPrimarySkill_toggled()
  328. {
  329. ui->tabWidget->setCurrentIndex(5);
  330. }
  331. void StartingBonus::on_radioButtonSecondarySkill_toggled()
  332. {
  333. ui->tabWidget->setCurrentIndex(6);
  334. }
  335. void StartingBonus::on_radioButtonResource_toggled()
  336. {
  337. ui->tabWidget->setCurrentIndex(7);
  338. }