|
|
@@ -15,17 +15,34 @@
|
|
|
#include "../GameEngine.h"
|
|
|
#include "../GameInstance.h"
|
|
|
|
|
|
+#include "../render/IRenderHandler.h"
|
|
|
+#include "../render/CAnimation.h"
|
|
|
+#include "../render/Canvas.h"
|
|
|
+#include "../render/CanvasImage.h"
|
|
|
#include "../gui/Shortcut.h"
|
|
|
#include "../gui/WindowHandler.h"
|
|
|
#include "../widgets/Buttons.h"
|
|
|
+#include "../widgets/GraphicalPrimitiveCanvas.h"
|
|
|
+#include "../widgets/TextControls.h"
|
|
|
+#include "../widgets/CTextInput.h"
|
|
|
#include "../widgets/Images.h"
|
|
|
+#include "../windows/GUIClasses.h"
|
|
|
+#include "../windows/CHeroOverview.h"
|
|
|
+#include "../windows/CCreatureWindow.h"
|
|
|
|
|
|
+#include "../../lib/GameLibrary.h"
|
|
|
#include "../../lib/gameState/CGameState.h"
|
|
|
#include "../../lib/StartInfo.h"
|
|
|
#include "../../lib/VCMIDirs.h"
|
|
|
#include "../../lib/CRandomGenerator.h"
|
|
|
#include "../../lib/callback/EditorCallback.h"
|
|
|
+#include "../../lib/entities/hero/CHero.h"
|
|
|
+#include "../../lib/entities/hero/CHeroClass.h"
|
|
|
+#include "../../lib/entities/hero/CHeroHandler.h"
|
|
|
+#include "../../lib/entities/faction/CTown.h"
|
|
|
+#include "../../lib/entities/faction/CTownHandler.h"
|
|
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
|
|
+#include "../../lib/mapObjects/CGTownInstance.h"
|
|
|
#include "../../lib/mapObjectConstructors/AObjectTypeHandler.h"
|
|
|
#include "../../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
|
|
#include "../../lib/mapping/CMap.h"
|
|
|
@@ -33,6 +50,8 @@
|
|
|
#include "../../lib/mapping/CMapEditManager.h"
|
|
|
#include "../../lib/mapping/CMapService.h"
|
|
|
#include "../../lib/mapping/MapFormat.h"
|
|
|
+#include "../../lib/texts/CGeneralTextHandler.h"
|
|
|
+#include "../../lib/texts/TextOperations.h"
|
|
|
#include "../../lib/filesystem/Filesystem.h"
|
|
|
|
|
|
void BattleOnlyMode::openBattleWindow()
|
|
|
@@ -42,69 +61,361 @@ void BattleOnlyMode::openBattleWindow()
|
|
|
|
|
|
BattleOnlyModeWindow::BattleOnlyModeWindow()
|
|
|
: CWindowObject(BORDERED)
|
|
|
+ , selectedTerrain(TerrainId::DIRT)
|
|
|
+ , selectedTown(FactionID::NONE)
|
|
|
{
|
|
|
OBJECT_CONSTRUCTION;
|
|
|
|
|
|
- pos.w = 640;
|
|
|
- pos.h = 480;
|
|
|
+ pos.w = 700;
|
|
|
+ pos.h = 330;
|
|
|
|
|
|
updateShadow();
|
|
|
center();
|
|
|
|
|
|
+ init();
|
|
|
+
|
|
|
backgroundTexture = std::make_shared<FilledTexturePlayerColored>(Rect(0, 0, pos.w, pos.h));
|
|
|
backgroundTexture->setPlayerColor(PlayerColor(1));
|
|
|
- buttonOk = std::make_shared<CButton>(Point(183, 388), AnimationPath::builtin("MuBchck"), CButton::tooltip(), [this](){ startBattle(); }, EShortcut::GLOBAL_ACCEPT);
|
|
|
- buttonAbort = std::make_shared<CButton>(Point(250, 388), AnimationPath::builtin("MuBcanc"), CButton::tooltip(), [this](){ close(); }, EShortcut::GLOBAL_CANCEL);
|
|
|
+ buttonOk = std::make_shared<CButton>(Point(281, 288), AnimationPath::builtin("MuBchck"), CButton::tooltip(), [this](){ startBattle(); }, EShortcut::GLOBAL_ACCEPT);
|
|
|
+ buttonAbort = std::make_shared<CButton>(Point(355, 288), AnimationPath::builtin("MuBcanc"), CButton::tooltip(), [this](){ close(); }, EShortcut::GLOBAL_CANCEL);
|
|
|
+ title = std::make_shared<CLabel>(350, 20, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyMode"));
|
|
|
+
|
|
|
+ battlegroundSelector = std::make_shared<CButton>(Point(10, 294), AnimationPath::builtin("GSPButtonClear"), CButton::tooltip(), [this](){
|
|
|
+ std::vector<std::string> texts;
|
|
|
+ std::vector<std::shared_ptr<IImage>> images;
|
|
|
+
|
|
|
+ auto terrains = LIBRARY->terrainTypeHandler->objects;
|
|
|
+ for (const auto & terrain : terrains)
|
|
|
+ {
|
|
|
+ texts.push_back(terrain->getNameTranslated());
|
|
|
+
|
|
|
+ const auto & patterns = LIBRARY->terviewh->getTerrainViewPatterns(terrain->getId());
|
|
|
+ TerrainViewPattern pattern;
|
|
|
+ for(auto & p : patterns)
|
|
|
+ if(p[0].id == "n1")
|
|
|
+ pattern = p[0];
|
|
|
+ auto image = ENGINE->renderHandler().loadImage(terrain->tilesFilename, pattern.mapping[0].first, 0, EImageBlitMode::OPAQUE);
|
|
|
+ image->scaleTo(Point(23, 23), EScalingAlgorithm::NEAREST);
|
|
|
+ images.push_back(image);
|
|
|
+ }
|
|
|
+
|
|
|
+ auto factions = LIBRARY->townh->objects;
|
|
|
+ factions.erase(std::remove_if(factions.begin(), factions.end(), [](const std::shared_ptr<CFaction>& n) {
|
|
|
+ return !n->town;
|
|
|
+ }), factions.end());
|
|
|
+ for (const auto & faction : factions)
|
|
|
+ {
|
|
|
+ texts.push_back(faction->getNameTranslated());
|
|
|
+
|
|
|
+ auto image = ENGINE->renderHandler().loadImage(AnimationPath::builtin("ITPA"), faction->town->clientInfo.icons[true][false] + 2, 0, EImageBlitMode::OPAQUE);
|
|
|
+ image->scaleTo(Point(35, 23), EScalingAlgorithm::NEAREST);
|
|
|
+ images.push_back(image);
|
|
|
+ }
|
|
|
+
|
|
|
+ ENGINE->windows().createAndPushWindow<CObjectListWindow>(texts, nullptr, LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeBattleground"), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeBattlegroundSelect"), [this, terrains, factions](int index){
|
|
|
+ if(terrains.size() > index)
|
|
|
+ {
|
|
|
+ selectedTerrain = terrains[index]->getId();
|
|
|
+ selectedTown = FactionID::NONE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ selectedTerrain = TerrainId::NONE;
|
|
|
+ selectedTown = factions[index - terrains.size()]->getId();
|
|
|
+ }
|
|
|
+ setTerrainButtonText();
|
|
|
+ setOkButtonEnabled();
|
|
|
+ }, (selectedTerrain != TerrainId::NONE ? static_cast<int>(selectedTerrain) : static_cast<int>(selectedTown + terrains.size())), images, true, true);
|
|
|
+ });
|
|
|
+
|
|
|
+ setTerrainButtonText();
|
|
|
+ setOkButtonEnabled();
|
|
|
+
|
|
|
+ heroSelector1 = std::make_shared<BattleOnlyModeHeroSelector>(*this, Point(0, 40));
|
|
|
+ heroSelector2 = std::make_shared<BattleOnlyModeHeroSelector>(*this, Point(0, 160));
|
|
|
}
|
|
|
|
|
|
-void BattleOnlyModeWindow::startBattle()
|
|
|
+void BattleOnlyModeWindow::init()
|
|
|
{
|
|
|
- auto map = std::make_unique<CMap>(nullptr);
|
|
|
+ map = std::make_unique<CMap>(nullptr);
|
|
|
map->version = EMapFormat::VCMI;
|
|
|
map->creationDateTime = std::time(nullptr);
|
|
|
- map->width = 4;
|
|
|
- map->height = 3;
|
|
|
+ map->width = 10;
|
|
|
+ map->height = 10;
|
|
|
map->mapLevels = 1;
|
|
|
map->battleOnly = true;
|
|
|
+
|
|
|
+ cb = std::make_unique<EditorCallback>(map.get());
|
|
|
+}
|
|
|
+
|
|
|
+void BattleOnlyModeWindow::setTerrainButtonText()
|
|
|
+{
|
|
|
+ battlegroundSelector->setTextOverlay(LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeBattleground") + ": " + (selectedTerrain != TerrainId::NONE ? selectedTerrain.toEntity(LIBRARY)->getNameTranslated() : selectedTown.toEntity(LIBRARY)->getNameTranslated()), EFonts::FONT_SMALL, Colors::WHITE);
|
|
|
+}
|
|
|
+
|
|
|
+void BattleOnlyModeWindow::setOkButtonEnabled()
|
|
|
+{
|
|
|
+ bool canStart = (selectedTerrain != TerrainId::NONE || selectedTown != FactionID::NONE);
|
|
|
+ canStart &= (heroSelector1 && heroSelector1->selectedHero && ((heroSelector2 && heroSelector2->selectedHero) || (selectedTown != FactionID::NONE && heroSelector2->selectedArmy->stacksCount())));
|
|
|
+ buttonOk->block(!canStart);
|
|
|
+}
|
|
|
+
|
|
|
+std::shared_ptr<IImage> drawBlackBox(Point size, std::string text)
|
|
|
+{
|
|
|
+ auto image = ENGINE->renderHandler().createImage(size, CanvasScalingPolicy::AUTO);
|
|
|
+ Canvas canvas = image->getCanvas();
|
|
|
+ canvas.drawColor(Rect(0, 0, size.x, size.y), Colors::BLACK);
|
|
|
+ canvas.drawText(Point(size.x / 2, size.y / 2), FONT_TINY, Colors::WHITE, ETextAlignment::CENTER, text);
|
|
|
+ return image;
|
|
|
+}
|
|
|
+
|
|
|
+BattleOnlyModeHeroSelector::BattleOnlyModeHeroSelector(BattleOnlyModeWindow& parent, Point position)
|
|
|
+: parent(parent)
|
|
|
+, selectedArmy(std::make_shared<CCreatureSet>())
|
|
|
+{
|
|
|
+ OBJECT_CONSTRUCTION;
|
|
|
+
|
|
|
+ pos.x += position.x;
|
|
|
+ pos.y += position.y;
|
|
|
+
|
|
|
+ backgroundImage = std::make_shared<CPicture>(ImagePath::builtin("heroSlotsBlue"), Point(0, 0));
|
|
|
+
|
|
|
+ for(size_t i=0; i<GameConstants::PRIMARY_SKILLS; i++)
|
|
|
+ {
|
|
|
+ auto image = std::make_shared<CAnimImage>(AnimationPath::builtin("PSKIL32"), i, 0, 78 + i * 36, 26);
|
|
|
+ primSkills.push_back(image);
|
|
|
+ primSkillsBorder.push_back(std::make_shared<GraphicalPrimitiveCanvas>(Rect(78 + i * 36, 26, 32, 32)));
|
|
|
+ primSkillsBorder.back()->addRectangle(Point(0, 0), Point(32, 32), ColorRGBA(44, 108, 255));
|
|
|
+ primSkillsInput.push_back(std::make_shared<CTextInput>(Rect(78 + i * 36, 58, 32, 16), EFonts::FONT_SMALL, ETextAlignment::CENTER, false));
|
|
|
+ primSkillsInput.back()->setFilterNumber(0, 100);
|
|
|
+ primSkillsInput.back()->setText("0");
|
|
|
+ }
|
|
|
+
|
|
|
+ creatureImage.resize(GameConstants::ARMY_SIZE);
|
|
|
+ creatureImageLabel.resize(GameConstants::ARMY_SIZE);
|
|
|
+
|
|
|
+ setHeroIcon();
|
|
|
+ setCreatureIcons();
|
|
|
+}
|
|
|
+
|
|
|
+void BattleOnlyModeHeroSelector::setHeroIcon()
|
|
|
+{
|
|
|
+ OBJECT_CONSTRUCTION;
|
|
|
+
|
|
|
+ if(!selectedHero)
|
|
|
+ {
|
|
|
+ heroImage = std::make_shared<CPicture>(drawBlackBox(Point(58, 64), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeSelect")), Point(6, 7));
|
|
|
+ heroLabel = std::make_shared<CLabel>(160, 16, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, LIBRARY->generaltexth->translate("core.genrltxt.507"));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ heroImage = std::make_shared<CPicture>(ENGINE->renderHandler().loadAnimation(AnimationPath::builtin("PortraitsLarge"), EImageBlitMode::COLORKEY)->getImage(selectedHero->getHeroType()->imageIndex), Point(6, 7));
|
|
|
+ heroLabel = std::make_shared<CLabel>(160, 16, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, selectedHero->getNameTranslated());
|
|
|
+ }
|
|
|
+
|
|
|
+ heroImage->addLClickCallback([this](){
|
|
|
+ auto heroes = LIBRARY->heroh->objects;
|
|
|
+ std::sort(heroes.begin(), heroes.end(), [](const std::shared_ptr<CHero>& a, const std::shared_ptr<CHero>& b) {
|
|
|
+ if (a->heroClass->getId() == b->heroClass->getId())
|
|
|
+ return a->getNameTranslated() < b->getNameTranslated();
|
|
|
+ if (a->heroClass->faction == b->heroClass->faction)
|
|
|
+ return a->heroClass->getId() < b->heroClass->getId();
|
|
|
+ return a->heroClass->faction < b->heroClass->faction;
|
|
|
+ });
|
|
|
+ heroes.erase(std::remove_if(heroes.begin(), heroes.end(), [](const std::shared_ptr<CHero>& n) {
|
|
|
+ return n->special;
|
|
|
+ }), heroes.end());
|
|
|
+
|
|
|
+ int selectedIndex = !selectedHero ? 0 : (1 + std::distance(heroes.begin(), std::find_if(heroes.begin(), heroes.end(), [this](const std::shared_ptr<CHero>& heroPtr) {
|
|
|
+ return heroPtr.get() == selectedHero->getHeroType();
|
|
|
+ })));
|
|
|
+
|
|
|
+ std::vector<std::string> texts;
|
|
|
+ std::vector<std::shared_ptr<IImage>> images;
|
|
|
+ // Add "no hero" option
|
|
|
+ texts.push_back(LIBRARY->generaltexth->translate("core.genrltxt.507"));
|
|
|
+ images.push_back(nullptr);
|
|
|
+ for (const auto & h : heroes)
|
|
|
+ {
|
|
|
+ texts.push_back(h->getNameTranslated());
|
|
|
+
|
|
|
+ auto image = ENGINE->renderHandler().loadImage(AnimationPath::builtin("PortraitsSmall"), h->imageIndex, 0, EImageBlitMode::OPAQUE);
|
|
|
+ image->scaleTo(Point(35, 23), EScalingAlgorithm::NEAREST);
|
|
|
+ images.push_back(image);
|
|
|
+ }
|
|
|
+ auto window = std::make_shared<CObjectListWindow>(texts, nullptr, LIBRARY->generaltexth->translate("object.core.hero.name"), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeHeroSelect"), [this, heroes](int index){
|
|
|
+ if(index == 0)
|
|
|
+ {
|
|
|
+ selectedHero.reset();
|
|
|
+ setHeroIcon();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ index--;
|
|
|
+ auto hero = heroes[index];
|
|
|
+
|
|
|
+ auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::HERO, hero->heroClass->getId());
|
|
|
+ auto templates = factory->getTemplates();
|
|
|
+ auto obj = std::dynamic_pointer_cast<CGHeroInstance>(factory->create(parent.cb.get(), templates.front()));
|
|
|
+ obj->setHeroType(hero->getId());
|
|
|
+
|
|
|
+ selectedHero = obj;
|
|
|
+ setHeroIcon();
|
|
|
+ parent.setOkButtonEnabled();
|
|
|
+ }, selectedIndex, images, true, true);
|
|
|
+ window->onPopup = [this, heroes](int index) {
|
|
|
+ if(index == 0)
|
|
|
+ return;
|
|
|
+ index--;
|
|
|
+
|
|
|
+ ENGINE->windows().createAndPushWindow<CHeroOverview>(heroes[index]->getId());
|
|
|
+ };
|
|
|
+ ENGINE->windows().pushWindow(window);
|
|
|
+ });
|
|
|
+
|
|
|
+ heroImage->addRClickCallback([this](){
|
|
|
+ if(!selectedHero)
|
|
|
+ return;
|
|
|
+
|
|
|
+ ENGINE->windows().createAndPushWindow<CHeroOverview>(selectedHero->getHeroType()->getId());
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+void BattleOnlyModeHeroSelector::setCreatureIcons()
|
|
|
+{
|
|
|
+ OBJECT_CONSTRUCTION;
|
|
|
+
|
|
|
+ for(int i = 0; i < creatureImage.size(); i++)
|
|
|
+ {
|
|
|
+ if(selectedArmy->slotEmpty(SlotID(i)))
|
|
|
+ {
|
|
|
+ creatureImage[i] = std::make_shared<CPicture>(drawBlackBox(Point(32, 32), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeSelect")), Point(6 + i * 36, 78));
|
|
|
+ creatureImageLabel[i].reset();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ auto creatureID = selectedArmy->Slots().at(SlotID(i))->getCreatureID();
|
|
|
+ creatureImage[i] = std::make_shared<CPicture>(ENGINE->renderHandler().loadAnimation(AnimationPath::builtin("CPRSMALL"), EImageBlitMode::COLORKEY)->getImage(LIBRARY->creh->objects.at(creatureID)->getIconIndex()), Point(6 + i * 36, 78));
|
|
|
+ creatureImageLabel[i] = std::make_shared<CLabel>(36 + i * 36, 112, FONT_SMALL, ETextAlignment::BOTTOMRIGHT, Colors::WHITE, TextOperations::formatMetric(selectedArmy->Slots().at(SlotID(i))->getCount(), 4));
|
|
|
+ }
|
|
|
+
|
|
|
+ creatureImage[i]->addLClickCallback([this, i](){
|
|
|
+ auto creatures = LIBRARY->creh->objects;
|
|
|
+ std::sort(creatures.begin(), creatures.end(), [](const std::shared_ptr<CCreature>& a, const std::shared_ptr<CCreature>& b) {
|
|
|
+ if (a->getLevel() == b->getLevel())
|
|
|
+ return a->getNameSingularTranslated() < b->getNameSingularTranslated();
|
|
|
+ if (a->getFactionID() == b->getFactionID())
|
|
|
+ return a->getLevel() < b->getLevel();
|
|
|
+ return a->getFactionID() < b->getFactionID();
|
|
|
+ });
|
|
|
+ creatures.erase(std::remove_if(creatures.begin(), creatures.end(), [](const std::shared_ptr<CCreature>& n) {
|
|
|
+ return n->special;
|
|
|
+ }), creatures.end());
|
|
|
+
|
|
|
+ int selectedIndex = selectedArmy->slotEmpty(SlotID(i)) ? 0 : (1 + std::distance(creatures.begin(), std::find_if(creatures.begin(), creatures.end(), [this, i](const std::shared_ptr<CCreature>& creaturePtr) {
|
|
|
+ return creaturePtr->getId() == selectedArmy->Slots().at(SlotID(i))->getId();
|
|
|
+ })));
|
|
|
+
|
|
|
+ std::vector<std::string> texts;
|
|
|
+ std::vector<std::shared_ptr<IImage>> images;
|
|
|
+ // Add "no creature" option
|
|
|
+ texts.push_back(LIBRARY->generaltexth->translate("core.genrltxt.507"));
|
|
|
+ images.push_back(nullptr);
|
|
|
+ for (const auto & c : creatures)
|
|
|
+ {
|
|
|
+ texts.push_back(c->getNameSingularTranslated());
|
|
|
+
|
|
|
+ auto image = ENGINE->renderHandler().loadImage(AnimationPath::builtin("CPRSMALL"), c->getIconIndex(), 0, EImageBlitMode::OPAQUE);
|
|
|
+ image->scaleTo(Point(23, 23), EScalingAlgorithm::NEAREST);
|
|
|
+ images.push_back(image);
|
|
|
+ }
|
|
|
+ auto window = std::make_shared<CObjectListWindow>(texts, nullptr, LIBRARY->generaltexth->translate("core.genrltxt.42"), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeCreatureSelect"), [this, creatures, i](int index){
|
|
|
+ if(index == 0)
|
|
|
+ {
|
|
|
+ if(!selectedArmy->slotEmpty(SlotID(i)))
|
|
|
+ selectedArmy->eraseStack(SlotID(i));
|
|
|
+ setCreatureIcons();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ index--;
|
|
|
+ auto creature = creatures[index];
|
|
|
+ int amount = selectedArmy->slotEmpty(SlotID(i)) ? 1 : selectedArmy->Slots().at(SlotID(i))->getCount();
|
|
|
+ ENGINE->windows().createAndPushWindow<NumberInputWindow>(amount, [this, creature, i](int quantity){
|
|
|
+ selectedArmy->setCreature(SlotID(i), creature->getId(), quantity);
|
|
|
+ setCreatureIcons();
|
|
|
+ });
|
|
|
+ }, selectedIndex, images, true, true);
|
|
|
+ window->onPopup = [this, creatures](int index) {
|
|
|
+ if(index == 0)
|
|
|
+ return;
|
|
|
+ index--;
|
|
|
+
|
|
|
+ ENGINE->windows().createAndPushWindow<CStackWindow>(creatures.at(index).get(), true);
|
|
|
+ };
|
|
|
+ ENGINE->windows().pushWindow(window);
|
|
|
+ });
|
|
|
+
|
|
|
+ creatureImage[i]->addRClickCallback([this, i](){
|
|
|
+ if(selectedArmy->slotEmpty(SlotID(i)))
|
|
|
+ return;
|
|
|
+
|
|
|
+ ENGINE->windows().createAndPushWindow<CStackWindow>(LIBRARY->creh->objects.at(selectedArmy->Slots().at(SlotID(i))->getCreatureID()).get(), true);
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void BattleOnlyModeWindow::startBattle()
|
|
|
+{
|
|
|
+ auto rng = &CRandomGenerator::getDefault();
|
|
|
|
|
|
map->initTerrain();
|
|
|
- map->getEditManager()->clearTerrain(&CRandomGenerator::getDefault());
|
|
|
+ map->getEditManager()->clearTerrain(rng);
|
|
|
|
|
|
- //auto terrain = LIBRARY->terrainTypeHandler->objects;
|
|
|
map->getEditManager()->getTerrainSelection().selectAll();
|
|
|
- map->getEditManager()->drawTerrain(TerrainId::GRASS, 0, &CRandomGenerator::getDefault());
|
|
|
+ map->getEditManager()->drawTerrain(selectedTerrain == TerrainId::NONE ? TerrainId::DIRT : selectedTerrain, 0, rng);
|
|
|
|
|
|
map->players[0].canComputerPlay = true;
|
|
|
map->players[0].canHumanPlay = true;
|
|
|
map->players[1] = map->players[0];
|
|
|
|
|
|
- auto cb = std::make_unique<EditorCallback>(map.get());
|
|
|
-
|
|
|
auto knownHeroes = LIBRARY->objtypeh->knownSubObjects(Obj::HERO);
|
|
|
|
|
|
- auto addHero = [&](MapObjectSubID heroType, PlayerColor color, const int3 & position)
|
|
|
+ auto addHero = [&](auto & selector, PlayerColor color, const int3 & position)
|
|
|
{
|
|
|
- auto it = knownHeroes.find(heroType);
|
|
|
- if (it == knownHeroes.end())
|
|
|
- return; // unknown hero type, nothing to add
|
|
|
+ selector->selectedHero->setOwner(color);
|
|
|
+ selector->selectedHero->pos = position;
|
|
|
+ for(size_t i=0; i<GameConstants::PRIMARY_SKILLS; i++)
|
|
|
+ selector->selectedHero->pushPrimSkill(PrimarySkill(i), std::stoi(selector->primSkillsInput[i]->getText()));
|
|
|
+ selector->selectedHero->clearSlots();
|
|
|
+ for(int slot = 0; slot < GameConstants::ARMY_SIZE; slot++)
|
|
|
+ if(!selector->selectedArmy->slotEmpty(SlotID(slot)))
|
|
|
+ selector->selectedHero->putStack(SlotID(slot), selector->selectedArmy->detachStack(SlotID(slot)));
|
|
|
+ map->getEditManager()->insertObject(selector->selectedHero);
|
|
|
+ };
|
|
|
|
|
|
- auto firstHeroType = *it;
|
|
|
- auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::HERO, firstHeroType);
|
|
|
+ addHero(heroSelector1, PlayerColor(0), int3(5, 6, 0));
|
|
|
+ if(selectedTown == FactionID::NONE)
|
|
|
+ addHero(heroSelector2, PlayerColor(1), int3(5, 5, 0));
|
|
|
+ else
|
|
|
+ {
|
|
|
+ auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::TOWN, selectedTown);
|
|
|
auto templates = factory->getTemplates();
|
|
|
+ auto obj = factory->create(cb.get(), templates.front());
|
|
|
+ auto townObj = std::dynamic_pointer_cast<CGTownInstance>(obj);
|
|
|
+ obj->setOwner(PlayerColor(1));
|
|
|
+ obj->pos = int3(5, 5, 0);
|
|
|
+ for (const auto & building : townObj->getTown()->getAllBuildings())
|
|
|
+ townObj->addBuilding(building);
|
|
|
+ if(!heroSelector2->selectedHero)
|
|
|
+ {
|
|
|
+ for(int slot = 0; slot < GameConstants::ARMY_SIZE; slot++)
|
|
|
+ if(!heroSelector2->selectedArmy->slotEmpty(SlotID(slot)))
|
|
|
+ townObj->getArmy()->putStack(SlotID(slot), heroSelector2->selectedArmy->detachStack(SlotID(slot)));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ addHero(heroSelector2, PlayerColor(1), int3(5, 5, 0));
|
|
|
|
|
|
- auto obj = std::dynamic_pointer_cast<CGHeroInstance>(factory->create(cb.get(), templates.front()));
|
|
|
- obj->setOwner(color);
|
|
|
- obj->pos = position;
|
|
|
- /*if(heroType == MapObjectSubID(1))
|
|
|
- {*/
|
|
|
- obj->pushPrimSkill(PrimarySkill::ATTACK, 100);
|
|
|
- obj->getArmy()->setCreature(SlotID(0), CreatureID(1), 10000);
|
|
|
- //}
|
|
|
- map->getEditManager()->insertObject(obj);
|
|
|
- };
|
|
|
-
|
|
|
- addHero(MapObjectSubID(1), PlayerColor(0), int3(2, 1, 0));
|
|
|
- addHero(MapObjectSubID(2), PlayerColor(1), int3(3, 1, 0));
|
|
|
+ map->getEditManager()->insertObject(townObj);
|
|
|
+ }
|
|
|
|
|
|
auto path = VCMIDirs::get().userDataPath() / "Maps";
|
|
|
boost::filesystem::create_directories(path);
|
|
|
@@ -122,3 +433,29 @@ void BattleOnlyModeWindow::startBattle()
|
|
|
GAME->server().setExtraOptionsInfo(extraOptions);
|
|
|
GAME->server().sendStartGame();
|
|
|
}
|
|
|
+
|
|
|
+NumberInputWindow::NumberInputWindow(int initialValue, std::function<void(int)> onValueSelected)
|
|
|
+ : CWindowObject(BORDERED)
|
|
|
+{
|
|
|
+ OBJECT_CONSTRUCTION;
|
|
|
+
|
|
|
+ pos.w = 200;
|
|
|
+ pos.h = 100;
|
|
|
+ center();
|
|
|
+
|
|
|
+ backgroundTexture = std::make_shared<FilledTexturePlayerColored>(Rect(0, 0, pos.w, pos.h));
|
|
|
+ backgroundTexture->setPlayerColor(PlayerColor(1));
|
|
|
+
|
|
|
+ buttonOk = std::make_shared<CButton>(Point(68, 60), AnimationPath::builtin("MuBchck"), CButton::tooltip(), [this, onValueSelected](){
|
|
|
+ int value = std::stoi(input->getText());
|
|
|
+ if(onValueSelected)
|
|
|
+ onValueSelected(value);
|
|
|
+ close();
|
|
|
+ }, EShortcut::GLOBAL_ACCEPT);
|
|
|
+
|
|
|
+ backgroundOverlay = std::make_shared<TransparentFilledRectangle>(Rect(50, 20, 100, 20), ColorRGBA(0, 0, 0, 128), ColorRGBA(64, 64, 64, 64), 1);
|
|
|
+ input = std::make_shared<CTextInput>(Rect(50, 20, 100, 20), EFonts::FONT_MEDIUM, ETextAlignment::CENTER, false);
|
|
|
+ input->setFilterNumber(1, 99999999);
|
|
|
+ input->setText(std::to_string(initialValue));
|
|
|
+ input->giveFocus();
|
|
|
+}
|