1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-21 21:17:49 +02:00

- Fixed mantis (starting another scenario crashes VCMI for now)

- Refactoring
This commit is contained in:
beegee1 2013-12-16 18:39:56 +00:00
parent 7d7e65a316
commit b9b25ef552
8 changed files with 312 additions and 256 deletions

@ -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()));
}
}

@ -886,6 +886,13 @@ static void listenForEvents()
startGame(&si);
}
break;
case PREPARE_RESTART_CAMPAIGN:
{
auto si = reinterpret_cast<StartInfo *>(ev.user.data1);
endGame();
startGame(si);
}
break;
case RETURN_TO_MENU_LOAD:
endGame();
CGPreGame::create();

@ -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

@ -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<CCampaignState> _ourCampaign)
: ourCampaign(std::move(_ourCampaign))
CBonusSelection::CBonusSelection(shared_ptr<CCampaignState> _ourCampaign) : ourCampaign(_ourCampaign)
{
init();
}
CBonusSelection::CBonusSelection( std::string campaignFName )
CBonusSelection::CBonusSelection(const std::string & campaignFName)
{
ourCampaign = make_shared<CCampaignState>(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<const ui8 *>(headerStr.data());
ourHeader = CMapService::loadMapHeader(buffer, headerStr.size()).release();
std::map<ui8, std::string> 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<CScenarioTravel::STravelBonus> & 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<std::string>(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<std::string>(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<BuildingID>());
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<BuildingID>());
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<std::pair<int, int> > toPrint; //primary skills to be listed <num, val>
const ui8* ptr = reinterpret_cast<const ui8*>(&bonDescs[i].info2);
for (int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
{
int leadingSkill = -1;
std::vector<std::pair<int, int> > toPrint; //primary skills to be listed <num, val>
const ui8* ptr = reinterpret_cast<const ui8*>(&bonDescs[i].info2);
for (int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
if (leadingSkill == -1 || ptr[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.size(); ++v)
if (ptr[g] != 0)
{
substitute += boost::lexical_cast<std::string>(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.size(); ++v)
{
substitute += boost::lexical_cast<std::string>(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<std::string>(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<std::string>(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<std::string>(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<std::string>(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<CScenarioTravel::STravelBonus> & bonDescs = scenario.travelOptions.bonusesToChoose;
if (bonDescs[id].type == CScenarioTravel::STravelBonus::HERO)
{
std::map<ui8, std::string> 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 )

@ -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<CCampaignState> _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<SCampPositions> 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<CRegion *> regions;
CRegion * highlightedRegion;
void loadPositionsOfGraphics();
shared_ptr<CCampaignState> 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<CCampaignState> _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<SCampPositions> campDescriptions;
std::vector<CRegion *> 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<CCampaignState> ourCampaign;
int selectedMap;
boost::optional<int> selectedBonus;
StartInfo startInfo;
CMapHeader * ourHeader;
};
/// Campaign selection screen

@ -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<const ui8 *>(mapContent.data());
map = CMapService::loadMap(buffer, mapContent.size()).release();
}

@ -433,16 +433,16 @@ bool CScenarioTravel::STravelBonus::isBonusForHero() const
void CCampaignState::mapConquered( const std::vector<CGHeroInstance*> & 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<CScenarioTravel::STravelBonus> 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<CScenarioTravel::STravelBonus> 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<CCampaign> _camp ) : camp(std::move(_camp))
{

@ -148,13 +148,13 @@ class DLL_LINKAGE CCampaignState
public:
unique_ptr<CCampaign> camp;
std::string campaignName;
std::vector<ui8> mapsConquered, mapsRemaining;
ui8 currentMap;
std::map<ui8, ui8> chosenCampaignBonuses; //used only for mode CAMPAIGN
//void initNewCampaign(const StartInfo &si);
void mapConquered(const std::vector<CGHeroInstance*> & heroes);
std::vector<ui8> mapsConquered, mapsRemaining;
boost::optional<si32> currentMap;
std::map<ui8, ui8> chosenCampaignBonuses;
//void initNewCampaign(const StartInfo &si);
void mapConquered(const std::vector<CGHeroInstance*> & heroes);
boost::optional<CScenarioTravel::STravelBonus> getBonusForCurrentMap() const;
const CCampaignScenario &getCurrentScenario() const;
ui8 currentBonusID() const;