فهرست منبع

Changed source and header filenames to correct UpperCase

Ivan Arkhipov 6 سال پیش
والد
کامیت
a792d3f7ce
53فایلهای تغییر یافته به همراه5551 افزوده شده و 4 حذف شده
  1. 15 4
      client.pro
  2. 55 0
      include/AbstractFactory.h
  3. 91 0
      include/Player.h
  4. 33 0
      include/PlayerManager.h
  5. 44 0
      include/Race.h
  6. 33 0
      include/RaceManager.h
  7. 56 0
      include/effects/Effect.h
  8. 15 0
      include/effects/MelleDamage.h
  9. 16 0
      include/effects/SelfHeal.h
  10. 46 0
      include/gui/GUI.h
  11. 156 0
      include/gui/GUI.ui
  12. 47 0
      include/gui/GuiSceneManager.h
  13. 32 0
      include/gui/MainMenu.h
  14. 69 0
      include/gui/MainMenu.ui
  15. 30 0
      include/gui/PlayerVsPlayerIntro.h
  16. 134 0
      include/gui/PlayerVsPlayerIntro.ui
  17. 35 0
      include/gui/PreBattleScene.h
  18. 171 0
      include/gui/PreBattleScene.ui
  19. 67 0
      include/gui/RaceIcon.h
  20. 87 0
      include/gui/RecruitmentScene.h
  21. 453 0
      include/gui/RecruitmentScene.ui
  22. 23 0
      include/gui/Scene.h
  23. 72 0
      include/gui/UnitIcon.h
  24. 30 0
      include/hotseatgame/gui/HotSeatGame.h
  25. 1710 0
      include/hotseatgame/gui/HotSeatGame.ui
  26. 15 0
      include/skills/MelleDamage.h
  27. 16 0
      include/skills/SelfHeal.h
  28. 68 0
      include/skills/Spell.h
  29. 14 0
      include/units/Mage.h
  30. 174 0
      include/units/Unit.h
  31. 16 0
      include/units/Warrior.h
  32. 22 0
      source/PlayerManager.cpp
  33. 90 0
      source/Race.cpp
  34. 50 0
      source/RaceManager.cpp
  35. 67 0
      source/effects/Effect.cpp
  36. 19 0
      source/effects/MelleDamage.cpp
  37. 19 0
      source/effects/SelfHeal.cpp
  38. 68 0
      source/gui/GUI.cpp
  39. 85 0
      source/gui/GuiSceneManager.cpp
  40. 28 0
      source/gui/MainMenu.cpp
  41. 30 0
      source/gui/PlayerVsPlayerIntro.cpp
  42. 74 0
      source/gui/PreBattleScene.cpp
  43. 138 0
      source/gui/RaceIcon.cpp
  44. 429 0
      source/gui/RecruitmentScene.cpp
  45. 6 0
      source/gui/Scene.cpp
  46. 140 0
      source/gui/UnitIcon.cpp
  47. 32 0
      source/hotseatgame/gui/HotSeatGame.cpp
  48. 7 0
      source/skills/MelleDamage.cpp
  49. 7 0
      source/skills/SelfHeal.cpp
  50. 75 0
      source/skills/Spell.cpp
  51. 7 0
      source/units/Mage.cpp
  52. 286 0
      source/units/Unit.cpp
  53. 49 0
      source/units/Warrior.cpp

+ 15 - 4
client.pro

@@ -55,10 +55,21 @@ exists($$DESTDIR/res) {
     } else {
             gioRes.commands += $(MKDIR) \"$$DESTDIR/res\" $$escape_expand(\n\t);
     }
-guiRes.commands += rcc.exe -binary $$PWD/gui.qrc -o $$DESTDIR/res/gui_data.gtr $$escape_expand(\n\t) \
-                  rcc.exe -binary $$PWD/units.qrc -o $$DESTDIR/res/unit_data.gtr $$escape_expand(\n\t) \
-                  rcc.exe -binary $$PWD/effects.qrc -o $$DESTDIR/res/effect_data.gtr $$escape_expand(\n\t) \
-                  rcc.exe -binary $$PWD/spells.qrc -o $$DESTDIR/res/spell_data.gtr
+
+win32 {
+    guiRes.commands += rcc.exe -binary $$PWD/gui.qrc -o $$DESTDIR/res/gui_data.gtr $$escape_expand(\n\t) \
+                       rcc.exe -binary $$PWD/units.qrc -o $$DESTDIR/res/unit_data.gtr $$escape_expand(\n\t) \
+                       rcc.exe -binary $$PWD/effects.qrc -o $$DESTDIR/res/effect_data.gtr $$escape_expand(\n\t) \
+                       rcc.exe -binary $$PWD/spells.qrc -o $$DESTDIR/res/spell_data.gtr
+}
+
+unix {
+    guiRes.commands += rcc -binary $$PWD/gui.qrc -o $$DESTDIR/res/gui_data.gtr $$escape_expand(\n\t) \
+                       rcc -binary $$PWD/units.qrc -o $$DESTDIR/res/unit_data.gtr $$escape_expand(\n\t) \
+                       rcc -binary $$PWD/effects.qrc -o $$DESTDIR/res/effect_data.gtr $$escape_expand(\n\t) \
+                       rcc -binary $$PWD/spells.qrc -o $$DESTDIR/res/spell_data.gtr
+}
+
 QMAKE_EXTRA_TARGETS += guiRes
 PRE_TARGETDEPS += BuildResources
 

+ 55 - 0
include/AbstractFactory.h

@@ -0,0 +1,55 @@
+#pragma once
+#include <iostream>
+#include <string>
+#include <map>
+
+template <class Base, typename CreatorParam>
+class AbstractCreator {
+public:
+	virtual ~AbstractCreator() {}
+    virtual Base* create(const CreatorParam &id) const = 0;
+};
+
+template <class ObjectClass, class Base, typename CreatorParam>
+class Creator : public AbstractCreator<Base, CreatorParam> {
+public:
+    Creator() {}
+	virtual ~Creator() {}
+    Base* create(const CreatorParam &params) const {
+        return dynamic_cast<Base*>(new ObjectClass(params));
+	}
+};
+
+template <class Base, class IdType>
+class ObjectFactory {
+protected:
+	typedef AbstractCreator<Base, IdType> AbstractFactory;
+	typedef std::map<IdType, AbstractFactory*> FactoryMap;
+	FactoryMap factory_;
+
+public:
+	ObjectFactory() {}
+	virtual ~ObjectFactory() {
+		for (auto& item : factory_)
+			delete item.second;
+	}
+
+    template <class C, typename CreatorParam>
+    void addClass(const IdType &id) {
+        registerClass(id, new Creator<C, Base, CreatorParam>());
+	}
+
+    template <typename CreatorParam>
+    Base* createObject(const IdType &idClass, const CreatorParam &parameters) {
+        return factory_[idClass]->create(parameters);
+	}
+
+protected:
+	void registerClass(const IdType &id, AbstractFactory *ConcreteFabric) {
+		typename FactoryMap::iterator it = factory_.find(id);
+		if (it == factory_.end())
+			factory_[id] = ConcreteFabric;
+		else
+			delete ConcreteFabric;
+	}
+};

+ 91 - 0
include/Player.h

@@ -0,0 +1,91 @@
+#ifndef INCLUDEPLAYER_H
+#define INCLUDEPLAYER_H
+
+#include "units/Unit.h"
+#include "RaceManager.h"
+
+#include <QObject>
+#include <QDebug>
+
+#include <set>
+
+class Race;
+
+template<class Obj, class Identifier>
+class ObjectFactory;
+
+class Player {
+    struct unit_comparator {
+        bool operator() (const Unit* lhs, const Unit* rhs) const {
+            if (rhs == nullptr)
+                return true;
+            if (lhs->getUnitBaseClassId() != rhs->getUnitBaseClassId())
+                return lhs->getUnitBaseClassId() < rhs->getUnitBaseClassId();
+            return lhs->getUnitId() < rhs->getUnitId();
+        }
+    };
+
+public:
+    Player() {
+        init(1);
+    }
+
+    void init(int id) {
+        player_name_ = "Игрок " + QString::number(id + 1);
+        race_ = RaceManager::getInstance().getRace(
+                    RaceManager::getInstance().getAvailableRacesList()[0]
+                );
+        units_.clear();
+    }
+
+    QString getPlayerName() {
+        return player_name_;
+    }
+
+    const std::multiset<Unit*, unit_comparator>& getUnits() {
+        return units_;
+    }
+
+    std::vector<Unit*> getUnitsAsVector() {
+        std::vector<Unit*> result;
+        for (auto unit: units_)
+            result.push_back(unit);
+        return result;
+    }
+
+    void addUnit(Unit *a) {
+        if (units_.size() >= 10)
+            return;
+        units_.insert(a);
+    }
+
+    void deleteUnit(Unit *a) {
+        qDebug() << "deleting unit " << a->getUnitName();
+        auto unit = units_.find(a);
+        if (unit != units_.end())
+            units_.erase(unit);
+    }
+
+    void clearUnits() {
+        units_.clear();
+    }
+
+    Race* getRace() {
+        return race_;
+    }
+
+    void setRace(Race* race) {
+        race_ = race;
+    }
+
+signals:
+
+public slots:
+
+private:
+    QString player_name_;
+    std::multiset<Unit*, unit_comparator> units_;
+    Race* race_;
+};
+
+#endif // INCLUDEPLAYER_H

+ 33 - 0
include/PlayerManager.h

@@ -0,0 +1,33 @@
+#ifndef INCLUDEPLAYERMANAGER_H
+#define INCLUDEPLAYERMANAGER_H
+
+#include <Player.h>
+
+#include <QObject>
+
+#include <vector>
+
+class PlayerManager : public QObject
+{
+    Q_OBJECT
+private:
+    explicit PlayerManager(QObject *parent = nullptr);
+public:
+    static PlayerManager& getInstance() {
+        static PlayerManager instance;
+        return instance;
+    }
+
+    Player* getPlayer(int id);
+    int getPlayersNum();
+    void setPlayersNum(int num);
+
+private:
+    std::vector<Player> players_;
+
+signals:
+
+public slots:
+};
+
+#endif // INCLUDEPLAYERMANAGER_H

+ 44 - 0
include/Race.h

@@ -0,0 +1,44 @@
+#ifndef INCLUDEACE_H
+#define INCLUDEACE_H
+
+#include <QObject>
+#include <QString>
+#include <QImage>
+
+#include <vector>
+
+#include "AbstractFactory.h"
+
+class Unit;
+
+class Race : public QObject
+{
+    Q_OBJECT
+public:
+    explicit Race(QString race_name, QObject *parent = nullptr);
+
+    Unit* createUnit(QString unit_name);
+
+    const std::vector<QString> &getAvailableUnitsList();
+    const std::vector<Unit*> &getAllUnitsList();
+
+    QString getRaceId();
+    QString getRaceName();
+    QImage getRaceIcon();
+    QString getRaceDescr();
+
+private:
+    QString race_id_;
+    QString race_name_;
+    QImage race_icon_;
+    QString race_descr_;
+    ObjectFactory<Unit, QString> units_factory_;
+    std::vector<QString> available_units_list_;
+    std::vector<Unit*> all_units_list_;
+
+signals:
+
+public slots:
+};
+
+#endif // INCLUDEACE_H

+ 33 - 0
include/RaceManager.h

@@ -0,0 +1,33 @@
+#ifndef INCLUDEACEMANAGER_H
+#define INCLUDEACEMANAGER_H
+
+#include <QObject>
+
+#include <vector>
+
+class Race;
+
+class RaceManager : public QObject
+{
+    Q_OBJECT
+private:
+    explicit RaceManager(QObject *parent = nullptr);
+public:
+    static RaceManager& getInstance() {
+        static RaceManager instance;
+        return instance;
+    }
+
+    Race* getRace(QString race_name);
+    const std::vector<QString>& getAvailableRacesList();
+
+private:
+    std::vector<QString> available_races_;
+    std::map<QString, Race*> races_;
+
+signals:
+
+public slots:
+};
+
+#endif // INCLUDEACEMANAGER_H

+ 56 - 0
include/effects/Effect.h

@@ -0,0 +1,56 @@
+//
+// Created by IgorBat on 17.03.2018.
+//
+
+#ifndef THE_GAME_EFFECT_H
+#define THE_GAME_EFFECT_H
+
+#pragma once
+#include <iostream>
+#include <vector>
+//#include "AbstractFactory.h"
+
+class Unit;
+class Cell;
+
+class Effect : public QObject {
+    Q_OBJECT
+
+public:
+    explicit Effect(QString parameters);
+
+    virtual ~Effect() {}
+
+    int getCount();
+    void setCount(int value);
+
+    int getDurability;
+    void setDurability(int value);
+
+    //---------------------------------------------//
+    //----------------GUI section------------------//
+    //---------------------------------------------//
+    QString getEffectName() const;
+    QString getEffectDescr() const;
+    QImage getEffectIcon() const;
+
+    //---------------------------------------------//
+    //-----------Parameters load section-----------//
+    //---------------------------------------------//
+
+private:
+    void loadEffectDescr(QString effect_folder);
+    void loadEffectIcon(QString effect_folder);
+public:
+    virtual void OperateOnCell(Cell* cell) = 0;
+    virtual void OperateOnUnit(Unit* unit) = 0;
+protected:
+    int count_;
+    int durability_;
+
+    // GUI values
+    QString effect_name_;
+    QString effect_descr_;
+    QImage effect_icon_;
+};
+#endif //THE_GAME_EFFECT_H

+ 15 - 0
include/effects/MelleDamage.h

@@ -0,0 +1,15 @@
+//
+// Created by IgorBat on 23.04.2018.
+//
+
+#ifndef GAME_CLIENT_MELLEDAMAGE_H
+#define GAME_CLIENT_MELLEDAMAGE_H
+#pragma once
+#include <cassert>
+#include "effect\effect.h"
+
+class melledamage : public Effect {
+    void OperateOnCell(Cell* cell);
+    void OperateOnUnit(Unit* unit);
+};
+#endif //GAME_CLIENT_MELLEDAMAGE_H

+ 16 - 0
include/effects/SelfHeal.h

@@ -0,0 +1,16 @@
+//
+// Created by IgorBat on 23.04.2018.
+//
+
+#ifndef GAME_CLIENT_SELFHEAL_H
+#define GAME_CLIENT_SELFHEAL_H
+#pragma once
+#include <cassert>
+#include "effect\effect.h"
+
+class selfheal : public Effect {
+    void OperateOnCell(Cell* cell);
+    void OperateOnUnit(Unit* unit);
+};
+
+#endif //GAME_CLIENT_SELFHEAL_H

+ 46 - 0
include/gui/GUI.h

@@ -0,0 +1,46 @@
+#ifndef GUI_H
+#define GUI_H
+
+#include <QMainWindow>
+#include <QGraphicsScene>
+#include <QMouseEvent>
+#include "RecruitmentScene.h"
+
+namespace Ui {
+class GUI;
+}
+
+class GUI : public QMainWindow
+{
+    Q_OBJECT
+
+public:
+    explicit GUI(QWidget *parent = 0);
+    ~GUI();
+    QWidget* mainContentScene();
+
+private:
+    Ui::GUI *ui_;
+
+    QGraphicsScene *scene_;
+    RecruitmentScene *rq_scene_;
+
+    QImage left_border_;
+    QImage left_up_corner_;
+    QImage up_border_;
+    QImage up_right_corner_;
+    QImage right_border_;
+    QImage right_bottom_corner_;
+    QImage bottom_border_;
+    QImage bottom_left_corner_;
+
+protected:
+    void mouseMoveEvent( QMouseEvent* e );
+    void mousePressEvent( QMouseEvent* e );
+    void mouseReleaseEvent( QMouseEvent* e );
+private:
+    int dx_;
+    int dy_;
+};
+
+#endif // GUI_H

