mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-12 02:28:11 +02:00
Added encapsulation for CampaignState class
This commit is contained in:
parent
8420a90aa4
commit
a08fe09517
@ -210,8 +210,8 @@ void ClientCommandManager::handleConvertTextCommand()
|
|||||||
for (auto const & campaignName : campaignList)
|
for (auto const & campaignName : campaignList)
|
||||||
{
|
{
|
||||||
auto state = CampaignHandler::getCampaign(campaignName.getName());
|
auto state = CampaignHandler::getCampaign(campaignName.getName());
|
||||||
for (auto const & part : state->mapPieces)
|
for (auto const & part : state->allScenarios())
|
||||||
state->getMap(part.first);
|
state->getMap(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
VLC->generaltexth->dumpAllTexts();
|
VLC->generaltexth->dumpAllTexts();
|
||||||
|
@ -51,10 +51,10 @@ void UserEventHandler::handleUserEvent(const SDL_UserEvent & user)
|
|||||||
CSH->campaignServerRestartLock.set(true);
|
CSH->campaignServerRestartLock.set(true);
|
||||||
CSH->endGameplay();
|
CSH->endGameplay();
|
||||||
auto ourCampaign = std::shared_ptr<CampaignState>(reinterpret_cast<CampaignState *>(user.data1));
|
auto ourCampaign = std::shared_ptr<CampaignState>(reinterpret_cast<CampaignState *>(user.data1));
|
||||||
auto & epilogue = ourCampaign->scenarios[ourCampaign->mapsConquered.back()].epilog;
|
auto & epilogue = ourCampaign->scenario(*ourCampaign->lastScenario()).epilog;
|
||||||
auto finisher = [=]()
|
auto finisher = [=]()
|
||||||
{
|
{
|
||||||
if(!ourCampaign->mapsRemaining.empty())
|
if(!ourCampaign->isCampaignFinished())
|
||||||
{
|
{
|
||||||
GH.windows().pushWindow(CMM);
|
GH.windows().pushWindow(CMM);
|
||||||
GH.windows().pushWindow(CMM->menu);
|
GH.windows().pushWindow(CMM->menu);
|
||||||
|
@ -64,7 +64,7 @@ CBonusSelection::CBonusSelection()
|
|||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||||
|
|
||||||
std::string bgName = getCampaign()->header.campaignRegions.campPrefix + "_BG.BMP";
|
std::string bgName = getCampaign()->getHeader().campaignRegions.campPrefix + "_BG.BMP";
|
||||||
setBackground(bgName);
|
setBackground(bgName);
|
||||||
|
|
||||||
panelBackground = std::make_shared<CPicture>("CAMPBRF.BMP", 456, 6);
|
panelBackground = std::make_shared<CPicture>("CAMPBRF.BMP", 456, 6);
|
||||||
@ -78,7 +78,7 @@ CBonusSelection::CBonusSelection()
|
|||||||
iconsMapSizes = std::make_shared<CAnimImage>("SCNRMPSZ", 4, 0, 735, 26);
|
iconsMapSizes = std::make_shared<CAnimImage>("SCNRMPSZ", 4, 0, 735, 26);
|
||||||
|
|
||||||
labelCampaignDescription = std::make_shared<CLabel>(481, 63, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, CGI->generaltexth->allTexts[38]);
|
labelCampaignDescription = std::make_shared<CLabel>(481, 63, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, CGI->generaltexth->allTexts[38]);
|
||||||
campaignDescription = std::make_shared<CTextBox>(getCampaign()->header.description, Rect(480, 86, 286, 117), 1);
|
campaignDescription = std::make_shared<CTextBox>(getCampaign()->getHeader().description, Rect(480, 86, 286, 117), 1);
|
||||||
|
|
||||||
mapName = std::make_shared<CLabel>(481, 219, FONT_BIG, ETextAlignment::TOPLEFT, Colors::YELLOW, CSH->mi->getName());
|
mapName = std::make_shared<CLabel>(481, 219, FONT_BIG, ETextAlignment::TOPLEFT, Colors::YELLOW, CSH->mi->getName());
|
||||||
labelMapDescription = std::make_shared<CLabel>(481, 253, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, CGI->generaltexth->allTexts[496]);
|
labelMapDescription = std::make_shared<CLabel>(481, 253, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, CGI->generaltexth->allTexts[496]);
|
||||||
@ -99,27 +99,25 @@ CBonusSelection::CBonusSelection()
|
|||||||
difficultyIcons[b] = std::make_shared<CAnimImage>("GSPBUT" + std::to_string(b + 3) + ".DEF", 0, 0, 709, 455);
|
difficultyIcons[b] = std::make_shared<CAnimImage>("GSPBUT" + std::to_string(b + 3) + ".DEF", 0, 0, 709, 455);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getCampaign()->header.difficultyChoosenByPlayer)
|
if(getCampaign()->getHeader().difficultyChoosenByPlayer)
|
||||||
{
|
{
|
||||||
buttonDifficultyLeft = std::make_shared<CButton>(Point(694, 508), "SCNRBLF.DEF", CButton::tooltip(), std::bind(&CBonusSelection::decreaseDifficulty, this));
|
buttonDifficultyLeft = std::make_shared<CButton>(Point(694, 508), "SCNRBLF.DEF", CButton::tooltip(), std::bind(&CBonusSelection::decreaseDifficulty, this));
|
||||||
buttonDifficultyRight = std::make_shared<CButton>(Point(738, 508), "SCNRBRT.DEF", CButton::tooltip(), std::bind(&CBonusSelection::increaseDifficulty, this));
|
buttonDifficultyRight = std::make_shared<CButton>(Point(738, 508), "SCNRBRT.DEF", CButton::tooltip(), std::bind(&CBonusSelection::increaseDifficulty, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int g = 0; g < getCampaign()->scenarios.size(); ++g)
|
for(auto scenarioID : getCampaign()->allScenarios())
|
||||||
{
|
{
|
||||||
auto scenarioID = static_cast<CampaignScenarioID>(g);
|
if(getCampaign()->isAvailable(scenarioID))
|
||||||
|
regions.push_back(std::make_shared<CRegion>(scenarioID, true, true, getCampaign()->getHeader().campaignRegions));
|
||||||
if(getCampaign()->conquerable(scenarioID))
|
else if(getCampaign()->isConquered(scenarioID)) //display as striped
|
||||||
regions.push_back(std::make_shared<CRegion>(scenarioID, true, true, getCampaign()->header.campaignRegions));
|
regions.push_back(std::make_shared<CRegion>(scenarioID, false, false, getCampaign()->getHeader().campaignRegions));
|
||||||
else if(getCampaign()->scenarios[scenarioID].conquered) //display as striped
|
|
||||||
regions.push_back(std::make_shared<CRegion>(scenarioID, false, false, getCampaign()->header.campaignRegions));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBonusSelection::createBonusesIcons()
|
void CBonusSelection::createBonusesIcons()
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||||
const CampaignScenario & scenario = getCampaign()->scenarios[CSH->campaignMap];
|
const CampaignScenario & scenario = getCampaign()->scenario(CSH->campaignMap);
|
||||||
const std::vector<CampaignBonus> & bonDescs = scenario.travelOptions.bonusesToChoose;
|
const std::vector<CampaignBonus> & bonDescs = scenario.travelOptions.bonusesToChoose;
|
||||||
groupBonuses = std::make_shared<CToggleGroup>(std::bind(&IServerAPI::setCampaignBonus, CSH, _1));
|
groupBonuses = std::make_shared<CToggleGroup>(std::bind(&IServerAPI::setCampaignBonus, CSH, _1));
|
||||||
|
|
||||||
@ -172,7 +170,7 @@ void CBonusSelection::createBonusesIcons()
|
|||||||
assert(faction != -1);
|
assert(faction != -1);
|
||||||
|
|
||||||
BuildingID buildID;
|
BuildingID buildID;
|
||||||
if(getCampaign()->header.version == CampaignVersion::VCMI)
|
if(getCampaign()->getHeader().version == CampaignVersion::VCMI)
|
||||||
buildID = BuildingID(bonDescs[i].info1);
|
buildID = BuildingID(bonDescs[i].info1);
|
||||||
else
|
else
|
||||||
buildID = CBuildingHandler::campToERMU(bonDescs[i].info1, faction, std::set<BuildingID>());
|
buildID = CBuildingHandler::campToERMU(bonDescs[i].info1, faction, std::set<BuildingID>());
|
||||||
@ -272,13 +270,13 @@ void CBonusSelection::createBonusesIcons()
|
|||||||
}
|
}
|
||||||
case CampaignBonusType::HEROES_FROM_PREVIOUS_SCENARIO:
|
case CampaignBonusType::HEROES_FROM_PREVIOUS_SCENARIO:
|
||||||
{
|
{
|
||||||
auto superhero = getCampaign()->scenarios[static_cast<CampaignScenarioID>(bonDescs[i].info2)].strongestHero(PlayerColor(bonDescs[i].info1));
|
auto superhero = getCampaign()->strongestHero(static_cast<CampaignScenarioID>(bonDescs[i].info2), PlayerColor(bonDescs[i].info1));
|
||||||
if(!superhero)
|
if(!superhero)
|
||||||
logGlobal->warn("No superhero! How could it be transferred?");
|
logGlobal->warn("No superhero! How could it be transferred?");
|
||||||
picNumber = superhero ? superhero->portrait : 0;
|
picNumber = superhero ? superhero->portrait : 0;
|
||||||
desc = CGI->generaltexth->allTexts[719];
|
desc = CGI->generaltexth->allTexts[719];
|
||||||
|
|
||||||
boost::algorithm::replace_first(desc, "%s", getCampaign()->scenarios[static_cast<CampaignScenarioID>(bonDescs[i].info2)].scenarioName);
|
boost::algorithm::replace_first(desc, "%s", getCampaign()->scenario(static_cast<CampaignScenarioID>(bonDescs[i].info2)).scenarioName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,10 +311,8 @@ void CBonusSelection::createBonusesIcons()
|
|||||||
groupBonuses->addToggle(i, bonusButton);
|
groupBonuses->addToggle(i, bonusButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(vstd::contains(getCampaign()->chosenCampaignBonuses, CSH->campaignMap))
|
if(getCampaign()->getBonusID(CSH->campaignMap))
|
||||||
{
|
groupBonuses->setSelected(*getCampaign()->getBonusID(CSH->campaignMap));
|
||||||
groupBonuses->setSelected(getCampaign()->chosenCampaignBonuses[CSH->campaignMap]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBonusSelection::updateAfterStateChange()
|
void CBonusSelection::updateAfterStateChange()
|
||||||
@ -325,7 +321,7 @@ void CBonusSelection::updateAfterStateChange()
|
|||||||
{
|
{
|
||||||
buttonRestart->disable();
|
buttonRestart->disable();
|
||||||
buttonStart->enable();
|
buttonStart->enable();
|
||||||
if(!getCampaign()->mapsConquered.empty())
|
if(!getCampaign()->conqueredScenarios().empty())
|
||||||
buttonBack->block(true);
|
buttonBack->block(true);
|
||||||
else
|
else
|
||||||
buttonBack->block(false);
|
buttonBack->block(false);
|
||||||
@ -342,7 +338,7 @@ void CBonusSelection::updateAfterStateChange()
|
|||||||
}
|
}
|
||||||
if(CSH->campaignBonus == -1)
|
if(CSH->campaignBonus == -1)
|
||||||
{
|
{
|
||||||
buttonStart->block(getCampaign()->scenarios[CSH->campaignMap].travelOptions.bonusesToChoose.size());
|
buttonStart->block(getCampaign()->scenario(CSH->campaignMap).travelOptions.bonusesToChoose.size());
|
||||||
}
|
}
|
||||||
else if(buttonStart->isBlocked())
|
else if(buttonStart->isBlocked())
|
||||||
{
|
{
|
||||||
@ -398,7 +394,7 @@ void CBonusSelection::startMap()
|
|||||||
CSH->sendStartGame();
|
CSH->sendStartGame();
|
||||||
};
|
};
|
||||||
|
|
||||||
const CampaignScenario & scenario = getCampaign()->scenarios[CSH->campaignMap];
|
const CampaignScenario & scenario = getCampaign()->scenario(CSH->campaignMap);
|
||||||
if(scenario.prolog.hasPrologEpilog)
|
if(scenario.prolog.hasPrologEpilog)
|
||||||
{
|
{
|
||||||
GH.windows().createAndPushWindow<CPrologEpilogVideo>(scenario.prolog, exitCb);
|
GH.windows().createAndPushWindow<CPrologEpilogVideo>(scenario.prolog, exitCb);
|
||||||
@ -464,7 +460,7 @@ CBonusSelection::CRegion::CRegion(CampaignScenarioID id, bool accessible, bool s
|
|||||||
pos.y += desc.ypos;
|
pos.y += desc.ypos;
|
||||||
|
|
||||||
std::string prefix = campDsc.campPrefix + desc.infix + "_";
|
std::string prefix = campDsc.campPrefix + desc.infix + "_";
|
||||||
std::string suffix = colors[campDsc.colorSuffixLength - 1][CSH->si->campState->scenarios[idOfMapAndRegion].regionColor];
|
std::string suffix = colors[campDsc.colorSuffixLength - 1][CSH->si->campState->scenario(idOfMapAndRegion).regionColor];
|
||||||
graphicsNotSelected = std::make_shared<CPicture>(prefix + "En" + suffix + ".BMP");
|
graphicsNotSelected = std::make_shared<CPicture>(prefix + "En" + suffix + ".BMP");
|
||||||
graphicsNotSelected->disable();
|
graphicsNotSelected->disable();
|
||||||
graphicsSelected = std::make_shared<CPicture>(prefix + "Se" + suffix + ".BMP");
|
graphicsSelected = std::make_shared<CPicture>(prefix + "Se" + suffix + ".BMP");
|
||||||
@ -513,7 +509,7 @@ void CBonusSelection::CRegion::clickLeft(tribool down, bool previousState)
|
|||||||
void CBonusSelection::CRegion::showPopupWindow()
|
void CBonusSelection::CRegion::showPopupWindow()
|
||||||
{
|
{
|
||||||
// FIXME: For some reason "down" is only ever contain indeterminate_value
|
// FIXME: For some reason "down" is only ever contain indeterminate_value
|
||||||
auto text = CSH->si->campState->scenarios[idOfMapAndRegion].regionText;
|
auto text = CSH->si->campState->scenario(idOfMapAndRegion).regionText;
|
||||||
if(!graphicsNotSelected->getSurface()->isTransparent(GH.getCursorPosition() - pos.topLeft()) && text.size())
|
if(!graphicsNotSelected->getSurface()->isTransparent(GH.getCursorPosition() - pos.topLeft()) && text.size())
|
||||||
{
|
{
|
||||||
CRClickPopup::createAndPush(text);
|
CRClickPopup::createAndPush(text);
|
||||||
|
@ -923,7 +923,7 @@ void CCastleBuildings::enterMagesGuild()
|
|||||||
const StartInfo *si = LOCPLINT->cb->getStartInfo();
|
const StartInfo *si = LOCPLINT->cb->getStartInfo();
|
||||||
// it would be nice to find a way to move this hack to config/mapOverrides.json
|
// it would be nice to find a way to move this hack to config/mapOverrides.json
|
||||||
if(si && si->campState && si->campState && // We're in campaign,
|
if(si && si->campState && si->campState && // We're in campaign,
|
||||||
(si->campState->header.filename == "DATA/YOG.H3C") && // which is "Birth of a Barbarian",
|
(si->campState->getHeader().filename == "DATA/YOG.H3C") && // which is "Birth of a Barbarian",
|
||||||
(hero->subID == 45)) // and the hero is Yog (based on Solmyr)
|
(hero->subID == 45)) // and the hero is Yog (based on Solmyr)
|
||||||
{
|
{
|
||||||
// "Yog has given up magic in all its forms..."
|
// "Yog has given up magic in all its forms..."
|
||||||
|
@ -1076,21 +1076,7 @@ void PlayerEndsGame::applyGs(CGameState * gs) const
|
|||||||
// keep all heroes from the winning player
|
// keep all heroes from the winning player
|
||||||
crossoverHeroes.push_back(hero);
|
crossoverHeroes.push_back(hero);
|
||||||
}
|
}
|
||||||
else if (vstd::contains(gs->scenarioOps->campState->getCurrentScenario().keepHeroes, HeroTypeID(hero->subID)))
|
|
||||||
{
|
|
||||||
// keep hero whether lost or won (like Xeron in AB campaign)
|
|
||||||
crossoverHeroes.push_back(hero);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// keep lost heroes which are in heroes pool
|
|
||||||
for (auto & heroPair : gs->hpool.heroesPool)
|
|
||||||
{
|
|
||||||
if (vstd::contains(gs->scenarioOps->campState->getCurrentScenario().keepHeroes, HeroTypeID(heroPair.first)))
|
|
||||||
{
|
|
||||||
crossoverHeroes.push_back(heroPair.second.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gs->scenarioOps->campState->setCurrentMapAsConquered(crossoverHeroes);
|
gs->scenarioOps->campState->setCurrentMapAsConquered(crossoverHeroes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,8 +62,8 @@ PlayerSettings * StartInfo::getPlayersSettings(const ui8 connectedPlayerId)
|
|||||||
|
|
||||||
std::string StartInfo::getCampaignName() const
|
std::string StartInfo::getCampaignName() const
|
||||||
{
|
{
|
||||||
if(campState->header.name.length())
|
if(campState->getHeader().name.empty())
|
||||||
return campState->header.name;
|
return campState->getHeader().name;
|
||||||
else
|
else
|
||||||
return VLC->generaltexth->allTexts[508];
|
return VLC->generaltexth->allTexts[508];
|
||||||
}
|
}
|
||||||
|
@ -111,14 +111,6 @@ std::shared_ptr<CampaignState> CampaignHandler::getCampaign( const std::string &
|
|||||||
scenarioID++;
|
scenarioID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < ret->scenarios.size(); i++)
|
|
||||||
{
|
|
||||||
auto scenarioID = static_cast<CampaignScenarioID>(i);
|
|
||||||
|
|
||||||
if(vstd::contains(ret->mapPieces, scenarioID)) //not all maps must be present in a campaign
|
|
||||||
ret->mapsRemaining.push_back(scenarioID);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +180,6 @@ CampaignScenario CampaignHandler::readScenarioFromJson(JsonNode & reader)
|
|||||||
};
|
};
|
||||||
|
|
||||||
CampaignScenario ret;
|
CampaignScenario ret;
|
||||||
ret.conquered = false;
|
|
||||||
ret.mapName = reader["map"].String();
|
ret.mapName = reader["map"].String();
|
||||||
for(auto & g : reader["preconditions"].Vector())
|
for(auto & g : reader["preconditions"].Vector())
|
||||||
ret.preconditionRegions.insert(static_cast<CampaignScenarioID>(g.Integer()));
|
ret.preconditionRegions.insert(static_cast<CampaignScenarioID>(g.Integer()));
|
||||||
@ -428,7 +419,6 @@ CampaignScenario CampaignHandler::readScenarioFromMemory( CBinaryReader & reader
|
|||||||
};
|
};
|
||||||
|
|
||||||
CampaignScenario ret;
|
CampaignScenario ret;
|
||||||
ret.conquered = false;
|
|
||||||
ret.mapName = reader.readBaseString();
|
ret.mapName = reader.readBaseString();
|
||||||
reader.readUInt32(); //packedMapSize - not used
|
reader.readUInt32(); //packedMapSize - not used
|
||||||
if(header.numberOfScenarios > 8) //unholy alliance
|
if(header.numberOfScenarios > 8) //unholy alliance
|
||||||
|
@ -83,7 +83,12 @@ void CampaignHeader::loadLegacyData(ui8 campId)
|
|||||||
numberOfScenarios = VLC->generaltexth->getCampaignLength(campId);
|
numberOfScenarios = VLC->generaltexth->getCampaignLength(campId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CampaignState::conquerable(CampaignScenarioID whichScenario) const
|
bool CampaignState::isConquered(CampaignScenarioID whichScenario) const
|
||||||
|
{
|
||||||
|
return vstd::contains(mapsConquered, whichScenario);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CampaignState::isAvailable(CampaignScenarioID whichScenario) const
|
||||||
{
|
{
|
||||||
//check for void scenraio
|
//check for void scenraio
|
||||||
if (!scenarios.at(whichScenario).isNotVoid())
|
if (!scenarios.at(whichScenario).isNotVoid())
|
||||||
@ -91,14 +96,14 @@ bool CampaignState::conquerable(CampaignScenarioID whichScenario) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scenarios.at(whichScenario).conquered)
|
if (vstd::contains(mapsConquered, whichScenario))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//check preconditioned regions
|
//check preconditioned regions
|
||||||
for (auto const & it : scenarios.at(whichScenario).preconditionRegions)
|
for (auto const & it : scenarios.at(whichScenario).preconditionRegions)
|
||||||
{
|
{
|
||||||
if (!scenarios.at(it).conquered)
|
if (!vstd::contains(mapsConquered, it))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -109,18 +114,18 @@ bool CampaignScenario::isNotVoid() const
|
|||||||
return !mapName.empty();
|
return !mapName.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
const CGHeroInstance * CampaignScenario::strongestHero(const PlayerColor & owner)
|
const CGHeroInstance * CampaignState::strongestHero(CampaignScenarioID scenarioId, const PlayerColor & owner) const
|
||||||
{
|
{
|
||||||
std::function<bool(JsonNode & node)> isOwned = [owner](JsonNode & node)
|
std::function<bool(const JsonNode & node)> isOwned = [owner](const JsonNode & node)
|
||||||
{
|
{
|
||||||
auto * h = CampaignState::crossoverDeserialize(node);
|
auto * h = CampaignState::crossoverDeserialize(node);
|
||||||
bool result = h->tempOwner == owner;
|
bool result = h->tempOwner == owner;
|
||||||
vstd::clear_pointer(h);
|
vstd::clear_pointer(h);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
auto ownedHeroes = crossoverHeroes | boost::adaptors::filtered(isOwned);
|
auto ownedHeroes = crossover.placedHeroes.at(scenarioId) | boost::adaptors::filtered(isOwned);
|
||||||
|
|
||||||
auto i = vstd::maxElementByFun(ownedHeroes, [](JsonNode & node)
|
auto i = vstd::maxElementByFun(ownedHeroes, [](const JsonNode & node)
|
||||||
{
|
{
|
||||||
auto * h = CampaignState::crossoverDeserialize(node);
|
auto * h = CampaignState::crossoverDeserialize(node);
|
||||||
double result = h->getHeroStrength();
|
double result = h->getHeroStrength();
|
||||||
@ -130,41 +135,43 @@ const CGHeroInstance * CampaignScenario::strongestHero(const PlayerColor & owner
|
|||||||
return i == ownedHeroes.end() ? nullptr : CampaignState::crossoverDeserialize(*i);
|
return i == ownedHeroes.end() ? nullptr : CampaignState::crossoverDeserialize(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CGHeroInstance *> CampaignScenario::getLostCrossoverHeroes()
|
std::vector<CGHeroInstance *> CampaignState::getLostCrossoverHeroes(CampaignScenarioID scenarioId) const
|
||||||
{
|
{
|
||||||
std::vector<CGHeroInstance *> lostCrossoverHeroes;
|
std::vector<CGHeroInstance *> lostCrossoverHeroes;
|
||||||
if(conquered)
|
|
||||||
{
|
for(auto node2 : crossover.placedHeroes.at(scenarioId))
|
||||||
for(auto node2 : placedCrossoverHeroes)
|
|
||||||
{
|
{
|
||||||
auto * hero = CampaignState::crossoverDeserialize(node2);
|
auto * hero = CampaignState::crossoverDeserialize(node2);
|
||||||
auto it = range::find_if(crossoverHeroes, [hero](JsonNode node)
|
auto it = range::find_if(crossover.crossoverHeroes.at(scenarioId), [hero](JsonNode node)
|
||||||
{
|
{
|
||||||
auto * h = CampaignState::crossoverDeserialize(node);
|
auto * h = CampaignState::crossoverDeserialize(node);
|
||||||
bool result = hero->subID == h->subID;
|
bool result = hero->subID == h->subID;
|
||||||
vstd::clear_pointer(h);
|
vstd::clear_pointer(h);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
if(it == crossoverHeroes.end())
|
if(it == crossover.crossoverHeroes.at(scenarioId).end())
|
||||||
{
|
{
|
||||||
lostCrossoverHeroes.push_back(hero);
|
lostCrossoverHeroes.push_back(hero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return lostCrossoverHeroes;
|
return lostCrossoverHeroes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<JsonNode> CampaignState::getCrossoverHeroes(CampaignScenarioID scenarioId) const
|
||||||
|
{
|
||||||
|
return crossover.crossoverHeroes.at(scenarioId);
|
||||||
|
}
|
||||||
|
|
||||||
void CampaignState::setCurrentMapAsConquered(const std::vector<CGHeroInstance *> & heroes)
|
void CampaignState::setCurrentMapAsConquered(const std::vector<CGHeroInstance *> & heroes)
|
||||||
{
|
{
|
||||||
scenarios.at(*currentMap).crossoverHeroes.clear();
|
crossover.crossoverHeroes[*currentMap].clear();
|
||||||
for(CGHeroInstance * hero : heroes)
|
for(CGHeroInstance * hero : heroes)
|
||||||
{
|
{
|
||||||
scenarios.at(*currentMap).crossoverHeroes.push_back(crossoverSerialize(hero));
|
crossover.crossoverHeroes[*currentMap].push_back(crossoverSerialize(hero));
|
||||||
}
|
}
|
||||||
|
|
||||||
mapsConquered.push_back(*currentMap);
|
mapsConquered.push_back(*currentMap);
|
||||||
mapsRemaining -= *currentMap;
|
|
||||||
scenarios.at(*currentMap).conquered = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<CampaignBonus> CampaignState::getBonusForCurrentMap() const
|
std::optional<CampaignBonus> CampaignState::getBonusForCurrentMap() const
|
||||||
@ -183,9 +190,12 @@ const CampaignScenario & CampaignState::getCurrentScenario() const
|
|||||||
return scenarios.at(*currentMap);
|
return scenarios.at(*currentMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
CampaignScenario & CampaignState::getCurrentScenario()
|
std::optional<ui8> CampaignState::getBonusID(CampaignScenarioID & which) const
|
||||||
{
|
{
|
||||||
return scenarios.at(*currentMap);
|
if (!chosenCampaignBonuses.count(which))
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
return chosenCampaignBonuses.at(which);
|
||||||
}
|
}
|
||||||
|
|
||||||
ui8 CampaignState::currentBonusID() const
|
ui8 CampaignState::currentBonusID() const
|
||||||
@ -242,11 +252,74 @@ JsonNode CampaignState::crossoverSerialize(CGHeroInstance * hero)
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGHeroInstance * CampaignState::crossoverDeserialize(JsonNode & node)
|
CGHeroInstance * CampaignState::crossoverDeserialize(const JsonNode & node)
|
||||||
{
|
{
|
||||||
JsonDeserializer handler(nullptr, node);
|
JsonDeserializer handler(nullptr, const_cast<JsonNode&>(node));
|
||||||
auto * hero = new CGHeroInstance();
|
auto * hero = new CGHeroInstance();
|
||||||
hero->ID = Obj::HERO;
|
hero->ID = Obj::HERO;
|
||||||
hero->serializeJsonOptions(handler);
|
hero->serializeJsonOptions(handler);
|
||||||
return hero;
|
return hero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CampaignState::setCurrentMap(CampaignScenarioID which)
|
||||||
|
{
|
||||||
|
assert(scenarios.count(which));
|
||||||
|
assert(scenarios.at(which).isNotVoid());
|
||||||
|
|
||||||
|
currentMap = which;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CampaignState::setCurrentMapBonus(ui8 which)
|
||||||
|
{
|
||||||
|
chosenCampaignBonuses[*currentMap] = which;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CampaignScenarioID> CampaignState::currentScenario() const
|
||||||
|
{
|
||||||
|
return currentMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CampaignScenarioID> CampaignState::lastScenario() const
|
||||||
|
{
|
||||||
|
if (mapsConquered.empty())
|
||||||
|
return std::nullopt;
|
||||||
|
return mapsConquered.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<CampaignScenarioID> CampaignState::conqueredScenarios() const
|
||||||
|
{
|
||||||
|
std::set<CampaignScenarioID> result;
|
||||||
|
result.insert(mapsConquered.begin(), mapsConquered.end());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<CampaignScenarioID> CampaignState::allScenarios() const
|
||||||
|
{
|
||||||
|
std::set<CampaignScenarioID> result;
|
||||||
|
|
||||||
|
for (auto const & entry : scenarios)
|
||||||
|
{
|
||||||
|
if (entry.second.isNotVoid())
|
||||||
|
result.insert(entry.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CampaignScenario & CampaignState::scenario(CampaignScenarioID which) const
|
||||||
|
{
|
||||||
|
assert(scenarios.count(which));
|
||||||
|
assert(scenarios.at(which).isNotVoid());
|
||||||
|
|
||||||
|
return scenarios.at(which);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CampaignState::isCampaignFinished() const
|
||||||
|
{
|
||||||
|
return conqueredScenarios() == allScenarios();
|
||||||
|
}
|
||||||
|
|
||||||
|
const CampaignHeader & CampaignState::getHeader() const
|
||||||
|
{
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
@ -156,22 +156,15 @@ public:
|
|||||||
std::set<CampaignScenarioID> preconditionRegions; //what we need to conquer to conquer this one (stored as bitfield in h3c)
|
std::set<CampaignScenarioID> preconditionRegions; //what we need to conquer to conquer this one (stored as bitfield in h3c)
|
||||||
ui8 regionColor = 0;
|
ui8 regionColor = 0;
|
||||||
ui8 difficulty = 0;
|
ui8 difficulty = 0;
|
||||||
bool conquered = false;
|
|
||||||
|
|
||||||
std::string regionText;
|
std::string regionText;
|
||||||
CampaignScenarioPrologEpilog prolog;
|
CampaignScenarioPrologEpilog prolog;
|
||||||
CampaignScenarioPrologEpilog epilog;
|
CampaignScenarioPrologEpilog epilog;
|
||||||
|
|
||||||
CampaignTravel travelOptions;
|
CampaignTravel travelOptions;
|
||||||
std::vector<HeroTypeID> keepHeroes; // contains list of heroes which should be kept for next scenario (doesn't matter if they lost)
|
|
||||||
std::vector<JsonNode> crossoverHeroes; // contains all heroes with the same state when the campaign scenario was finished
|
|
||||||
std::vector<JsonNode> placedCrossoverHeroes; // contains all placed crossover heroes defined by hero placeholders when the scenario was started
|
|
||||||
|
|
||||||
void loadPreconditionRegions(ui32 regions);
|
void loadPreconditionRegions(ui32 regions);
|
||||||
bool isNotVoid() const;
|
bool isNotVoid() const;
|
||||||
// FIXME: due to usage of JsonNode I can't make these methods const
|
|
||||||
const CGHeroInstance * strongestHero(const PlayerColor & owner);
|
|
||||||
std::vector<CGHeroInstance *> getLostCrossoverHeroes(); /// returns a list of crossover heroes which started the scenario, but didn't complete it
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int formatVersion)
|
template <typename Handler> void serialize(Handler &h, const int formatVersion)
|
||||||
{
|
{
|
||||||
@ -180,44 +173,85 @@ public:
|
|||||||
h & preconditionRegions;
|
h & preconditionRegions;
|
||||||
h & regionColor;
|
h & regionColor;
|
||||||
h & difficulty;
|
h & difficulty;
|
||||||
h & conquered;
|
|
||||||
h & regionText;
|
h & regionText;
|
||||||
h & prolog;
|
h & prolog;
|
||||||
h & epilog;
|
h & epilog;
|
||||||
h & travelOptions;
|
h & travelOptions;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DLL_LINKAGE CampaignHeroes
|
||||||
|
{
|
||||||
|
using ScenarioHeroesList = std::vector<JsonNode>;
|
||||||
|
using CampaignHeroesList = std::map<CampaignScenarioID, ScenarioHeroesList>;
|
||||||
|
|
||||||
|
CampaignHeroesList crossoverHeroes; // contains all heroes with the same state when the campaign scenario was finished
|
||||||
|
CampaignHeroesList placedHeroes; // contains all placed crossover heroes defined by hero placeholders when the scenario was started
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int formatVersion)
|
||||||
|
{
|
||||||
h & crossoverHeroes;
|
h & crossoverHeroes;
|
||||||
h & placedCrossoverHeroes;
|
h & placedHeroes;
|
||||||
h & keepHeroes;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CampaignState
|
class DLL_LINKAGE CampaignState
|
||||||
{
|
{
|
||||||
public:
|
friend class CampaignHandler;
|
||||||
CampaignHeader header;
|
|
||||||
|
/// List of all maps completed by player, in order of their completion
|
||||||
|
std::vector<CampaignScenarioID> mapsConquered;
|
||||||
|
|
||||||
std::map<CampaignScenarioID, CampaignScenario> scenarios;
|
std::map<CampaignScenarioID, CampaignScenario> scenarios;
|
||||||
std::map<CampaignScenarioID, std::string > mapPieces; //binary h3ms, scenario number -> map data
|
std::map<CampaignScenarioID, std::string > mapPieces; //binary h3ms, scenario number -> map data
|
||||||
|
std::map<CampaignScenarioID, ui8> chosenCampaignBonuses;
|
||||||
std::vector<CampaignScenarioID> mapsConquered;
|
|
||||||
std::vector<CampaignScenarioID> mapsRemaining;
|
|
||||||
std::optional<CampaignScenarioID> currentMap;
|
std::optional<CampaignScenarioID> currentMap;
|
||||||
|
|
||||||
std::map<CampaignScenarioID, ui8> chosenCampaignBonuses;
|
CampaignHeader header;
|
||||||
|
CampaignHeroes crossover;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
std::optional<CampaignScenarioID> lastScenario() const;
|
||||||
|
std::optional<CampaignScenarioID> currentScenario() const;
|
||||||
|
std::set<CampaignScenarioID> allScenarios() const;
|
||||||
|
std::set<CampaignScenarioID> conqueredScenarios() const;
|
||||||
|
|
||||||
|
const CampaignScenario & scenario(CampaignScenarioID which) const;
|
||||||
|
|
||||||
std::optional<CampaignBonus> getBonusForCurrentMap() const;
|
std::optional<CampaignBonus> getBonusForCurrentMap() const;
|
||||||
const CampaignScenario & getCurrentScenario() const;
|
const CampaignScenario & getCurrentScenario() const;
|
||||||
|
|
||||||
|
std::optional<ui8> getBonusID(CampaignScenarioID & which) const;
|
||||||
ui8 currentBonusID() const;
|
ui8 currentBonusID() const;
|
||||||
bool conquerable(CampaignScenarioID whichScenario) const;
|
|
||||||
|
/// Returns true if selected scenario can be selected and started by player
|
||||||
|
bool isAvailable(CampaignScenarioID whichScenario) const;
|
||||||
|
|
||||||
|
/// Returns true if selected scenario has been already completed by player
|
||||||
|
bool isConquered(CampaignScenarioID whichScenario) const;
|
||||||
|
|
||||||
|
/// Returns true if all available scenarios have been completed and campaign is finished
|
||||||
|
bool isCampaignFinished() const;
|
||||||
|
|
||||||
|
const CampaignHeader & getHeader() const;
|
||||||
|
|
||||||
std::unique_ptr<CMap> getMap(CampaignScenarioID scenarioId) const;
|
std::unique_ptr<CMap> getMap(CampaignScenarioID scenarioId) const;
|
||||||
std::unique_ptr<CMapHeader> getMapHeader(CampaignScenarioID scenarioId) const;
|
std::unique_ptr<CMapHeader> getMapHeader(CampaignScenarioID scenarioId) const;
|
||||||
std::shared_ptr<CMapInfo> getMapInfo(CampaignScenarioID scenarioId) const;
|
std::shared_ptr<CMapInfo> getMapInfo(CampaignScenarioID scenarioId) const;
|
||||||
|
|
||||||
CampaignScenario & getCurrentScenario();
|
void setCurrentMap(CampaignScenarioID which);
|
||||||
|
void setCurrentMapBonus(ui8 which);
|
||||||
void setCurrentMapAsConquered(const std::vector<CGHeroInstance*> & heroes);
|
void setCurrentMapAsConquered(const std::vector<CGHeroInstance*> & heroes);
|
||||||
|
|
||||||
|
const CGHeroInstance * strongestHero(CampaignScenarioID scenarioId, const PlayerColor & owner) const;
|
||||||
|
|
||||||
|
/// returns a list of crossover heroes which started the scenario, but didn't complete it
|
||||||
|
std::vector<CGHeroInstance *> getLostCrossoverHeroes(CampaignScenarioID scenarioId) const;
|
||||||
|
|
||||||
|
std::vector<JsonNode> getCrossoverHeroes(CampaignScenarioID scenarioId) const;
|
||||||
|
|
||||||
static JsonNode crossoverSerialize(CGHeroInstance * hero);
|
static JsonNode crossoverSerialize(CGHeroInstance * hero);
|
||||||
static CGHeroInstance * crossoverDeserialize(JsonNode & node);
|
static CGHeroInstance * crossoverDeserialize(const JsonNode & node);
|
||||||
|
|
||||||
CampaignState() = default;
|
CampaignState() = default;
|
||||||
|
|
||||||
@ -225,8 +259,8 @@ public:
|
|||||||
{
|
{
|
||||||
h & header;
|
h & header;
|
||||||
h & scenarios;
|
h & scenarios;
|
||||||
|
h & crossover;
|
||||||
h & mapPieces;
|
h & mapPieces;
|
||||||
h & mapsRemaining;
|
|
||||||
h & mapsConquered;
|
h & mapsConquered;
|
||||||
h & currentMap;
|
h & currentMap;
|
||||||
h & chosenCampaignBonuses;
|
h & chosenCampaignBonuses;
|
||||||
|
@ -65,7 +65,7 @@ CrossoverHeroesList CGameStateCampaign::getCrossoverHeroesFromPreviousScenarios(
|
|||||||
auto scenarioID = static_cast<CampaignScenarioID>(bonus->info2);
|
auto scenarioID = static_cast<CampaignScenarioID>(bonus->info2);
|
||||||
|
|
||||||
std::vector<CGHeroInstance *> heroes;
|
std::vector<CGHeroInstance *> heroes;
|
||||||
for(auto & node : campaignState->scenarios.at(scenarioID).crossoverHeroes)
|
for(auto & node : campaignState->getCrossoverHeroes(scenarioID))
|
||||||
{
|
{
|
||||||
auto * h = CampaignState::crossoverDeserialize(node);
|
auto * h = CampaignState::crossoverDeserialize(node);
|
||||||
heroes.push_back(h);
|
heroes.push_back(h);
|
||||||
@ -76,14 +76,13 @@ CrossoverHeroesList CGameStateCampaign::getCrossoverHeroesFromPreviousScenarios(
|
|||||||
return crossoverHeroes;
|
return crossoverHeroes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(campaignState->mapsConquered.empty())
|
if(!campaignState->lastScenario())
|
||||||
return crossoverHeroes;
|
return crossoverHeroes;
|
||||||
|
|
||||||
for(auto mapNr : campaignState->mapsConquered)
|
for(auto mapNr : campaignState->conqueredScenarios())
|
||||||
{
|
{
|
||||||
// create a list of deleted heroes
|
// create a list of deleted heroes
|
||||||
auto & scenario = campaignState->scenarios[mapNr];
|
auto lostCrossoverHeroes = campaignState->getLostCrossoverHeroes(mapNr);
|
||||||
auto lostCrossoverHeroes = scenario.getLostCrossoverHeroes();
|
|
||||||
|
|
||||||
// remove heroes which didn't reached the end of the scenario, but were available at the start
|
// remove heroes which didn't reached the end of the scenario, but were available at the start
|
||||||
for(auto * hero : lostCrossoverHeroes)
|
for(auto * hero : lostCrossoverHeroes)
|
||||||
@ -96,7 +95,7 @@ CrossoverHeroesList CGameStateCampaign::getCrossoverHeroesFromPreviousScenarios(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now add heroes which completed the scenario
|
// now add heroes which completed the scenario
|
||||||
for(auto node : scenario.crossoverHeroes)
|
for(auto node : campaignState->getCrossoverHeroes(mapNr))
|
||||||
{
|
{
|
||||||
auto * hero = CampaignState::crossoverDeserialize(node);
|
auto * hero = CampaignState::crossoverDeserialize(node);
|
||||||
// add new heroes and replace old heroes with newer ones
|
// add new heroes and replace old heroes with newer ones
|
||||||
@ -116,7 +115,7 @@ CrossoverHeroesList CGameStateCampaign::getCrossoverHeroesFromPreviousScenarios(
|
|||||||
crossoverHeroes.heroesFromAnyPreviousScenarios.push_back(hero);
|
crossoverHeroes.heroesFromAnyPreviousScenarios.push_back(hero);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mapNr == campaignState->mapsConquered.back())
|
if(mapNr == campaignState->lastScenario())
|
||||||
{
|
{
|
||||||
crossoverHeroes.heroesFromPreviousScenario.push_back(hero);
|
crossoverHeroes.heroesFromPreviousScenario.push_back(hero);
|
||||||
}
|
}
|
||||||
@ -392,7 +391,7 @@ void CGameStateCampaign::giveCampaignBonusToHero(CGHeroInstance * hero)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto bb = std::make_shared<Bonus>(
|
auto bb = std::make_shared<Bonus>(
|
||||||
BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CAMPAIGN_BONUS, val, static_cast<int>(*gameState->scenarioOps->campState->currentMap), g
|
BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CAMPAIGN_BONUS, val, static_cast<int>(*gameState->scenarioOps->campState->currentScenario()), g
|
||||||
);
|
);
|
||||||
hero->addNewBonus(bb);
|
hero->addNewBonus(bb);
|
||||||
}
|
}
|
||||||
@ -445,8 +444,6 @@ void CGameStateCampaign::replaceHeroesPlaceholders(const std::vector<CampaignHer
|
|||||||
gameState->map->instanceNames[heroToPlace->instanceName] = heroToPlace;
|
gameState->map->instanceNames[heroToPlace->instanceName] = heroToPlace;
|
||||||
|
|
||||||
delete heroPlaceholder;
|
delete heroPlaceholder;
|
||||||
|
|
||||||
gameState->scenarioOps->campState->getCurrentScenario().placedCrossoverHeroes.push_back(CampaignState::crossoverSerialize(heroToPlace));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,7 +625,7 @@ void CGameStateCampaign::initTowns()
|
|||||||
gameState->map->towns[g]->pos == pi.posOfMainTown)
|
gameState->map->towns[g]->pos == pi.posOfMainTown)
|
||||||
{
|
{
|
||||||
BuildingID buildingId;
|
BuildingID buildingId;
|
||||||
if(gameState->scenarioOps->campState->header.version == CampaignVersion::VCMI)
|
if(gameState->scenarioOps->campState->getHeader().version == CampaignVersion::VCMI)
|
||||||
buildingId = BuildingID(chosenBonus->info1);
|
buildingId = BuildingID(chosenBonus->info1);
|
||||||
else
|
else
|
||||||
buildingId = CBuildingHandler::campToERMU(chosenBonus->info1, gameState->map->towns[g]->subID, gameState->map->towns[g]->builtBuildings);
|
buildingId = CBuildingHandler::campToERMU(chosenBonus->info1, gameState->map->towns[g]->subID, gameState->map->towns[g]->builtBuildings);
|
||||||
|
@ -296,8 +296,8 @@ bool CVCMIServer::prepareToStartGame()
|
|||||||
{
|
{
|
||||||
case StartInfo::CAMPAIGN:
|
case StartInfo::CAMPAIGN:
|
||||||
logNetwork->info("Preparing to start new campaign");
|
logNetwork->info("Preparing to start new campaign");
|
||||||
si->campState->currentMap = std::make_optional(campaignMap);
|
si->campState->setCurrentMap(campaignMap);
|
||||||
si->campState->chosenCampaignBonuses[campaignMap] = campaignBonus;
|
si->campState->setCurrentMapBonus(campaignBonus);
|
||||||
gh->init(si.get());
|
gh->init(si.get());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -668,7 +668,7 @@ void CVCMIServer::updateStartInfoOnMapChange(std::shared_ptr<CMapInfo> mapInfo,
|
|||||||
si = CMemorySerializer::deepCopy(*mi->scenarioOptionsOfSave);
|
si = CMemorySerializer::deepCopy(*mi->scenarioOptionsOfSave);
|
||||||
si->mode = StartInfo::LOAD_GAME;
|
si->mode = StartInfo::LOAD_GAME;
|
||||||
if(si->campState)
|
if(si->campState)
|
||||||
campaignMap = si->campState->currentMap.value();
|
campaignMap = si->campState->currentScenario().value();
|
||||||
|
|
||||||
for(auto & ps : si->playerInfos)
|
for(auto & ps : si->playerInfos)
|
||||||
{
|
{
|
||||||
@ -873,7 +873,7 @@ void CVCMIServer::optionNextCastle(PlayerColor player, int dir)
|
|||||||
void CVCMIServer::setCampaignMap(CampaignScenarioID mapId)
|
void CVCMIServer::setCampaignMap(CampaignScenarioID mapId)
|
||||||
{
|
{
|
||||||
campaignMap = mapId;
|
campaignMap = mapId;
|
||||||
si->difficulty = si->campState->scenarios[mapId].difficulty;
|
si->difficulty = si->campState->scenario(mapId).difficulty;
|
||||||
campaignBonus = -1;
|
campaignBonus = -1;
|
||||||
updateStartInfoOnMapChange(si->campState->getMapInfo(mapId));
|
updateStartInfoOnMapChange(si->campState->getMapInfo(mapId));
|
||||||
}
|
}
|
||||||
@ -882,7 +882,7 @@ void CVCMIServer::setCampaignBonus(int bonusId)
|
|||||||
{
|
{
|
||||||
campaignBonus = bonusId;
|
campaignBonus = bonusId;
|
||||||
|
|
||||||
const CampaignScenario & scenario = si->campState->scenarios[campaignMap];
|
const CampaignScenario & scenario = si->campState->scenario(campaignMap);
|
||||||
const std::vector<CampaignBonus> & bonDescs = scenario.travelOptions.bonusesToChoose;
|
const std::vector<CampaignBonus> & bonDescs = scenario.travelOptions.bonusesToChoose;
|
||||||
if(bonDescs[bonusId].type == CampaignBonusType::HERO)
|
if(bonDescs[bonusId].type == CampaignBonusType::HERO)
|
||||||
{
|
{
|
||||||
|
@ -211,18 +211,18 @@ void ApplyOnServerNetPackVisitor::visitLobbySetMap(LobbySetMap & pack)
|
|||||||
|
|
||||||
void ApplyOnServerNetPackVisitor::visitLobbySetCampaign(LobbySetCampaign & pack)
|
void ApplyOnServerNetPackVisitor::visitLobbySetCampaign(LobbySetCampaign & pack)
|
||||||
{
|
{
|
||||||
srv.si->mapname = pack.ourCampaign->header.filename;
|
srv.si->mapname = pack.ourCampaign->getHeader().filename;
|
||||||
srv.si->mode = StartInfo::CAMPAIGN;
|
srv.si->mode = StartInfo::CAMPAIGN;
|
||||||
srv.si->campState = pack.ourCampaign;
|
srv.si->campState = pack.ourCampaign;
|
||||||
srv.si->turnTime = 0;
|
srv.si->turnTime = 0;
|
||||||
bool isCurrentMapConquerable = pack.ourCampaign->currentMap && pack.ourCampaign->conquerable(*pack.ourCampaign->currentMap);
|
|
||||||
for(int i = 0; i < pack.ourCampaign->scenarios.size(); i++)
|
|
||||||
{
|
|
||||||
auto scenarioID = static_cast<CampaignScenarioID>(i);
|
|
||||||
|
|
||||||
if(pack.ourCampaign->conquerable(scenarioID))
|
bool isCurrentMapConquerable = pack.ourCampaign->currentScenario() && pack.ourCampaign->isAvailable(*pack.ourCampaign->currentScenario());
|
||||||
|
|
||||||
|
for(auto scenarioID : pack.ourCampaign->allScenarios())
|
||||||
{
|
{
|
||||||
if(!isCurrentMapConquerable || (isCurrentMapConquerable && scenarioID == *pack.ourCampaign->currentMap))
|
if(pack.ourCampaign->isAvailable(scenarioID))
|
||||||
|
{
|
||||||
|
if(!isCurrentMapConquerable || (isCurrentMapConquerable && scenarioID == *pack.ourCampaign->currentScenario()))
|
||||||
{
|
{
|
||||||
srv.setCampaignMap(scenarioID);
|
srv.setCampaignMap(scenarioID);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user