mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-23 22:37:55 +02:00
Formatting & cleanup
This commit is contained in:
@@ -68,59 +68,55 @@ CrossoverHeroesList CGameStateCampaign::getCrossoverHeroesFromPreviousScenarios(
|
|||||||
auto * h = CCampaignState::crossoverDeserialize(node);
|
auto * h = CCampaignState::crossoverDeserialize(node);
|
||||||
heroes.push_back(h);
|
heroes.push_back(h);
|
||||||
}
|
}
|
||||||
crossoverHeroes.heroesFromAnyPreviousScenarios = crossoverHeroes.heroesFromPreviousScenario = heroes;
|
crossoverHeroes.heroesFromAnyPreviousScenarios = heroes;
|
||||||
|
crossoverHeroes.heroesFromPreviousScenario = heroes;
|
||||||
|
|
||||||
|
return crossoverHeroes;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if(campaignState->mapsConquered.empty())
|
||||||
|
return crossoverHeroes;
|
||||||
|
|
||||||
|
for(auto mapNr : campaignState->mapsConquered)
|
||||||
{
|
{
|
||||||
if(!campaignState->mapsConquered.empty())
|
// 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)
|
||||||
{
|
{
|
||||||
std::vector<CGHeroInstance *> heroes = {};
|
// auto hero = CCampaignState::crossoverDeserialize(node);
|
||||||
|
vstd::erase_if(crossoverHeroes.heroesFromAnyPreviousScenarios, [hero](CGHeroInstance * h)
|
||||||
crossoverHeroes.heroesFromAnyPreviousScenarios = crossoverHeroes.heroesFromPreviousScenario = heroes;
|
|
||||||
crossoverHeroes.heroesFromPreviousScenario = heroes;
|
|
||||||
|
|
||||||
for(auto mapNr : campaignState->mapsConquered)
|
|
||||||
{
|
{
|
||||||
// create a list of deleted heroes
|
return hero->subID == h->subID;
|
||||||
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
|
// now add heroes which completed the scenario
|
||||||
for(auto * hero : lostCrossoverHeroes)
|
for(auto node : scenario.crossoverHeroes)
|
||||||
{
|
{
|
||||||
// auto hero = CCampaignState::crossoverDeserialize(node);
|
auto * hero = CCampaignState::crossoverDeserialize(node);
|
||||||
vstd::erase_if(crossoverHeroes.heroesFromAnyPreviousScenarios, [hero](CGHeroInstance * h)
|
// add new heroes and replace old heroes with newer ones
|
||||||
{
|
auto it = range::find_if(crossoverHeroes.heroesFromAnyPreviousScenarios, [hero](CGHeroInstance * h)
|
||||||
return hero->subID == h->subID;
|
{
|
||||||
});
|
return hero->subID == h->subID;
|
||||||
}
|
});
|
||||||
|
|
||||||
// now add heroes which completed the scenario
|
if(it != crossoverHeroes.heroesFromAnyPreviousScenarios.end())
|
||||||
for(auto node : scenario.crossoverHeroes)
|
{
|
||||||
{
|
// replace old hero with newer one
|
||||||
auto * hero = CCampaignState::crossoverDeserialize(node);
|
crossoverHeroes.heroesFromAnyPreviousScenarios[it - crossoverHeroes.heroesFromAnyPreviousScenarios.begin()] = hero;
|
||||||
// add new heroes and replace old heroes with newer ones
|
}
|
||||||
auto it = range::find_if(crossoverHeroes.heroesFromAnyPreviousScenarios, [hero](CGHeroInstance * h)
|
else
|
||||||
{
|
{
|
||||||
return hero->subID == h->subID;
|
// add new hero
|
||||||
});
|
crossoverHeroes.heroesFromAnyPreviousScenarios.push_back(hero);
|
||||||
|
}
|
||||||
|
|
||||||
if(it != crossoverHeroes.heroesFromAnyPreviousScenarios.end())
|
if(mapNr == campaignState->mapsConquered.back())
|
||||||
{
|
{
|
||||||
// replace old hero with newer one
|
crossoverHeroes.heroesFromPreviousScenario.push_back(hero);
|
||||||
crossoverHeroes.heroesFromAnyPreviousScenarios[it - crossoverHeroes.heroesFromAnyPreviousScenarios.begin()] = hero;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// add new hero
|
|
||||||
crossoverHeroes.heroesFromAnyPreviousScenarios.push_back(hero);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapNr == campaignState->mapsConquered.back())
|
|
||||||
{
|
|
||||||
crossoverHeroes.heroesFromPreviousScenario.push_back(hero);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,89 +235,86 @@ void CGameStateCampaign::prepareCrossoverHeroes(std::vector<CampaignHeroReplacem
|
|||||||
|
|
||||||
void CGameStateCampaign::placeCampaignHeroes()
|
void CGameStateCampaign::placeCampaignHeroes()
|
||||||
{
|
{
|
||||||
if (gameState->scenarioOps->campState)
|
// place bonus hero
|
||||||
|
auto campaignBonus = gameState->scenarioOps->campState->getBonusForCurrentMap();
|
||||||
|
bool campaignGiveHero = campaignBonus && campaignBonus->type == CScenarioTravel::STravelBonus::HERO;
|
||||||
|
|
||||||
|
if(campaignGiveHero)
|
||||||
{
|
{
|
||||||
// place bonus hero
|
auto playerColor = PlayerColor(campaignBonus->info1);
|
||||||
auto campaignBonus = gameState->scenarioOps->campState->getBonusForCurrentMap();
|
auto it = gameState->scenarioOps->playerInfos.find(playerColor);
|
||||||
bool campaignGiveHero = campaignBonus && campaignBonus->type == CScenarioTravel::STravelBonus::HERO;
|
if(it != gameState->scenarioOps->playerInfos.end())
|
||||||
|
|
||||||
if(campaignGiveHero)
|
|
||||||
{
|
{
|
||||||
auto playerColor = PlayerColor(campaignBonus->info1);
|
auto heroTypeId = campaignBonus->info2;
|
||||||
auto it = gameState->scenarioOps->playerInfos.find(playerColor);
|
if(heroTypeId == 0xffff) // random bonus hero
|
||||||
if(it != gameState->scenarioOps->playerInfos.end())
|
|
||||||
{
|
{
|
||||||
auto heroTypeId = campaignBonus->info2;
|
heroTypeId = gameState->pickUnusedHeroTypeRandomly(playerColor);
|
||||||
if(heroTypeId == 0xffff) // random bonus hero
|
}
|
||||||
{
|
|
||||||
heroTypeId = gameState->pickUnusedHeroTypeRandomly(playerColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
gameState->placeStartingHero(playerColor, HeroTypeID(heroTypeId), gameState->map->players[playerColor.getNum()].posOfMainTown);
|
gameState->placeStartingHero(playerColor, HeroTypeID(heroTypeId), gameState->map->players[playerColor.getNum()].posOfMainTown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace heroes placeholders
|
||||||
|
auto crossoverHeroes = getCrossoverHeroesFromPreviousScenarios();
|
||||||
|
|
||||||
|
if(!crossoverHeroes.heroesFromAnyPreviousScenarios.empty())
|
||||||
|
{
|
||||||
|
logGlobal->debug("\tGenerate list of hero placeholders");
|
||||||
|
auto campaignHeroReplacements = generateCampaignHeroesToReplace(crossoverHeroes);
|
||||||
|
|
||||||
|
logGlobal->debug("\tPrepare crossover heroes");
|
||||||
|
prepareCrossoverHeroes(campaignHeroReplacements, gameState->scenarioOps->campState->getCurrentScenario().travelOptions);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// with the same hero type id
|
||||||
|
std::vector<CGHeroInstance *> removedHeroes;
|
||||||
|
|
||||||
|
for(auto & campaignHeroReplacement : campaignHeroReplacements)
|
||||||
|
{
|
||||||
|
auto * hero = gameState->getUsedHero(HeroTypeID(campaignHeroReplacement.hero->subID));
|
||||||
|
if(hero)
|
||||||
|
{
|
||||||
|
removedHeroes.push_back(hero);
|
||||||
|
gameState->map->heroesOnMap -= hero;
|
||||||
|
gameState->map->objects[hero->id.getNum()] = nullptr;
|
||||||
|
gameState->map->removeBlockVisTiles(hero, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace heroes placeholders
|
logGlobal->debug("\tReplace placeholders with heroes");
|
||||||
auto crossoverHeroes = getCrossoverHeroesFromPreviousScenarios();
|
replaceHeroesPlaceholders(campaignHeroReplacements);
|
||||||
|
|
||||||
if(!crossoverHeroes.heroesFromAnyPreviousScenarios.empty())
|
// now add removed heroes again with unused type ID
|
||||||
|
for(auto * hero : removedHeroes)
|
||||||
{
|
{
|
||||||
logGlobal->debug("\tGenerate list of hero placeholders");
|
si32 heroTypeId = 0;
|
||||||
auto campaignHeroReplacements = generateCampaignHeroesToReplace(crossoverHeroes);
|
if(hero->ID == Obj::HERO)
|
||||||
|
|
||||||
logGlobal->debug("\tPrepare crossover heroes");
|
|
||||||
prepareCrossoverHeroes(campaignHeroReplacements, gameState->scenarioOps->campState->getCurrentScenario().travelOptions);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
// with the same hero type id
|
|
||||||
std::vector<CGHeroInstance *> removedHeroes;
|
|
||||||
|
|
||||||
for(auto & campaignHeroReplacement : campaignHeroReplacements)
|
|
||||||
{
|
{
|
||||||
auto * hero = gameState->getUsedHero(HeroTypeID(campaignHeroReplacement.hero->subID));
|
heroTypeId = gameState->pickUnusedHeroTypeRandomly(hero->tempOwner);
|
||||||
if(hero)
|
|
||||||
{
|
|
||||||
removedHeroes.push_back(hero);
|
|
||||||
gameState->map->heroesOnMap -= hero;
|
|
||||||
gameState->map->objects[hero->id.getNum()] = nullptr;
|
|
||||||
gameState->map->removeBlockVisTiles(hero, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if(hero->ID == Obj::PRISON)
|
||||||
logGlobal->debug("\tReplace placeholders with heroes");
|
|
||||||
replaceHeroesPlaceholders(campaignHeroReplacements);
|
|
||||||
|
|
||||||
// now add removed heroes again with unused type ID
|
|
||||||
for(auto * hero : removedHeroes)
|
|
||||||
{
|
{
|
||||||
si32 heroTypeId = 0;
|
auto unusedHeroTypeIds = gameState->getUnusedAllowedHeroes();
|
||||||
if(hero->ID == Obj::HERO)
|
if(!unusedHeroTypeIds.empty())
|
||||||
{
|
{
|
||||||
heroTypeId = gameState->pickUnusedHeroTypeRandomly(hero->tempOwner);
|
heroTypeId = (*RandomGeneratorUtil::nextItem(unusedHeroTypeIds, gameState->getRandomGenerator())).getNum();
|
||||||
}
|
|
||||||
else if(hero->ID == Obj::PRISON)
|
|
||||||
{
|
|
||||||
auto unusedHeroTypeIds = gameState->getUnusedAllowedHeroes();
|
|
||||||
if(!unusedHeroTypeIds.empty())
|
|
||||||
{
|
|
||||||
heroTypeId = (*RandomGeneratorUtil::nextItem(unusedHeroTypeIds, gameState->getRandomGenerator())).getNum();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logGlobal->error("No free hero type ID found to replace prison.");
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(0); // should not happen
|
logGlobal->error("No free hero type ID found to replace prison.");
|
||||||
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
hero->subID = heroTypeId;
|
|
||||||
hero->portrait = hero->subID;
|
|
||||||
gameState->map->getEditManager()->insertObject(hero);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(0); // should not happen
|
||||||
|
}
|
||||||
|
|
||||||
|
hero->subID = heroTypeId;
|
||||||
|
hero->portrait = hero->subID;
|
||||||
|
gameState->map->getEditManager()->insertObject(hero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,56 +338,63 @@ void CGameStateCampaign::giveCampaignBonusToHero(CGHeroInstance * hero)
|
|||||||
if(!curBonus)
|
if(!curBonus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(curBonus->isBonusForHero())
|
assert(curBonus->isBonusForHero());
|
||||||
|
|
||||||
|
//apply bonus
|
||||||
|
switch(curBonus->type)
|
||||||
{
|
{
|
||||||
//apply bonus
|
|
||||||
switch (curBonus->type)
|
|
||||||
{
|
|
||||||
case CScenarioTravel::STravelBonus::SPELL:
|
case CScenarioTravel::STravelBonus::SPELL:
|
||||||
|
{
|
||||||
hero->addSpellToSpellbook(SpellID(curBonus->info2));
|
hero->addSpellToSpellbook(SpellID(curBonus->info2));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CScenarioTravel::STravelBonus::MONSTER:
|
case CScenarioTravel::STravelBonus::MONSTER:
|
||||||
|
{
|
||||||
|
for(int i = 0; i < GameConstants::ARMY_SIZE; i++)
|
||||||
{
|
{
|
||||||
for(int i=0; i<GameConstants::ARMY_SIZE; i++)
|
if(hero->slotEmpty(SlotID(i)))
|
||||||
{
|
{
|
||||||
if(hero->slotEmpty(SlotID(i)))
|
hero->addToSlot(SlotID(i), CreatureID(curBonus->info2), curBonus->info3);
|
||||||
{
|
break;
|
||||||
hero->addToSlot(SlotID(i), CreatureID(curBonus->info2), curBonus->info3);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CScenarioTravel::STravelBonus::ARTIFACT:
|
case CScenarioTravel::STravelBonus::ARTIFACT:
|
||||||
|
{
|
||||||
if(!gameState->giveHeroArtifact(hero, static_cast<ArtifactID>(curBonus->info2)))
|
if(!gameState->giveHeroArtifact(hero, static_cast<ArtifactID>(curBonus->info2)))
|
||||||
logGlobal->error("Cannot give starting artifact - no free slots!");
|
logGlobal->error("Cannot give starting artifact - no free slots!");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CScenarioTravel::STravelBonus::SPELL_SCROLL:
|
case CScenarioTravel::STravelBonus::SPELL_SCROLL:
|
||||||
{
|
{
|
||||||
CArtifactInstance * scroll = ArtifactUtils::createScroll(SpellID(curBonus->info2));
|
CArtifactInstance * scroll = ArtifactUtils::createScroll(SpellID(curBonus->info2));
|
||||||
const auto slot = ArtifactUtils::getArtAnyPosition(hero, scroll->getTypeId());
|
const auto slot = ArtifactUtils::getArtAnyPosition(hero, scroll->getTypeId());
|
||||||
if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
|
if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
|
||||||
scroll->putAt(ArtifactLocation(hero, slot));
|
scroll->putAt(ArtifactLocation(hero, slot));
|
||||||
else
|
else
|
||||||
logGlobal->error("Cannot give starting scroll - no free slots!");
|
logGlobal->error("Cannot give starting scroll - no free slots!");
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CScenarioTravel::STravelBonus::PRIMARY_SKILL:
|
case CScenarioTravel::STravelBonus::PRIMARY_SKILL:
|
||||||
|
{
|
||||||
|
const ui8 * ptr = reinterpret_cast<const ui8 *>(&curBonus->info2);
|
||||||
|
for(int g = 0; g < GameConstants::PRIMARY_SKILLS; ++g)
|
||||||
{
|
{
|
||||||
const ui8* ptr = reinterpret_cast<const ui8*>(&curBonus->info2);
|
int val = ptr[g];
|
||||||
for (int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
|
if(val == 0)
|
||||||
{
|
{
|
||||||
int val = ptr[g];
|
continue;
|
||||||
if (val == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto bb = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CAMPAIGN_BONUS, val, *gameState->scenarioOps->campState->currentMap, g);
|
|
||||||
hero->addNewBonus(bb);
|
|
||||||
}
|
}
|
||||||
|
auto bb = std::make_shared<Bonus>(
|
||||||
|
BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CAMPAIGN_BONUS, val, *gameState->scenarioOps->campState->currentMap, g
|
||||||
|
);
|
||||||
|
hero->addNewBonus(bb);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CScenarioTravel::STravelBonus::SECONDARY_SKILL:
|
case CScenarioTravel::STravelBonus::SECONDARY_SKILL:
|
||||||
|
{
|
||||||
hero->setSecSkillLevel(SecondarySkill(curBonus->info2), curBonus->info3, true);
|
hero->setSecSkillLevel(SecondarySkill(curBonus->info2), curBonus->info3, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ struct CampaignHeroReplacement
|
|||||||
|
|
||||||
struct CrossoverHeroesList
|
struct CrossoverHeroesList
|
||||||
{
|
{
|
||||||
std::vector<CGHeroInstance *> heroesFromPreviousScenario, heroesFromAnyPreviousScenarios;
|
std::vector<CGHeroInstance *> heroesFromPreviousScenario;
|
||||||
|
std::vector<CGHeroInstance *> heroesFromAnyPreviousScenarios;
|
||||||
void addHeroToBothLists(CGHeroInstance * hero);
|
void addHeroToBothLists(CGHeroInstance * hero);
|
||||||
void removeHeroFromBothLists(CGHeroInstance * hero);
|
void removeHeroFromBothLists(CGHeroInstance * hero);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user