mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
- fixed #1643 -> hero placeholder handling
- fixed bug when loading victory/loss conditions of the 3rd scenario in the first ROE campaign - fixed bug when loading artifacts to hero of the 3rd scenario in the first ROE campaign (due to corrupt H3M map) - implemented function object to quickly find a object by it's sub ID in a list - added netbackbase.h to header list in CMake - removed false message which said that the server loaded the map successfully
This commit is contained in:
parent
27be6a8f13
commit
d4fd361d4b
@ -326,10 +326,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
|||||||
c << ui8(2) << ui8(1); //new game; one client
|
c << ui8(2) << ui8(1); //new game; one client
|
||||||
c << *si;
|
c << *si;
|
||||||
c >> pom8;
|
c >> pom8;
|
||||||
if(pom8)
|
if(pom8) throw std::runtime_error("Server cannot open the map!");
|
||||||
throw std::runtime_error("Server cannot open the map!");
|
|
||||||
else
|
|
||||||
logNetwork->infoStream() << "Server opened map properly.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c >> si;
|
c >> si;
|
||||||
|
@ -432,6 +432,23 @@ CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, PlayerColor pl
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGameState::CrossoverHeroesList::addHeroToBothLists(CGHeroInstance * hero)
|
||||||
|
{
|
||||||
|
heroesFromPreviousScenario.push_back(hero);
|
||||||
|
heroesFromAnyPreviousScenarios.push_back(hero);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGameState::CrossoverHeroesList::removeHeroFromBothLists(CGHeroInstance * hero)
|
||||||
|
{
|
||||||
|
heroesFromPreviousScenario -= hero;
|
||||||
|
heroesFromAnyPreviousScenarios -= hero;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGameState::CampaignHeroReplacement::CampaignHeroReplacement(CGHeroInstance * hero, ObjectInstanceID heroPlaceholderId) : hero(hero), heroPlaceholderId(heroPlaceholderId)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int CGameState::pickNextHeroType(PlayerColor owner) const
|
int CGameState::pickNextHeroType(PlayerColor owner) const
|
||||||
{
|
{
|
||||||
const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(owner);
|
const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(owner);
|
||||||
@ -1104,15 +1121,15 @@ void CGameState::placeCampaignHeroes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// replace heroes placeholders
|
// replace heroes placeholders
|
||||||
auto sourceCrossoverHeroes = getCrossoverHeroesFromPreviousScenario();
|
auto crossoverHeroes = getCrossoverHeroesFromPreviousScenarios();
|
||||||
|
|
||||||
if(!sourceCrossoverHeroes.empty())
|
if(!crossoverHeroes.heroesFromAnyPreviousScenarios.empty())
|
||||||
{
|
{
|
||||||
logGlobal->debugStream() << "\tPrepare crossover heroes";
|
|
||||||
auto crossoverHeroes = prepareCrossoverHeroes(sourceCrossoverHeroes, scenarioOps->campState->getCurrentScenario().travelOptions);
|
|
||||||
|
|
||||||
logGlobal->debugStream() << "\tGenerate list of hero placeholders";
|
logGlobal->debugStream() << "\tGenerate list of hero placeholders";
|
||||||
const auto campaignHeroReplacements = generateCampaignHeroesToReplace(crossoverHeroes);
|
auto campaignHeroReplacements = generateCampaignHeroesToReplace(crossoverHeroes);
|
||||||
|
|
||||||
|
logGlobal->debugStream() << "\tPrepare crossover heroes";
|
||||||
|
prepareCrossoverHeroes(campaignHeroReplacements, scenarioOps->campState->getCurrentScenario().travelOptions);
|
||||||
|
|
||||||
// remove same heroes on the map which will be added through crossover heroes
|
// remove same heroes on the map which will be added through crossover heroes
|
||||||
// INFO: we will remove heroes because later it may be possible that the API doesn't allow having heroes
|
// INFO: we will remove heroes because later it may be possible that the API doesn't allow having heroes
|
||||||
@ -1121,7 +1138,7 @@ void CGameState::placeCampaignHeroes()
|
|||||||
|
|
||||||
for(auto & campaignHeroReplacement : campaignHeroReplacements)
|
for(auto & campaignHeroReplacement : campaignHeroReplacements)
|
||||||
{
|
{
|
||||||
auto hero = getUsedHero(HeroTypeID(campaignHeroReplacement.first->subID));
|
auto hero = getUsedHero(HeroTypeID(campaignHeroReplacement.hero->subID));
|
||||||
if(hero)
|
if(hero)
|
||||||
{
|
{
|
||||||
removedHeroes.push_back(hero);
|
removedHeroes.push_back(hero);
|
||||||
@ -1176,30 +1193,58 @@ void CGameState::placeStartingHero(PlayerColor playerColor, HeroTypeID heroTypeI
|
|||||||
map->getEditManager()->insertObject(hero, townPos);
|
map->getEditManager()->insertObject(hero, townPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CGHeroInstance *> CGameState::getCrossoverHeroesFromPreviousScenario() const
|
CGameState::CrossoverHeroesList CGameState::getCrossoverHeroesFromPreviousScenarios() const
|
||||||
{
|
{
|
||||||
std::vector<CGHeroInstance *> crossoverHeroes;
|
CrossoverHeroesList crossoverHeroes;
|
||||||
|
|
||||||
auto campaignState = scenarioOps->campState;
|
auto campaignState = scenarioOps->campState;
|
||||||
auto bonus = campaignState->getBonusForCurrentMap();
|
auto bonus = campaignState->getBonusForCurrentMap();
|
||||||
if (bonus->type == CScenarioTravel::STravelBonus::HEROES_FROM_PREVIOUS_SCENARIO)
|
if (bonus->type == CScenarioTravel::STravelBonus::HEROES_FROM_PREVIOUS_SCENARIO)
|
||||||
{
|
{
|
||||||
crossoverHeroes = campaignState->camp->scenarios[bonus->info2].crossoverHeroes;
|
crossoverHeroes.heroesFromAnyPreviousScenarios = crossoverHeroes.heroesFromPreviousScenario = campaignState->camp->scenarios[bonus->info2].crossoverHeroes;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(!campaignState->mapsConquered.empty())
|
if(!campaignState->mapsConquered.empty())
|
||||||
{
|
{
|
||||||
crossoverHeroes = campaignState->camp->scenarios[campaignState->mapsConquered.back()].crossoverHeroes;
|
crossoverHeroes.heroesFromPreviousScenario = campaignState->camp->scenarios[campaignState->mapsConquered.back()].crossoverHeroes;
|
||||||
|
|
||||||
|
for(auto mapNr : campaignState->mapsConquered)
|
||||||
|
{
|
||||||
|
// create a list of deleted heroes
|
||||||
|
auto & scenario = campaignState->camp->scenarios[mapNr];
|
||||||
|
auto lostCrossoverHeroes = scenario.getLostCrossoverHeroes();
|
||||||
|
|
||||||
|
// remove heroes which didn't reached the end of the scenario, but were available at the start
|
||||||
|
for(auto hero : lostCrossoverHeroes)
|
||||||
|
{
|
||||||
|
range::remove_if(crossoverHeroes.heroesFromAnyPreviousScenarios, CGObjectInstanceBySubIdFinder(hero));
|
||||||
|
}
|
||||||
|
|
||||||
|
// now add heroes which completed the scenario
|
||||||
|
for(auto hero : scenario.crossoverHeroes)
|
||||||
|
{
|
||||||
|
// add new heroes and replace old heroes with newer ones
|
||||||
|
range::remove_if(crossoverHeroes.heroesFromAnyPreviousScenarios, CGObjectInstanceBySubIdFinder(hero));
|
||||||
|
crossoverHeroes.heroesFromAnyPreviousScenarios.push_back(hero);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::move(crossoverHeroes);
|
return std::move(crossoverHeroes);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CGHeroInstance *> CGameState::prepareCrossoverHeroes(const std::vector<CGHeroInstance *> & sourceCrossoverHeroes, const CScenarioTravel & travelOptions)
|
void CGameState::prepareCrossoverHeroes(std::vector<CGameState::CampaignHeroReplacement> & campaignHeroReplacements, const CScenarioTravel & travelOptions) const
|
||||||
{
|
{
|
||||||
auto crossoverHeroes = sourceCrossoverHeroes; //TODO deep copy hero instances
|
//TODO deep copy hero instances
|
||||||
|
|
||||||
|
// create heroes list for convenience iterating
|
||||||
|
std::vector<CGHeroInstance *> crossoverHeroes;
|
||||||
|
for(auto & campaignHeroReplacement : campaignHeroReplacements)
|
||||||
|
{
|
||||||
|
crossoverHeroes.push_back(campaignHeroReplacement.hero);
|
||||||
|
}
|
||||||
|
|
||||||
if(!(travelOptions.whatHeroKeeps & 1))
|
if(!(travelOptions.whatHeroKeeps & 1))
|
||||||
{
|
{
|
||||||
@ -1280,8 +1325,6 @@ std::vector<CGHeroInstance *> CGameState::prepareCrossoverHeroes(const std::vect
|
|||||||
return !(travelOptions.monstersKeptByHero[crid / 8] & (1 << (crid % 8)) );
|
return !(travelOptions.monstersKeptByHero[crid / 8] & (1 << (crid % 8)) );
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::move(crossoverHeroes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameState::placeStartingHeroes()
|
void CGameState::placeStartingHeroes()
|
||||||
@ -2696,9 +2739,9 @@ std::set<HeroTypeID> CGameState::getUnusedAllowedHeroes(bool alsoIncludeNotAllow
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > CGameState::generateCampaignHeroesToReplace(std::vector<CGHeroInstance *> & crossoverHeroes)
|
std::vector<CGameState::CampaignHeroReplacement> CGameState::generateCampaignHeroesToReplace(CrossoverHeroesList & crossoverHeroes)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > campaignHeroReplacements;
|
std::vector<CampaignHeroReplacement> campaignHeroReplacements;
|
||||||
|
|
||||||
auto removeHeroPlaceholder = [this](CGHeroPlaceholder * heroPlaceholder)
|
auto removeHeroPlaceholder = [this](CGHeroPlaceholder * heroPlaceholder)
|
||||||
{
|
{
|
||||||
@ -2708,56 +2751,50 @@ std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > CGameState::generateC
|
|||||||
};
|
};
|
||||||
|
|
||||||
//selecting heroes by type
|
//selecting heroes by type
|
||||||
for(int g = 0; g < map->objects.size(); ++g)
|
for(auto obj : map->objects)
|
||||||
{
|
{
|
||||||
CGObjectInstance * obj = map->objects[g];
|
|
||||||
if(obj && obj->ID == Obj::HERO_PLACEHOLDER)
|
if(obj && obj->ID == Obj::HERO_PLACEHOLDER)
|
||||||
{
|
{
|
||||||
CGHeroPlaceholder * hp = static_cast<CGHeroPlaceholder*>(obj);
|
auto heroPlaceholder = dynamic_cast<CGHeroPlaceholder *>(obj.get());
|
||||||
|
if(heroPlaceholder->subID != 0xFF) //select by type
|
||||||
const ObjectInstanceID gid = ObjectInstanceID(g);
|
|
||||||
if(hp->subID != 0xFF) //select by type
|
|
||||||
{
|
{
|
||||||
bool found = false;
|
auto it = range::find_if(crossoverHeroes.heroesFromAnyPreviousScenarios, [heroPlaceholder](CGHeroInstance * hero)
|
||||||
for(auto ghi : crossoverHeroes)
|
|
||||||
{
|
{
|
||||||
if (ghi->subID == hp->subID)
|
return hero->subID == heroPlaceholder->subID;
|
||||||
|
});
|
||||||
|
if(it == crossoverHeroes.heroesFromAnyPreviousScenarios.end())
|
||||||
{
|
{
|
||||||
found = true;
|
removeHeroPlaceholder(heroPlaceholder);
|
||||||
campaignHeroReplacements.push_back(std::make_pair(ghi, gid));
|
|
||||||
crossoverHeroes -= ghi;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
if(!found)
|
|
||||||
{
|
{
|
||||||
removeHeroPlaceholder(hp);
|
campaignHeroReplacements.push_back(CampaignHeroReplacement(*it, obj->id));
|
||||||
|
crossoverHeroes.removeHeroFromBothLists(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//selecting heroes by power
|
//selecting heroes by power
|
||||||
std::sort(crossoverHeroes.begin(), crossoverHeroes.end(), [](const CGHeroInstance * a, const CGHeroInstance * b)
|
range::sort(crossoverHeroes.heroesFromPreviousScenario, [](const CGHeroInstance * a, const CGHeroInstance * b)
|
||||||
{
|
{
|
||||||
return a->getHeroStrength() > b->getHeroStrength();
|
return a->getHeroStrength() > b->getHeroStrength();
|
||||||
}); //sort, descending strength
|
}); //sort, descending strength
|
||||||
|
|
||||||
// sort hero placeholders descending power
|
// sort hero placeholders descending power
|
||||||
std::vector<CGHeroPlaceholder *> heroPlaceholders;
|
std::vector<CGHeroPlaceholder *> heroPlaceholders;
|
||||||
for(int g = 0; g < map->objects.size(); ++g)
|
for(auto obj : map->objects)
|
||||||
{
|
{
|
||||||
CGObjectInstance * obj = map->objects[g];
|
|
||||||
if(obj && obj->ID == Obj::HERO_PLACEHOLDER)
|
if(obj && obj->ID == Obj::HERO_PLACEHOLDER)
|
||||||
{
|
{
|
||||||
CGHeroPlaceholder * hp = dynamic_cast<CGHeroPlaceholder*>(obj);
|
auto heroPlaceholder = dynamic_cast<CGHeroPlaceholder *>(obj.get());
|
||||||
if(hp->subID == 0xFF) //select by power
|
if(heroPlaceholder->subID == 0xFF) //select by power
|
||||||
{
|
{
|
||||||
heroPlaceholders.push_back(hp);
|
heroPlaceholders.push_back(heroPlaceholder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(heroPlaceholders.begin(), heroPlaceholders.end(), [](const CGHeroPlaceholder * a, const CGHeroPlaceholder * b)
|
range::sort(heroPlaceholders, [](const CGHeroPlaceholder * a, const CGHeroPlaceholder * b)
|
||||||
{
|
{
|
||||||
return a->power > b->power;
|
return a->power > b->power;
|
||||||
});
|
});
|
||||||
@ -2765,9 +2802,9 @@ std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > CGameState::generateC
|
|||||||
for(int i = 0; i < heroPlaceholders.size(); ++i)
|
for(int i = 0; i < heroPlaceholders.size(); ++i)
|
||||||
{
|
{
|
||||||
auto heroPlaceholder = heroPlaceholders[i];
|
auto heroPlaceholder = heroPlaceholders[i];
|
||||||
if(crossoverHeroes.size() > i)
|
if(crossoverHeroes.heroesFromPreviousScenario.size() > i)
|
||||||
{
|
{
|
||||||
campaignHeroReplacements.push_back(std::make_pair(crossoverHeroes[i], heroPlaceholder->id));
|
campaignHeroReplacements.push_back(CampaignHeroReplacement(crossoverHeroes.heroesFromPreviousScenario[i], heroPlaceholder->id));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2778,16 +2815,16 @@ std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > CGameState::generateC
|
|||||||
return campaignHeroReplacements;
|
return campaignHeroReplacements;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameState::replaceHeroesPlaceholders(const std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > &campHeroReplacements)
|
void CGameState::replaceHeroesPlaceholders(const std::vector<CGameState::CampaignHeroReplacement> & campaignHeroReplacements)
|
||||||
{
|
{
|
||||||
for(auto obj : campHeroReplacements)
|
for(auto campaignHeroReplacement : campaignHeroReplacements)
|
||||||
{
|
{
|
||||||
CGHeroPlaceholder *placeholder = dynamic_cast<CGHeroPlaceholder*>(getObjInstance(obj.second));
|
auto heroPlaceholder = dynamic_cast<CGHeroPlaceholder*>(getObjInstance(campaignHeroReplacement.heroPlaceholderId));
|
||||||
|
|
||||||
CGHeroInstance *heroToPlace = obj.first;
|
CGHeroInstance *heroToPlace = campaignHeroReplacement.hero;
|
||||||
heroToPlace->id = obj.second;
|
heroToPlace->id = campaignHeroReplacement.heroPlaceholderId;
|
||||||
heroToPlace->tempOwner = placeholder->tempOwner;
|
heroToPlace->tempOwner = heroPlaceholder->tempOwner;
|
||||||
heroToPlace->pos = placeholder->pos;
|
heroToPlace->pos = heroPlaceholder->pos;
|
||||||
heroToPlace->type = VLC->heroh->heroes[heroToPlace->subID];
|
heroToPlace->type = VLC->heroh->heroes[heroToPlace->subID];
|
||||||
|
|
||||||
for(auto &&i : heroToPlace->stacks)
|
for(auto &&i : heroToPlace->stacks)
|
||||||
@ -2808,6 +2845,8 @@ void CGameState::replaceHeroesPlaceholders(const std::vector<std::pair<CGHeroIns
|
|||||||
map->heroesOnMap.push_back(heroToPlace);
|
map->heroesOnMap.push_back(heroToPlace);
|
||||||
map->objects[heroToPlace->id.getNum()] = heroToPlace;
|
map->objects[heroToPlace->id.getNum()] = heroToPlace;
|
||||||
map->addBlockVisTiles(heroToPlace);
|
map->addBlockVisTiles(heroToPlace);
|
||||||
|
|
||||||
|
scenarioOps->campState->getCurrentScenario().placedCrossoverHeroes.push_back(heroToPlace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,6 +460,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct CrossoverHeroesList
|
||||||
|
{
|
||||||
|
std::vector<CGHeroInstance *> heroesFromPreviousScenario, heroesFromAnyPreviousScenarios;
|
||||||
|
void addHeroToBothLists(CGHeroInstance * hero);
|
||||||
|
void removeHeroFromBothLists(CGHeroInstance * hero);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CampaignHeroReplacement
|
||||||
|
{
|
||||||
|
CampaignHeroReplacement(CGHeroInstance * hero, ObjectInstanceID heroPlaceholderId);
|
||||||
|
CGHeroInstance * hero;
|
||||||
|
ObjectInstanceID heroPlaceholderId;
|
||||||
|
};
|
||||||
|
|
||||||
// ----- initialization -----
|
// ----- initialization -----
|
||||||
|
|
||||||
void initNewGame();
|
void initNewGame();
|
||||||
@ -472,15 +486,15 @@ private:
|
|||||||
void randomizeObject(CGObjectInstance *cur);
|
void randomizeObject(CGObjectInstance *cur);
|
||||||
void initPlayerStates();
|
void initPlayerStates();
|
||||||
void placeCampaignHeroes();
|
void placeCampaignHeroes();
|
||||||
std::vector<CGHeroInstance *> getCrossoverHeroesFromPreviousScenario() const;
|
CrossoverHeroesList getCrossoverHeroesFromPreviousScenarios() const;
|
||||||
|
|
||||||
/// gets prepared and copied hero instances with crossover heroes from prev. scenario and travel options from current scenario
|
|
||||||
std::vector<CGHeroInstance *> prepareCrossoverHeroes(const std::vector<CGHeroInstance *> & sourceCrossoverHeroes, const CScenarioTravel & travelOptions);
|
|
||||||
|
|
||||||
/// returns heroes and placeholders in where heroes will be put
|
/// returns heroes and placeholders in where heroes will be put
|
||||||
std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > generateCampaignHeroesToReplace(std::vector<CGHeroInstance *> & crossoverHeroes);
|
std::vector<CampaignHeroReplacement> generateCampaignHeroesToReplace(CrossoverHeroesList & crossoverHeroes);
|
||||||
|
|
||||||
void replaceHeroesPlaceholders(const std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > &campHeroReplacements);
|
/// gets prepared and copied hero instances with crossover heroes from prev. scenario and travel options from current scenario
|
||||||
|
void prepareCrossoverHeroes(std::vector<CampaignHeroReplacement> & campaignHeroReplacements, const CScenarioTravel & travelOptions) const;
|
||||||
|
|
||||||
|
void replaceHeroesPlaceholders(const std::vector<CampaignHeroReplacement> & campaignHeroReplacements);
|
||||||
void placeStartingHeroes();
|
void placeStartingHeroes();
|
||||||
void placeStartingHero(PlayerColor playerColor, HeroTypeID heroTypeId, int3 townPos);
|
void placeStartingHero(PlayerColor playerColor, HeroTypeID heroTypeId, int3 townPos);
|
||||||
void initStartingResources();
|
void initStartingResources();
|
||||||
|
@ -94,6 +94,7 @@ set(lib_HEADERS
|
|||||||
int3.h
|
int3.h
|
||||||
Interprocess.h
|
Interprocess.h
|
||||||
NetPacks.h
|
NetPacks.h
|
||||||
|
NetPacksBase.h
|
||||||
RegisterTypes.h
|
RegisterTypes.h
|
||||||
StartInfo.h
|
StartInfo.h
|
||||||
UnlockGuard.h
|
UnlockGuard.h
|
||||||
|
@ -519,6 +519,16 @@ bool CGObjectInstance::passableFor(PlayerColor color) const
|
|||||||
return getPassableness() & 1<<color.getNum();
|
return getPassableness() & 1<<color.getNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CGObjectInstanceBySubIdFinder::CGObjectInstanceBySubIdFinder(CGObjectInstance * obj) : obj(obj)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGObjectInstanceBySubIdFinder::operator()(CGObjectInstance * obj) const
|
||||||
|
{
|
||||||
|
return this->obj->subID == obj->subID;
|
||||||
|
}
|
||||||
|
|
||||||
static int lowestSpeed(const CGHeroInstance * chi)
|
static int lowestSpeed(const CGHeroInstance * chi)
|
||||||
{
|
{
|
||||||
if(!chi->Slots().size())
|
if(!chi->Slots().size())
|
||||||
|
@ -228,6 +228,18 @@ protected:
|
|||||||
void getNameVis(std::string &hname) const;
|
void getNameVis(std::string &hname) const;
|
||||||
void giveDummyBonus(ObjectInstanceID heroID, ui8 duration = Bonus::ONE_DAY) const;
|
void giveDummyBonus(ObjectInstanceID heroID, ui8 duration = Bonus::ONE_DAY) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// function object which can be used to find an object with an specific sub ID
|
||||||
|
class CGObjectInstanceBySubIdFinder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CGObjectInstanceBySubIdFinder(CGObjectInstance * obj);
|
||||||
|
bool operator()(CGObjectInstance * obj) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CGObjectInstance * obj;
|
||||||
|
};
|
||||||
|
|
||||||
class CGHeroPlaceholder : public CGObjectInstance
|
class CGHeroPlaceholder : public CGObjectInstance
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -337,6 +337,23 @@ const CGHeroInstance * CCampaignScenario::strongestHero( PlayerColor owner ) con
|
|||||||
return i == ownedHeroes.end() ? nullptr : *i;
|
return i == ownedHeroes.end() ? nullptr : *i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<CGHeroInstance *> CCampaignScenario::getLostCrossoverHeroes() const
|
||||||
|
{
|
||||||
|
std::vector<CGHeroInstance *> lostCrossoverHeroes;
|
||||||
|
if(conquered)
|
||||||
|
{
|
||||||
|
for(auto hero : placedCrossoverHeroes)
|
||||||
|
{
|
||||||
|
auto it = range::find_if(crossoverHeroes, CGObjectInstanceBySubIdFinder(hero));
|
||||||
|
if(it == crossoverHeroes.end())
|
||||||
|
{
|
||||||
|
lostCrossoverHeroes.push_back(hero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::move(lostCrossoverHeroes);
|
||||||
|
}
|
||||||
|
|
||||||
bool CScenarioTravel::STravelBonus::isBonusForHero() const
|
bool CScenarioTravel::STravelBonus::isBonusForHero() const
|
||||||
{
|
{
|
||||||
return type == SPELL || type == MONSTER || type == ARTIFACT || type == SPELL_SCROLL || type == PRIMARY_SKILL
|
return type == SPELL || type == MONSTER || type == ARTIFACT || type == SPELL_SCROLL || type == PRIMARY_SKILL
|
||||||
@ -376,6 +393,11 @@ const CCampaignScenario & CCampaignState::getCurrentScenario() const
|
|||||||
return camp->scenarios[*currentMap];
|
return camp->scenarios[*currentMap];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCampaignScenario & CCampaignState::getCurrentScenario()
|
||||||
|
{
|
||||||
|
return camp->scenarios[*currentMap];
|
||||||
|
}
|
||||||
|
|
||||||
ui8 CCampaignState::currentBonusID() const
|
ui8 CCampaignState::currentBonusID() const
|
||||||
{
|
{
|
||||||
return chosenCampaignBonuses.at(*currentMap);
|
return chosenCampaignBonuses.at(*currentMap);
|
||||||
|
@ -109,15 +109,17 @@ public:
|
|||||||
|
|
||||||
CScenarioTravel travelOptions;
|
CScenarioTravel travelOptions;
|
||||||
std::vector<CGHeroInstance *> crossoverHeroes; // contains all heroes with the same state when the campaign scenario was finished
|
std::vector<CGHeroInstance *> crossoverHeroes; // contains all heroes with the same state when the campaign scenario was finished
|
||||||
|
std::vector<CGHeroInstance *> placedCrossoverHeroes; // contains all placed crossover heroes defined by hero placeholders when the scenario was started
|
||||||
|
|
||||||
const CGHeroInstance * strongestHero(PlayerColor owner) const;
|
const CGHeroInstance * strongestHero(PlayerColor owner) const;
|
||||||
void loadPreconditionRegions(ui32 regions);
|
void loadPreconditionRegions(ui32 regions);
|
||||||
bool isNotVoid() const;
|
bool isNotVoid() const;
|
||||||
|
std::vector<CGHeroInstance *> getLostCrossoverHeroes() const; /// 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)
|
||||||
{
|
{
|
||||||
h & mapName & scenarioName & packedMapSize & preconditionRegions & regionColor & difficulty & conquered & regionText &
|
h & mapName & scenarioName & packedMapSize & preconditionRegions & regionColor & difficulty & conquered & regionText &
|
||||||
prolog & epilog & travelOptions & crossoverHeroes;
|
prolog & epilog & travelOptions & crossoverHeroes & placedCrossoverHeroes;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -152,6 +154,7 @@ public:
|
|||||||
void setCurrentMapAsConquered(const std::vector<CGHeroInstance*> & heroes);
|
void setCurrentMapAsConquered(const std::vector<CGHeroInstance*> & heroes);
|
||||||
boost::optional<CScenarioTravel::STravelBonus> getBonusForCurrentMap() const;
|
boost::optional<CScenarioTravel::STravelBonus> getBonusForCurrentMap() const;
|
||||||
const CCampaignScenario & getCurrentScenario() const;
|
const CCampaignScenario & getCurrentScenario() const;
|
||||||
|
CCampaignScenario & getCurrentScenario();
|
||||||
ui8 currentBonusID() const;
|
ui8 currentBonusID() const;
|
||||||
|
|
||||||
CCampaignState();
|
CCampaignState();
|
||||||
|
@ -9,23 +9,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "MapFormatH3M.h"
|
|
||||||
|
|
||||||
#include <boost/crc.hpp>
|
#include <boost/crc.hpp>
|
||||||
|
|
||||||
#include "../CStopWatch.h"
|
#include "MapFormatH3M.h"
|
||||||
|
|
||||||
#include "../filesystem/Filesystem.h"
|
|
||||||
#include "CMap.h"
|
#include "CMap.h"
|
||||||
|
|
||||||
|
#include "../CStopWatch.h"
|
||||||
|
#include "../filesystem/Filesystem.h"
|
||||||
#include "../CSpellHandler.h"
|
#include "../CSpellHandler.h"
|
||||||
#include "../CCreatureHandler.h"
|
#include "../CCreatureHandler.h"
|
||||||
#include "../CGeneralTextHandler.h"
|
#include "../CGeneralTextHandler.h"
|
||||||
#include "../CHeroHandler.h"
|
#include "../CHeroHandler.h"
|
||||||
#include "../CObjectHandler.h"
|
#include "../CObjectHandler.h"
|
||||||
#include "../CDefObjInfoHandler.h"
|
#include "../CDefObjInfoHandler.h"
|
||||||
|
|
||||||
#include "../VCMI_Lib.h"
|
#include "../VCMI_Lib.h"
|
||||||
|
#include "../NetPacksBase.h"
|
||||||
|
|
||||||
|
|
||||||
const bool CMapLoaderH3M::IS_PROFILING_ENABLED = false;
|
const bool CMapLoaderH3M::IS_PROFILING_ENABLED = false;
|
||||||
@ -442,7 +440,6 @@ void CMapLoaderH3M::readVictoryLossConditions()
|
|||||||
{
|
{
|
||||||
EventCondition cond(EventCondition::CONTROL);
|
EventCondition cond(EventCondition::CONTROL);
|
||||||
cond.objectType = Obj::CREATURE_GENERATOR1; // FIXME: generators 2-4?
|
cond.objectType = Obj::CREATURE_GENERATOR1; // FIXME: generators 2-4?
|
||||||
cond.position = readInt3();
|
|
||||||
|
|
||||||
specialVictory.effect.toOtherMessage = VLC->generaltexth->allTexts[289];
|
specialVictory.effect.toOtherMessage = VLC->generaltexth->allTexts[289];
|
||||||
specialVictory.onFulfill = VLC->generaltexth->allTexts[288];
|
specialVictory.onFulfill = VLC->generaltexth->allTexts[288];
|
||||||
@ -473,7 +470,7 @@ void CMapLoaderH3M::readVictoryLossConditions()
|
|||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
//bool allowNormalVictory = reader.readBool();
|
|
||||||
// if condition is human-only turn it into following construction: AllOf(human, condition)
|
// if condition is human-only turn it into following construction: AllOf(human, condition)
|
||||||
if (!appliesToAI)
|
if (!appliesToAI)
|
||||||
{
|
{
|
||||||
@ -869,7 +866,17 @@ bool CMapLoaderH3M::loadArtifactToSlot(CGHeroInstance * hero, int slot)
|
|||||||
slot = ArtifactPosition::SPELLBOOK;
|
slot = ArtifactPosition::SPELLBOOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
hero->putArtifact(ArtifactPosition(slot), createArtifact(aid));
|
// this is needed, because some H3M maps (last scenario of ROE map) contain invalid data like misplaced artifacts
|
||||||
|
auto artifact = createArtifact(aid);
|
||||||
|
auto artifactPos = ArtifactPosition(slot);
|
||||||
|
if (artifact->canBePutAt(ArtifactLocation(hero, artifactPos)))
|
||||||
|
{
|
||||||
|
hero->putArtifact(artifactPos, artifact);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logGlobal->debugStream() << "Artifact can't be put at the specified location."; //TODO add more debugging information
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isArt;
|
return isArt;
|
||||||
|
Loading…
Reference in New Issue
Block a user