+ 156 - 0
include/gui/GUI.ui

@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>GUI</class>
+ <widget class="QMainWindow" name="GUI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1024</width>
+    <height>800</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>GUI</string>
+  </property>
+  <widget class="QWidget" name="centralWidget">
+   <widget class="QLabel" name="botleft_corner_">
+    <property name="geometry">
+     <rect>
+      <x>-3</x>
+      <y>758</y>
+      <width>45</width>
+      <height>45</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/window/thick_opaque-border-botleft.png&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="left_border_">
+    <property name="geometry">
+     <rect>
+      <x>-3</x>
+      <y>42</y>
+      <width>51</width>
+      <height>716</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head&gt;&lt;body&gt;
+&lt;div style=&quot;background:url(:/assets/window/thick_opaque-border-left.png);&quot; width=&quot;100%&quot; height=&quot;100%&quot; /&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;
+&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="topleft_corner_">
+    <property name="geometry">
+     <rect>
+      <x>-3</x>
+      <y>-3</y>
+      <width>45</width>
+      <height>45</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/window/thick_opaque-border-topleft.png&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="top_border_">
+    <property name="geometry">
+     <rect>
+      <x>42</x>
+      <y>-3</y>
+      <width>937</width>
+      <height>45</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;div style=&quot;background:url(:/assets/window/thick_opaque-border-top.png);&quot; width=&quot;100%&quot; height=&quot;100%&quot; /&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="topright_corner_">
+    <property name="geometry">
+     <rect>
+      <x>979</x>
+      <y>-3</y>
+      <width>45</width>
+      <height>45</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/window/thick_opaque-border-topright.png&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="right_border_">
+    <property name="geometry">
+     <rect>
+      <x>979</x>
+      <y>42</y>
+      <width>45</width>
+      <height>716</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head&gt;&lt;body&gt;
+&lt;div style=&quot;background:url(:/assets/window/thick_opaque-border-right.png);&quot; width=&quot;100%&quot; height=&quot;100%&quot; /&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;
+&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="bottom_border_">
+    <property name="geometry">
+     <rect>
+      <x>42</x>
+      <y>758</y>
+      <width>937</width>
+      <height>45</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;div style=&quot;background:url(:/assets/window/thick_opaque-border-bottom.png);&quot; width=&quot;100%&quot; height=&quot;100%&quot; /&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="botright_corner">
+    <property name="geometry">
+     <rect>
+      <x>979</x>
+      <y>758</y>
+      <width>45</width>
+      <height>45</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/window/thick_opaque-border-botright.png&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="background">
+    <property name="geometry">
+     <rect>
+      <x>42</x>
+      <y>42</y>
+      <width>938</width>
+      <height>716</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head&gt;&lt;body&gt;
+&lt;div style=&quot;background:url(:/assets/window/thick_opaque-background.png);&quot; width=&quot;100%&quot; height=&quot;100%&quot; /&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;
+&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QWidget" name="main_content_" native="true">
+    <property name="geometry">
+     <rect>
+      <x>40</x>
+      <y>40</y>
+      <width>940</width>
+      <height>720</height>
+     </rect>
+    </property>
+    <layout class="QGridLayout" name="content_"/>
+   </widget>
+  </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>

+ 47 - 0
include/gui/GuiSceneManager.h

@@ -0,0 +1,47 @@
+#ifndef INCLUDEGUIGUISCENEMANAGER_H
+#define INCLUDEGUIGUISCENEMANAGER_H
+
+#include <QObject>
+
+#include <map>
+
+class GUI;
+class Scene;
+
+class GuiSceneManager : public QObject
+{
+    Q_OBJECT
+private:
+    explicit GuiSceneManager(QObject *parent = nullptr);
+    ~GuiSceneManager();
+
+public:
+    static GuiSceneManager& getInstance() {
+        static GuiSceneManager instance;
+        return instance;
+    }
+
+    bool registerScene(QString scene_name, Scene* name);
+
+    bool changeScene(QString scene_name, QString args = "");
+
+    bool showDetachedScene(QString scene_name, QString args = "");
+
+    bool hideDetachedScene(QString scene_name);
+
+    bool hideMainWindow();
+
+    bool showMainWindow();
+
+private:
+    std::map<QString, Scene*> scenes_;
+
+    QString current_scene_;
+    GUI* gui_;
+
+signals:
+
+public slots:
+};
+
+#endif // INCLUDEGUIGUISCENEMANAGER_H

+ 32 - 0
include/gui/MainMenu.h

@@ -0,0 +1,32 @@
+#ifndef MAINMENU_H
+#define MAINMENU_H
+
+#include "gui/Scene.h"
+
+#include <QWidget>
+
+namespace Ui {
+class MainMenu;
+}
+
+class MainMenu : public Scene
+{
+    Q_OBJECT
+
+public:
+    explicit MainMenu(QWidget *parent = 0);
+    ~MainMenu();
+
+    void ParseArgs(QString args) {}
+
+private slots:
+
+    void on_exit_button_clicked();
+
+    void on_pvp_local_battle_button_clicked();
+
+private:
+    Ui::MainMenu *ui;
+};
+
+#endif // MAINMENU_H

+ 69 - 0
include/gui/MainMenu.ui

@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainMenu</class>
+ <widget class="Scene" name="MainMenu">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>940</width>
+    <height>720</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <widget class="QLabel" name="title_">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>60</y>
+     <width>941</width>
+     <height>101</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:24pt; color:#b12d2d;&quot;&gt;Супер-мега-крутая-игрушка-название-которой-мы-ещё-не-придумали&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+   <property name="wordWrap">
+    <bool>true</bool>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="pvp_local_battle_button">
+   <property name="geometry">
+    <rect>
+     <x>200</x>
+     <y>190</y>
+     <width>481</width>
+     <height>251</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Игрок против игрока</string>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="exit_button">
+   <property name="geometry">
+    <rect>
+     <x>200</x>
+     <y>470</y>
+     <width>481</width>
+     <height>221</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Выйти из игры</string>
+   </property>
+  </widget>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>Scene</class>
+   <extends>QWidget</extends>
+   <header location="global">gui/scene.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

+ 30 - 0
include/gui/PlayerVsPlayerIntro.h

@@ -0,0 +1,30 @@
+#ifndef PLAYERVSPLAYERINTRO_H
+#define PLAYERVSPLAYERINTRO_H
+
+#include "gui/Scene.h"
+
+#include <QWidget>
+
+namespace Ui {
+class PlayerVsPlayerIntro;
+}
+
+class PlayerVsPlayerIntro : public Scene
+{
+    Q_OBJECT
+
+public:
+    explicit PlayerVsPlayerIntro(QWidget *parent = 0);
+    ~PlayerVsPlayerIntro();
+
+    void ParseArgs(QString args) {}
+private slots:
+    void on_back_to_menu_clicked();
+
+    void on_go_next_clicked();
+
+private:
+    Ui::PlayerVsPlayerIntro *ui;
+};
+
+#endif // PLAYERVSPLAYERINTRO_H

+ 134 - 0
include/gui/PlayerVsPlayerIntro.ui

@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PlayerVsPlayerIntro</class>
+ <widget class="Scene" name="PlayerVsPlayerIntro">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>940</width>
+    <height>720</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <widget class="QLabel" name="divider_">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>45</y>
+     <width>940</width>
+     <height>91</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/recruitscene/divider.png&quot; width=&quot;940&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="title_">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>941</width>
+     <height>71</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:24pt; color:#b12d2d;&quot;&gt;Режим: игрок против игрока&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="title_1">
+   <property name="geometry">
+    <rect>
+     <x>90</x>
+     <y>120</y>
+     <width>751</width>
+     <height>151</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:16pt; color:#FDEAA8;&quot;&gt;Этот режим включает в себя стандартное пошаговое сражение между двумя игроками в отсутствие какого-либо сценария. Каждому игроку будет предложено выбрать расу и набрать армию в соответствии с указанным бюджетом. &lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+   <property name="wordWrap">
+    <bool>true</bool>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label">
+   <property name="geometry">
+    <rect>
+     <x>200</x>
+     <y>290</y>
+     <width>501</width>
+     <height>261</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img width=&quot;500&quot; src=&quot;:/assets/pvp_intro/picture.jpg&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="go_next">
+   <property name="geometry">
+    <rect>
+     <x>630</x>
+     <y>630</y>
+     <width>221</width>
+     <height>61</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Продолжить</string>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="back_to_menu">
+   <property name="geometry">
+    <rect>
+     <x>70</x>
+     <y>630</y>
+     <width>191</width>
+     <height>61</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Назад</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_2">
+   <property name="geometry">
+    <rect>
+     <x>310</x>
+     <y>570</y>
+     <width>141</width>
+     <height>31</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:12pt; color:#b12d2d;&quot;&gt;Кол-во монет:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QLineEdit" name="money_">
+   <property name="geometry">
+    <rect>
+     <x>462</x>
+     <y>577</y>
+     <width>111</width>
+     <height>20</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>1000</string>
+   </property>
+  </widget>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>Scene</class>
+   <extends>QWidget</extends>
+   <header>gui/scene.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

+ 35 - 0
include/gui/PreBattleScene.h

@@ -0,0 +1,35 @@
+#ifndef PREBATTLESCENE_H
+#define PREBATTLESCENE_H
+
+#include <QWidget>
+
+#include "gui/Scene.h"
+
+#include <vector>
+
+class UnitIcon;
+
+namespace Ui {
+class PreBattleScene;
+}
+
+class PreBattleScene : public Scene
+{
+    Q_OBJECT
+
+public:
+    explicit PreBattleScene(QWidget *parent = 0);
+    ~PreBattleScene();
+
+    void init() override;
+
+private slots:
+    void on_start_battle_clicked();
+
+private:
+    std::vector<UnitIcon*> units_player_1_;
+    std::vector<UnitIcon*> units_player_2_;
+    Ui::PreBattleScene *ui;
+};
+
+#endif // PREBATTLESCENE_H

+ 171 - 0
include/gui/PreBattleScene.ui

@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PreBattleScene</class>
+ <widget class="QWidget" name="PreBattleScene">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>940</width>
+    <height>720</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <widget class="QLabel" name="label">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>10</y>
+     <width>981</width>
+     <height>651</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/common/pergam.png&quot; width=&quot;940&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_2">
+   <property name="geometry">
+    <rect>
+     <x>340</x>
+     <y>280</y>
+     <width>301</width>
+     <height>211</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/pvp_intro/pre-battle1.jpg&quot; width=&quot;300&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QWidget" name="units_player_2_" native="true">
+   <property name="geometry">
+    <rect>
+     <x>550</x>
+     <y>140</y>
+     <width>320</width>
+     <height>128</height>
+    </rect>
+   </property>
+   <layout class="QGridLayout" name="units_player_2_layout_">
+    <property name="leftMargin">
+     <number>0</number>
+    </property>
+    <property name="topMargin">
+     <number>0</number>
+    </property>
+    <property name="rightMargin">
+     <number>0</number>
+    </property>
+    <property name="bottomMargin">
+     <number>0</number>
+    </property>
+    <property name="spacing">
+     <number>0</number>
+    </property>
+   </layout>
+  </widget>
+  <widget class="QWidget" name="units_player_1_" native="true">
+   <property name="geometry">
+    <rect>
+     <x>110</x>
+     <y>140</y>
+     <width>320</width>
+     <height>128</height>
+    </rect>
+   </property>
+   <layout class="QGridLayout" name="units_player_1_layout_">
+    <property name="leftMargin">
+     <number>0</number>
+    </property>
+    <property name="topMargin">
+     <number>0</number>
+    </property>
+    <property name="rightMargin">
+     <number>0</number>
+    </property>
+    <property name="bottomMargin">
+     <number>0</number>
+    </property>
+    <property name="spacing">
+     <number>0</number>
+    </property>
+   </layout>
+  </widget>
+  <widget class="QPushButton" name="start_battle">
+   <property name="geometry">
+    <rect>
+     <x>650</x>
+     <y>510</y>
+     <width>231</width>
+     <height>71</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>В бой!</string>
+   </property>
+  </widget>
+  <widget class="RaceIcon" name="race_icon_1_">
+   <property name="geometry">
+    <rect>
+     <x>110</x>
+     <y>300</y>
+     <width>128</width>
+     <height>128</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>TextLabel</string>
+   </property>
+  </widget>
+  <widget class="RaceIcon" name="race_icon_2_">
+   <property name="geometry">
+    <rect>
+     <x>710</x>
+     <y>300</y>
+     <width>128</width>
+     <height>128</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>TextLabel</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="title_1">
+   <property name="geometry">
+    <rect>
+     <x>110</x>
+     <y>80</y>
+     <width>320</width>
+     <height>61</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:24pt; color:#b12d2d;&quot;&gt;Игрок 1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="title_2">
+   <property name="geometry">
+    <rect>
+     <x>550</x>
+     <y>80</y>
+     <width>320</width>
+     <height>61</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:24pt; color:#b12d2d;&quot;&gt;Игрок 2&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>RaceIcon</class>
+   <extends>QLabel</extends>
+   <header>gui/raceicon.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

+ 67 - 0
include/gui/RaceIcon.h

@@ -0,0 +1,67 @@
+#ifndef RACEICON_H
+#define RACEICON_H
+
+#include "Race.h"
+
+#include <QObject>
+#include <QWidget>
+#include <QLabel>
+#include <QImage>
+#include <QPixmap>
+#include <QPainter>
+#include <QTime>
+
+class RaceIcon : public QLabel {
+Q_OBJECT
+
+public:
+    explicit RaceIcon(QWidget* parent = 0, int width = 64, int height = 64);
+    ~RaceIcon();
+
+    void setRaceIcon(QImage icon);
+    void resize(int w, int h);
+    void unsetRaceIcon();
+
+    Race* getRace();
+    void setRace(Race* race);
+
+    int getState();
+    void setState(int state);
+
+    void deactivate();
+    void activate();
+
+protected:
+    void mousePressEvent(QMouseEvent* event) override;
+    void enterEvent(QEvent* event) override;
+    void leaveEvent(QEvent* event) override;
+
+signals:
+    void clicked(RaceIcon*);
+    void doubleclicked(RaceIcon*);
+    void hovered(RaceIcon*);
+    void unhovered(RaceIcon*);
+
+private:
+    void drawIcon();
+
+    int width_;
+    int height_;
+
+    int state_; // 0 = not initialized;
+                // 1 = default;
+                // 2 = hover;
+                // 3 = active;
+
+    QPixmap pixmap_;
+    QImage active_border_;
+    QImage hover_border_;
+    QImage default_border_;
+    QImage icon_;
+
+    QTime previous_click_time_;
+
+    Race* race_;
+};
+
+#endif // RACEICON_H

+ 87 - 0
include/gui/RecruitmentScene.h

