optional<CampaignSetup> CampaignBuilder::prepareCampaign(function<optional<RetiredGames>(CampaignType)> genRetired,
    CampaignType type, string worldName) {
  Vec2 size(17, 9);
  int numBlocked = 0.6 * size.x * size.y;
  Table<Campaign::SiteInfo> terrain = getTerrain(random, size, numBlocked);
  auto retired = genRetired(type);
  View::CampaignMenuState menuState { true, false};
  setCountLimits(options);
  const auto playerRole = getPlayerRole();
  while (1) {
    Campaign campaign(terrain, type, playerRole, worldName);
    if (auto pos = considerStaticPlayerPos(campaign)) {
      campaign.clearSite(*pos);
      setPlayerPos(campaign, *pos, avatarInfo.playerCreature->getMaxViewIdUpgrade());
    }
    placeVillains(campaign, getVillainCounts(type, options), retired, avatarInfo.tribeAlignment);
    while (1) {
      bool updateMap = false;
      campaign.influenceSize = options->getIntValue(OptionId::INFLUENCE_SIZE);
      campaign.refreshInfluencePos();
      CampaignAction action = autoConfirm(type) ? CampaignActionId::CONFIRM
          : view->prepareCampaign({
              campaign,
              (retired && type == CampaignType::FREE_PLAY) ? optional<RetiredGames&>(*retired) : none,
              avatarInfo.playerCreature.get(),
              getPrimaryOptions(),
              getSecondaryOptions(type),
              getSiteChoiceTitle(type),
              getIntroText(),
              getAvailableTypes().transform([](CampaignType t) -> View::CampaignOptions::CampaignTypeInfo {
                  return {t, getCampaignTypeDescription(t)};}),
              getMenuWarning(type)
              }, options, menuState);
      switch (action.getId()) {
        case CampaignActionId::REROLL_MAP:
          terrain = getTerrain(random, size, numBlocked);
          updateMap = true;
          break;
        case CampaignActionId::UPDATE_MAP:
          updateMap = true;
          break;
        case CampaignActionId::CHANGE_TYPE:
          type = action.get<CampaignType>();
          retired = genRetired(type);
          updateMap = true;
          break;
        case CampaignActionId::UPDATE_OPTION:
          switch (action.get<OptionId>()) {
            case OptionId::PLAYER_NAME:
            case OptionId::GENERATE_MANA:
            case OptionId::INFLUENCE_SIZE:
              break;
            default:
              updateMap = true;
              break;
          }
          break;
        case CampaignActionId::CANCEL:
          return none;
        case CampaignActionId::CHOOSE_SITE:
          if (!considerStaticPlayerPos(campaign))
            setPlayerPos(campaign, action.get<Vec2>(), avatarInfo.playerCreature->getMaxViewIdUpgrade());
          break;
        case CampaignActionId::CONFIRM:
          if (!retired || retired->getNumActive() > 0 || playerRole != PlayerRole::KEEPER ||
              retired->getAllGames().empty() ||
              view->yesOrNoPrompt("The imps are going to be sad if you don't add any retired dungeons. Continue?")) {
            string name = avatarInfo.playerCreature->getName().firstOrBare();
            string gameIdentifier = name + "_" + campaign.worldName + getNewIdSuffix();
            string gameDisplayName = name + " of " + campaign.worldName;
            return CampaignSetup{campaign, gameIdentifier, gameDisplayName,
                getIntroMessages(type)};
          }
      }
      if (updateMap)
        break;
    }
  }
}
Exemple #2
0
optional<Campaign> Campaign::prepareCampaign(View* view, Options* options, RetiredGames&& retired,
    RandomGen& random) {
  Vec2 size(16, 9);
  int numBlocked = 0.6 * size.x * size.y;
  Table<SiteInfo> terrain = getTerrain(random, size, numBlocked);
  string worldName = NameGenerator::get(NameGeneratorId::WORLD)->getNext();
  options->setDefaultString(OptionId::KEEPER_NAME, NameGenerator::get(NameGeneratorId::FIRST)->getNext());
  while (1) {
    //options->setLimits(OptionId::RETIRED_VILLAINS, 0, min<int>(retired.size(), 4)); 
    options->setLimits(OptionId::MAIN_VILLAINS, 0, 9); 
    options->setLimits(OptionId::LESSER_VILLAINS, 0, 8); 
    options->setLimits(OptionId::ALLIES, 0, 6); 
    options->setLimits(OptionId::INFLUENCE_SIZE, 3, 6); 
    int numRetired = min(retired.getNumActive(), options->getIntValue(OptionId::MAIN_VILLAINS));
    int numMain = options->getIntValue(OptionId::MAIN_VILLAINS) - numRetired;
    int numLesser = options->getIntValue(OptionId::LESSER_VILLAINS);
    int numAllies = options->getIntValue(OptionId::ALLIES);
    vector<VillainInfo> mainVillains;
    while (mainVillains.size() < numMain)
      append(mainVillains, random.permutation(getMainVillains()));
    mainVillains.resize(numMain);
    vector<VillainInfo> lesserVillains;
    while (lesserVillains.size() < numLesser)
      append(lesserVillains, random.permutation(getLesserVillains()));
    lesserVillains.resize(numLesser);
    vector<VillainInfo> allies;
    while (allies.size() < numAllies)
      append(allies, random.permutation(getAllies()));
    allies.resize(numAllies);
    Campaign campaign(terrain);
    campaign.worldName = worldName;
    vector<Vec2> freePos;
    for (Vec2 v : Rectangle(size))
      if (campaign.sites[v].canEmbark())
        freePos.push_back(v);
    for (int i : All(mainVillains)) {
      Vec2 pos = random.choose(freePos);
      removeElement(freePos, pos);
      campaign.sites[pos].dweller = mainVillains[i];
    }
    vector<RetiredGames::RetiredGame> activeGames = retired.getActiveGames();
    for (int i : Range(numRetired)) {
      Vec2 pos = random.choose(freePos);
      removeElement(freePos, pos);
      campaign.sites[pos].dweller = RetiredInfo{activeGames[i].gameInfo, activeGames[i].fileInfo};
    }
    for (int i : All(lesserVillains)) {
      Vec2 pos = random.choose(freePos);
      removeElement(freePos, pos);
      campaign.sites[pos].dweller = lesserVillains[i];
    }
    for (int i : All(allies)) {
      Vec2 pos = random.choose(freePos);
      removeElement(freePos, pos);
      campaign.sites[pos].dweller = allies[i];
    }
    while (1) {
      bool updateMap = false;
      campaign.influenceSize = options->getIntValue(OptionId::INFLUENCE_SIZE);
      campaign.refreshInfluencePos();
      CampaignAction action = view->prepareCampaign(campaign, options, retired);
      switch (action.getId()) {
        case CampaignActionId::REROLL_MAP:
            terrain = getTerrain(random, size, numBlocked);
            worldName = NameGenerator::get(NameGeneratorId::WORLD)->getNext();
            options->setDefaultString(OptionId::KEEPER_NAME, NameGenerator::get(NameGeneratorId::FIRST)->getNext());
        case CampaignActionId::UPDATE_MAP:
            updateMap = true; break;
        case CampaignActionId::UPDATE_OPTION:
            switch (action.get<OptionId>()) {
              case OptionId::KEEPER_NAME:
              case OptionId::INFLUENCE_SIZE: break;
              default: updateMap = true; break;
            }
            break;
        case CampaignActionId::CANCEL:
            return none;
        case CampaignActionId::CHOOSE_SITE:
            if (campaign.playerPos)
              campaign.clearSite(*campaign.playerPos);
            campaign.playerPos = action.get<Vec2>();
            campaign.sites[*campaign.playerPos].dweller = PlayerInfo{ViewId::KEEPER};
            break;
        case CampaignActionId::CONFIRM:
            return campaign;
      }
      if (updateMap)
        break;
    }
  }
}