1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

introduce BattleOnlyModeStartInfo for multiplayer

This commit is contained in:
Laserlicht
2025-10-25 19:06:28 +02:00
parent 134017a7cd
commit fcdc100761
4 changed files with 104 additions and 66 deletions

View File

@@ -19,6 +19,7 @@
#include "lobby/ExtraOptionsTab.h" #include "lobby/ExtraOptionsTab.h"
#include "lobby/SelectionTab.h" #include "lobby/SelectionTab.h"
#include "lobby/CBonusSelection.h" #include "lobby/CBonusSelection.h"
#include "lobby/BattleOnlyMode.h"
#include "globalLobby/GlobalLobbyWindow.h" #include "globalLobby/GlobalLobbyWindow.h"
#include "globalLobby/GlobalLobbyServerSetup.h" #include "globalLobby/GlobalLobbyServerSetup.h"
#include "globalLobby/GlobalLobbyClient.h" #include "globalLobby/GlobalLobbyClient.h"
@@ -113,6 +114,9 @@ void ApplyOnLobbyScreenNetPackVisitor::visitLobbyGuiAction(LobbyGuiAction & pack
if(!lobby || !handler.isGuest()) if(!lobby || !handler.isGuest())
return; return;
if(auto topWindow = ENGINE->windows().topWindow<BattleOnlyModeWindow>())
topWindow->close();
switch(pack.action) switch(pack.action)
{ {
case LobbyGuiAction::NO_TAB: case LobbyGuiAction::NO_TAB:
@@ -133,6 +137,9 @@ void ApplyOnLobbyScreenNetPackVisitor::visitLobbyGuiAction(LobbyGuiAction & pack
case LobbyGuiAction::OPEN_EXTRA_OPTIONS: case LobbyGuiAction::OPEN_EXTRA_OPTIONS:
lobby->toggleTab(lobby->tabExtraOptions); lobby->toggleTab(lobby->tabExtraOptions);
break; break;
case LobbyGuiAction::BATTLE_MODE:
BattleOnlyMode::openBattleWindow();
break;
} }
} }

View File