@@ -0,0 +1,87 @@
+#ifndef RECRUITMENTSCENE_H
+#define RECRUITMENTSCENE_H
+
+#include "gui/Scene.h"
+
+#include <QWidget>
+
+#include <vector>
+
+class UnitIcon;
+class RaceIcon;
+class Player;
+class Unit;
+class Race;
+
+namespace Ui {
+class RecruitmentScene;
+}
+
+class RecruitmentScene : public Scene
+{
+    Q_OBJECT
+
+public:
+    explicit RecruitmentScene(QWidget *parent = 0);
+    ~RecruitmentScene();
+
+    void parseArgs(QString args) override;
+    void init() override;
+
+public slots:
+    void onUnitIconHovered(UnitIcon*);
+    void onUnitIconUnHovered(UnitIcon*);
+    void onUnitIconClicked(UnitIcon*);
+    void onUnitIconDoubleClicked(UnitIcon*);
+
+    void onChosenUnitIconHovered(UnitIcon*);
+    void onChosenUnitIconUnHovered(UnitIcon*);
+    void onChosenUnitIconClicked(UnitIcon*);
+    void onChosenUnitIconDoubleClicked(UnitIcon*);
+
+    void onRaceIconHovered(RaceIcon*);
+    void onRaceIconUnHovered(RaceIcon*);
+    void onRaceIconClicked(RaceIcon*);
+    void onRaceIconDoubleClicked(RaceIcon*);
+
+    void onGradeUnitIconHovered(UnitIcon*);
+    void onGradeUnitIconUnHovered(UnitIcon*);
+    void onGradeUnitIconClicked(UnitIcon*);
+    void onGradeUnitIconDoubleClicked(UnitIcon*);
+
+private:
+    void initAvailableRaces();
+    void initAvailableUnits();
+    void showChosenUnits();
+
+    void setDescriptionTitle(QString title);
+    void setDescriptionText(QString text);
+    void setDescriptionIcon(QImage icon);
+
+    void updateSpecsWidget(Unit* unit);
+    void changeRace(Race* race);
+    void setMoney(int money_);
+
+private slots:
+    void on_back_button_clicked();
+
+    void on_apply_clicked();
+
+private:
+    int available_money_;
+    int current_money_;
+
+    int current_player_id_;
+    Player* current_player_;
+
+    Ui::RecruitmentScene *ui;
+    UnitIcon* available_units_icons_[5];
+    UnitIcon* chosen_units_icons_[10];
+
+    RaceIcon* available_races_icons_[3];
+
+    UnitIcon* prev_grade_units_icons[4];
+    UnitIcon* next_grade_units_icons[4];
+};
+
+#endif // RECRUITMENTSCENE_H

+ 453 - 0
include/gui/RecruitmentScene.ui

@@ -0,0 +1,453 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RecruitmentScene</class>
+ <widget class="Scene" name="RecruitmentScene">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>940</width>
+    <height>720</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <widget class="QLabel" name="chosen_race_text_">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>120</y>
+     <width>191</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:14pt; color:#FDEAA8;&quot;&gt;Выбранная раса:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="RaceIcon" name="chosen_race_image_">
+   <property name="geometry">
+    <rect>
+     <x>200</x>
+     <y>110</y>
+     <width>100</width>
+     <height>100</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/units/warcraft/raceicon.png&quot; width=&quot;100&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="available_races_text_">
+   <property name="geometry">
+    <rect>
+     <x>450</x>
+     <y>150</y>
+     <width>201</width>
+     <height>31</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:14pt; color:#FDEAA8;&quot;&gt;Доступные расы:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QWidget" name="available_races_list_" native="true">
+   <property name="geometry">
+    <rect>
+     <x>660</x>
+     <y>130</y>
+     <width>216</width>
+     <height>72</height>
+    </rect>
+   </property>
+   <layout class="QHBoxLayout" name="availableRacesLayout_">
+    <property name="spacing">
+     <number>0</number>
+    </property>
+    <property name="leftMargin">
+     <number>0</number>
+    </property>
+    <property name="topMargin">
+     <number>0</number>
+    </property>
+    <property name="rightMargin">
+     <number>0</number>
+    </property>
+    <property name="bottomMargin">
+     <number>0</number>
+    </property>
+   </layout>
+  </widget>
+  <widget class="QLabel" name="divider_">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>45</y>
+     <width>940</width>
+     <height>91</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/recruitscene/divider.png&quot; width=&quot;940&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="title_">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>940</width>
+     <height>71</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:24pt; color:#b12d2d;&quot;&gt;Набор юнитов&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="chosen_units_label_">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>380</y>
+     <width>221</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:14pt; color:#FDEAA8;&quot;&gt;Выбранные юниты:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="available_units_text_">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>250</y>
+     <width>201</width>
+     <height>31</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:14pt; color:#fdeaa8;&quot;&gt;Доступные классы:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QWidget" name="available_units_list_" native="true">
+   <property name="geometry">
+    <rect>
+     <x>30</x>
+     <y>290</y>
+     <width>320</width>
+     <height>64</height>
+    </rect>
+   </property>
+   <layout class="QGridLayout" name="available_units_layout_">
+    <property name="leftMargin">
+     <number>0</number>
+    </property>
+    <property name="topMargin">
+     <number>0</number>
+    </property>
+    <property name="rightMargin">
+     <number>0</number>
+    </property>
+    <property name="bottomMargin">
+     <number>0</number>
+    </property>
+    <property name="spacing">
+     <number>0</number>
+    </property>
+   </layout>
+  </widget>
+  <widget class="QWidget" name="chosen_units_grid_" native="true">
+   <property name="geometry">
+    <rect>
+     <x>30</x>
+     <y>430</y>
+     <width>320</width>
+     <height>128</height>
+    </rect>
+   </property>
+   <layout class="QGridLayout" name="chosen_units_layout_">
+    <property name="leftMargin">
+     <number>0</number>
+    </property>
+    <property name="topMargin">
+     <number>0</number>
+    </property>
+    <property name="rightMargin">
+     <number>0</number>
+    </property>
+    <property name="bottomMargin">
+     <number>0</number>
+    </property>
+    <property name="spacing">
+     <number>0</number>
+    </property>
+   </layout>
+  </widget>
+  <widget class="QPushButton" name="apply">
+   <property name="geometry">
+    <rect>
+     <x>610</x>
+     <y>640</y>
+     <width>281</width>
+     <height>61</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Завершить выбор</string>
+   </property>
+  </widget>
+  <widget class="QWidget" name="description_scroll_widget_" native="true">
+   <property name="geometry">
+    <rect>
+     <x>590</x>
+     <y>250</y>
+     <width>321</width>
+     <height>441</height>
+    </rect>
+   </property>
+   <widget class="QLabel" name="background_scroll_label_">
+    <property name="geometry">
+     <rect>
+      <x>0</x>
+      <y>0</y>
+      <width>321</width>
+      <height>421</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/common/Scroll.png&quot; width=&quot;321&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="desctiption_title_">
+    <property name="geometry">
+     <rect>
+      <x>100</x>
+      <y>70</y>
+      <width>161</width>
+      <height>41</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; font-size:16px; color:#000080;&quot;&gt;Название юнита&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+    <property name="wordWrap">
+     <bool>true</bool>
+    </property>
+   </widget>
+   <widget class="QLabel" name="description_text_">
+    <property name="geometry">
+     <rect>
+      <x>40</x>
+      <y>120</y>
+      <width>231</width>
+      <height>191</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#000080;&quot;&gt;Здоровье:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#000080;&quot;&gt;Сила:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#000080;&quot;&gt;Урон:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#000080;&quot;&gt;Удар:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#000080;&quot;&gt;Удача:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#000080;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+    </property>
+   </widget>
+   <widget class="UnitIcon" name="description_icon_">
+    <property name="geometry">
+     <rect>
+      <x>50</x>
+      <y>70</y>
+      <width>45</width>
+      <height>45</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/units/warcraft/blademaster/icon.png&quot; width=&quot;45&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+  </widget>
+  <widget class="QPushButton" name="back_button">
+   <property name="geometry">
+    <rect>
+     <x>50</x>
+     <y>650</y>
+     <width>161</width>
+     <height>61</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>На главное меню</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="available_money_text_">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>160</y>
+     <width>191</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:10pt; color:#ff0000;&quot;&gt;Ресурсы: 0000000 &lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QWidget" name="unit_spec_widget_" native="true">
+   <property name="geometry">
+    <rect>
+     <x>380</x>
+     <y>270</y>
+     <width>180</width>
+     <height>291</height>
+    </rect>
+   </property>
+   <widget class="QLabel" name="spec_title_">
+    <property name="geometry">
+     <rect>
+      <x>0</x>
+      <y>10</y>
+      <width>180</width>
+      <height>21</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt; color:#fdeaa8;&quot;&gt;Специализация&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="arrow_down_1_">
+    <property name="geometry">
+     <rect>
+      <x>80</x>
+      <y>80</y>
+      <width>31</width>
+      <height>61</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/common/strelka.png&quot; width=&quot;25&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="UnitIcon" name="current_spec_unit_">
+    <property name="geometry">
+     <rect>
+      <x>70</x>
+      <y>140</y>
+      <width>45</width>
+      <height>45</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/units/warcraft/chaosorc/icon.png&quot; width=&quot;45&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QWidget" name="next_gen_units_list_" native="true">
+    <property name="geometry">
+     <rect>
+      <x>0</x>
+      <y>240</y>
+      <width>180</width>
+      <height>45</height>
+     </rect>
+    </property>
+    <layout class="QHBoxLayout" name="next_gen_units_layout_">
+     <property name="spacing">
+      <number>0</number>
+     </property>
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
+     </property>
+    </layout>
+   </widget>
+   <widget class="QLabel" name="arrow_down_2_">
+    <property name="geometry">
+     <rect>
+      <x>80</x>
+      <y>180</y>
+      <width>31</width>
+      <height>61</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img src=&quot;:/assets/common/strelka.png&quot; width=&quot;25&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+    </property>
+   </widget>
+   <widget class="QWidget" name="prev_gen_units_list_" native="true">
+    <property name="geometry">
+     <rect>
+      <x>0</x>
+      <y>40</y>
+      <width>180</width>
+      <height>45</height>
+     </rect>
+    </property>
+    <layout class="QHBoxLayout" name="prev_gen_units_layout">
+     <property name="spacing">
+      <number>0</number>
+     </property>
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
+     </property>
+    </layout>
+   </widget>
+  </widget>
+  <zorder>divider_</zorder>
+  <zorder>chosen_race_text_</zorder>
+  <zorder>chosen_race_image_</zorder>
+  <zorder>available_races_text_</zorder>
+  <zorder>available_races_list_</zorder>
+  <zorder>title_</zorder>
+  <zorder>chosen_units_label_</zorder>
+  <zorder>available_units_list_</zorder>
+  <zorder>chosen_units_grid_</zorder>
+  <zorder>description_scroll_widget_</zorder>
+  <zorder>back_button</zorder>
+  <zorder>available_units_text_</zorder>
+  <zorder>available_money_text_</zorder>
+  <zorder>apply</zorder>
+  <zorder>unit_spec_widget_</zorder>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>Scene</class>
+   <extends>QWidget</extends>
+   <header>gui/scene.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>UnitIcon</class>
+   <extends>QLabel</extends>
+   <header>gui/uniticon.h</header>
+   <slots>
+    <signal>clicked()</signal>
+    <signal>doubleclicked()</signal>
+    <signal>hovered()</signal>
+    <signal>unhovered()</signal>
+   </slots>
+  </customwidget>
+  <customwidget>
+   <class>RaceIcon</class>
+   <extends>QLabel</extends>
+   <header>gui/raceicon.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

+ 23 - 0
include/gui/Scene.h

@@ -0,0 +1,23 @@
+#ifndef INCLUDEGUISCENE_H
+#define INCLUDEGUISCENE_H
+
+#include <QWidget>
+
+class Scene : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit Scene(QWidget *parent = nullptr);
+
+    virtual ~Scene() {}
+
+    virtual void parseArgs(QString) {}
+
+    virtual void init() {}
+
+signals:
+
+public slots:
+};
+
+#endif // INCLUDEGUISCENE_H

+ 72 - 0
include/gui/UnitIcon.h

@@ -0,0 +1,72 @@
+#ifndef UNITICON_H
+#define UNITICON_H
+
+#include "units/Unit.h"
+
+#include <QObject>
+#include <QWidget>
+#include <QLabel>
+#include <QImage>
+#include <QPixmap>
+#include <QPainter>
+#include <QTime>
+
+class UnitIcon : public QLabel {
+Q_OBJECT
+
+public:
+    explicit UnitIcon(QWidget* parent = 0, int width = 64, int height = 64);
+    ~UnitIcon();
+
+    void setUnitIcon(QString racename, QString unitname);
+    void setUnitIcon(QImage icon);
+    void resize(int w, int h);
+    void unsetUnitIcon();
+
+    Unit* getUnit();
+    void setUnit(Unit* unit);
+
+    void deactivate();
+    void activate();
+
+    void setState(int state);
+
+protected:
+    void mousePressEvent(QMouseEvent* event);
+    void enterEvent(QEvent* event);
+    void leaveEvent(QEvent* event);
+
+
+signals:
+    void clicked(UnitIcon*);
+    void doubleclicked(UnitIcon*);
+    void hovered(UnitIcon*);
+    void unhovered(UnitIcon*);
+
+private:
+    void drawIcon();
+
+    int width_;
+    int height_;
+
+    int state_; // 0 = not initialized;
+                // 1 = default;
+                // 2 = hover;
+                // 3 = active;
+
+    QPixmap pixmap_;
+    QImage active_border_;
+    QImage hover_border_;
+    QImage default_border_;
+    QImage icon_;
+
+    QTime previous_click_time_;
+
+    QImage result_;
+
+    Unit* unit_;
+};
+
+
+
+#endif // UNITICON_H

+ 30 - 0
include/hotseatgame/gui/HotSeatGame.h

@@ -0,0 +1,30 @@
+#ifndef HOTSEATGAME_H
+#define HOTSEATGAME_H
+
+#include <QWidget>
+#include "gui/scene.h"
+
+namespace Ui {
+class HotSeatGame;
+}
+
+class HotSeatGame : public Scene
+{
+    Q_OBJECT
+
+public:
+    explicit HotSeatGame(QWidget *parent = 0);
+    ~HotSeatGame();
+
+    void init() override;
+
+
+private slots:
+
+    void on_surrender_button__clicked();
+
+private:
+    Ui::HotSeatGame *ui;
+};
+
+#endif // HOTSEATGAME_H

+ 1710 - 0
include/hotseatgame/gui/HotSeatGame.ui

