mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-01 00:45:26 +02:00
- Fixed bug when the type id of the hero placeholder is the same as a already placed hero or prisoned hero
This commit is contained in:
@ -1127,13 +1127,55 @@ void CGameState::placeCampaignHeroes()
|
|||||||
const auto campaignHeroReplacements = generateCampaignHeroesToReplace(crossoverHeroes);
|
const auto campaignHeroReplacements = generateCampaignHeroesToReplace(crossoverHeroes);
|
||||||
|
|
||||||
// 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
|
||||||
/*for(auto & campaignHeroReplacement : campaignHeroReplacement)
|
// INFO: we will remove heroes because later it may be possible that the API doesn't allow having heroes
|
||||||
|
// with the same hero type id
|
||||||
|
std::vector<CGHeroInstance *> removedHeroes;
|
||||||
|
|
||||||
|
for(auto & campaignHeroReplacement : campaignHeroReplacements)
|
||||||
{
|
{
|
||||||
campaignHeroReplacement.first->subID
|
auto hero = getUsedHero(HeroTypeID(campaignHeroReplacement.first->subID));
|
||||||
}*/
|
if(hero)
|
||||||
|
{
|
||||||
|
removedHeroes.push_back(hero);
|
||||||
|
map->heroesOnMap -= hero;
|
||||||
|
map->objects[hero->id.getNum()] = nullptr;
|
||||||
|
map->removeBlockVisTiles(hero, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logGlobal->debugStream() << "\tReplace placeholders with heroes";
|
logGlobal->debugStream() << "\tReplace placeholders with heroes";
|
||||||
replaceHeroesPlaceholders(campaignHeroReplacements);
|
replaceHeroesPlaceholders(campaignHeroReplacements);
|
||||||
|
|
||||||
|
// now add removed heroes again with unused type ID
|
||||||
|
for(auto hero : removedHeroes)
|
||||||
|
{
|
||||||
|
si32 heroTypeId = 0;
|
||||||
|
if(hero->ID == Obj::HERO)
|
||||||
|
{
|
||||||
|
heroTypeId = pickUnusedHeroTypeRandomly(hero->tempOwner);
|
||||||
|
}
|
||||||
|
else if(hero->ID == Obj::PRISON)
|
||||||
|
{
|
||||||
|
auto unusedHeroTypeIds = getUnusedAllowedHeroes();
|
||||||
|
if(!unusedHeroTypeIds.empty())
|
||||||
|
{
|
||||||
|
heroTypeId = std::next(unusedHeroTypeIds.begin(), ran() % unusedHeroTypeIds.size())->getNum();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logGlobal->errorStream() << "No free hero type ID found to replace prison.";
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(0); // should not happen
|
||||||
|
}
|
||||||
|
|
||||||
|
hero->subID = heroTypeId;
|
||||||
|
hero->portrait = hero->subID;
|
||||||
|
map->getEditManager()->insertObject(hero, hero->pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1143,7 +1185,7 @@ void CGameState::placeStartingHero(PlayerColor playerColor, HeroTypeID heroTypeI
|
|||||||
townPos.x += 1;
|
townPos.x += 1;
|
||||||
|
|
||||||
CGHeroInstance * hero = static_cast<CGHeroInstance*>(createObject(Obj::HERO, heroTypeId.getNum(), townPos, playerColor));
|
CGHeroInstance * hero = static_cast<CGHeroInstance*>(createObject(Obj::HERO, heroTypeId.getNum(), townPos, playerColor));
|
||||||
hero->initHero();
|
hero->initHeroDefInfo();
|
||||||
map->getEditManager()->insertObject(hero, townPos);
|
map->getEditManager()->insertObject(hero, townPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2721,7 +2763,8 @@ std::vector<std::pair<CGHeroInstance*, ObjectInstanceID> > CGameState::generateC
|
|||||||
if(!found)
|
if(!found)
|
||||||
{
|
{
|
||||||
auto nh = new CGHeroInstance();
|
auto nh = new CGHeroInstance();
|
||||||
nh->initHero(HeroTypeID(hp->subID));
|
nh->subID = hp->subID;
|
||||||
|
nh->initHeroDefInfo();
|
||||||
campaignHeroReplacements.push_back(std::make_pair(nh, gid));
|
campaignHeroReplacements.push_back(std::make_pair(nh, gid));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2803,22 +2846,33 @@ 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);
|
||||||
|
|
||||||
//const auto & travelOptions = scenarioOps->campState->getCurrentScenario().travelOptions;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGameState::isUsedHero(HeroTypeID hid) const
|
bool CGameState::isUsedHero(HeroTypeID hid) const
|
||||||
|
{
|
||||||
|
return getUsedHero(hid);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGHeroInstance * CGameState::getUsedHero(HeroTypeID hid) const
|
||||||
{
|
{
|
||||||
for(auto hero : map->heroesOnMap) //heroes instances initialization
|
for(auto hero : map->heroesOnMap) //heroes instances initialization
|
||||||
|
{
|
||||||
if(hero->subID == hid.getNum())
|
if(hero->subID == hid.getNum())
|
||||||
return true;
|
{
|
||||||
|
return hero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(auto obj : map->objects) //prisons
|
for(auto obj : map->objects) //prisons
|
||||||
if(obj && obj->ID == Obj::PRISON && obj->subID == hid.getNum())
|
{
|
||||||
return true;
|
if(obj && obj->ID == Obj::PRISON && obj->subID == hid.getNum())
|
||||||
|
{
|
||||||
|
return dynamic_cast<CGHeroInstance *>(obj.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGPathNode::CGPathNode()
|
CGPathNode::CGPathNode()
|
||||||
|
@ -498,6 +498,7 @@ private:
|
|||||||
|
|
||||||
// ---- misc helpers -----
|
// ---- misc helpers -----
|
||||||
|
|
||||||
|
CGHeroInstance * getUsedHero(HeroTypeID hid) const;
|
||||||
bool isUsedHero(HeroTypeID hid) const; //looks in heroes and prisons
|
bool isUsedHero(HeroTypeID hid) const; //looks in heroes and prisons
|
||||||
std::set<HeroTypeID> getUnusedAllowedHeroes(bool alsoIncludeNotAllowed = false) const;
|
std::set<HeroTypeID> getUnusedAllowedHeroes(bool alsoIncludeNotAllowed = false) const;
|
||||||
std::pair<Obj,int> pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns <type, subtype>
|
std::pair<Obj,int> pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns <type, subtype>
|
||||||
|
Reference in New Issue
Block a user