From 2b7e554807b59bf610081e92cd41c5f27930493d Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 23 Jun 2023 21:35:14 +0300 Subject: [PATCH] Formatting & cleanup --- lib/gameState/CGameStateCampaign.cpp | 276 +++++++++++++-------------- lib/gameState/CGameStateCampaign.h | 3 +- 2 files changed, 140 insertions(+), 139 deletions(-) diff --git a/lib/gameState/CGameStateCampaign.cpp b/lib/gameState/CGameStateCampaign.cpp index 9cdc1ae56..6d303b853 100644 --- a/lib/gameState/CGameStateCampaign.cpp +++ b/lib/gameState/CGameStateCampaign.cpp @@ -68,59 +68,55 @@ CrossoverHeroesList CGameStateCampaign::getCrossoverHeroesFromPreviousScenarios( auto * h = CCampaignState::crossoverDeserialize(node); 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 heroes = {}; - - crossoverHeroes.heroesFromAnyPreviousScenarios = crossoverHeroes.heroesFromPreviousScenario = heroes; - crossoverHeroes.heroesFromPreviousScenario = heroes; - - for(auto mapNr : campaignState->mapsConquered) + // auto hero = CCampaignState::crossoverDeserialize(node); + vstd::erase_if(crossoverHeroes.heroesFromAnyPreviousScenarios, [hero](CGHeroInstance * h) { - // create a list of deleted heroes - auto & scenario = campaignState->camp->scenarios[mapNr]; - auto lostCrossoverHeroes = scenario.getLostCrossoverHeroes(); + return hero->subID == h->subID; + }); + } - // remove heroes which didn't reached the end of the scenario, but were available at the start - for(auto * hero : lostCrossoverHeroes) - { - // auto hero = CCampaignState::crossoverDeserialize(node); - vstd::erase_if(crossoverHeroes.heroesFromAnyPreviousScenarios, [hero](CGHeroInstance * h) - { - return hero->subID == h->subID; - }); - } + // now add heroes which completed the scenario + for(auto node : scenario.crossoverHeroes) + { + auto * hero = CCampaignState::crossoverDeserialize(node); + // 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; + }); - // now add heroes which completed the scenario - for(auto node : scenario.crossoverHeroes) - { - auto * hero = CCampaignState::crossoverDeserialize(node); - // 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; - }); + if(it != crossoverHeroes.heroesFromAnyPreviousScenarios.end()) + { + // replace old hero with newer one + crossoverHeroes.heroesFromAnyPreviousScenarios[it - crossoverHeroes.heroesFromAnyPreviousScenarios.begin()] = hero; + } + else + { + // add new hero + crossoverHeroes.heroesFromAnyPreviousScenarios.push_back(hero); + } - if(it != crossoverHeroes.heroesFromAnyPreviousScenarios.end()) - { - // replace old hero with newer one - 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); - } - } + if(mapNr == campaignState->mapsConquered.back()) + { + crossoverHeroes.heroesFromPreviousScenario.push_back(hero); } } } @@ -239,89 +235,86 @@ void CGameStateCampaign::prepareCrossoverHeroes(std::vectorscenarioOps->campState) + // place bonus hero + auto campaignBonus = gameState->scenarioOps->campState->getBonusForCurrentMap(); + bool campaignGiveHero = campaignBonus && campaignBonus->type == CScenarioTravel::STravelBonus::HERO; + + if(campaignGiveHero) { - // place bonus hero - auto campaignBonus = gameState->scenarioOps->campState->getBonusForCurrentMap(); - bool campaignGiveHero = campaignBonus && campaignBonus->type == CScenarioTravel::STravelBonus::HERO; - - if(campaignGiveHero) + auto playerColor = PlayerColor(campaignBonus->info1); + auto it = gameState->scenarioOps->playerInfos.find(playerColor); + if(it != gameState->scenarioOps->playerInfos.end()) { - auto playerColor = PlayerColor(campaignBonus->info1); - auto it = gameState->scenarioOps->playerInfos.find(playerColor); - if(it != gameState->scenarioOps->playerInfos.end()) + auto heroTypeId = campaignBonus->info2; + if(heroTypeId == 0xffff) // random bonus hero { - auto heroTypeId = campaignBonus->info2; - if(heroTypeId == 0xffff) // random bonus hero - { - heroTypeId = gameState->pickUnusedHeroTypeRandomly(playerColor); - } + 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 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 - auto crossoverHeroes = getCrossoverHeroesFromPreviousScenarios(); + logGlobal->debug("\tReplace placeholders with heroes"); + 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"); - 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 removedHeroes; - - for(auto & campaignHeroReplacement : campaignHeroReplacements) + si32 heroTypeId = 0; + if(hero->ID == Obj::HERO) { - 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); - } + heroTypeId = gameState->pickUnusedHeroTypeRandomly(hero->tempOwner); } - - logGlobal->debug("\tReplace placeholders with heroes"); - replaceHeroesPlaceholders(campaignHeroReplacements); - - // now add removed heroes again with unused type ID - for(auto * hero : removedHeroes) + else if(hero->ID == Obj::PRISON) { - si32 heroTypeId = 0; - if(hero->ID == Obj::HERO) + auto unusedHeroTypeIds = gameState->getUnusedAllowedHeroes(); + if(!unusedHeroTypeIds.empty()) { - heroTypeId = gameState->pickUnusedHeroTypeRandomly(hero->tempOwner); - } - 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); - } + heroTypeId = (*RandomGeneratorUtil::nextItem(unusedHeroTypeIds, gameState->getRandomGenerator())).getNum(); } 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) return; - if(curBonus->isBonusForHero()) + assert(curBonus->isBonusForHero()); + + //apply bonus + switch(curBonus->type) { - //apply bonus - switch (curBonus->type) - { case CScenarioTravel::STravelBonus::SPELL: + { hero->addSpellToSpellbook(SpellID(curBonus->info2)); break; + } case CScenarioTravel::STravelBonus::MONSTER: + { + for(int i = 0; i < GameConstants::ARMY_SIZE; i++) { - for(int i=0; islotEmpty(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; + } case CScenarioTravel::STravelBonus::ARTIFACT: + { if(!gameState->giveHeroArtifact(hero, static_cast(curBonus->info2))) logGlobal->error("Cannot give starting artifact - no free slots!"); break; + } case CScenarioTravel::STravelBonus::SPELL_SCROLL: - { - CArtifactInstance * scroll = ArtifactUtils::createScroll(SpellID(curBonus->info2)); - const auto slot = ArtifactUtils::getArtAnyPosition(hero, scroll->getTypeId()); - if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot)) - scroll->putAt(ArtifactLocation(hero, slot)); - else - logGlobal->error("Cannot give starting scroll - no free slots!"); - } + { + CArtifactInstance * scroll = ArtifactUtils::createScroll(SpellID(curBonus->info2)); + const auto slot = ArtifactUtils::getArtAnyPosition(hero, scroll->getTypeId()); + if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot)) + scroll->putAt(ArtifactLocation(hero, slot)); + else + logGlobal->error("Cannot give starting scroll - no free slots!"); break; + } case CScenarioTravel::STravelBonus::PRIMARY_SKILL: + { + const ui8 * ptr = reinterpret_cast(&curBonus->info2); + for(int g = 0; g < GameConstants::PRIMARY_SKILLS; ++g) { - const ui8* ptr = reinterpret_cast(&curBonus->info2); - for (int g=0; g(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CAMPAIGN_BONUS, val, *gameState->scenarioOps->campState->currentMap, g); - hero->addNewBonus(bb); + continue; } + auto bb = std::make_shared( + BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CAMPAIGN_BONUS, val, *gameState->scenarioOps->campState->currentMap, g + ); + hero->addNewBonus(bb); } break; + } case CScenarioTravel::STravelBonus::SECONDARY_SKILL: + { hero->setSecSkillLevel(SecondarySkill(curBonus->info2), curBonus->info3, true); break; } diff --git a/lib/gameState/CGameStateCampaign.h b/lib/gameState/CGameStateCampaign.h index d77cf4c7d..ec996201a 100644 --- a/lib/gameState/CGameStateCampaign.h +++ b/lib/gameState/CGameStateCampaign.h @@ -27,7 +27,8 @@ struct CampaignHeroReplacement struct CrossoverHeroesList { - std::vector heroesFromPreviousScenario, heroesFromAnyPreviousScenarios; + std::vector heroesFromPreviousScenario; + std::vector heroesFromAnyPreviousScenarios; void addHeroToBothLists(CGHeroInstance * hero); void removeHeroFromBothLists(CGHeroInstance * hero); };