@@ -0,0 +1,1710 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HotSeatGame</class>
+ <widget class="QWidget" name="HotSeatGame">
+  <property name="windowModality">
+   <enum>Qt::ApplicationModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1421</width>
+    <height>897</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="sizeIncrement">
+   <size>
+    <width>0</width>
+    <height>0</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="autoFillBackground">
+   <bool>true</bool>
+  </property>
+  <property name="styleSheet">
+   <string notr="true">background:url(:/assets/window/thick_opaque-background.png)</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <property name="sizeConstraint">
+    <enum>QLayout::SetMinAndMaxSize</enum>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <item row="5" column="0">
+    <widget class="QWidget" name="widget_11" native="true">
+     <property name="minimumSize">
+      <size>
+       <width>44</width>
+       <height>43</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>44</width>
+       <height>43</height>
+      </size>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">background:url(:/assets/window/thick_opaque-border-botleft.png)</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="4">
+    <widget class="QWidget" name="widget_15" native="true">
+     <property name="minimumSize">
+      <size>
+       <width>44</width>
+       <height>44</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>44</width>
+       <height>44</height>
+      </size>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">background:url(:/assets/window/thick_opaque-border-topright.png)</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1" rowspan="2">
+    <widget class="QWidget" name="unit_chars_widget_" native="true">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Fixed" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="minimumSize">
+      <size>
+       <width>250</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="layoutDirection">
+      <enum>Qt::LeftToRight</enum>
+     </property>
+     <property name="autoFillBackground">
+      <bool>false</bool>
+     </property>
+     <property name="styleSheet">
+      <string notr="true"/>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_4">
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <property name="spacing">
+       <number>0</number>
+      </property>
+      <item row="0" column="0">
+       <widget class="QWidget" name="border_upleft_" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-topleft.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1" colspan="3">
+       <widget class="QWidget" name="border_up_" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>5</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>5</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-top.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="4">
+       <widget class="QWidget" name="border_upright_" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-topright.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0" rowspan="11">
+       <widget class="QWidget" name="border_left_" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>5</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>5</width>
+          <height>16777215</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-left.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="2">
+       <widget class="QLabel" name="unit_icon_">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>150</width>
+          <height>150</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>150</width>
+          <height>150</height>
+         </size>
+        </property>
+        <property name="layoutDirection">
+         <enum>Qt::LeftToRight</enum>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::Panel</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <property name="lineWidth">
+         <number>5</number>
+        </property>
+        <property name="text">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;:/assets/units/human/atraty-rider/icon.png&quot; width=&quot;120&quot; height=&quot;120&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1" colspan="3">
+       <widget class="QLabel" name="unit_name_">
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>50</height>
+         </size>
+        </property>
+        <property name="font">
+         <font>
+          <family>Viking Cyr</family>
+          <pointsize>10</pointsize>
+         </font>
+        </property>
+        <property name="text">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; color:#68fafa;&quot;&gt;Название юнита&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <spacer name="verticalSpacer">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>15</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="5" column="1">
+       <spacer name="verticalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>15</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="7" column="1" colspan="3">
+       <widget class="QFrame" name="effects_frame_">
+        <property name="minimumSize">
+         <size>
+          <width>32</width>
+          <height>36</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>36</height>
+         </size>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::StyledPanel</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Raised</enum>
+        </property>
+        <layout class="QGridLayout" name="gridLayout_7">
+         <property name="leftMargin">
+          <number>3</number>
+         </property>
+         <property name="topMargin">
+          <number>3</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <property name="spacing">
+          <number>3</number>
+         </property>
+         <item row="0" column="7" rowspan="2">
+          <widget class="QWidget" name="effect_8_" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="11">
+          <widget class="QWidget" name="effect_12_" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="8" rowspan="2">
+          <widget class="QWidget" name="effect_9_" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="10" rowspan="2">
+          <widget class="QWidget" name="effect_11_" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="9" rowspan="2">
+          <widget class="QWidget" name="effect_10_" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="0" rowspan="2">
+          <widget class="QWidget" name="effect_13_" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="1" rowspan="2">
+          <widget class="QWidget" name="effect_14_" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="2" rowspan="2">
+          <widget class="QWidget" name="effect_15_" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="3" rowspan="2">
+          <widget class="QWidget" name="effect_16_" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="4" rowspan="2">
+          <widget class="QWidget" name="effect_17" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="5" rowspan="2">
+          <widget class="QWidget" name="effect_6_" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="6" rowspan="2">
+          <widget class="QWidget" name="effect_7_" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="10">
+          <widget class="QWidget" name="widget_22" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="11">
+          <widget class="QWidget" name="widget_21" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="9">
+          <widget class="QWidget" name="widget_23" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="8">
+          <widget class="QWidget" name="widget_24" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="7">
+          <widget class="QWidget" name="widget_25" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="6">
+          <widget class="QWidget" name="widget_26" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="5">
+          <widget class="QWidget" name="widget_27" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="4">
+          <widget class="QWidget" name="widget_28" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="3">
+          <widget class="QWidget" name="widget_29" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="2">
+          <widget class="QWidget" name="widget_30" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="1">
+          <widget class="QWidget" name="widget_31" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="0">
+          <widget class="QWidget" name="widget_32" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/standart_effect.png);</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item row="8" column="1">
+       <spacer name="verticalSpacer_4">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>15</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="9" column="1" colspan="3">
+       <widget class="QLabel" name="char_traits_">
+        <property name="minimumSize">
+         <size>
+          <width>250</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::Panel</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <property name="lineWidth">
+         <number>0</number>
+        </property>
+        <property name="text">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600; color:#d1d100;&quot;&gt;Характеристики:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#ffffff;&quot;&gt;Очки жизни: 9087654&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#ffffff;&quot;&gt;Атака: 219-18927&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#ffffff;&quot;&gt;Инициатива: 187&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#ffffff;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#ffffff;&quot;&gt;Сила: 1&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#ffffff;&quot;&gt;Ловкость: 1&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#ffffff;&quot;&gt;Интеллект: 4&lt;br/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#ffffff;&quot;&gt;Физ. защита: 1&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#ffffff;&quot;&gt;Маг. защита: 3&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+        </property>
+        <property name="margin">
+         <number>10</number>
+        </property>
+       </widget>
+      </item>
+      <item row="10" column="1">
+       <spacer name="horizontalSpacer_3">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>50</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="10" column="2">
+       <widget class="QPushButton" name="end_turn_button_">
+        <property name="styleSheet">
+         <string notr="true">color: rgb(159, 159, 0);</string>
+        </property>
+        <property name="text">
+         <string>Закончить ход</string>
+        </property>
+        <property name="autoDefault">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="10" column="3">
+       <spacer name="horizontalSpacer_4">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>50</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="11" column="1">
+       <spacer name="horizontalSpacer_5">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>50</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="11" column="2">
+       <widget class="QPushButton" name="surrender_button_">
+        <property name="styleSheet">
+         <string notr="true">color: rgb(159, 159, 0);</string>
+        </property>
+        <property name="text">
+         <string>Сдаться</string>
+        </property>
+        <property name="autoDefault">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="12" column="0">
+       <widget class="QWidget" name="border_botleft_" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-botleft.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="12" column="1" colspan="3">
+       <widget class="QWidget" name="border_bottom_" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-bottom.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="12" column="4">
+       <widget class="QWidget" name="border_botright_" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-botright.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="1" colspan="3">
+       <widget class="QWidget" name="action_buttons" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>60</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>60</height>
+         </size>
+        </property>
+        <layout class="QGridLayout" name="gridLayout_5">
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <property name="spacing">
+          <number>0</number>
+         </property>
+         <item row="0" column="0">
+          <widget class="QPushButton" name="pushButton">
+           <property name="minimumSize">
+            <size>
+             <width>60</width>
+             <height>60</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>60</width>
+             <height>60</height>
+            </size>
+           </property>
+           <property name="styleSheet">
+            <string notr="true">background-image: url(:/assets/hotseatpvp/scroll_red.png);</string>
+           </property>
+           <property name="text">
+            <string/>
+           </property>
+           <property name="autoDefault">
+            <bool>false</bool>
+           </property>
+           <property name="flat">
+            <bool>false</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item row="6" column="1" colspan="3">
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600; color:#d1d100;&quot;&gt;Эффекты:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="4" rowspan="11">
+       <widget class="QWidget" name="border_right_" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>8</width>
+          <height>16777215</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-right.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="11" column="3">
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="QWidget" name="widget_17" native="true">
+     <property name="minimumSize">
+      <size>
+       <width>44</width>
+       <height>44</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>44</width>
+       <height>44</height>
+      </size>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">background:url(:/assets/window/thick_opaque-border-topleft.png)</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1" colspan="3">
+    <widget class="QWidget" name="widget_16" native="true">
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>44</height>
+      </size>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">background:url(:/assets/window/thick_opaque-border-top.png)</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" rowspan="4">
+    <widget class="QWidget" name="widget_6" native="true">
+     <property name="styleSheet">
+      <string notr="true">background:url(:/assets/window/thick_opaque-border-left.png)</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="4">
+    <widget class="QWidget" name="widget_14" native="true">
+     <property name="minimumSize">
+      <size>
+       <width>44</width>
+       <height>43</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>44</width>
+       <height>43</height>
+      </size>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">background:url(:/assets/window/thick_opaque-border-botright.png)</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="1" colspan="3">
+    <widget class="QWidget" name="widget_12" native="true">
+     <property name="styleSheet">
+      <string notr="true">background:url(:/assets/window/thick_opaque-border-bottom.png)</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <widget class="QWidget" name="divider" native="true"/>
+   </item>
+   <item row="1" column="2" rowspan="3" colspan="2">
+    <widget class="QWidget" name="game_widget_" native="true">
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>16777215</width>
+       <height>16777215</height>
+      </size>
+     </property>
+     <property name="sizeIncrement">
+      <size>
+       <width>1</width>
+       <height>1</height>
+      </size>
+     </property>
+     <property name="baseSize">
+      <size>
+       <width>1</width>
+       <height>1</height>
+      </size>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_6">
+      <property name="leftMargin">
+       <number>0</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="rightMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <property name="spacing">
+       <number>0</number>
+      </property>
+      <item row="0" column="0">
+       <widget class="QWidget" name="border_upleft_2" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>26</width>
+          <height>25</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>26</width>
+          <height>25</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/strong_translucent-border-topleft.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QWidget" name="border_up_2" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>25</width>
+          <height>25</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>25</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/strong_translucent-border-top.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="2">
+       <widget class="QWidget" name="border_upright_2" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>25</width>
+          <height>25</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>25</width>
+          <height>25</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/strong_translucent-border-topright.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QWidget" name="border_left_2" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>26</width>
+          <height>26</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>26</width>
+          <height>16777215</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/strong_translucent-border-left.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QWidget" name="game_widget_1" native="true">
+        <property name="styleSheet">
+         <string notr="true">background-image: url(:/assets/window/strong_translucent-background.png);</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="2">
+       <widget class="QWidget" name="border_right_2" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>25</width>
+          <height>25</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>26</width>
+          <height>16777215</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/strong_translucent-border-right.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QWidget" name="border_botleft_2" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>26</width>
+          <height>26</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>26</width>
+          <height>26</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/strong_translucent-border-botleft.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QWidget" name="border_bottom_2" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>26</width>
+          <height>26</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>26</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/strong_translucent-border_bottom.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="2">
+       <widget class="QWidget" name="border_botright_2" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>25</width>
+          <height>26</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>25</width>
+          <height>26</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/strong_translucent-border-botright.png)</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="4" column="1" colspan="3">
+    <widget class="QWidget" name="helper" native="true">
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>75</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>16777215</width>
+       <height>75</height>
+      </size>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <property name="spacing">
+       <number>0</number>
+      </property>
+      <item row="0" column="2">
+       <widget class="QWidget" name="border_upright_1" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-topright.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QWidget" name="border_bottom_1" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-bottom.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="0">
+       <widget class="QWidget" name="border_upleft_1" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-topleft.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QWidget" name="border_left_1" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>5</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>5</width>
+          <height>16777215</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-left.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="2">
+       <widget class="QWidget" name="border_right_1" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>8</width>
+          <height>16777215</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-right.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QWidget" name="border_up_1" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>5</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>5</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-top.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QWidget" name="border_botleft_1" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-botleft.png)</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QWidget" name="container_" native="true">
+        <layout class="QGridLayout" name="gridLayout_3">
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <property name="spacing">
+          <number>0</number>
+         </property>
+         <item row="0" column="0">
+          <widget class="QLabel" name="label_2">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="text">
+            <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt; color:#ffffff;&quot;&gt;Это подсказка. Она подсказывает, что можно сделать. А может и нет.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item row="2" column="2">
+       <widget class="QWidget" name="border_botright_1" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>8</width>
+          <height>8</height>
+         </size>
+        </property>
+        <property name="styleSheet">
+         <string notr="true">background:url(:/assets/window/opaque-border-botright.png)</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="1" column="4" rowspan="4">
+    <widget class="QWidget" name="widget_13" native="true">
+     <property name="styleSheet">
+      <string notr="true">background:url(:/assets/window/thick_opaque-border-right.png)</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 15 - 0
include/skills/MelleDamage.h

@@ -0,0 +1,15 @@
+//
+// Created by IgorBat on 23.04.2018.
+//
+
+#ifndef GAME_CLIENT_MELLEDAMAGE_H
+#define GAME_CLIENT_MELLEDAMAGE_H
+#pragma once
+#include <cassert>
+#include "skills\spell.h"
+
+class melledamage : public Effect {
+    void CastSpell(Cell* from, Cell* where, Unit* who, Unit* whom);
+};
+
+#endif //GAME_CLIENT_MELLEDAMAGE_H

+ 16 - 0
include/skills/SelfHeal.h

@@ -0,0 +1,16 @@
+//
+// Created by IgorBat on 23.04.2018.
+//
+
+#ifndef GAME_CLIENT_SELFHEAL_H
+#define GAME_CLIENT_SELFHEAL_H
+#pragma once
+#include <cassert>
+#include "skills\spell.h"
+
+class selfheal : public Spell {
+    void CastSpell(Cell* from, Cell* where, Unit* who, Unit* whom);
+
+};
+
+#endif //GAME_CLIENT_SELFHEAL_H

+ 68 - 0
include/skills/Spell.h

@@ -0,0 +1,68 @@
+//
+// Created by IgorBat on 17.03.2018.
+//
+
+#ifndef THE_GAME_SPELL_H
+#define THE_GAME_SPELL_H
+
+#pragma once
+#include <iostream>
+#include <vector>
+#include <list>
+//#include "AbstractFactory.h"
+#include "effect.h"
+
+class Unit{
+    std :: list <Effect> effectsOnUnit;
+};
+class Cell{
+    std :: list <Effect> effectsOnCell;
+};
+class Spell : public QObject {
+    Q_OBJECT
+
+protected:
+    std :: list <Effect> effects_;
+private:
+    int distance_;
+    bool forCell_;
+public:
+    explicit Spell(QString parameters);
+
+    virtual ~Spell() {}
+
+    int getDistance();
+    void setDistance(int value);
+
+    bool getForCell();
+    void setForCell(bool value);
+
+    virtual bool canCastToCell(Cell* destination, Cell* from);
+
+    virtual void CastSpell(Cell* from, Cell* where, Unit* who, Unit* whom) = 0;
+
+    int getDistance();
+    void setDistance(int Value);
+
+    bool getForCell();
+    void setForCell(bool Value);
+
+    QString getSpellName() const;
+    QString getSpellDescr() const;
+    QImage getSpellIcon() const;
+
+    //---------------------------------------------//
+    //-----------Parameters load section-----------//
+    //---------------------------------------------//
+
+private:
+    void loadSpellTraits(QString spell_folder);
+    void loadSpellDescr(QString spell_folder);
+    void loadSpellIcon(QString spell_folder);
+
+    // GUI values
+    QString spell_name_;
+    QString spell_descr_;
+    QImage spell_icon_;
+};
+#endif //THE_GAME_SPELL_H

+ 14 - 0
include/units/Mage.h

@@ -0,0 +1,14 @@
+#ifndef UNITS_MAGE_H
+#define UNITS_MAGE_H
+
+#include "units/Unit.h"
+
+#include <QObject>
+
+class Mage : public Unit
+{
+public:
+    explicit Mage(QString parameters);
+};
+
+#endif // UNITS_MAGE_H

+ 174 - 0
include/units/Unit.h