@@ -51,6 +51,7 @@
#include "../../lib/mapping/CMapService.h" #include "../../lib/mapping/CMapService.h"
#include "../../lib/mapping/MapFormat.h" #include "../../lib/mapping/MapFormat.h"
#include "../../lib/texts/CGeneralTextHandler.h" #include "../../lib/texts/CGeneralTextHandler.h"
#include "../../lib/texts/MetaString.h"
#include "../../lib/texts/TextOperations.h" #include "../../lib/texts/TextOperations.h"
#include "../../lib/filesystem/Filesystem.h" #include "../../lib/filesystem/Filesystem.h"
@@ -59,10 +60,17 @@ void BattleOnlyMode::openBattleWindow()
ENGINE->windows().createAndPushWindow<BattleOnlyModeWindow>(); ENGINE->windows().createAndPushWindow<BattleOnlyModeWindow>();
} }
BattleOnlyModeStartInfo::BattleOnlyModeStartInfo()
: selectedTerrain(TerrainId::DIRT)
, selectedTown(FactionID::NONE)
{
for(auto & element : selectedArmy)
element = std::make_shared<CCreatureSet>();
}
BattleOnlyModeWindow::BattleOnlyModeWindow() BattleOnlyModeWindow::BattleOnlyModeWindow()
: CWindowObject(BORDERED) : CWindowObject(BORDERED)
, selectedTerrain(TerrainId::DIRT) , startInfo(std::make_shared<BattleOnlyModeStartInfo>())
, selectedTown(FactionID::NONE)
{ {
OBJECT_CONSTRUCTION; OBJECT_CONSTRUCTION;
@@ -112,29 +120,29 @@ BattleOnlyModeWindow::BattleOnlyModeWindow()
ENGINE->windows().createAndPushWindow<CObjectListWindow>(texts, nullptr, LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeBattlefield"), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeBattlefieldSelect"), [this, terrains, factions](int index){ ENGINE->windows().createAndPushWindow<CObjectListWindow>(texts, nullptr, LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeBattlefield"), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeBattlefieldSelect"), [this, terrains, factions](int index){
if(terrains.size() > index) if(terrains.size() > index)
{ {
selectedTerrain = terrains[index]->getId(); startInfo->selectedTerrain = terrains[index]->getId();
selectedTown = FactionID::NONE; startInfo->selectedTown = FactionID::NONE;
} }
else else
{ {
selectedTerrain = TerrainId::NONE; startInfo->selectedTerrain = TerrainId::NONE;
auto it = std::next(factions.begin(), index - terrains.size()); auto it = std::next(factions.begin(), index - terrains.size());
if (it != factions.end()) if (it != factions.end())
selectedTown = *it; startInfo->selectedTown = *it;
} }
setTerrainButtonText(); setTerrainButtonText();
setOkButtonEnabled(); setOkButtonEnabled();
}, (selectedTerrain != TerrainId::NONE ? static_cast<int>(selectedTerrain) : static_cast<int>(selectedTown + terrains.size())), images, true, true); }, (startInfo->selectedTerrain != TerrainId::NONE ? static_cast<int>(startInfo->selectedTerrain) : static_cast<int>(startInfo->selectedTown + terrains.size())), images, true, true);
}); });
buttonReset = std::make_shared<CButton>(Point(289, 174), AnimationPath::builtin("GSPButtonClear"), CButton::tooltip(), [this](){ buttonReset = std::make_shared<CButton>(Point(289, 174), AnimationPath::builtin("GSPButtonClear"), CButton::tooltip(), [this](){
selectedTerrain = TerrainId::DIRT; startInfo->selectedTerrain = TerrainId::DIRT;
selectedTown = FactionID::NONE; startInfo->selectedTown = FactionID::NONE;
setTerrainButtonText(); setTerrainButtonText();
setOkButtonEnabled(); setOkButtonEnabled();
heroSelector1->selectedHero.reset(); startInfo->selectedHero[0].reset();
heroSelector2->selectedHero.reset(); startInfo->selectedHero[1].reset();
heroSelector1->selectedArmy->clearSlots(); startInfo->selectedArmy[0]->clearSlots();
heroSelector2->selectedArmy->clearSlots(); startInfo->selectedArmy[1]->clearSlots();
for(size_t i=0; i<GameConstants::ARMY_SIZE; i++) for(size_t i=0; i<GameConstants::ARMY_SIZE; i++)
{ {
heroSelector1->selectedArmyInput.at(i)->setText("1"); heroSelector1->selectedArmyInput.at(i)->setText("1");
@@ -151,8 +159,8 @@ BattleOnlyModeWindow::BattleOnlyModeWindow()
setTerrainButtonText(); setTerrainButtonText();
setOkButtonEnabled(); setOkButtonEnabled();
heroSelector1 = std::make_shared<BattleOnlyModeHeroSelector>(*this, Point(0, 40)); heroSelector1 = std::make_shared<BattleOnlyModeHeroSelector>(0, *this, Point(0, 40));
heroSelector2 = std::make_shared<BattleOnlyModeHeroSelector>(*this, Point(260, 40)); heroSelector2 = std::make_shared<BattleOnlyModeHeroSelector>(1, *this, Point(260, 40));
} }
void BattleOnlyModeWindow::init() void BattleOnlyModeWindow::init()
@@ -164,19 +172,20 @@ void BattleOnlyModeWindow::init()
map->height = 10; map->height = 10;
map->mapLevels = 1; map->mapLevels = 1;
map->battleOnly = true; map->battleOnly = true;
map->name = MetaString::createFromTextID("vcmi.lobby.battleOnlyMode");
cb = std::make_unique<EditorCallback>(map.get()); cb = std::make_unique<EditorCallback>(map.get());
} }
void BattleOnlyModeWindow::setTerrainButtonText() void BattleOnlyModeWindow::setTerrainButtonText()
{ {
battlefieldSelector->setTextOverlay(LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeBattlefield") + ": " + (selectedTerrain != TerrainId::NONE ? selectedTerrain.toEntity(LIBRARY)->getNameTranslated() : selectedTown.toEntity(LIBRARY)->getNameTranslated()), EFonts::FONT_SMALL, Colors::WHITE); battlefieldSelector->setTextOverlay(LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeBattlefield") + ": " + (startInfo->selectedTerrain != TerrainId::NONE ? startInfo->selectedTerrain.toEntity(LIBRARY)->getNameTranslated() : startInfo->selectedTown.toEntity(LIBRARY)->getNameTranslated()), EFonts::FONT_SMALL, Colors::WHITE);
} }
void BattleOnlyModeWindow::setOkButtonEnabled() void BattleOnlyModeWindow::setOkButtonEnabled()
{ {
bool canStart = (selectedTerrain != TerrainId::NONE || selectedTown != FactionID::NONE); bool canStart = (startInfo->selectedTerrain != TerrainId::NONE || startInfo->selectedTown != FactionID::NONE);
canStart &= (heroSelector1 && heroSelector1->selectedHero && ((heroSelector2 && heroSelector2->selectedHero) || (selectedTown != FactionID::NONE && heroSelector2->selectedArmy->stacksCount()))); canStart &= (startInfo->selectedHero[0] && ((startInfo->selectedHero[1]) || (startInfo->selectedTown != FactionID::NONE && startInfo->selectedArmy[1]->stacksCount())));
buttonOk->block(!canStart); buttonOk->block(!canStart);
} }
@@ -189,9 +198,9 @@ std::shared_ptr<IImage> drawBlackBox(Point size, std::string text)
return image; return image;
} }
BattleOnlyModeHeroSelector::BattleOnlyModeHeroSelector(BattleOnlyModeWindow& parent, Point position) BattleOnlyModeHeroSelector::BattleOnlyModeHeroSelector(int id, BattleOnlyModeWindow& p, Point position)
: parent(parent) : parent(p)
, selectedArmy(std::make_shared<CCreatureSet>()) , id(id)
{ {
OBJECT_CONSTRUCTION; OBJECT_CONSTRUCTION;
@@ -209,6 +218,9 @@ BattleOnlyModeHeroSelector::BattleOnlyModeHeroSelector(BattleOnlyModeWindow& par
primSkillsInput.push_back(std::make_shared<CTextInput>(Rect(78 + i * 36, 58, 32, 16), EFonts::FONT_SMALL, ETextAlignment::CENTER, false)); 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()->setFilterNumber(0, 100);
primSkillsInput.back()->setText("0"); primSkillsInput.back()->setText("0");
primSkillsInput.back()->setCallback([this, i, id](const std::string & text){
parent.startInfo->primSkillLevel[id][i] = std::stoi(primSkillsInput[i]->getText());
});
} }
creatureImage.resize(GameConstants::ARMY_SIZE); creatureImage.resize(GameConstants::ARMY_SIZE);
@@ -217,9 +229,9 @@ BattleOnlyModeHeroSelector::BattleOnlyModeHeroSelector(BattleOnlyModeWindow& par
selectedArmyInput.push_back(std::make_shared<CTextInput>(Rect(5 + i * 36, 113, 32, 16), EFonts::FONT_SMALL, ETextAlignment::CENTER, false)); selectedArmyInput.push_back(std::make_shared<CTextInput>(Rect(5 + i * 36, 113, 32, 16), EFonts::FONT_SMALL, ETextAlignment::CENTER, false));
selectedArmyInput.back()->setFilterNumber(1, 10000000, 3); selectedArmyInput.back()->setFilterNumber(1, 10000000, 3);
selectedArmyInput.back()->setText("1"); selectedArmyInput.back()->setText("1");
selectedArmyInput.back()->setCallback([this, i](const std::string & text){ selectedArmyInput.back()->setCallback([this, i, id](const std::string & text){
if(!selectedArmy->slotEmpty(SlotID(i))) if(!parent.startInfo->selectedArmy[id]->slotEmpty(SlotID(i)))
selectedArmy->setCreature(SlotID(i), selectedArmy->getCreature(SlotID(i))->getId(), TextOperations::parseMetric<int>(text)); parent.startInfo->selectedArmy[id]->setCreature(SlotID(i), parent.startInfo->selectedArmy[id]->getCreature(SlotID(i))->getId(), TextOperations::parseMetric<int>(text));
}); });
} }
@@ -231,15 +243,19 @@ void BattleOnlyModeHeroSelector::setHeroIcon()
{ {
OBJECT_CONSTRUCTION; OBJECT_CONSTRUCTION;
if(!selectedHero) if(!parent.startInfo->selectedHero[id])
{ {
heroImage = std::make_shared<CPicture>(drawBlackBox(Point(58, 64), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeSelect")), Point(6, 7)); 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")); heroLabel = std::make_shared<CLabel>(160, 16, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, LIBRARY->generaltexth->translate("core.genrltxt.507"));
for(size_t i=0; i<GameConstants::PRIMARY_SKILLS; i++)
primSkillsInput[i]->setText(std::to_string(parent.startInfo->primSkillLevel[id][i]));
} }
else else
{ {
heroImage = std::make_shared<CPicture>(ENGINE->renderHandler().loadAnimation(AnimationPath::builtin("PortraitsLarge"), EImageBlitMode::COLORKEY)->getImage(selectedHero->getHeroType()->imageIndex), Point(6, 7)); heroImage = std::make_shared<CPicture>(ENGINE->renderHandler().loadAnimation(AnimationPath::builtin("PortraitsLarge"), EImageBlitMode::COLORKEY)->getImage(parent.startInfo->selectedHero[id]->getHeroType()->imageIndex), Point(6, 7));
heroLabel = std::make_shared<CLabel>(160, 16, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, selectedHero->getNameTranslated()); heroLabel = std::make_shared<CLabel>(160, 16, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, parent.startInfo->selectedHero[id]->getNameTranslated());
for(size_t i=0; i<GameConstants::PRIMARY_SKILLS; i++)
primSkillsInput[i]->setText("0");
} }
heroImage->addLClickCallback([this](){ heroImage->addLClickCallback([this](){
@@ -255,8 +271,8 @@ void BattleOnlyModeHeroSelector::setHeroIcon()
return heroA->heroClass->faction < heroB->heroClass->faction; return heroA->heroClass->faction < heroB->heroClass->faction;
}); });
int selectedIndex = !selectedHero ? 0 : (1 + std::distance(heroes.begin(), std::find_if(heroes.begin(), heroes.end(), [this](auto heroID) { int selectedIndex = !parent.startInfo->selectedHero[id] ? 0 : (1 + std::distance(heroes.begin(), std::find_if(heroes.begin(), heroes.end(), [this](auto heroID) {
return heroID == selectedHero->getHeroType()->getId(); return heroID == parent.startInfo->selectedHero[id]->getHeroType()->getId();
}))); })));
std::vector<std::string> texts; std::vector<std::string> texts;
@@ -275,7 +291,7 @@ void BattleOnlyModeHeroSelector::setHeroIcon()
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){ 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) if(index == 0)
{ {
selectedHero.reset(); parent.startInfo->selectedHero[id].reset();
setHeroIcon(); setHeroIcon();
return; return;
} }
@@ -287,7 +303,10 @@ void BattleOnlyModeHeroSelector::setHeroIcon()
auto obj = std::dynamic_pointer_cast<CGHeroInstance>(factory->create(parent.cb.get(), templates.front())); auto obj = std::dynamic_pointer_cast<CGHeroInstance>(factory->create(parent.cb.get(), templates.front()));
obj->setHeroType(hero); obj->setHeroType(hero);
selectedHero = obj; parent.startInfo->selectedHero[id] = obj;
for(size_t i=0; i<GameConstants::PRIMARY_SKILLS; i++)
parent.startInfo->primSkillLevel[id][i] = 0;
setHeroIcon(); setHeroIcon();
parent.setOkButtonEnabled(); parent.setOkButtonEnabled();
}, selectedIndex, images, true, true); }, selectedIndex, images, true, true);
@@ -302,10 +321,10 @@ void BattleOnlyModeHeroSelector::setHeroIcon()
}); });
heroImage->addRClickCallback([this](){ heroImage->addRClickCallback([this](){
if(!selectedHero) if(!parent.startInfo->selectedHero[id])
return; return;
ENGINE->windows().createAndPushWindow<CHeroOverview>(selectedHero->getHeroType()->getId()); ENGINE->windows().createAndPushWindow<CHeroOverview>(parent.startInfo->selectedHero[id]->getHeroType()->getId());
}); });
} }
@@ -315,11 +334,11 @@ void BattleOnlyModeHeroSelector::setCreatureIcons()
for(int i = 0; i < creatureImage.size(); i++) for(int i = 0; i < creatureImage.size(); i++)
{ {
if(selectedArmy->slotEmpty(SlotID(i))) if(parent.startInfo->selectedArmy[id]->slotEmpty(SlotID(i)))
creatureImage[i] = std::make_shared<CPicture>(drawBlackBox(Point(32, 32), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeSelect")), Point(6 + i * 36, 78)); creatureImage[i] = std::make_shared<CPicture>(drawBlackBox(Point(32, 32), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeSelect")), Point(6 + i * 36, 78));
else else
{ {
auto creatureID = selectedArmy->Slots().at(SlotID(i))->getCreatureID(); auto creatureID = parent.startInfo->selectedArmy[id]->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)); 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));
} }
@@ -336,8 +355,8 @@ void BattleOnlyModeHeroSelector::setCreatureIcons()
return creatureA->getFactionID() < creatureB->getFactionID(); return creatureA->getFactionID() < creatureB->getFactionID();
}); });
int selectedIndex = selectedArmy->slotEmpty(SlotID(i)) ? 0 : (1 + std::distance(creatures.begin(), std::find_if(creatures.begin(), creatures.end(), [this, i](auto creatureID) { int selectedIndex = parent.startInfo->selectedArmy[id]->slotEmpty(SlotID(i)) ? 0 : (1 + std::distance(creatures.begin(), std::find_if(creatures.begin(), creatures.end(), [this, i](auto creatureID) {
return creatureID == selectedArmy->Slots().at(SlotID(i))->getId(); return creatureID == parent.startInfo->selectedArmy[id]->Slots().at(SlotID(i))->getId();
}))); })));
std::vector<std::string> texts; std::vector<std::string> texts;
@@ -356,15 +375,15 @@ void BattleOnlyModeHeroSelector::setCreatureIcons()
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){ 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(index == 0)
{ {
if(!selectedArmy->slotEmpty(SlotID(i))) if(!parent.startInfo->selectedArmy[id]->slotEmpty(SlotID(i)))
selectedArmy->eraseStack(SlotID(i)); parent.startInfo->selectedArmy[id]->eraseStack(SlotID(i));
setCreatureIcons(); setCreatureIcons();
return; return;
} }
index--; index--;
auto creature = creatures.at(index).toCreature(); auto creature = creatures.at(index).toCreature();
selectedArmy->setCreature(SlotID(i), creature->getId(), 100); parent.startInfo->selectedArmy[id]->setCreature(SlotID(i), creature->getId(), 100);
selectedArmyInput[SlotID(i)]->setText("100"); selectedArmyInput[SlotID(i)]->setText("100");
setCreatureIcons(); setCreatureIcons();
}, selectedIndex, images, true, true); }, selectedIndex, images, true, true);
@@ -379,10 +398,10 @@ void BattleOnlyModeHeroSelector::setCreatureIcons()
}); });
creatureImage[i]->addRClickCallback([this, i](){ creatureImage[i]->addRClickCallback([this, i](){
if(selectedArmy->slotEmpty(SlotID(i))) if(parent.startInfo->selectedArmy[id]->slotEmpty(SlotID(i)))
return; return;
ENGINE->windows().createAndPushWindow<CStackWindow>(LIBRARY->creh->objects.at(selectedArmy->Slots().at(SlotID(i))->getCreatureID()).get(), true); ENGINE->windows().createAndPushWindow<CStackWindow>(LIBRARY->creh->objects.at(parent.startInfo->selectedArmy[id]->Slots().at(SlotID(i))->getCreatureID()).get(), true);
}); });
} }
} }
@@ -395,7 +414,7 @@ void BattleOnlyModeWindow::startBattle()
map->getEditManager()->clearTerrain(rng); map->getEditManager()->clearTerrain(rng);
map->getEditManager()->getTerrainSelection().selectAll(); map->getEditManager()->getTerrainSelection().selectAll();
map->getEditManager()->drawTerrain(selectedTerrain == TerrainId::NONE ? TerrainId::DIRT : selectedTerrain, 0, rng); map->getEditManager()->drawTerrain(startInfo->selectedTerrain == TerrainId::NONE ? TerrainId::DIRT : startInfo->selectedTerrain, 0, rng);
map->players[0].canComputerPlay = true; map->players[0].canComputerPlay = true;
map->players[0].canHumanPlay = true; map->players[0].canHumanPlay = true;
@@ -403,25 +422,25 @@ void BattleOnlyModeWindow::startBattle()
auto knownHeroes = LIBRARY->objtypeh->knownSubObjects(Obj::HERO); auto knownHeroes = LIBRARY->objtypeh->knownSubObjects(Obj::HERO);
auto addHero = [&](auto & selector, PlayerColor color, const int3 & position) auto addHero = [&](int sel, PlayerColor color, const int3 & position)
{ {
selector->selectedHero->setOwner(color); startInfo->selectedHero[sel]->setOwner(color);
selector->selectedHero->pos = position; startInfo->selectedHero[sel]->pos = position;
for(size_t i=0; i<GameConstants::PRIMARY_SKILLS; i++) for(size_t i=0; i<GameConstants::PRIMARY_SKILLS; i++)
selector->selectedHero->pushPrimSkill(PrimarySkill(i), std::stoi(selector->primSkillsInput[i]->getText())); startInfo->selectedHero[sel]->pushPrimSkill(PrimarySkill(i), startInfo->primSkillLevel[sel][i]);
selector->selectedHero->clearSlots(); startInfo->selectedHero[sel]->clearSlots();
for(int slot = 0; slot < GameConstants::ARMY_SIZE; slot++) for(int slot = 0; slot < GameConstants::ARMY_SIZE; slot++)
if(!selector->selectedArmy->slotEmpty(SlotID(slot))) if(!startInfo->selectedArmy[sel]->slotEmpty(SlotID(slot)))
selector->selectedHero->putStack(SlotID(slot), selector->selectedArmy->detachStack(SlotID(slot))); startInfo->selectedHero[sel]->putStack(SlotID(slot), startInfo->selectedArmy[sel]->detachStack(SlotID(slot)));
map->getEditManager()->insertObject(selector->selectedHero); map->getEditManager()->insertObject(startInfo->selectedHero[sel]);
}; };
addHero(heroSelector1, PlayerColor(0), int3(5, 6, 0)); addHero(0, PlayerColor(0), int3(5, 6, 0));
if(selectedTown == FactionID::NONE) if(startInfo->selectedTown == FactionID::NONE)
addHero(heroSelector2, PlayerColor(1), int3(5, 5, 0)); addHero(1, PlayerColor(1), int3(5, 5, 0));
else else
{ {
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::TOWN, selectedTown); auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::TOWN, startInfo->selectedTown);
auto templates = factory->getTemplates(); auto templates = factory->getTemplates();
auto obj = factory->create(cb.get(), templates.front()); auto obj = factory->create(cb.get(), templates.front());
auto townObj = std::dynamic_pointer_cast<CGTownInstance>(obj); auto townObj = std::dynamic_pointer_cast<CGTownInstance>(obj);
@@ -429,14 +448,14 @@ void BattleOnlyModeWindow::startBattle()
obj->pos = int3(5, 5, 0); obj->pos = int3(5, 5, 0);
for (const auto & building : townObj->getTown()->getAllBuildings()) for (const auto & building : townObj->getTown()->getAllBuildings())
townObj->addBuilding(building); townObj->addBuilding(building);
if(!heroSelector2->selectedHero) if(!startInfo->selectedHero[1])
{ {
for(int slot = 0; slot < GameConstants::ARMY_SIZE; slot++) for(int slot = 0; slot < GameConstants::ARMY_SIZE; slot++)
if(!heroSelector2->selectedArmy->slotEmpty(SlotID(slot))) if(!startInfo->selectedArmy[1]->slotEmpty(SlotID(slot)))
townObj->getArmy()->putStack(SlotID(slot), heroSelector2->selectedArmy->detachStack(SlotID(slot))); townObj->getArmy()->putStack(SlotID(slot), startInfo->selectedArmy[1]->detachStack(SlotID(slot)));
} }
else else
addHero(heroSelector2, PlayerColor(1), int3(5, 5, 0)); addHero(1, PlayerColor(1), int3(5, 5, 0));
map->getEditManager()->insertObject(townObj); map->getEditManager()->insertObject(townObj);
} }

