diff --git a/client/CAdvmapInterface.cpp b/client/CAdvmapInterface.cpp index b74590f57..9279c0e99 100644 --- a/client/CAdvmapInterface.cpp +++ b/client/CAdvmapInterface.cpp @@ -1536,5 +1536,13 @@ CAdventureOptions::CAdventureOptions(): void CAdventureOptions::showScenarioInfo() { - GH.pushInt(new CScenarioInfo(LOCPLINT->cb->getMapHeader(), LOCPLINT->cb->getStartInfo())); + auto campState = LOCPLINT->cb->getStartInfo()->campState; + if(campState) + { + GH.pushInt(new CBonusSelection(campState)); + } + else + { + GH.pushInt(new CScenarioInfo(LOCPLINT->cb->getMapHeader(), LOCPLINT->cb->getStartInfo())); + } } diff --git a/client/CMT.cpp b/client/CMT.cpp index 542b4cf26..a581c9c6a 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -886,6 +886,13 @@ static void listenForEvents() startGame(&si); } break; + case PREPARE_RESTART_CAMPAIGN: + { + auto si = reinterpret_cast(ev.user.data1); + endGame(); + startGame(si); + } + break; case RETURN_TO_MENU_LOAD: endGame(); CGPreGame::create(); diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 91bec233a..7c1c0baf0 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -78,7 +78,8 @@ enum STOP_CLIENT = 3, RESTART_GAME, RETURN_TO_MENU_LOAD, - FULLSCREEN_TOGGLED + FULLSCREEN_TOGGLED, + PREPARE_RESTART_CAMPAIGN }; /// Central class for managing user interface logic diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 004b64bc8..00dcde741 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -3119,6 +3119,13 @@ void CBonusSelection::init() diffLb = nullptr; diffRb = nullptr; bonuses = nullptr; + selectedMap = 0; + + // Initialize start info + startInfo.mapname = ourCampaign->camp->header.filename; + startInfo.mode = StartInfo::CAMPAIGN; + startInfo.campState = ourCampaign; + startInfo.turnTime = 0; OBJ_CONSTRUCTION_CAPTURING_ALL; static const std::string bgNames [] = {"E1_BG.BMP", "G2_BG.BMP", "E2_BG.BMP", "G1_BG.BMP", "G3_BG.BMP", "N1_BG.BMP", @@ -3137,6 +3144,7 @@ void CBonusSelection::init() blitAt(panel, 456, 6, background); startB = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::startMap, this), 475, 536, "CBBEGIB.DEF", SDLK_RETURN); + restartB = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::restartMap, this), 475, 536, "CBRESTB.DEF", SDLK_RETURN); backB = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::goBack, this), 624, 536, "CBCANCB.DEF", SDLK_ESCAPE); //campaign name @@ -3151,11 +3159,11 @@ void CBonusSelection::init() //campaign description graphics->fonts[FONT_SMALL]->renderTextLeft(background, CGI->generaltexth->allTexts[38], Colors::YELLOW, Point(481, 63)); - cmpgDesc = new CTextBox(ourCampaign->camp->header.description, Rect(480, 86, 286, 117), 1); - //cmpgDesc->showAll(background); + campaignDescription = new CTextBox(ourCampaign->camp->header.description, Rect(480, 86, 286, 117), 1); + //campaignDescription->showAll(background); //map description - mapDesc = new CTextBox("", Rect(480, 280, 286, 117), 1); + mapDescription = new CTextBox("", Rect(480, 280, 286, 117), 1); //bonus choosing graphics->fonts[FONT_MEDIUM]->renderTextLeft(background, CGI->generaltexth->allTexts[71], Colors::WHITE, Point(511, 432)); @@ -3181,15 +3189,6 @@ void CBonusSelection::init() } } - //unlock if no bonuses -- it's acceptable - - -// //init campaign state if necessary -// if (ourCampaign->campaignName.size() == 0) -// { -// ourCampaign->initNewCampaign(sInfo); -// } - //allies / enemies graphics->fonts[FONT_SMALL]->renderTextLeft(background, CGI->generaltexth->allTexts[390] + ":", Colors::WHITE, Point(486, 407)); graphics->fonts[FONT_SMALL]->renderTextLeft(background, CGI->generaltexth->allTexts[391] + ":", Colors::WHITE, Point(619, 407)); @@ -3215,26 +3214,22 @@ void CBonusSelection::init() //difficulty selection buttons if (ourCampaign->camp->header.difficultyChoosenByPlayer) { - diffLb = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::changeDiff, this, false), 694, 508, "SCNRBLF.DEF"); - diffRb = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::changeDiff, this, true), 738, 508, "SCNRBRT.DEF"); + diffLb = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::decreaseDifficulty, this), 694, 508, "SCNRBLF.DEF"); + diffRb = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::increaseDifficulty, this), 738, 508, "SCNRBRT.DEF"); } //load miniflags sFlags = CDefHandler::giveDef("ITGFLAGS.DEF"); } - -CBonusSelection::CBonusSelection(shared_ptr _ourCampaign) - : ourCampaign(std::move(_ourCampaign)) +CBonusSelection::CBonusSelection(shared_ptr _ourCampaign) : ourCampaign(_ourCampaign) { init(); } -CBonusSelection::CBonusSelection( std::string campaignFName ) +CBonusSelection::CBonusSelection(const std::string & campaignFName) { ourCampaign = make_shared(CCampaignHandler::getCampaign(campaignFName)); - - sInfo.campState = ourCampaign; init(); } @@ -3295,31 +3290,43 @@ void CBonusSelection::loadPositionsOfGraphics() assert(idx == CGI->generaltexth->campaignMapNames.size()); } -void CBonusSelection::selectMap( int whichOne, bool initialSelect ) +void CBonusSelection::selectMap(int mapNr, bool initialSelect) { - if(initialSelect || ourCampaign->currentMap != whichOne) + if(initialSelect || selectedMap != mapNr) { - sInfo.difficulty = ourCampaign->camp->scenarios[whichOne].difficulty; - sInfo.mapname = ourCampaign->camp->header.filename; - sInfo.mode = StartInfo::CAMPAIGN; - sInfo.campState = ourCampaign; - ourCampaign->currentMap = whichOne; + // initialize restart / start button + if(!ourCampaign->currentMap || *ourCampaign->currentMap != mapNr) + { + // draw start button + restartB->disable(); + startB->enable(); + } + else + { + // draw restart button + startB->disable(); + restartB->enable(); + } + + startInfo.difficulty = ourCampaign->camp->scenarios[mapNr].difficulty; + selectedMap = mapNr; + selectedBonus = boost::none; //get header delete ourHeader; - std::string & headerStr = ourCampaign->camp->mapPieces.find(whichOne)->second; + std::string & headerStr = ourCampaign->camp->mapPieces.find(mapNr)->second; auto buffer = reinterpret_cast(headerStr.data()); ourHeader = CMapService::loadMapHeader(buffer, headerStr.size()).release(); std::map names; names[1] = settings["general"]["playerName"].String(); - updateStartInfo(ourCampaign->camp->header.filename, sInfo, ourHeader, names); - sInfo.turnTime = 0; - sInfo.difficulty = ourCampaign->camp->scenarios[whichOne].difficulty; + updateStartInfo(ourCampaign->camp->header.filename, startInfo, ourHeader, names); - mapDesc->setText(ourHeader->description); + mapDescription->setText(ourHeader->description); updateBonusSelection(); + + GH.totalRedraw(); } } @@ -3338,7 +3345,7 @@ void CBonusSelection::show(SDL_Surface * to) //map description printAtLoc(CGI->generaltexth->allTexts[496], 481, 253, FONT_SMALL, Colors::YELLOW, to); - mapDesc->showAll(to); //showAll because CTextBox has no show() + mapDescription->showAll(to); //showAll because CTextBox has no show() //map size icon int temp; @@ -3367,7 +3374,7 @@ void CBonusSelection::show(SDL_Surface * to) int ex = 629 + graphics->fonts[FONT_SMALL]->getStringWidth(CGI->generaltexth->allTexts[391]); TeamID myT; myT = ourHeader->players[playerColor.getNum()].team; - for (auto i = sInfo.playerInfos.cbegin(); i != sInfo.playerInfos.cend(); i++) + for (auto i = startInfo.playerInfos.cbegin(); i != startInfo.playerInfos.cend(); i++) { int *myx = ((i->first == playerColor || ourHeader->players[i->first.getNum()].team == myT) ? &fx : &ex); blitAtLoc(sFlags->ourImages[i->first.getNum()].bitmap, *myx, 405, to); @@ -3375,7 +3382,7 @@ void CBonusSelection::show(SDL_Surface * to) } //difficulty - blitAtLoc(diffPics[sInfo.difficulty], 709, 455, to); + blitAtLoc(diffPics[startInfo.difficulty], 709, 455, to); CIntObject::show(to); } @@ -3394,7 +3401,7 @@ void CBonusSelection::updateBonusSelection() //resource - BORES.DEF //player - CREST58.DEF //hero - PORTRAITSLARGE (HPL###.BMPs) - const CCampaignScenario &scenario = ourCampaign->camp->scenarios[sInfo.campState->currentMap]; + const CCampaignScenario &scenario = ourCampaign->camp->scenarios[selectedMap]; const std::vector & bonDescs = scenario.travelOptions.bonusesToChoose; updateStartButtonState(-1); @@ -3407,180 +3414,192 @@ void CBonusSelection::updateBonusSelection() } bonuses->buttons.clear(); - static const char *bonusPics[] = {"SPELLBON.DEF", "TWCRPORT.DEF", "", "ARTIFBON.DEF", "SPELLBON.DEF", - "PSKILBON.DEF", "SSKILBON.DEF", "BORES.DEF", "PORTRAITSLARGE", "PORTRAITSLARGE"}; + static const char *bonusPics[] = {"SPELLBON.DEF", "TWCRPORT.DEF", "", "ARTIFBON.DEF", "SPELLBON.DEF", + "PSKILBON.DEF", "SSKILBON.DEF", "BORES.DEF", "PORTRAITSLARGE", "PORTRAITSLARGE"}; - for(int i = 0; i < bonDescs.size(); i++) + for(int i = 0; i < bonDescs.size(); i++) + { + std::string picName=bonusPics[bonDescs[i].type]; + size_t picNumber=bonDescs[i].info2; + + std::string desc; + switch(bonDescs[i].type) { - std::string picName=bonusPics[bonDescs[i].type]; - size_t picNumber=bonDescs[i].info2; - - std::string desc; - switch(bonDescs[i].type) + case CScenarioTravel::STravelBonus::SPELL: + desc = CGI->generaltexth->allTexts[715]; + boost::algorithm::replace_first(desc, "%s", CGI->spellh->spells[bonDescs[i].info2]->name); + break; + case CScenarioTravel::STravelBonus::MONSTER: + picNumber = bonDescs[i].info2 + 2; + desc = CGI->generaltexth->allTexts[717]; + boost::algorithm::replace_first(desc, "%d", boost::lexical_cast(bonDescs[i].info3)); + boost::algorithm::replace_first(desc, "%s", CGI->creh->creatures[bonDescs[i].info2]->namePl); + break; + case CScenarioTravel::STravelBonus::BUILDING: { - case CScenarioTravel::STravelBonus::SPELL: - desc = CGI->generaltexth->allTexts[715]; - boost::algorithm::replace_first(desc, "%s", CGI->spellh->spells[bonDescs[i].info2]->name); - break; - case CScenarioTravel::STravelBonus::MONSTER: - picNumber = bonDescs[i].info2 + 2; - desc = CGI->generaltexth->allTexts[717]; - boost::algorithm::replace_first(desc, "%d", boost::lexical_cast(bonDescs[i].info3)); - boost::algorithm::replace_first(desc, "%s", CGI->creh->creatures[bonDescs[i].info2]->namePl); - break; - case CScenarioTravel::STravelBonus::BUILDING: + int faction = -1; + for(auto & elem : startInfo.playerInfos) { - int faction = -1; - for(auto & elem : sInfo.playerInfos) + if (elem.second.playerID) { - if (elem.second.playerID) - { - faction = elem.second.castle; - break; - } - + faction = elem.second.castle; + break; } - assert(faction != -1); - BuildingID buildID = CBuildingHandler::campToERMU(bonDescs[i].info1, faction, std::set()); - picName = graphics->ERMUtoPicture[faction][buildID]; - picNumber = -1; - - if (vstd::contains(CGI->townh->factions[faction]->town->buildings, buildID)) - desc = CGI->townh->factions[faction]->town->buildings.find(buildID)->second->Name(); } - break; - case CScenarioTravel::STravelBonus::ARTIFACT: - desc = CGI->generaltexth->allTexts[715]; - boost::algorithm::replace_first(desc, "%s", CGI->arth->artifacts[bonDescs[i].info2]->Name()); - break; - case CScenarioTravel::STravelBonus::SPELL_SCROLL: - desc = CGI->generaltexth->allTexts[716]; - boost::algorithm::replace_first(desc, "%s", CGI->spellh->spells[bonDescs[i].info2]->name); - break; - case CScenarioTravel::STravelBonus::PRIMARY_SKILL: + assert(faction != -1); + + BuildingID buildID = CBuildingHandler::campToERMU(bonDescs[i].info1, faction, std::set()); + picName = graphics->ERMUtoPicture[faction][buildID]; + picNumber = -1; + + if (vstd::contains(CGI->townh->factions[faction]->town->buildings, buildID)) + desc = CGI->townh->factions[faction]->town->buildings.find(buildID)->second->Name(); + } + break; + case CScenarioTravel::STravelBonus::ARTIFACT: + desc = CGI->generaltexth->allTexts[715]; + boost::algorithm::replace_first(desc, "%s", CGI->arth->artifacts[bonDescs[i].info2]->Name()); + break; + case CScenarioTravel::STravelBonus::SPELL_SCROLL: + desc = CGI->generaltexth->allTexts[716]; + boost::algorithm::replace_first(desc, "%s", CGI->spellh->spells[bonDescs[i].info2]->name); + break; + case CScenarioTravel::STravelBonus::PRIMARY_SKILL: + { + int leadingSkill = -1; + std::vector > toPrint; //primary skills to be listed + const ui8* ptr = reinterpret_cast(&bonDescs[i].info2); + for (int g=0; g > toPrint; //primary skills to be listed - const ui8* ptr = reinterpret_cast(&bonDescs[i].info2); - for (int g=0; g ptr[leadingSkill]) { - if (leadingSkill == -1 || ptr[g] > ptr[leadingSkill]) - { - leadingSkill = g; - } - if (ptr[g] != 0) - { - toPrint.push_back(std::make_pair(g, ptr[g])); - } + leadingSkill = g; } - picNumber = leadingSkill; - desc = CGI->generaltexth->allTexts[715]; - - std::string substitute; //text to be printed instead of %s - for (int v=0; v(toPrint[v].second); - substitute += " " + CGI->generaltexth->primarySkillNames[toPrint[v].first]; - if(v != toPrint.size() - 1) - { - substitute += ", "; - } + toPrint.push_back(std::make_pair(g, ptr[g])); } + } + picNumber = leadingSkill; + desc = CGI->generaltexth->allTexts[715]; - boost::algorithm::replace_first(desc, "%s", substitute); + std::string substitute; //text to be printed instead of %s + for (int v=0; v(toPrint[v].second); + substitute += " " + CGI->generaltexth->primarySkillNames[toPrint[v].first]; + if(v != toPrint.size() - 1) + { + substitute += ", "; + } + } + + boost::algorithm::replace_first(desc, "%s", substitute); + break; + } + case CScenarioTravel::STravelBonus::SECONDARY_SKILL: + desc = CGI->generaltexth->allTexts[718]; + + boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->levels[bonDescs[i].info3 - 1]); //skill level + boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->skillName[bonDescs[i].info2]); //skill name + picNumber = bonDescs[i].info2 * 3 + bonDescs[i].info3 - 1; + + break; + case CScenarioTravel::STravelBonus::RESOURCE: + { + int serialResID = 0; + switch(bonDescs[i].info1) + { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: + serialResID = bonDescs[i].info1; + break; + case 0xFD: //wood + ore + serialResID = 7; + break; + case 0xFE: //rare resources + serialResID = 8; break; } - case CScenarioTravel::STravelBonus::SECONDARY_SKILL: - desc = CGI->generaltexth->allTexts[718]; + picNumber = serialResID; - boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->levels[bonDescs[i].info3 - 1]); //skill level - boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->skillName[bonDescs[i].info2]); //skill name - picNumber = bonDescs[i].info2 * 3 + bonDescs[i].info3 - 1; - - break; - case CScenarioTravel::STravelBonus::RESOURCE: + desc = CGI->generaltexth->allTexts[717]; + boost::algorithm::replace_first(desc, "%d", boost::lexical_cast(bonDescs[i].info2)); + std::string replacement; + if (serialResID <= 6) { - int serialResID = 0; - switch(bonDescs[i].info1) - { - case 0: case 1: case 2: case 3: case 4: case 5: case 6: - serialResID = bonDescs[i].info1; - break; - case 0xFD: //wood + ore - serialResID = 7; - break; - case 0xFE: //rare resources - serialResID = 8; - break; - } - picNumber = serialResID; - - desc = CGI->generaltexth->allTexts[717]; - boost::algorithm::replace_first(desc, "%d", boost::lexical_cast(bonDescs[i].info2)); - std::string replacement; - if (serialResID <= 6) - { - replacement = CGI->generaltexth->restypes[serialResID]; - } - else - { - replacement = CGI->generaltexth->allTexts[714 + serialResID]; - } - boost::algorithm::replace_first(desc, "%s", replacement); - } - break; - case CScenarioTravel::STravelBonus::PLAYER_PREV_SCENARIO: - { - auto superhero = ourCampaign->camp->scenarios[bonDescs[i].info2].strongestHero(PlayerColor(bonDescs[i].info1)); - if (!superhero) logGlobal->warnStream() << "No superhero! How could it be transfered?"; - picNumber = superhero ? superhero->portrait : 0; - desc = CGI->generaltexth->allTexts[719]; - - boost::algorithm::replace_first(desc, "%s", ourCampaign->camp->scenarios[bonDescs[i].info2].scenarioName); //scenario - } - - break; - case CScenarioTravel::STravelBonus::HERO: - - desc = CGI->generaltexth->allTexts[718]; - boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->capColors[bonDescs[i].info1]); //hero's color - - if (bonDescs[i].info2 == 0xFFFF) - { - boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->allTexts[101]); //hero's name - picNumber = -1; - picName = "CBONN1A3.BMP"; + replacement = CGI->generaltexth->restypes[serialResID]; } else { - boost::algorithm::replace_first(desc, "%s", CGI->heroh->heroes[bonDescs[i].info2]->name); //hero's name + replacement = CGI->generaltexth->allTexts[714 + serialResID]; } - break; + boost::algorithm::replace_first(desc, "%s", replacement); + } + break; + case CScenarioTravel::STravelBonus::PLAYER_PREV_SCENARIO: + { + auto superhero = ourCampaign->camp->scenarios[bonDescs[i].info2].strongestHero(PlayerColor(bonDescs[i].info1)); + if (!superhero) logGlobal->warnStream() << "No superhero! How could it be transfered?"; + picNumber = superhero ? superhero->portrait : 0; + desc = CGI->generaltexth->allTexts[719]; + + boost::algorithm::replace_first(desc, "%s", ourCampaign->camp->scenarios[bonDescs[i].info2].scenarioName); //scenario } - CHighlightableButton *bonusButton = new CHighlightableButton(desc, desc, 0, 475 + i*68, 455, "", i); + break; + case CScenarioTravel::STravelBonus::HERO: - if (picNumber != -1) - picName += ":" + boost::lexical_cast(picNumber); + desc = CGI->generaltexth->allTexts[718]; + boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->capColors[bonDescs[i].info1]); //hero's color - auto anim = new CAnimation(); - anim->setCustom(picName, 0); - bonusButton->setImage(anim); - const SDL_Color brightYellow = { 242, 226, 110, 0 }; - bonusButton->borderColor = brightYellow; - bonuses->addButton(bonusButton); + if (bonDescs[i].info2 == 0xFFFF) + { + boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->allTexts[101]); //hero's name + picNumber = -1; + picName = "CBONN1A3.BMP"; + } + else + { + boost::algorithm::replace_first(desc, "%s", CGI->heroh->heroes[bonDescs[i].info2]->name); //hero's name + } + break; } + + CHighlightableButton *bonusButton = new CHighlightableButton(desc, desc, 0, 475 + i*68, 455, "", i); + + if (picNumber != -1) + picName += ":" + boost::lexical_cast(picNumber); + + auto anim = new CAnimation(); + anim->setCustom(picName, 0); + bonusButton->setImage(anim); + const SDL_Color brightYellow = { 242, 226, 110, 0 }; + bonusButton->borderColor = brightYellow; + bonuses->addButton(bonusButton); + } + + // set bonus if already chosen + if(vstd::contains(ourCampaign->chosenCampaignBonuses, selectedMap)) + { + bonuses->select(ourCampaign->chosenCampaignBonuses[selectedMap], false); + } +} + +void CBonusSelection::updateCampaignState() +{ + ourCampaign->currentMap = selectedMap; + ourCampaign->chosenCampaignBonuses[selectedMap] = *selectedBonus; } void CBonusSelection::startMap() { - auto si = new StartInfo(sInfo); + updateCampaignState(); - const CCampaignScenario & scenario = ourCampaign->camp->scenarios[ourCampaign->currentMap]; - - logGlobal->infoStream() << "Starting scenario " << int(ourCampaign->currentMap); + logGlobal->infoStream() << "Starting scenario " << selectedMap; + const CCampaignScenario & scenario = ourCampaign->camp->scenarios[selectedMap]; + auto si = new StartInfo(startInfo); auto exitCb = [si]() { CGP->showLoadingScreen(boost::bind(&startGame, si, (CConnection *)nullptr)); @@ -3596,26 +3615,41 @@ void CBonusSelection::startMap() } } -void CBonusSelection::selectBonus( int id ) +void CBonusSelection::restartMap() +{ + updateCampaignState(); + auto si = new StartInfo(startInfo); // copy before this object will be destroyed + + GH.popIntTotally(this); + LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[67], [si] + { + SDL_Event event; + event.type = SDL_USEREVENT; + event.user.code = PREPARE_RESTART_CAMPAIGN; + event.user.data1 = si; + SDL_PushEvent(&event); + }, 0); +} + +void CBonusSelection::selectBonus(int id) { // Total redraw is needed because the border around the bonus images // have to be undrawn/drawn. - if (!vstd::contains(sInfo.campState->chosenCampaignBonuses, sInfo.campState->currentMap) - || id != sInfo.campState->currentBonusID()) + if (!selectedBonus || *selectedBonus != id) { - sInfo.campState->chosenCampaignBonuses[sInfo.campState->currentMap] = id; + selectedBonus = id; GH.totalRedraw(); updateStartButtonState(id); } - const CCampaignScenario &scenario = ourCampaign->camp->scenarios[sInfo.campState->currentMap]; + const CCampaignScenario &scenario = ourCampaign->camp->scenarios[selectedMap]; const std::vector & bonDescs = scenario.travelOptions.bonusesToChoose; if (bonDescs[id].type == CScenarioTravel::STravelBonus::HERO) { std::map names; names[1] = settings["general"]["playerName"].String(); - for(auto & elem : sInfo.playerInfos) + for(auto & elem : startInfo.playerInfos) { if(elem.first == PlayerColor(bonDescs[id].info1)) ::setPlayer(elem.second, 1, names); @@ -3625,24 +3659,26 @@ void CBonusSelection::selectBonus( int id ) } } -void CBonusSelection::changeDiff( bool increase ) +void CBonusSelection::increaseDifficulty() { - if (increase) - { - sInfo.difficulty = std::min(sInfo.difficulty + 1, 4); - } - else - { - sInfo.difficulty = std::max(sInfo.difficulty - 1, 0); - } + startInfo.difficulty = std::min(startInfo.difficulty + 1, 4); } -void CBonusSelection::updateStartButtonState( int selected /*= -1*/ ) +void CBonusSelection::decreaseDifficulty() +{ + startInfo.difficulty = std::max(startInfo.difficulty - 1, 0); +} + +void CBonusSelection::updateStartButtonState(int selected /*= -1*/) { if(selected == -1) - startB->setState( ourCampaign->getCurrentScenario().travelOptions.bonusesToChoose.size() ? CButtonBase::BLOCKED : CButtonBase::NORMAL); + { + startB->setState(ourCampaign->camp->scenarios[selectedMap].travelOptions.bonusesToChoose.size() ? CButtonBase::BLOCKED : CButtonBase::NORMAL); + } else if(startB->getState() == CButtonBase::BLOCKED) + { startB->setState(CButtonBase::NORMAL); + } } CBonusSelection::CRegion::CRegion( CBonusSelection * _owner, bool _accessible, bool _selectable, int _myNumber ) diff --git a/client/CPreGame.h b/client/CPreGame.h index 8d413e587..0dc8c04ea 100644 --- a/client/CPreGame.h +++ b/client/CPreGame.h @@ -452,12 +452,15 @@ public: /// Campaign screen where you can choose one out of three starting bonuses class CBonusSelection : public CIntObject { - SDL_Surface * background; - CAdventureMapButton * startB, * backB; +public: + CBonusSelection(const std::string & campaignFName); + CBonusSelection(shared_ptr _ourCampaign); + ~CBonusSelection(); - //campaign & map descriptions: - CTextBox * cmpgDesc, * mapDesc; + void showAll(SDL_Surface * to) override; + void show(SDL_Surface * to) override; +private: struct SCampPositions { std::string campPrefix; @@ -473,8 +476,6 @@ class CBonusSelection : public CIntObject }; - std::vector campDescriptions; - class CRegion : public CIntObject { CBonusSelection * owner; @@ -482,6 +483,7 @@ class CBonusSelection : public CIntObject bool accessible; //false if region should be striped bool selectable; //true if region should be selectable int myNumber; //number of region + public: std::string rclickText; CRegion(CBonusSelection * _owner, bool _accessible, bool _selectable, int _myNumber); @@ -492,40 +494,40 @@ class CBonusSelection : public CIntObject void show(SDL_Surface * to); }; - std::vector regions; - CRegion * highlightedRegion; - - void loadPositionsOfGraphics(); - shared_ptr ourCampaign; - CMapHeader *ourHeader; - CDefHandler *sizes; //icons of map sizes - SDL_Surface* diffPics[5]; //pictures of difficulties, user-selectable (or not if campaign locks this) - CAdventureMapButton * diffLb, * diffRb; //buttons for changing difficulty - void changeDiff(bool increase); //if false, then decrease - - - void updateStartButtonState(int selected = -1); //-1 -- no bonus is selected - //bonus selection - void updateBonusSelection(); - CHighlightableButtonsGroup * bonuses; - -public: - StartInfo sInfo; - CDefHandler *sFlags; - - void selectMap(int whichOne, bool initialSelect); - void selectBonus(int id); void init(); + void loadPositionsOfGraphics(); + void updateStartButtonState(int selected = -1); //-1 -- no bonus is selected + void updateBonusSelection(); + void updateCampaignState(); - CBonusSelection(std::string campaignFName); - CBonusSelection(shared_ptr _ourCampaign); - ~CBonusSelection(); - - void showAll(SDL_Surface * to); - void show(SDL_Surface * to); - + // Event handlers void goBack(); void startMap(); + void restartMap(); + void selectMap(int mapNr, bool initialSelect); + void selectBonus(int id); + void increaseDifficulty(); + void decreaseDifficulty(); + + // GUI components + SDL_Surface * background; + CAdventureMapButton * startB, * restartB, * backB; + CTextBox * campaignDescription, * mapDescription; + std::vector campDescriptions; + std::vector regions; + CRegion * highlightedRegion; + CHighlightableButtonsGroup * bonuses; + SDL_Surface * diffPics[5]; //pictures of difficulties, user-selectable (or not if campaign locks this) + CAdventureMapButton * diffLb, * diffRb; //buttons for changing difficulty + CDefHandler * sizes; //icons of map sizes + CDefHandler * sFlags; + + // Data + shared_ptr ourCampaign; + int selectedMap; + boost::optional selectedBonus; + StartInfo startInfo; + CMapHeader * ourHeader; }; /// Campaign selection screen diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index cdc6c7eb2..7955b85ea 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -807,7 +807,7 @@ void CGameState::init(StartInfo * si) { continue; } - auto bb = new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::CAMPAIGN_BONUS, val, scenarioOps->campState->currentMap, g); + auto bb = new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::CAMPAIGN_BONUS, val, *scenarioOps->campState->currentMap, g); hero->addNewBonus(bb); } } @@ -886,9 +886,9 @@ void CGameState::init(StartInfo * si) { logGlobal->infoStream() << "Open campaign map file: " << scenarioOps->campState->currentMap; auto campaign = scenarioOps->campState; - assert(vstd::contains(campaign->camp->mapPieces, scenarioOps->campState->currentMap)); + assert(vstd::contains(campaign->camp->mapPieces, *scenarioOps->campState->currentMap)); - std::string & mapContent = campaign->camp->mapPieces[scenarioOps->campState->currentMap]; + std::string & mapContent = campaign->camp->mapPieces[*scenarioOps->campState->currentMap]; auto buffer = reinterpret_cast(mapContent.data()); map = CMapService::loadMap(buffer, mapContent.size()).release(); } diff --git a/lib/mapping/CCampaignHandler.cpp b/lib/mapping/CCampaignHandler.cpp index 158ff5bd6..216c4a9ef 100644 --- a/lib/mapping/CCampaignHandler.cpp +++ b/lib/mapping/CCampaignHandler.cpp @@ -433,16 +433,16 @@ bool CScenarioTravel::STravelBonus::isBonusForHero() const void CCampaignState::mapConquered( const std::vector & heroes ) { - camp->scenarios[currentMap].prepareCrossoverHeroes(heroes); - mapsConquered.push_back(currentMap); - mapsRemaining -= currentMap; - camp->scenarios[currentMap].conquered = true; + camp->scenarios[*currentMap].prepareCrossoverHeroes(heroes); + mapsConquered.push_back(*currentMap); + mapsRemaining -= *currentMap; + camp->scenarios[*currentMap].conquered = true; } boost::optional CCampaignState::getBonusForCurrentMap() const { auto bonuses = getCurrentScenario().travelOptions.bonusesToChoose; - assert(chosenCampaignBonuses.count(currentMap) || bonuses.size() == 0); + assert(chosenCampaignBonuses.count(*currentMap) || bonuses.size() == 0); if(bonuses.size()) return bonuses[currentBonusID()]; else @@ -451,16 +451,18 @@ boost::optional CCampaignState::getBonusForCurren const CCampaignScenario & CCampaignState::getCurrentScenario() const { - return camp->scenarios[currentMap]; + return camp->scenarios[*currentMap]; +} + +ui8 CCampaignState::currentBonusID() const +{ + return chosenCampaignBonuses.at(*currentMap); +} + +CCampaignState::CCampaignState() +{ + } - -ui8 CCampaignState::currentBonusID() const -{ - return chosenCampaignBonuses.at(currentMap); -} - -CCampaignState::CCampaignState() -{} CCampaignState::CCampaignState( unique_ptr _camp ) : camp(std::move(_camp)) { diff --git a/lib/mapping/CCampaignHandler.h b/lib/mapping/CCampaignHandler.h index aea87e6fa..edf22c194 100644 --- a/lib/mapping/CCampaignHandler.h +++ b/lib/mapping/CCampaignHandler.h @@ -148,13 +148,13 @@ class DLL_LINKAGE CCampaignState public: unique_ptr camp; std::string campaignName; - std::vector mapsConquered, mapsRemaining; - ui8 currentMap; - - std::map chosenCampaignBonuses; //used only for mode CAMPAIGN - - //void initNewCampaign(const StartInfo &si); - void mapConquered(const std::vector & heroes); + std::vector mapsConquered, mapsRemaining; + boost::optional currentMap; + + std::map chosenCampaignBonuses; + + //void initNewCampaign(const StartInfo &si); + void mapConquered(const std::vector & heroes); boost::optional getBonusForCurrentMap() const; const CCampaignScenario &getCurrentScenario() const; ui8 currentBonusID() const;