@@ -0,0 +1,174 @@
+#pragma once
+
+#include "AbstractFactory.h"
+#include <QObject>
+#include <QString>
+#include <QImage>
+#include <iostream>
+#include <vector>
+
+class Spell {
+public:
+    int a;
+};
+
+class Cell;
+
+class Unit : public QObject {
+    Q_OBJECT
+
+public:
+    explicit Unit(QString parameters);
+
+    virtual ~Unit() {}
+
+    //---------------------------------------------//
+    //---------Basic traits getters section--------//
+    //---------------------------------------------//
+
+	double getExperience();
+    int getLevel();
+    int getMovementSpeed();
+    int getInitiative();
+
+    int getIntelligence();
+    int getStrength();
+    int getAgility();
+
+    int getActivityPoints();
+    int getAttackPoints();
+    int getAttackCost();
+    int getAttackRange();
+    int getStartingActivityPoints();
+
+    int getHealthPoints();
+
+    int getMagicDefence();
+    int getPhysicDefence();
+
+    int getCost();
+    void setCost(int value);
+    virtual bool isCharacter();
+
+    std::vector<QString> getParentSpecs();
+    std::vector<QString> getUpgradeSpecs();
+
+    //---------------------------------------------//
+    //------------Unit location section------------//
+    //---------------------------------------------//
+
+    Cell* getLocation();
+    void setLocation(Cell* to);
+
+	double getRealX();
+	void setRealX(double x);
+
+	double getRealY();
+	void setRealY(double y);
+
+
+    //---------------------------------------------//
+    //--------Damage checkers & calculators--------//
+    //---------------------------------------------//
+
+    virtual int reduceIncomingDamage(std::string damageType, int value);
+
+    virtual	bool canAttackForDistance(std::string, int) {return false;}
+
+    virtual bool canAttackToCell(Cell* ) {return false;}
+
+    virtual bool canAttackUnit(Unit* ) {return false;}
+
+
+
+    //---------------------------------------------//
+    //-------Movement checkers & calculators-------//
+    //---------------------------------------------//
+
+
+    int lenOfActualPath(Cell* destination);
+
+    virtual bool canMoveForDistance(int distance);
+
+    virtual bool canMoveToCell(Cell* destination);
+
+    virtual void moveToCell(Cell* destination);
+
+    virtual int theSameNear();
+
+    //---------------------------------------------//
+    //----------------GUI section------------------//
+    //---------------------------------------------//
+
+    QString getUnitId() const;
+    QString getUnitName() const;
+    QString getUnitDescr() const;
+    QString getUnitBaseClassId() const;
+    std::vector<QString> getUnitTraits() const;
+    QImage getUnitIcon() const;
+
+    //---------------------------------------------//
+    //-----------Parameters load section-----------//
+    //---------------------------------------------//
+
+private:
+    void loadUnitName(QString unit_folder);
+    void loadUnitDescr(QString unit_folder);
+    void loadUnitBaseClass(QString unit_folder);
+    void loadUnitTraits(QString unit_folder);
+    void loadUnitIcon(QString unit_folder);
+    void loadUnitPrevSpecs(QString unit_folder);
+    void loadUnitUpgradeSpecs(QString unit_folder);
+
+public:
+    bool operator <(const Unit &b) {
+        if (base_class_id_ != b.base_class_id_)
+            return base_class_id_ < b.base_class_id_;
+        return unit_id_ < b.unit_id_;
+    }
+
+protected:
+    std::vector <Spell> skills_;
+
+    //personal information
+    int cost_;
+
+    std::vector<QString> parent_specs_;
+    std::vector<QString> upgrade_specs_;
+
+    double experience_;
+    int level_;
+    std::string race_; //lower case
+
+    //actions and events
+    double initiative_;
+    int activity_points_;
+
+    //movement
+    Cell* location_;
+    int movement_speed_;	//how many cells can move for one activity point
+    double real_x_;
+    double real_y_;
+
+    //attack action
+    int agility_;
+    int attack_range_;
+    int intelligence_;
+    int strength_;
+    int attack_cost_;     //how many activity points does attack cost
+    int starting_activity_points_;
+
+    //durability
+    int health_points_;
+    int magic_defence_;  //less or equal 40
+    int physic_defence_; //less or equal 40
+
+    // GUI values
+    QString race_id_;
+    QString unit_id_;
+
+    QString unit_name_;
+    QString unit_descr_;
+    QString base_class_id_;
+    QImage unit_icon_;
+};

+ 16 - 0
include/units/Warrior.h

@@ -0,0 +1,16 @@
+#ifndef UNITS_WARRIOR_H
+#define UNITS_WARRIOR_H
+
+#include "units/Unit.h"
+
+#include <QObject>
+#include <QString>
+
+class Warrior : public Unit
+{
+public:
+    explicit Warrior(QString parameters);
+    int reduceIncomingDamage(std::string damageType, int damage) override;
+};
+
+#endif // UNITS_WARRIOR_H

+ 22 - 0
source/PlayerManager.cpp

@@ -0,0 +1,22 @@
+#include "PlayerManager.h"
+#include <cassert>
+
+PlayerManager::PlayerManager(QObject *parent) : QObject(parent)
+{
+
+}
+
+Player* PlayerManager::getPlayer(int id) {
+    assert(unsigned(id) < players_.size());
+    return &players_[id];
+}
+
+int PlayerManager::getPlayersNum() {
+    return players_.size();
+}
+
+void PlayerManager::setPlayersNum(int num) {
+    players_.resize(num);
+    for (int i = 0; i < num; i++)
+        players_[i].init(i);
+}

+ 90 - 0
source/Race.cpp

@@ -0,0 +1,90 @@
+#include "Race.h"
+#include "units/Unit.h"
+#include "units/Warrior.h"
+#include "units/Mage.h"
+
+#include <QFile>
+#include <QTextStream>
+#include <QString>
+#include <QDebug>
+
+#include <cassert>
+#include <vector>
+#include <algorithm>
+
+Race::Race(QString race_name, QObject *parent) : QObject(parent)
+{
+    race_id_ = race_name;
+
+    units_factory_.addClass<Warrior, QString>("Warrior");
+    units_factory_.addClass<Warrior, QString>("Mage");
+    units_factory_.addClass<Warrior, QString>("Rider");
+    units_factory_.addClass<Warrior, QString>("Rogue");
+    units_factory_.addClass<Warrior, QString>("Archer");
+
+    QFile file(":/assets/units/" + race_name + "/units.txt");
+    file.open(QIODevice::ReadOnly);
+    QTextStream in(&file);
+    in.setCodec("UTF-8");
+    QString unit_name = in.readLine();
+
+    while (!in.atEnd()) {
+        available_units_list_.push_back(unit_name);
+        all_units_list_.push_back(createUnit(unit_name));
+        unit_name = in.readLine();
+    }
+
+    if (unit_name.length() > 2) {
+        available_units_list_.push_back(unit_name);
+        all_units_list_.push_back(createUnit(unit_name));
+    }
+
+    QFile file0(":/assets/units/" + race_name + "/racename.txt");
+    file0.open(QIODevice::ReadOnly);
+    QTextStream in0(&file0);
+    in0.setCodec("UTF-8");
+    race_name_ = in0.readLine();
+
+    QFile file1(":/assets/units/" + race_name + "/descr.txt");
+    file1.open(QIODevice::ReadOnly);
+    QTextStream in1(&file1);
+    in1.setCodec("UTF-8");
+    race_descr_ = in1.readAll();
+
+    race_icon_.load(":/assets/units/" + race_name + "/icon.png");
+}
+
+QString Race::getRaceId() {
+    return race_id_;
+}
+
+QString Race::getRaceName() {
+    return race_name_;
+}
+
+QImage Race::getRaceIcon() {
+    return race_icon_;
+}
+
+QString Race::getRaceDescr() {
+    return race_descr_;
+}
+
+Unit* Race::createUnit(QString unit_name) {
+    qDebug() << unit_name;
+    QFile file(":/assets/units/" + race_id_ + "/" + unit_name + "/baseclass.txt");
+    file.open(QIODevice::ReadOnly);
+    QTextStream in(&file);
+    in.setCodec("UTF-8");
+    QString class_id = in.readLine();
+    qDebug() << "Creating unit of base class " << class_id << " and major class" <<  race_id_ + "|" + unit_name;
+    return units_factory_.createObject<QString>(class_id, race_id_ + "|" + unit_name);
+}
+
+const std::vector<QString>& Race::getAvailableUnitsList() {
+    return available_units_list_;
+}
+
+const std::vector<Unit*> &Race::getAllUnitsList() {
+    return all_units_list_;
+}

+ 50 - 0
source/RaceManager.cpp

@@ -0,0 +1,50 @@
+#include "RaceManager.h"
+#include "Race.h"
+
+#include <QFile>
+#include <QDebug>
+#include <QTextStream>
+#include <QDebug>
+
+RaceManager::RaceManager(QObject *parent) : QObject(parent)
+{
+    QFile file(":/assets/units/races.txt");
+    file.open(QIODevice::ReadOnly);
+    QTextStream in(&file);
+    in.setCodec("UTF-8");
+    QString race_name = in.readLine();
+
+    while(!in.atEnd()) {
+        if (races_.count(race_name) != 0) {
+            qWarning() << "Warning! found double occurences of races in raceslist.txt";
+            continue;
+        }
+        if (race_name.length() < 2)
+            continue;
+        //qDebug() << available_races_;
+        available_races_.push_back(race_name);
+        races_[race_name] = new Race(race_name);
+        race_name = in.readLine();
+    }
+
+    if (race_name.length() >= 2) {
+        //qDebug() << available_races_;
+        available_races_.push_back(race_name);
+        races_[race_name] = new Race(race_name);
+        race_name = in.readLine();
+    }
+
+}
+
+Race* RaceManager::getRace(QString race_name) {
+    if (races_.count(race_name) == 0) {
+        qWarning() << "Error! Not found race with name " << race_name;
+        return nullptr;
+    }
+
+    return races_[race_name];
+}
+
+const std::vector<QString>& RaceManager::getAvailableRacesList() {
+    return available_races_;
+}

+ 67 - 0
source/effects/Effect.cpp

@@ -0,0 +1,67 @@
+//
+// Created by IgorBat on 21.04.2018.
+//
+#include "abstractfactory.h"
+#include "effects/effect.h"
+
+#include <iostream>
+#include <algorithm>
+#include <cassert>
+#include <string>
+
+#include <QFile>
+#include <QString>
+#include <QTextStream>
+
+Effect::Effect(QString parameters) {
+    QStringList params = parameters.split("|");
+
+    assert(params.size() >= 3);
+
+    effect_name_ = params[0];
+    setCount(params[1].toInt());
+    setDurability(params[2].toInt());
+    QString effect_folder = ":/assets/effects/" + effect_name_ + "/";
+
+    loadEffectDescr(effect_folder);
+    loadEffectIcon(effect_folder);
+}
+
+void Effect::loadEffectDescr(QString effect_folder) {
+    QFile file(effect_folder + "descr.txt");
+    file.open(QIODevice::ReadOnly);
+    QTextStream in(&file);
+    in.setCodec("UTF-8");
+    effect_descr_ = in.readAll();
+}
+
+void Effect::loadEffectIcon(QString effect_folder) {
+    effect_icon_.load(effect_folder + "icon.png");
+}
+
+
+QString Effect::getEffectName() const {
+    return effect_name_;
+}
+
+QString Effect::getEffectDescr() const {
+    return effect_descr_;
+}
+
+QImage Effect::getEffectIcon() const {
+    return effect_icon_;
+}
+
+int Effect::getCount(){
+    return count_;
+}
+void Effect::setCount(int value){
+    count_ = value;
+}
+
+int Effect::getDurability(){
+        return durability_;
+};
+void Effect::setDurability(int value){
+    durability_ = value;
+}

+ 19 - 0
source/effects/MelleDamage.cpp

@@ -0,0 +1,19 @@
+//
+// Created by IgorBat on 23.04.2018.
+//
+
+#pragma once
+#include <cassert>
+#include "effect\melledamage.h"
+#include "units\unit.h"
+#include <string>
+
+void melledamage::OperateOnCell(Cell* cell){
+    throw std :: string("CAN'T TOUCH THIS")
+}
+
+void melledamage::OperateOnUnit(Unit* unit){
+    int temp = unit -> reduceIncomingDamage("p", count_);
+    unit ->setHealthPoints(unit -> getHealthPoints() - temp);
+    //check_on_death
+}

+ 19 - 0
source/effects/SelfHeal.cpp

@@ -0,0 +1,19 @@
+//
+// Created by IgorBat on 23.04.2018.
+//
+
+
+#pragma once
+#include <cassert>
+#include "effect\selfdamage.h"
+#include "units\unit.h"
+#include <string>
+
+void melledamage::OperateOnCell(Cell* cell){
+    throw std :: string("CAN'T TOUCH THIS")
+}
+
+void melledamage::OperateOnUnit(Unit* unit){
+    unit.setHealthPoints(unit.getHealthPoints() + count_);
+    //check_on_death
+}

+ 68 - 0
source/gui/GUI.cpp

@@ -0,0 +1,68 @@
+#include <gui/GUI.h>
+#include <ui_gui.h>
+#include <gui/RecruitmentScene.h>
+#include <QDebug>
+
+GUI::GUI(QWidget *parent) :
+    QMainWindow(parent, Qt::Window | Qt::FramelessWindowHint),
+    ui_(new Ui::GUI), dx_(0), dy_(0)
+{
+    ui_->setupUi(this);
+    setWindowTitle("Супер-мега-клёвая-игрушка-название-которой-мы-ещё-не-придумали");
+}
+
+GUI::~GUI()
+{
+    delete ui_;
+}
+
+QWidget* GUI::mainContentScene() {
+    return ui_->main_content_;
+}
+
+
+void GUI::mouseMoveEvent( QMouseEvent* e ) {
+    if( e->buttons() | Qt::LeftButton ) {
+        QPoint pt=mapFromGlobal(QCursor::pos());
+        QWidget* child=childAt(pt);
+
+        if (child == 0) {
+            setGeometry(pos().x() + (pt.x() - dx_ ), pos().y() + (pt.y() - dy_ ), width(), height());
+            return;
+        }
+        QString cname = child->metaObject()->className();
+        if (cname != "QPushButton" && cname != "QComboBox" && cname != "RaceIcon" && cname != "UnitIcon"){ // отключаем перетягивание при наведение на активные элементы
+            setGeometry(pos().x() + ( pt.x() - dx_ ), pos().y() + ( pt.y() - dy_ ), width(), height());
+        } else {
+            dx_ = pt.x();
+            dy_ = pt.y();
+        }
+    }
+}
+
+void GUI::mousePressEvent( QMouseEvent* e ) {
+    if(e->button() == Qt::LeftButton) {
+        QPoint pt = mapFromGlobal(QCursor::pos());
+        QWidget* child=childAt(pt);
+
+        if (child == 0)
+            return;
+
+        QString cname = child->metaObject()->className();
+        if (cname == "QPushButton" || cname == "QComboBox" || cname == "QLabel")
+           return;
+
+        dx_ = pt.x();
+        dy_ = pt.y();
+        setCursor( Qt::OpenHandCursor );
+    }
+}
+
+void GUI::mouseReleaseEvent( QMouseEvent* e ) {
+    if( e->button() == Qt::LeftButton ) {
+        QPoint pt=mapFromGlobal(QCursor::pos());
+        setCursor( Qt::ArrowCursor );
+        dx_ = pt.x();
+        dy_ = pt.y();
+    }
+}

+ 85 - 0
source/gui/GuiSceneManager.cpp