View File

@@ -36,6 +36,20 @@ public:
static void openBattleWindow(); static void openBattleWindow();
}; };
class BattleOnlyModeStartInfo
{
public:
TerrainId selectedTerrain;
FactionID selectedTown;
std::array<std::shared_ptr<CGHeroInstance>, 2> selectedHero;
std::array<std::shared_ptr<CCreatureSet>, 2> selectedArmy;
std::array<std::array<int, GameConstants::PRIMARY_SKILLS>, 2> primSkillLevel;
BattleOnlyModeStartInfo();
};
class BattleOnlyModeHeroSelector : public CIntObject class BattleOnlyModeHeroSelector : public CIntObject
{ {
private: private:
@@ -45,24 +59,25 @@ private:
std::shared_ptr<CPicture> heroImage; std::shared_ptr<CPicture> heroImage;
std::shared_ptr<CLabel> heroLabel; std::shared_ptr<CLabel> heroLabel;
std::vector<std::shared_ptr<CPicture>> creatureImage; std::vector<std::shared_ptr<CPicture>> creatureImage;
int id;
public: public:
std::vector<std::shared_ptr<CAnimImage>> primSkills; std::vector<std::shared_ptr<CAnimImage>> primSkills;
std::vector<std::shared_ptr<GraphicalPrimitiveCanvas>> primSkillsBorder; std::vector<std::shared_ptr<GraphicalPrimitiveCanvas>> primSkillsBorder;
std::vector<std::shared_ptr<CTextInput>> primSkillsInput; std::vector<std::shared_ptr<CTextInput>> primSkillsInput;
std::shared_ptr<CGHeroInstance> selectedHero;
std::shared_ptr<CCreatureSet> selectedArmy;
std::vector<std::shared_ptr<CTextInput>> selectedArmyInput; std::vector<std::shared_ptr<CTextInput>> selectedArmyInput;
void setHeroIcon(); void setHeroIcon();
void setCreatureIcons(); void setCreatureIcons();
BattleOnlyModeHeroSelector(BattleOnlyModeWindow& parent, Point position); BattleOnlyModeHeroSelector(int id, BattleOnlyModeWindow& parent, Point position);
}; };
class BattleOnlyModeWindow : public CWindowObject class BattleOnlyModeWindow : public CWindowObject
{ {
friend class BattleOnlyModeHeroSelector; friend class BattleOnlyModeHeroSelector;
private: private:
std::shared_ptr<BattleOnlyModeStartInfo> startInfo;
std::unique_ptr<CMap> map; std::unique_ptr<CMap> map;
std::shared_ptr<EditorCallback> cb; std::shared_ptr<EditorCallback> cb;
@@ -76,9 +91,6 @@ private:
std::shared_ptr<BattleOnlyModeHeroSelector> heroSelector1; std::shared_ptr<BattleOnlyModeHeroSelector> heroSelector1;
std::shared_ptr<BattleOnlyModeHeroSelector> heroSelector2; std::shared_ptr<BattleOnlyModeHeroSelector> heroSelector2;
TerrainId selectedTerrain;
FactionID selectedTown;
void init(); void init();
void setTerrainButtonText(); void setTerrainButtonText();
void setOkButtonEnabled(); void setOkButtonEnabled();

View File

@@ -90,7 +90,7 @@ struct DLL_LINKAGE LobbyChatMessage : public CLobbyPackToPropagate
struct DLL_LINKAGE LobbyGuiAction : public CLobbyPackToPropagate struct DLL_LINKAGE LobbyGuiAction : public CLobbyPackToPropagate
{ {
enum EAction : ui8 { enum EAction : ui8 {
NONE, NO_TAB, OPEN_OPTIONS, OPEN_SCENARIO_LIST, OPEN_RANDOM_MAP_OPTIONS, OPEN_TURN_OPTIONS, OPEN_EXTRA_OPTIONS NONE, NO_TAB, OPEN_OPTIONS, OPEN_SCENARIO_LIST, OPEN_RANDOM_MAP_OPTIONS, OPEN_TURN_OPTIONS, OPEN_EXTRA_OPTIONS, BATTLE_MODE
} action = NONE; } action = NONE;