recruitmentscene.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. #include "ui/hotseat_recruitment/recruitmentscene.h"
  2. #include "ui/dialog_form/dialogform.h"
  3. #include "ui_recruitmentscene.h"
  4. #include "gui/guiscenemanager.h"
  5. #include "gui/scene.h"
  6. #include "hotseatgame/gameproperties.h"
  7. #include "player.h"
  8. #include "playermanager.h"
  9. #include "race.h"
  10. #include "racemanager.h"
  11. #include "soundengine.h"
  12. #include <QString>
  13. #include <QStringList>
  14. #include <QMovie>
  15. #include <QDebug>
  16. #include <QMouseEvent>
  17. #include <vector>
  18. RecruitmentScene::RecruitmentScene(QWidget *parent)
  19. : Scene(parent)
  20. , ui(new Ui::RecruitmentScene)
  21. {
  22. ui->setupUi(this);
  23. movie = new QMovie(":/assets/hotseat_recruit/image.gif");\
  24. movie->setScaledSize(QSize(600, 420));
  25. movie->supportedFormats();
  26. ui->image->setMovie(movie);
  27. movie->start();
  28. watcher = new ButtonEventListener(this);
  29. ui->complete_choice_button->installEventFilter(watcher);
  30. ui->back_button->installEventFilter(watcher);
  31. // Создаём обработчик событий нажатия иконок рас
  32. race_icon_watcher = new RaceIconEventListener(this, this);
  33. for (unsigned i = 0; i < GameProperties::RACES_MAXNUM; i++) {
  34. QLabel* race_icon = findChild<QLabel*>("available_race_" + QString::number(i));
  35. if (race_icon)
  36. race_icon->installEventFilter(race_icon_watcher);
  37. }
  38. ui->chosen_race_image_->installEventFilter(race_icon_watcher);
  39. // Создаём обработчик событий нажатия иконок юнитов
  40. unit_icon_watcher = new UnitIconEventListener(this, this);
  41. for (unsigned i = 0; i < GameProperties::AVAILABLE_UNIT_MAXNUM; i++) {
  42. QLabel* unit_icon = findChild<QLabel*>("available_unit_" + QString::number(i));
  43. if (unit_icon)
  44. unit_icon->installEventFilter(unit_icon_watcher);
  45. }
  46. for (unsigned i = 0; i < GameProperties::MAX_PARTY_SIZE; i++) {
  47. QLabel* unit_icon = findChild<QLabel*>("chosen_unit_" + QString::number(i));
  48. if (unit_icon)
  49. unit_icon->installEventFilter(unit_icon_watcher);
  50. }
  51. }
  52. RecruitmentScene::~RecruitmentScene()
  53. {
  54. }
  55. void RecruitmentScene::parseArgs(QString args) {
  56. QStringList list = args.split("|");
  57. if (list.size() < 2) {
  58. // TODO: ERROR MESSAGE - incorrect arguments number
  59. GuiSceneManager::getInstance().changeScene("main_menu");
  60. }
  61. current_player_id_ = list[0].toInt();
  62. current_player_ = PlayerManager::getInstance().getPlayer(current_player_id_);
  63. available_money_ = std::max(0, list[1].toInt());
  64. if (!current_player_) {
  65. // TODO: ERROR MESSAGE - incorrect argument - player_id;
  66. GuiSceneManager::getInstance().changeScene("main_menu");
  67. }
  68. DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
  69. if (!form)
  70. return;
  71. form->setTitle("Найм юнитов для игрока: " + current_player_->getPlayerName());
  72. form->setShowCancel(false);
  73. form->setText("Игрок \"" + current_player_->getPlayerName() + "\", пришло время вам набрать свой отряд!");
  74. GuiSceneManager::getInstance().show("dialog_form");
  75. form->exec();
  76. GuiSceneManager::getInstance().hide("dialog_form");
  77. }
  78. void RecruitmentScene::init() {
  79. current_money_ = available_money_;
  80. initAvailableRaces();
  81. initAvailableUnits();
  82. showChosenUnits();
  83. ui->title_->setText(
  84. "<p align=\"center\">Набор юнитов - " + current_player_->getPlayerName() + "</p>"
  85. );
  86. QString race_name = current_player_->getRace()->getRaceId();
  87. ui->chosen_race_image_->setText(
  88. "<img src=\":/assets/units/" + race_name + "/icon.png\" width=\"100\" height=\"100\"/>"
  89. );
  90. updateMoney();
  91. }
  92. Player *RecruitmentScene::getActivePlayer()
  93. {
  94. return current_player_;
  95. }
  96. bool RecruitmentScene::buyUnit(std::shared_ptr<Unit> unit)
  97. {
  98. if (!unit || unit->getCost() > current_money_ || current_player_->getUnits().size() >= GameProperties::MAX_PARTY_SIZE)
  99. return false;
  100. current_player_->addUnit(unit);
  101. current_money_ -= unit->getCost();
  102. updateMoney();
  103. showChosenUnits();
  104. return true;
  105. }
  106. bool RecruitmentScene::removeUnit(std::shared_ptr<Unit> unit) {
  107. current_money_ += unit->getCost();
  108. updateMoney();
  109. current_player_->deleteUnit(unit);
  110. showChosenUnits();
  111. return true;
  112. }
  113. void RecruitmentScene::initAvailableRaces() {
  114. auto races = RaceManager::getInstance().getAvailableRacesList();
  115. races_list.clear();
  116. for (unsigned i = 0; i < std::min(size_t(GameProperties::RACES_MAXNUM), races.size()); i++) {
  117. QString race_name = races[i];
  118. races_list.push_back(RaceManager::getInstance().getRace(race_name));
  119. QLabel* race_icon = findChild<QLabel*>("available_race_" + QString::number(i));
  120. if (race_icon)
  121. race_icon->setText("<img src=\":/assets/units/" + race_name + "/icon.png\" width=\"66\" height=\"66\"/>");
  122. }
  123. }
  124. void RecruitmentScene::initAvailableUnits() {
  125. auto units_list = current_player_->getRace()->getAllUnitsList();
  126. available_units_list.clear();
  127. for (unsigned i = 0; i < std::min(size_t(GameProperties::AVAILABLE_UNIT_MAXNUM), units_list.size()); i++) {
  128. QString race_name = current_player_->getRace()->getRaceId();
  129. QString unit_name = units_list[i]->getUnitId();
  130. available_units_list.push_back(units_list[i]);
  131. QLabel* unit_icon = findChild<QLabel*>("available_unit_" + QString::number(i));
  132. qDebug() << "<img src=\":/assets/units/" + race_name + "/" + unit_name + "/icon.png\" width=\"58\" height=\"58\"/>";
  133. if (unit_icon)
  134. unit_icon->setText("<img src=\":/assets/units/" + race_name + "/" + unit_name + "/icon.png\" width=\"58\" height=\"58\"/>");
  135. }
  136. }
  137. void RecruitmentScene::showChosenUnits() {
  138. unsigned counter = 0;
  139. chosen_units_list.clear();
  140. for (auto unit : current_player_->getUnits()) {
  141. if (counter >= GameProperties::MAX_PARTY_SIZE)
  142. break;
  143. QString unit_name = unit->getUnitId();
  144. chosen_units_list.push_back(unit);
  145. QString race_name = current_player_->getRace()->getRaceId();
  146. QLabel* unit_icon = findChild<QLabel*>("chosen_unit_" + QString::number(counter));
  147. if (unit_icon) {
  148. unit_icon->setText("<img src=\":/assets/units/" + race_name + "/" + unit_name + "/icon.png\" width=\"58\" height=\"58\"/>");
  149. unit_icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_default.png);\nbackground-color: rgb(253, 234, 168);");
  150. }
  151. counter++;
  152. }
  153. for (unsigned i = counter; i < GameProperties::MAX_PARTY_SIZE; i++) {
  154. QLabel* unit_icon = findChild<QLabel*>("chosen_unit_" + QString::number(i));
  155. if (unit_icon) {
  156. unit_icon->setText("");
  157. unit_icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_default.png);\nbackground-color: rgb(253, 234, 168);");
  158. }
  159. }
  160. }
  161. void RecruitmentScene::changeRace(std::shared_ptr<Race> race) {
  162. current_player_->clearUnits();
  163. current_player_->setRace(race);
  164. init();
  165. }
  166. void RecruitmentScene::updateMoney() {
  167. ui->available_money_text_->setText("Монеты: " + QString::number(current_money_));
  168. }
  169. void RecruitmentScene::on_back_button_clicked() {
  170. GuiSceneManager::getInstance().changeScene("pvp_intro");
  171. }
  172. void RecruitmentScene::on_complete_choice_button_clicked()
  173. {
  174. qDebug() << "Exiting recruit army scene with player_id =" << current_player_id_;
  175. if (current_player_id_ == 0) {
  176. qDebug() << "Changing to 1";
  177. GuiSceneManager::getInstance().changeScene("recruit_army", "1|" + QString::number(available_money_));
  178. } else {
  179. GuiSceneManager::getInstance().changeScene("prebattle");
  180. }
  181. }
  182. RaceIconEventListener::RaceIconEventListener(QObject *parent, RecruitmentScene* scene)
  183. : QObject(parent)
  184. , scene_(scene) {
  185. }
  186. bool RaceIconEventListener::eventFilter(QObject *watched, QEvent *event) {
  187. QLabel* icon = qobject_cast<QLabel*>(watched);
  188. if (!icon) {
  189. return false;
  190. }
  191. if (event->type() == QEvent::Enter) {
  192. if (icon->objectName() != "chosen_race_image_") {
  193. icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_hover.png);\nbackground-color: rgb(253, 234, 168);");
  194. SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_hover.mp3");
  195. unsigned race_id_number = icon->objectName().mid(icon->objectName().lastIndexOf('_') + 1).toInt();
  196. IconHint *hint = new IconHint(scene_);
  197. hint->setHintText("ЛКМ - сменить расу<br>ПКМ - открыть окно информации");
  198. hint->setHintTitle("Раса \"" + scene_->races_list[race_id_number]->getRaceName() + "\"");
  199. hint->move(icon->mapToGlobal(QPoint(0,0)).x() + icon->width() / 2 - hint->width() / 2, icon->mapToGlobal(QPoint(0,0)).y() + icon->height() + 2);
  200. } else {
  201. QString race_name = scene_->getActivePlayer()->getRace()->getRaceName();
  202. IconHint *hint = new IconHint(scene_);
  203. hint->setHintTitle("Раса \"" + race_name + "\"");
  204. hint->setHintText("ПКМ - открыть окно информации");
  205. hint->move(icon->mapToGlobal(QPoint(0,0)).x() + icon->width() / 2 - hint->width() / 2, icon->mapToGlobal(QPoint(0,0)).y() + icon->height() + 2);
  206. }
  207. return false;
  208. }
  209. if (event->type() == QEvent::Leave) {
  210. if (icon->objectName() != "chosen_race_image_") {
  211. icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_default.png);\nbackground-color: rgb(253, 234, 168);");
  212. SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_hover.mp3");
  213. if (!scene_)
  214. return false;
  215. }
  216. QList<IconHint*> hints = scene_->findChildren<IconHint*>("hint");
  217. for (auto &hint : hints) {
  218. hint->hide();
  219. hint->deleteLater();
  220. }
  221. return false;
  222. }
  223. if (event->type() == QEvent::MouseButtonPress) {
  224. if (icon->objectName() != "chosen_race_image_")
  225. icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_active.png);\nbackground-color: rgb(253, 234, 168);");
  226. SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_click.mp3");
  227. }
  228. if (event->type() == QEvent::MouseButtonRelease) {
  229. if (icon->objectName() != "chosen_race_image_")
  230. icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_hover.png);\nbackground-color: rgb(253, 234, 168);");
  231. QMouseEvent *evt = dynamic_cast<QMouseEvent*>(event);
  232. if (evt->button() == Qt::LeftButton) {
  233. if (icon->objectName() == "chosen_race_image_")
  234. return false;
  235. GuiSceneManager::getInstance().show("dialog_form");
  236. DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
  237. if (!form)
  238. return false;
  239. form->setTitle("Смена расы");
  240. form->setShowCancel(true);
  241. form->setText("Вы уверены, что хотите сменить расу? В этом случае все нанятые и улучшенные юниты исчезнут, а число монет будет восстановлено");
  242. form->exec();
  243. if (form->isOk()) {
  244. unsigned race_id_number = icon->objectName().mid(icon->objectName().lastIndexOf('_') + 1).toInt();
  245. scene_->changeRace(scene_->races_list[race_id_number]);
  246. }
  247. GuiSceneManager::getInstance().hide("dialog_form");
  248. }
  249. if (evt->button() == Qt::RightButton) {
  250. DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
  251. if (!form)
  252. return false;
  253. form->setTitle("Окно информации о расе");
  254. form->setShowCancel(false);
  255. form->setText("Окно информации о расе пока недоступно, извините");
  256. GuiSceneManager::getInstance().show("dialog_form");
  257. form->exec();
  258. GuiSceneManager::getInstance().hide("dialog_form");
  259. return false;
  260. }
  261. }
  262. return false;
  263. }
  264. UnitIconEventListener::UnitIconEventListener(QObject *parent, RecruitmentScene *scene)
  265. : QObject(parent)
  266. , scene_(scene) {
  267. }
  268. bool UnitIconEventListener::eventFilter(QObject *watched, QEvent *event) {
  269. QLabel* icon = qobject_cast<QLabel*>(watched);
  270. if (!icon) {
  271. qDebug() << __FILE__ << " " << __LINE__ << " cannot cast to icon!";
  272. return false;
  273. }
  274. unsigned unit_id_number = icon->objectName().mid(icon->objectName().lastIndexOf('_') + 1).toInt();
  275. QString icon_name = icon->objectName();
  276. if (icon_name.contains("available_unit") && unit_id_number >= scene_->available_units_list.size()) {
  277. return false;
  278. }
  279. if (icon_name.contains("chosen_unit") && unit_id_number >= scene_->chosen_units_list.size()) {
  280. return false;
  281. }
  282. std::shared_ptr<Unit> unit;
  283. if (icon_name.contains("available_unit"))
  284. unit = scene_->available_units_list[unit_id_number];
  285. else
  286. unit = scene_->chosen_units_list[unit_id_number];
  287. if (event->type() == QEvent::Enter) {
  288. icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_hover.png);\nbackground-color: rgb(253, 234, 168);");
  289. SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_hover.mp3");
  290. IconHint *hint = new IconHint(scene_);
  291. hint->resize(300, 300);
  292. hint->setHintTitle(unit->getUnitName());
  293. QString buttons_hint;
  294. if (icon_name.contains("available_unit"))
  295. buttons_hint = "<br>ЛКМ - нанять юнита<br>ПКМ - информация и улучшения";
  296. if (icon_name.contains("chosen_unit"))
  297. buttons_hint = "<br>ЛКМ - информация и улучшения<br>ПКМ - вернуть юнита";
  298. hint->setHintText("Стоимость: " + QString::number(unit->getCost()) + buttons_hint);
  299. hint->move(icon->mapToGlobal(QPoint(0,0)).x() + icon->width() / 2 - hint->width() / 2, icon->mapToGlobal(QPoint(0,0)).y() + icon->height() + 2);
  300. }
  301. if (event->type() == QEvent::Leave) {
  302. icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_default.png);\nbackground-color: rgb(253, 234, 168);");
  303. SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_hover.mp3");
  304. QList<IconHint*> hints = scene_->findChildren<IconHint*>("hint");
  305. for (auto &hint : hints) {
  306. hint->hide();
  307. hint->deleteLater();
  308. }
  309. }
  310. if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) {
  311. icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_active.png);\nbackground-color: rgb(253, 234, 168);");
  312. SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_click.mp3");
  313. }
  314. if (event->type() == QEvent::MouseButtonRelease) {
  315. icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_hover.png);\nbackground-color: rgb(253, 234, 168);");
  316. QMouseEvent *evt = dynamic_cast<QMouseEvent*>(event);
  317. if (evt->button() == Qt::LeftButton) {
  318. if (icon_name.contains("available_unit")) {
  319. if (scene_->buyUnit(unit))
  320. return false;
  321. DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
  322. if (!form)
  323. return false;
  324. form->setTitle("Набор юнита " + unit->getUnitName());
  325. form->setShowCancel(false);
  326. form->setText("Не могу нанять юнита. Проверьте, возможно он слишком дорогой или для него нет места в отряде?");
  327. GuiSceneManager::getInstance().show("dialog_form");
  328. form->exec();
  329. GuiSceneManager::getInstance().hide("dialog_form");
  330. return false;
  331. }
  332. if (icon_name.contains("chosen_unit")) {
  333. DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
  334. if (!form) {
  335. return false;
  336. }
  337. form->setTitle("Окно информации о юните " + unit->getUnitName());
  338. form->setShowCancel(false);
  339. form->setText("К сожалению, окно информации о юните и его улучшениях временно недоступно<br>В данной версии вы можете выбирать только из юнитов первого звена");
  340. GuiSceneManager::getInstance().show("dialog_form");
  341. form->exec();
  342. GuiSceneManager::getInstance().hide("dialog_form");
  343. return false;
  344. }
  345. }
  346. if (evt->button() == Qt::RightButton) {
  347. if (icon_name.contains("available_unit")) {
  348. DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
  349. if (!form) {
  350. return false;
  351. }
  352. form->setTitle("Окно информации о юните " + unit->getUnitName());
  353. form->setShowCancel(false);
  354. form->setText("К сожалению, окно информации о юните и его улучшениях временно недоступно :( <br> В данной версии вы можете выбирать только из юнитов первого звена");
  355. GuiSceneManager::getInstance().show("dialog_form");
  356. form->exec();
  357. GuiSceneManager::getInstance().hide("dialog_form");
  358. return false;
  359. }
  360. if (icon_name.contains("chosen_unit")) {
  361. scene_->removeUnit(unit);
  362. QList<IconHint*> hints = scene_->findChildren<IconHint*>("hint");
  363. for (auto &hint : hints) {
  364. hint->hide();
  365. hint->deleteLater();
  366. }
  367. if (scene_->childAt(QCursor::pos()) == icon) {
  368. QEvent *event = new QEvent(QEvent::Enter);
  369. QCoreApplication::postEvent(icon, event);
  370. }
  371. }
  372. }
  373. }
  374. return false;
  375. }