@@ -0,0 +1,85 @@
+#include "gui/GuiSceneManager.h"
+#include "gui/GUI.h"
+#include "gui/MainMenu.h"
+#include "gui/PlayerVsPlayerIntro.h"
+#include "gui/PreBattleScene.h"
+#include "hotseatgame\gui\HotSeatGame.h"
+
+#include <QResource>
+#include <QApplication>
+
+GuiSceneManager::GuiSceneManager(QObject *parent) : QObject(parent) {
+    gui_ = new GUI();
+    gui_->show();
+    current_scene_ = "none";
+
+    QResource::registerResource(QApplication::applicationDirPath() + "/res/gui_data.gtr");
+    QResource::registerResource(QApplication::applicationDirPath() + "/res/unit_data.gtr");
+    QResource::registerResource(QApplication::applicationDirPath() + "/res/spell_data.gtr");
+    QResource::registerResource(QApplication::applicationDirPath() + "/res/effect_data.gtr");
+
+    registerScene("main_menu", new MainMenu(gui_->mainContentScene()));
+    registerScene("pvp_intro", new PlayerVsPlayerIntro(gui_->mainContentScene()));
+    registerScene("recruit_army", new RecruitmentScene(gui_->mainContentScene()));
+    registerScene("prebattle", new PreBattleScene(gui_->mainContentScene()));
+    registerScene("hotseatgame", new HotSeatGame());
+
+    changeScene("main_menu");
+}
+
+GuiSceneManager::~GuiSceneManager() {}
+
+
+bool GuiSceneManager::registerScene(QString scene_name, Scene* scene) {
+    if (scene_name == "none")
+        return false;
+
+    if (scenes_.count(scene_name) != 0) {
+        delete scene;
+        return false;
+    }
+
+    scenes_[scene_name] = scene;
+    return true;
+}
+
+bool GuiSceneManager::changeScene(QString scene_name, QString args) {
+    if (scene_name == "main_window") {
+        return false;
+    }
+
+    if (current_scene_ != "none")
+        scenes_[current_scene_]->hide();
+
+    scenes_[scene_name]->parseArgs(args);
+    scenes_[scene_name]->init();
+    scenes_[scene_name]->show();
+    current_scene_ = scene_name;
+    return true;
+}
+
+bool GuiSceneManager::hideMainWindow() {
+    gui_->hide();
+    return true;
+}
+
+bool GuiSceneManager::showMainWindow() {
+    gui_->show();
+    return true;
+}
+
+bool GuiSceneManager::hideDetachedScene(QString scene_name) {
+    if (scenes_.count(scene_name) == 0 || !scenes_[scene_name])
+        return false;
+    scenes_[scene_name]->hide();
+    return true;
+}
+
+bool GuiSceneManager::showDetachedScene(QString scene_name, QString args) {
+    if (scenes_.count(scene_name) == 0 || !scenes_[scene_name])
+        return false;
+    scenes_[scene_name]->parseArgs(args);
+    scenes_[scene_name]->init();
+    scenes_[scene_name]->show();
+    return true;
+}

+ 28 - 0
source/gui/MainMenu.cpp

@@ -0,0 +1,28 @@
+#include "gui/MainMenu.h"
+#include "gui/GuiSceneManager.h"
+#include "ui_mainmenu.h"
+
+#include <QString>
+#include <QApplication>
+
+MainMenu::MainMenu(QWidget *parent) :
+    Scene(parent),
+    ui(new Ui::MainMenu)
+{
+    ui->setupUi(this);
+}
+
+MainMenu::~MainMenu()
+{
+    delete ui;
+}
+
+void MainMenu::on_exit_button_clicked()
+{
+    QApplication::quit();
+}
+
+void MainMenu::on_pvp_local_battle_button_clicked()
+{
+    GuiSceneManager::getInstance().changeScene("pvp_intro");
+}

+ 30 - 0
source/gui/PlayerVsPlayerIntro.cpp

@@ -0,0 +1,30 @@
+#include "gui/PlayerVsPlayerIntro.h"
+#include "gui/GuiSceneManager.h"
+#include "PlayerManager.h"
+#include "gui/Scene.h"
+
+#include "ui_playervsplayerintro.h"
+
+PlayerVsPlayerIntro::PlayerVsPlayerIntro(QWidget *parent) :
+    Scene(parent),
+    ui(new Ui::PlayerVsPlayerIntro)
+{
+    ui->setupUi(this);
+}
+
+PlayerVsPlayerIntro::~PlayerVsPlayerIntro()
+{
+    delete ui;
+}
+
+void PlayerVsPlayerIntro::on_back_to_menu_clicked()
+{
+    GuiSceneManager::getInstance().changeScene("main_menu");
+}
+
+void PlayerVsPlayerIntro::on_go_next_clicked()
+{
+    PlayerManager::getInstance().setPlayersNum(2);
+    /// TODO - Check if money input correct
+    GuiSceneManager::getInstance().changeScene("recruit_army", "0|" + ui->money_->text());
+}

+ 74 - 0
source/gui/PreBattleScene.cpp

@@ -0,0 +1,74 @@
+
+#include "gui/PreBattleScene.h"
+
+#include "Player.h"
+#include "PlayerManager.h"
+#include "Race.h"
+#include "RaceManager.h"
+
+#include "gui/RaceIcon.h"
+#include "gui/UnitIcon.h"
+#include "gui/GuiSceneManager.h"
+#include "ui_prebattlescene.h"
+
+#include <QMessageBox>
+
+PreBattleScene::PreBattleScene(QWidget *parent) :
+    Scene(parent),
+    ui(new Ui::PreBattleScene)
+{
+    ui->setupUi(this);
+}
+
+PreBattleScene::~PreBattleScene()
+{
+    delete ui;
+}
+
+void PreBattleScene::init() {
+    Player *player = PlayerManager::getInstance().getPlayer(0);
+
+    ui->race_icon_1_->setRaceIcon(player->getRace()->getRaceIcon());
+    ui->race_icon_1_->resize(128, 128);
+    ui->race_icon_1_->setState(5);
+
+    units_player_1_.resize(10);
+    auto units = player->getUnitsAsVector();
+    for (unsigned i = 0; i < 10; i++) {
+        units_player_1_[i] = new UnitIcon();
+        if (i < units.size())
+            units_player_1_[i]->setUnitIcon(units[i]->getUnitIcon());
+        else
+            units_player_1_[i]->setUnitIcon("norace", "nounit");
+        units_player_1_[i]->setState(5);
+        ui->units_player_1_layout_->addWidget(units_player_1_[i], i / 5, i % 5);
+    }
+
+    player = PlayerManager::getInstance().getPlayer(1);
+    ui->race_icon_2_->setRaceIcon(player->getRace()->getRaceIcon());
+    ui->race_icon_2_->resize(128, 128);
+    ui->race_icon_2_->setState(5);
+
+    units_player_2_.resize(10);
+    units = player->getUnitsAsVector();
+    for (unsigned i = 0; i < 10; i++) {
+        units_player_2_[i] = new UnitIcon();
+        if (i < units.size())
+            units_player_2_[i]->setUnitIcon(units[i]->getUnitIcon());
+        else
+            units_player_2_[i]->setUnitIcon("norace", "nounit");
+        units_player_2_[i]->setState(5);
+        ui->units_player_2_layout_->addWidget(units_player_2_[i], i / 5, i % 5);
+    }
+
+    setWindowState(Qt::WindowFullScreen);
+}
+
+void PreBattleScene::on_start_battle_clicked()
+{
+    //QMessageBox msg(QMessageBox::Information, "Нельзя сотворить здесь!", "Не ну имейте терпение! Всё будет! Но попозже... :)");
+    //msg.exec();
+
+    //GuiSceneManager::getInstance().changeScene("main_menu");
+    GuiSceneManager::getInstance().showDetachedScene("hotseatgame");
+}

+ 138 - 0
source/gui/RaceIcon.cpp

@@ -0,0 +1,138 @@
+#include <gui/RaceIcon.h>
+#include <QDebug>
+#include <QTime>
+#include <QEvent>
+#include <QMouseEvent>
+
+RaceIcon::RaceIcon(QWidget* parent, int width, int height)
+    : QLabel(parent)
+{
+    state_ = 0;
+    width_ = width;
+    height_ = height;
+
+    setAttribute(Qt::WA_Hover, false);
+    installEventFilter(this);
+
+    default_border_.load(":/assets/common/unit_icon_default.png");
+    hover_border_.load(":/assets/common/unit_icon_hover.png");
+    active_border_.load(":/assets/common/unit_icon_active.png");
+    icon_.load(":/assets/units/norace/nounit/icon.png");
+
+    drawIcon();
+}
+
+RaceIcon::~RaceIcon()
+{}
+
+void RaceIcon::drawIcon() {
+    QPixmap combined(width_, height_);
+    combined.fill(Qt::black);
+
+    if (state_ >= 5) {
+        combined.fill(QColor(0, 0, 0, 0));
+    }
+
+    QPainter p(&combined);
+
+    if (state_ != 0) {
+        p.drawImage(QPoint(4, 4), icon_.scaled(width_ - 8, height_ - 8, Qt::KeepAspectRatio));
+    }
+
+    if (state_ == 0 || state_ == 1)
+        p.drawImage(QPoint(0, 0), default_border_.scaled(width_, height_, Qt::KeepAspectRatio));
+
+    if (state_ == 2)
+        p.drawImage(QPoint(0, 0), hover_border_.scaled(width_, height_, Qt::KeepAspectRatio));
+
+    if (state_ == 3)
+        p.drawImage(QPoint(0, 0), active_border_.scaled(width_, height_, Qt::KeepAspectRatio));
+
+    p.end();
+    setPixmap(combined);
+}
+
+Race* RaceIcon::getRace() {
+    return race_;
+}
+
+void RaceIcon::setRace(Race* race) {
+    race_ = race;
+}
+
+int RaceIcon::getState() {
+    return state_;
+}
+
+void RaceIcon::setState(int state) {
+    state_ = state;
+    drawIcon();
+}
+
+void RaceIcon::setRaceIcon(QImage icon) {
+    icon_ = icon;
+    if (state_ == 0)
+        state_ = 1;
+    drawIcon();
+}
+
+
+void RaceIcon::unsetRaceIcon() {
+    state_ = 0;
+    drawIcon();
+}
+
+void RaceIcon::resize(int w, int h) {
+    width_ = w;
+    height_ = h;
+    drawIcon();
+}
+
+void RaceIcon::deactivate() {
+    if (state_ > 1)
+        state_ = 1;
+    drawIcon();
+}
+
+void RaceIcon::activate() {
+    state_ = 3;
+    drawIcon();
+}
+
+void RaceIcon::mousePressEvent(QMouseEvent* event)
+{
+    if (state_ == 0 || state_ >= 5)
+        return;
+
+    activate();
+
+    QTime current_time = QTime::currentTime();
+    if (current_time.msecsSinceStartOfDay() - previous_click_time_.msecsSinceStartOfDay() < 350) {
+        deactivate();
+        emit doubleclicked(this);
+    } else {
+        previous_click_time_ = current_time;
+        emit clicked(this);
+    }
+}
+
+void RaceIcon::enterEvent(QEvent* event)
+{
+
+    if (state_ == 0 || state_ == 3 || state_ >= 5)
+        return;
+
+    state_ = 2;
+    drawIcon();
+    emit hovered(this);
+}
+
+void RaceIcon::leaveEvent(QEvent* event)
+{
+    if (state_ == 0 || state_ == 3 || state_ >= 5)
+        return;
+
+    state_ = 1;
+    drawIcon();
+    emit unhovered(this);
+}

+ 429 - 0
source/gui/RecruitmentScene.cpp

@@ -0,0 +1,429 @@
+#include <gui/RecruitmentScene.h>
+#include <gui/UnitIcon.h>
+#include <gui/RaceIcon.h>
+#include <gui/GuiSceneManager.h>
+#include <gui/Scene.h>
+#include <PlayerManager.h>
+#include <Player.h>
+#include <RaceManager.h>
+#include <Race.h>
+
+#include <ui_recruitmentscene.h>
+#include <QHBoxLayout>
+#include <QString>
+#include <QStringList>
+
+#include <cassert>
+#include <vector>
+
+RecruitmentScene::RecruitmentScene(QWidget *parent)
+    : Scene(parent)
+    , ui(new Ui::RecruitmentScene)
+{
+    ui->setupUi(this);
+
+    for (int i = 0; i < 5; i++) {
+        available_units_icons_[i] = new UnitIcon();
+        ui->available_units_layout_->addWidget(available_units_icons_[i], 0, i);
+
+        connect(available_units_icons_[i], SIGNAL(clicked(UnitIcon*)), this, SLOT(onUnitIconClicked(UnitIcon*)));
+        connect(available_units_icons_[i], SIGNAL(hovered(UnitIcon*)), this, SLOT(onUnitIconHovered(UnitIcon*)));
+        connect(available_units_icons_[i], SIGNAL(unhovered(UnitIcon*)), this, SLOT(onUnitIconUnHovered(UnitIcon*)));
+        connect(available_units_icons_[i], SIGNAL(doubleclicked(UnitIcon*)), this, SLOT(onUnitIconDoubleClicked(UnitIcon*)));
+    }
+
+    for (int i = 0; i < 3; i++) {
+        available_races_icons_[i] = new RaceIcon();
+        ui->availableRacesLayout_->addWidget(available_races_icons_[i], i);
+
+        connect(available_races_icons_[i], SIGNAL(clicked(RaceIcon*)), this, SLOT(onRaceIconClicked(RaceIcon*)));
+        connect(available_races_icons_[i], SIGNAL(hovered(RaceIcon*)), this, SLOT(onRaceIconHovered(RaceIcon*)));
+        connect(available_races_icons_[i], SIGNAL(unhovered(RaceIcon*)), this, SLOT(onRaceIconUnHovered(RaceIcon*)));
+        connect(available_races_icons_[i], SIGNAL(doubleclicked(RaceIcon*)), this, SLOT(onRaceIconDoubleClicked(RaceIcon*)));
+
+    }
+
+    for (int i = 0; i < 10; i++) {
+        chosen_units_icons_[i] = new UnitIcon();
+        ui->chosen_units_layout_->addWidget(chosen_units_icons_[i], i / 5, i % 5);
+
+        connect(chosen_units_icons_[i], SIGNAL(clicked(UnitIcon*)), this, SLOT(onChosenUnitIconClicked(UnitIcon*)));
+        connect(chosen_units_icons_[i], SIGNAL(hovered(UnitIcon*)), this, SLOT(onChosenUnitIconHovered(UnitIcon*)));
+        connect(chosen_units_icons_[i], SIGNAL(unhovered(UnitIcon*)), this, SLOT(onChosenUnitIconUnHovered(UnitIcon*)));
+        connect(chosen_units_icons_[i], SIGNAL(doubleclicked(UnitIcon*)), this, SLOT(onChosenUnitIconDoubleClicked(UnitIcon*)));
+    }
+
+    for (int i = 0; i < 4; i++) {
+        prev_grade_units_icons[i] = new UnitIcon();
+        ui->prev_gen_units_layout->addWidget(prev_grade_units_icons[i]);
+
+        connect(prev_grade_units_icons[i], SIGNAL(clicked(UnitIcon*)), this, SLOT(onGradeUnitIconClicked(UnitIcon*)));
+        connect(prev_grade_units_icons[i], SIGNAL(hovered(UnitIcon*)), this, SLOT(onGradeUnitIconHovered(UnitIcon*)));
+        connect(prev_grade_units_icons[i], SIGNAL(unhovered(UnitIcon*)), this, SLOT(onGradeUnitIconUnHovered(UnitIcon*)));
+        connect(prev_grade_units_icons[i], SIGNAL(doubleclicked(UnitIcon*)), this, SLOT(onGradeUnitIconDoubleClicked(UnitIcon*)));
+
+
+        next_grade_units_icons[i] = new UnitIcon();
+        ui->next_gen_units_layout_->addWidget(next_grade_units_icons[i]);
+
+        connect(next_grade_units_icons[i], SIGNAL(clicked(UnitIcon*)), this, SLOT(onGradeUnitIconClicked(UnitIcon*)));
+        connect(next_grade_units_icons[i], SIGNAL(hovered(UnitIcon*)), this, SLOT(onGradeUnitIconHovered(UnitIcon*)));
+        connect(next_grade_units_icons[i], SIGNAL(unhovered(UnitIcon*)), this, SLOT(onGradeUnitIconUnHovered(UnitIcon*)));
+        connect(next_grade_units_icons[i], SIGNAL(doubleclicked(UnitIcon*)), this, SLOT(onGradeUnitIconDoubleClicked(UnitIcon*)));
+    }
+
+    ui->description_icon_->resize(45, 45);
+    ui->description_text_->setWordWrap(true);
+
+    ui->current_spec_unit_->resize(45, 45);
+    ui->current_spec_unit_->setUnitIcon("warcraft", "chaosorc");
+}
+
+RecruitmentScene::~RecruitmentScene()
+{
+}
+
+void RecruitmentScene::parseArgs(QString args) {
+    QStringList list = args.split("|");
+    assert(list.size() >= 2);
+
+    current_player_id_ = list[0].toInt();
+    current_player_ = PlayerManager::getInstance().getPlayer(current_player_id_);
+    available_money_ = list[1].toInt();
+
+    init();
+}
+
+void RecruitmentScene::init() {
+    current_money_ = available_money_;
+    initAvailableRaces();
+    initAvailableUnits();
+    showChosenUnits();
+
+    ui->title_->setText(
+        "<html><head/><body><p align=\"center\"><span style=\"font-size:24pt; color:#b12d2d;\">Набор юнитов - "
+        + current_player_->getPlayerName()
+        + "</span></p></body></html>"
+    );
+
+    setDescriptionIcon(current_player_->getRace()->getRaceIcon());
+    setDescriptionText(current_player_->getRace()->getRaceDescr());
+    setDescriptionTitle(current_player_->getRace()->getRaceName());
+
+    ui->chosen_race_image_->resize(100, 100);
+    ui->chosen_race_image_->setRaceIcon(current_player_->getRace()->getRaceIcon());
+    ui->chosen_race_image_->setState(5);
+
+    ui->unit_spec_widget_->hide();
+
+    setMoney(current_money_);
+}
+
+void RecruitmentScene::initAvailableRaces() {
+    auto races = RaceManager::getInstance().getAvailableRacesList();
+
+    int race_id = 0;
+    for (QString race_name : races) {
+        assert(race_id < 3);
+        auto race = RaceManager::getInstance().getRace(race_name);
+        available_races_icons_[race_id]->setRaceIcon(race->getRaceIcon());
+        available_races_icons_[race_id]->setRace(race);
+        race_id++;
+    }
+
+
+}
+
+void RecruitmentScene::initAvailableUnits() {
+    int unit_id = 0;
+    for (int i = 0; i < 5; i++) {
+        available_units_icons_[i]->setUnitIcon("norace", "nounit");
+        available_units_icons_[i]->setState(5);
+    }
+
+    for (Unit* unit : current_player_->getRace()->getAllUnitsList()) {
+        available_units_icons_[unit_id]->setState(0);
+        available_units_icons_[unit_id]->setUnitIcon(unit->getUnitIcon());
+        available_units_icons_[unit_id]->setUnit(unit);
+        unit_id++;
+    }
+}
+
+void RecruitmentScene::showChosenUnits() {
+    for (int i = 0; i < 10; i++) {
+        chosen_units_icons_[i]->unsetUnitIcon();
+        chosen_units_icons_[i]->setUnit(nullptr);
+    }
+
+    int counter = 0;
+    for (auto unit : current_player_->getUnits()) {
+        chosen_units_icons_[counter]->setUnitIcon(unit->getUnitIcon());
+        chosen_units_icons_[counter]->setUnit(unit);
+        counter++;
+    }
+}
+
+void RecruitmentScene::updateSpecsWidget(Unit *unit) {
+    auto next_specs = unit->getUpgradeSpecs();
+    auto prev_specs = unit->getParentSpecs();
+
+    ui->prev_gen_units_list_->resize(45 * prev_specs.size(), 45);
+    ui->next_gen_units_list_->resize(45 * next_specs.size(), 45);
+
+    ui->prev_gen_units_list_->move((180 - 45 * prev_specs.size()) / 2, 40);
+    ui->next_gen_units_list_->move((180 - 45 * next_specs.size()) / 2, 240);
+
+    for (int i = 0; i < 4; i++) {
+        prev_grade_units_icons[i]->hide();
+        next_grade_units_icons[i]->hide();
+    }
+
+    int prev_specs_num = 0;
+    for (unsigned i = 0; i < prev_specs.size(); i++) {
+        if (prev_specs[i].length() <= 2)
+            continue;
+
+        delete prev_grade_units_icons[i]->getUnit();
+
+        prev_grade_units_icons[i]->resize(45, 45);
+        prev_grade_units_icons[i]->unsetUnitIcon();
+        prev_grade_units_icons[i]->setUnit(current_player_->getRace()->createUnit(prev_specs[i]));
+        prev_grade_units_icons[i]->show();
+
+        prev_specs_num++;
+    }
+
+    if (prev_specs_num == 0) {
+        ui->spec_title_->move(0, 110);
+        ui->prev_gen_units_list_->hide();
+        ui->arrow_down_1_->hide();
+    } else {
+        ui->spec_title_->move(0, 10);
+        ui->prev_gen_units_list_->show();
+        ui->arrow_down_1_->show();
+    }
+
+    int next_specs_num = 0;
+    for (unsigned i = 0; i < next_specs.size(); i++) {
+        if (next_specs[i].length() <= 2)
+            continue;
+
+        delete next_grade_units_icons[i]->getUnit();
+
+        next_grade_units_icons[i]->resize(45, 45);
+        next_grade_units_icons[i]->unsetUnitIcon();
+        next_grade_units_icons[i]->setUnit(current_player_->getRace()->createUnit(next_specs[i]));
+        next_grade_units_icons[i]->show();
+
+        next_specs_num++;
+    }
+
+    if (next_specs_num == 0) {
+        ui->next_gen_units_list_->hide();
+        ui->arrow_down_2_->hide();
+    } else {
+        ui->next_gen_units_list_->show();
+        ui->arrow_down_2_->show();
+    }
+
+    ui->current_spec_unit_->setUnit(unit);
+    ui->current_spec_unit_->setState(5);
+}
+
+void RecruitmentScene::changeRace(Race *race) {
+    current_player_->clearUnits();
+    current_player_->setRace(race);
+    init();
+}
+
+void RecruitmentScene::setMoney(int money_) {
+   ui->available_money_text_->setText("<html><head/><body><p>"
+                                      "<span style=\"font-size:10pt; color:#ff0000;\">Ресурсы: "
+                                      + QString::number(money_) +
+                                      "</span></p></body></html>");
+}
+
+
+
+void RecruitmentScene::on_back_button_clicked()
+{
+    GuiSceneManager::getInstance().changeScene("main_menu");
+}
+
+
+
+void RecruitmentScene::setDescriptionTitle(QString title) {
+    ui->desctiption_title_->setText("<html><head/><body><p align=\"center\">"
+                                    "<span style=\" font-weight:600; font-size:16px; color:#000080;\">"
+                                    + title +
+                                    "</span></p></body></html>");
+}
+
+void RecruitmentScene::setDescriptionText(QString text) {
+    ui->description_text_->setText("<html><head/><body><p><span style=\"color:#000080;\">"
+                                   + text
+                                   + "</span></p></body></html>");
+}
+
+void RecruitmentScene::setDescriptionIcon(QImage icon) {
+    ui->description_icon_->setUnitIcon(icon);
+    ui->description_icon_->setState(0);
+}
+
+
+
+
+void RecruitmentScene::onUnitIconHovered(UnitIcon*) {
+
+}
+
+void RecruitmentScene::onUnitIconUnHovered(UnitIcon*) {
+
+}
+
+void RecruitmentScene::onUnitIconClicked(UnitIcon* icon) {
+    setDescriptionIcon(icon->getUnit()->getUnitIcon());
+    setDescriptionText(icon->getUnit()->getUnitDescr());
+    setDescriptionTitle(icon->getUnit()->getUnitName());
+
+    for (int i = 0; i < 5; i++) {
+        if (available_units_icons_[i] != icon)
+            available_units_icons_[i]->deactivate();
+    }
+
+    for (int i = 0; i < 10; i++) {
+        chosen_units_icons_[i]->deactivate();
+    }
+
+    for (int i = 0; i < 3; i++) {
+        available_races_icons_[i]->deactivate();
+    }
+
+    ui->unit_spec_widget_->hide();
+}
+
+void RecruitmentScene::onUnitIconDoubleClicked(UnitIcon* icon) {
+    if (current_player_->getUnits().size() >= 10)
+        return;
+
+    current_player_->addUnit(current_player_->getRace()->createUnit(icon->getUnit()->getUnitId()));
+    showChosenUnits();
+}
+
+
+
+void RecruitmentScene::onChosenUnitIconHovered(UnitIcon*) {}
+
+void RecruitmentScene::onChosenUnitIconUnHovered(UnitIcon*) {}
+
+void RecruitmentScene::onChosenUnitIconClicked(UnitIcon* icon) {
+    setDescriptionIcon(icon->getUnit()->getUnitIcon());
+    setDescriptionText(icon->getUnit()->getUnitDescr());
+    setDescriptionTitle(icon->getUnit()->getUnitName());
+
+    for (int i = 0; i < 5; i++) {
+        available_units_icons_[i]->deactivate();
+    }
+
+    for (int i = 0; i < 10; i++) {
+        if (chosen_units_icons_[i] != icon)
+            chosen_units_icons_[i]->deactivate();
+    }
+
+    for (int i = 0; i < 3; i++) {
+        available_races_icons_[i]->deactivate();
+    }
+
+    updateSpecsWidget(icon->getUnit());
+    ui->unit_spec_widget_->show();
+}
+
+void RecruitmentScene::onChosenUnitIconDoubleClicked(UnitIcon* icon) {
+    current_player_->deleteUnit(icon->getUnit());
+    showChosenUnits();
+    ui->unit_spec_widget_->hide();
+}
+
+
+
+void RecruitmentScene::onRaceIconHovered(RaceIcon*) {
+
+}
+
+void RecruitmentScene::onRaceIconUnHovered(RaceIcon*) {
+
+}
+
+void RecruitmentScene::onRaceIconClicked(RaceIcon* icon) {
+    setDescriptionIcon(icon->getRace()->getRaceIcon());
+    setDescriptionText(icon->getRace()->getRaceDescr());
+    setDescriptionTitle(icon->getRace()->getRaceName());
+
+    for (int i = 0; i < 5; i++) {
+        available_units_icons_[i]->deactivate();
+    }
+
+    for (int i = 0; i < 10; i++) {
+        chosen_units_icons_[i]->deactivate();
+    }
+
+    for (int i = 0; i < 3; i++) {
+        if (available_races_icons_[i] != icon)
+            available_races_icons_[i]->deactivate();
+    }
+
+    ui->unit_spec_widget_->hide();
+}
+
+void RecruitmentScene::onRaceIconDoubleClicked(RaceIcon* icon) {
+    if (icon->getRace() != current_player_->getRace())
+        changeRace(icon->getRace());
+}
+
+
+void RecruitmentScene::onGradeUnitIconHovered(UnitIcon*) {}
+
+void RecruitmentScene::onGradeUnitIconUnHovered(UnitIcon*) {}
+
+void RecruitmentScene::onGradeUnitIconClicked(UnitIcon* icon) {
+    setDescriptionIcon(icon->getUnit()->getUnitIcon());
+    setDescriptionText(icon->getUnit()->getUnitDescr());
+    setDescriptionTitle(icon->getUnit()->getUnitName());
+
+    for (int i = 0; i < 4; i++) {
+        if (prev_grade_units_icons[i] != icon)
+            prev_grade_units_icons[i]->deactivate();
+        if (next_grade_units_icons[i] != icon)
+            next_grade_units_icons[i]->deactivate();
+    }
+}
+
+void RecruitmentScene::onGradeUnitIconDoubleClicked(UnitIcon* icon) {
+    current_player_->deleteUnit(ui->current_spec_unit_->getUnit());
+
+    auto new_unit = current_player_->getRace()->createUnit(icon->getUnit()->getUnitId());
+
+    current_player_->addUnit(new_unit);
+
+    updateSpecsWidget(new_unit);
+    showChosenUnits();
+
+    for (int i = 0; i < 10; i++) {
+        if (chosen_units_icons_[i]->getUnit() == new_unit)
+            chosen_units_icons_[i]->activate();
+    }
+    current_money_ -= 100;
+    setMoney(current_money_);
+}
+
+
+void RecruitmentScene::on_apply_clicked()
+{
+    qDebug() << "Exiting recruit army scene with player_id =" << current_player_id_;
+    if (current_player_id_ == 0) {
+        qDebug() << "Changing to 1";
+        GuiSceneManager::getInstance().changeScene("recruit_army", "1|" + QString::number(available_money_));
+    } else {
+        GuiSceneManager::getInstance().changeScene("prebattle");
+    }
+}

+ 6 - 0
source/gui/Scene.cpp

@@ -0,0 +1,6 @@
+#include "gui/Scene.h"
+
+Scene::Scene(QWidget *parent) : QWidget(parent)
+{
+
+}

+ 140 - 0
source/gui/UnitIcon.cpp

@@ -0,0 +1,140 @@
+#include <gui/UnitIcon.h>
+#include <QDebug>
+#include <QTime>
+#include <QBitmap>
+
+UnitIcon::UnitIcon(QWidget* parent, int width, int height)
+    : QLabel(parent)
+{
+    state_ = 0;
+    width_ = width;
+    height_ = height;
+    unit_ = nullptr;
+
+    setAttribute(Qt::WA_Hover, true);
+    installEventFilter(this);
+
+    default_border_.load(":/assets/common/unit_icon_default.png");
+    hover_border_.load(":/assets/common/unit_icon_hover.png");
+    active_border_.load(":/assets/common/unit_icon_active.png");
+
+    drawIcon();
+}
+
+UnitIcon::~UnitIcon()
+{
+}
+
+Unit* UnitIcon::getUnit() {
+    if (!unit_)
+        return nullptr;
+
+    return unit_;
+}
+
+void UnitIcon::setUnit(Unit* unit) {
+    unit_ = unit;
+    if (unit_ != nullptr)
+        setUnitIcon(unit_->getUnitIcon());
+    return;
+}
+
+void UnitIcon::setState(int state) {
+    state_ = state;
+}
+
+
+void UnitIcon::drawIcon() {
+    QPixmap combined(width_, height_);
+    combined.fill(QColor(253, 234, 168));
+    QPainter p(&combined);
+
+    if (state_ != 0)
+        p.drawImage(QPoint(4, 4), icon_.scaled(width_ - 8, height_ - 8, Qt::KeepAspectRatio));
+
+    if (state_ != 2 && state_ != 3)
+        p.drawImage(QPoint(0, 0), default_border_.scaled(width_, height_, Qt::KeepAspectRatio));
+
+    if (state_ == 2)
+        p.drawImage(QPoint(0, 0), hover_border_.scaled(width_, height_, Qt::KeepAspectRatio));
+
+    if (state_ == 3)
+        p.drawImage(QPoint(0, 0), active_border_.scaled(width_, height_, Qt::KeepAspectRatio));
+
+    p.end();
+
+    setPixmap(combined);
+}
+
+void UnitIcon::setUnitIcon(QString racename, QString unitname) {
+    icon_.load(":/assets/units/" + racename + "/" + unitname + "/icon.png");
+    if (state_ == 0)
+        state_ = 1;
+    drawIcon();
+}
+
+void UnitIcon::setUnitIcon(QImage icon) {
+    icon_ = icon;
+    if (state_ == 0)
+        state_ = 1;
+    drawIcon();
+}
+
+void UnitIcon::unsetUnitIcon() {
+    state_ = 0;
+    drawIcon();
+}
+
+void UnitIcon::resize(int w, int h) {
+    width_ = w;
+    height_ = h;
+    drawIcon();
+}
+
+void UnitIcon::deactivate() {
+    if (state_ > 1)
+        state_ = 1;
+    drawIcon();
+}
+
+void UnitIcon::activate() {
+    state_ = 3;
+    drawIcon();
+}
+
+void UnitIcon::mousePressEvent(QMouseEvent*)
+{
+    if (state_ == 0 || unit_ == nullptr || state_ >= 5)
+        return;
+
+    activate();
+
+    QTime current_time = QTime::currentTime();
+    if (current_time.msecsSinceStartOfDay() - previous_click_time_.msecsSinceStartOfDay() < 350) {
+        deactivate();
+        emit doubleclicked(this);
+    } else {
+        previous_click_time_ = current_time;
+        emit clicked(this);
+    }
+}
+
+void UnitIcon::enterEvent(QEvent*)
+{
+    if (state_ == 0 || state_ == 3 || unit_ == nullptr || state_ >= 5)
+        return;
+
+    state_ = 2;
+    drawIcon();
+    emit hovered(this);
+}
+
+void UnitIcon::leaveEvent(QEvent*)
+{
+    if (state_ == 0 || state_ == 3 || unit_ == nullptr || state_ >= 5)
+        return;
+
+    state_ = 1;
+    drawIcon();
+    emit unhovered(this);
+}

+ 32 - 0
source/hotseatgame/gui/HotSeatGame.cpp

@@ -0,0 +1,32 @@
+#include "hotseatgame\gui\hotseatgame.h"
+#include "ui_hotseatgame.h"
+#include "gui/guiscenemanager.h"
+
+#include <QDebug>
+
+HotSeatGame::HotSeatGame(QWidget *parent) :
+    Scene(parent),
+    ui(new Ui::HotSeatGame)
+{
+    qDebug() << "Initialising game";
+    ui->setupUi(this);
+    setWindowState(Qt::WindowFullScreen);
+}
+
+void HotSeatGame::init() {
+    GuiSceneManager::getInstance().hideMainWindow();
+}
+
+
+HotSeatGame::~HotSeatGame()
+{
+    delete ui;
+}
+
+void HotSeatGame::on_surrender_button__clicked()
+{
+    GuiSceneManager::getInstance().showMainWindow();
+    GuiSceneManager::getInstance().hideDetachedScene("hotseatgame");
+    //GuiSceneManager::getInstance().changeScene("hotseatgame_results");
+    GuiSceneManager::getInstance().changeScene("main_menu");
+}

+ 7 - 0
source/skills/MelleDamage.cpp

@@ -0,0 +1,7 @@
+//
+// Created by IgorBat on 23.04.2018.
+//
+
+void melledamage::CastSpell(Cell* from, Cell* where, Unit* who, Unit* whom){
+    effects_[0] -> OperateOnUnit(whom);
+}

+ 7 - 0
source/skills/SelfHeal.cpp

@@ -0,0 +1,7 @@
+//
+// Created by IgorBat on 23.04.2018.
+//
+
+void selfheal::CastSpell(Cell* from, Cell* where, Unit* who, Unit* whom){
+    effects_[0] -> OperateOnUnit(who);
+}

+ 75 - 0
source/skills/Spell.cpp

@@ -0,0 +1,75 @@
+//
+// Created by IgorBat on 21.04.2018.
+//
+
+#include "abstractfactory.h"
+#include "skills/spell.h"
+
+#include <iostream>
+#include <algorithm>
+#include <cassert>
+#include <string>
+
+#include <QFile>
+#include <QString>
+#include <QTextStream>
+
+Spell::Spell(QString parameters) {
+    QStringList params = parameters.split("\n");
+    assert(params.size() >= 1);
+    spell_name_ = param[0];
+    QString spell_folder = ":/assets/skills/" + spell_name_ + "/";
+
+    loadSpellDescr(spell_folder);
+    loadSpellIcon(spell_folder);
+    loadSpellTraits(spell_folder);
+}
+
+void Spell::loadSpellDescr(QString spell_folder) {
+    QFile file(spell_folder + "descr.txt");
+    file.open(QIODevice::ReadOnly);
+    QTextStream in(&file);
+    in.setCodec("UTF-8");
+    spell_descr_ = in.readAll();
+}
+
+void Spell::loadSpellIcon(QString spell_folder) {
+    spell_icon_.load(spell_folder + "icon.png");
+}
+
+void Spell::loadSpellTraits(QString spell_folder) {
+    /*
+     * you can do it by yourself, i need to sleep
+     */
+
+}
+
+QString Spell::getSpellName() const {
+    return spell_name_;
+}
+
+QString Spell::getSpellDescr() const {
+    return spell_descr_;
+}
+
+QImage Spell::getSpellIcon() const {
+    return spell_icon_;
+}
+
+int Spell::getDistance(){
+    return distance_;
+}
+void setDistance(int value){
+    distance_ = value;
+}
+
+bool getForCell(){
+    return forCell_;
+}
+void setForCell(bool value){
+    forCell_ = value;
+}
+bool Spell::canCastToCell(Cell* destination, Cell* from){
+    if(from -> lenOfActualPath(destination) == 1) return true;
+    return false;
+}

+ 7 - 0
source/units/Mage.cpp

@@ -0,0 +1,7 @@
+#include "units/Mage.h"
+#include "units/Unit.h"
+
+Mage::Mage(QString parameters) : Unit(parameters)
+{
+
+}

+ 286 - 0
source/units/Unit.cpp

@@ -0,0 +1,286 @@
+#include "AbstractFactory.h"
+#include "units/Unit.h"
+#include "Cell.h"
+
+#include <iostream>
+#include <algorithm>
+#include <cassert>
+#include <string>
+
+#include <QFile>
+#include <QString>
+#include <QTextStream>
+
+Unit::Unit(QString parameters) {
+    QStringList params = parameters.split("|");
+
+    assert(params.size() >= 2);
+
+    race_id_ = params[0];
+    unit_id_ = params[1];
+
+    QString unit_folder = ":/assets/units/" + race_id_ + "/" + unit_id_ + "/";
+
+    loadUnitName(unit_folder);
+    loadUnitDescr(unit_folder);
+    loadUnitBaseClass(unit_folder);
+    loadUnitTraits(unit_folder);
+    loadUnitIcon(unit_folder);
+    loadUnitPrevSpecs(unit_folder);
+    loadUnitUpgradeSpecs(unit_folder);
+}
+
+void Unit::loadUnitName(QString unit_folder) {
+    QFile file(unit_folder + "unitname.txt");
+    file.open(QIODevice::ReadOnly);
+    QTextStream in(&file);
+    in.setCodec("UTF-8");
+    unit_name_ = in.readLine();
+}
+
+void Unit::loadUnitDescr(QString unit_folder) {
+    QFile file(unit_folder + "descr.txt");
+    file.open(QIODevice::ReadOnly);
+    QTextStream in(&file);
+    in.setCodec("UTF-8");
+    unit_descr_ = in.readAll();
+}
+
+void Unit::loadUnitBaseClass(QString unit_folder) {
+    QFile file(unit_folder + "baseclass.txt");
+    file.open(QIODevice::ReadOnly);
+    QTextStream in(&file);
+    in.setCodec("UTF-8");
+    base_class_id_ = in.readLine();
+}
+
+void Unit::loadUnitTraits(QString unit_folder) {
+   // TO BE DONE!!!
+    health_points_ = rand();
+    activity_points_ = rand();
+    attack_cost_ = rand();
+    attack_range_ = rand();
+}
+
+void Unit::loadUnitIcon(QString unit_folder) {
+    unit_icon_.load(unit_folder + "icon.png");
+}
+
+void Unit::loadUnitPrevSpecs(QString unit_folder) {
+    QFile file(unit_folder + "prevgrades.txt");
+    file.open(QIODevice::ReadOnly);
+    QTextStream in(&file);
+    in.setCodec("UTF-8");
+    QString line = in.readLine();
+    while (!in.atEnd()) {
+        parent_specs_.push_back(line);
+        line = in.readLine();
+    }
+    parent_specs_.push_back(line);
+    line = in.readLine();
+
+}
+
+void Unit::loadUnitUpgradeSpecs(QString unit_folder) {
+    QFile file(unit_folder + "nextgrades.txt");
+    file.open(QIODevice::ReadOnly);
+    QTextStream in(&file);
+    in.setCodec("UTF-8");
+    QString line = in.readLine();
+    while (!in.atEnd()) {
+        upgrade_specs_.push_back(line);
+        line = in.readLine();
+    }
+    upgrade_specs_.push_back(line);
+    line = in.readLine();
+}
+
+int Unit::getCost(){
+	return cost_;
+}
+
+std::vector<QString> Unit::getParentSpecs(){
+    return parent_specs_;
+}
+
+std::vector<QString> Unit::getUpgradeSpecs(){
+	return upgrade_specs_;
+}
+
+double Unit::getExperience() {
+	return experience_;
+}
+
+int Unit::getLevel() {
+	return level_;
+}
+
+int Unit::getHealthPoints() {
+	return health_points_;
+}
+
+int Unit::getAttackRange() {
+	return attack_range_;
+}
+
+int Unit::getActivityPoints(){
+	return activity_points_;
+}
+
+int Unit::getStartingActivityPoints() {
+	return starting_activity_points_;
+}
+
+Cell* Unit::getLocation() {
+	return location_;
+}
+
+void Unit::setLocation(Cell* to) {
+	location_ = to;
+}
+
+int Unit::getMovementSpeed() {
+	return movement_speed_;
+}
+
+int Unit::getAttackCost(){
+	return attack_cost_;
+}
+
+int Unit::getInitiative() {
+	return initiative_;
+}
+
+int Unit::getIntelligence() {
+	return intelligence_;
+}
+
+int Unit::getStrength() {
+	return strength_;
+}
+
+int Unit::getAgility() {
+	return agility_;
+}
+
+int Unit::getAttackPoints(){
+	return attack_cost_;
+}
+
+int Unit::getMagicDefence() {
+	return magic_defence_;
+}
+
+int Unit::getPhysicDefence() {
+	return physic_defence_;
+}
+
+double Unit::getRealX() {
+	return real_x_;
+}
+
+void Unit::setRealX(double x) {
+	real_x_ = x;
+}
+
+double Unit::getRealY() {
+	return real_y_;
+}
+
+void Unit::setRealY(double y) {
+	real_y_ = y;
+}
+
+bool Unit::isCharacter(){
+    return true;
+}
+
+int Unit::theSameNear(){
+    short near_qnt = 0;
+    if (this->location_->getleftUp()->getCharacter()->base_class_id_ == this->base_class_id_){
+        near_qnt++;
+    }
+    if (this->location_->getleft()->getCharacter()->base_class_id_ == this->base_class_id_){
+        near_qnt++;
+    }
+    if (this->location_->getleftDown()->getCharacter()->base_class_id_ == this->base_class_id_){
+        near_qnt++;
+    }
+    if (this->location_->getrightUp()->getCharacter()->base_class_id_ == this->base_class_id_){
+        near_qnt++;
+    }
+    if (this->location_->getright()->getCharacter()->base_class_id_ == this->base_class_id_){
+        near_qnt++;
+    }
+    if (this->location_->getrightDown()->getCharacter()->base_class_id_ == this->base_class_id_){
+        near_qnt++;
+    }
+
+    return near_qnt;
+}
+
+int Unit::reduceIncomingDamage(std::string damageType, int damage) { //returns damage after reducing by defence
+	assert("Incorrect damage type in call reduceIncomingDamage(), expected" &&
+        (damageType[0] == 'p' || damageType[0] == 'P' || damageType[0] == 'm' || damageType[0] == 'M'));
+	assert("Magic defence of unit is incorrectly high (>40), but must be" && magic_defence_ <= 40);
+	assert("Physic defence of unit is incorrectly high (>40), but must be" && physic_defence_ <= 40);
+	if (damageType[0] == 'p' || damageType[0] == 'P') {
+        return (damage - 2.5 * double(damage) * double(physic_defence_) / 100.0);
+	}
+	else if (damageType[0] == 'm' || damageType[0] == 'M') {
+        return (damage - 2.5 * double(damage) * double(magic_defence_) / 100.0);
+	}
+    return damage;
+}
+
+int Unit::lenOfActualPath(Cell* destination) {
+    return getLocation()->actualPath(destination).size() - 1;
+}
+
+bool Unit::canMoveForDistance(int distance) {
+	return (activity_points_ * movement_speed_ >= distance);
+}
+
+bool Unit::canMoveToCell(Cell* destination) {
+	return (destination->isEmpty() && lenOfActualPath(destination) > 0 && canMoveForDistance(lenOfActualPath(destination)));
+}	
+
+void Unit::moveToCell(Cell* destination) {
+	if (!canMoveToCell(destination))
+		return;	//here could be a gui-message about failed move (x-mark, for example)
+	else {
+        activity_points_ -= lenOfActualPath(destination)/movement_speed_;
+        if (lenOfActualPath(destination) % movement_speed_)
+            activity_points_ -= 1;
+		setLocation(destination);
+	}
+}
+
+QString Unit::getUnitId() const {
+    return unit_id_;
+}
+
+QString Unit::getUnitName() const {
+    return unit_name_;
+}
+
+QString Unit::getUnitDescr() const {
+    return unit_descr_;
+}
+
+QString Unit::getUnitBaseClassId() const {
+    return base_class_id_;
+}
+
+std::vector<QString> Unit::getUnitTraits() const {
+    return {
+            QString::number(health_points_),
+            QString::number(attack_range_),
+            QString::number(activity_points_),
+            QString::number(initiative_)
+    };
+}
+
+QImage Unit::getUnitIcon() const {
+    return unit_icon_;
+}

+ 49 - 0
source/units/Warrior.cpp

@@ -0,0 +1,49 @@
+#include "units/Warrior.h"
+#include "units/Unit.h"
+#include <cassert>
+
+Warrior::Warrior(QString parameters) : Unit(parameters)
+{
+
+}
+
+int Warrior::reduceIncomingDamage(std::string damageType, int damage) { //returns damage after reducing by defence
+    assert("Incorrect damage type in call reduceIncomingDamage(), expected" &&
+        (damageType[0] == 'p' || damageType[0] == 'P' || damageType[0] == 'm' || damageType[0] == 'M'));
+    assert("Magic defence of unit is incorrectly high (>40), but must be" && magic_defence_ <= 40);
+    assert("Physic defence of unit is incorrectly high (>40), but must be" && physic_defence_ <= 40);
+    int near_same = this->theSameNear();
+
+
+    int active_defence;
+    if (damageType[0] == 'p' || damageType[0] == 'P') {
+        active_defence = physic_defence_;
+    }
+    else if (damageType[0] == 'm' || damageType[0] == 'M') {
+        active_defence = magic_defence_;
+    } else {
+        // THIS PART SHOULD BE UNREACHABLE
+        active_defence = physic_defence_;
+    }
+
+    //return (damage - 2.5 * damage * active_defence / 100);
+    int reduced_damage;
+    switch (near_same) {
+    case 0:
+        reduced_damage = damage - 2.5 * double(damage) * double(active_defence) / 100.0;
+        break;
+    case 1:
+        reduced_damage = damage - 2.9 * double(damage) * double(active_defence) / 100.0;
+        break;
+    case 2:
+        reduced_damage = damage - 3.3 * double(damage) * double(active_defence) / 100.0;
+        break;
+    case 3:
+        reduced_damage = damage - 3.7 * double(damage) * double(active_defence) / 100.0;
+        break;
+    default:
+        reduced_damage = damage - 4.1 * double(damage) * double(active_defence) / 100.0;
+        break;
+    }
+    return reduced_damage;
+}