mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +02:00
Merge pull request #2973 from IvanSavenko/identifier_explicit_constructor
Improvements to type safety of Identifier class
This commit is contained in:
@@ -156,13 +156,6 @@
|
||||
{ "frame" : 152, "file" : "HPL009SH.bmp"},
|
||||
{ "frame" : 153, "file" : "HPL008SH.bmp"},
|
||||
{ "frame" : 154, "file" : "HPL001SH.bmp"},
|
||||
{ "frame" : 155, "file" : "HPL131DM.bmp"},
|
||||
{ "frame" : 156, "file" : "HPL129MK.bmp"},
|
||||
{ "frame" : 157, "file" : "HPL002SH.bmp"},
|
||||
{ "frame" : 158, "file" : "HPL132Wl.bmp"},
|
||||
{ "frame" : 159, "file" : "HPL133Nc.bmp"},
|
||||
{ "frame" : 160, "file" : "HPL134Nc.bmp"},
|
||||
{ "frame" : 161, "file" : "HPL135Wi.bmp"},
|
||||
{ "frame" : 162, "file" : "HPL136Wi.bmp"}
|
||||
{ "frame" : 155, "file" : "HPL131DM.bmp"}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -157,14 +157,7 @@
|
||||
{ "frame" : 153, "file" : "HPS008SH.bmp"},
|
||||
{ "frame" : 154, "file" : "HPS001SH.bmp"},
|
||||
{ "frame" : 155, "file" : "HPS131DM.bmp"},
|
||||
{ "frame" : 156, "file" : "HPS129MK.bmp"},
|
||||
{ "frame" : 157, "file" : "HPS002SH.bmp"},
|
||||
{ "frame" : 158, "file" : "HPS132Wl.bmp"},
|
||||
{ "frame" : 159, "file" : "HPS133Nc.bmp"},
|
||||
{ "frame" : 160, "file" : "HPS134Nc.bmp"},
|
||||
{ "frame" : 161, "file" : "HPS135Wi.bmp"},
|
||||
{ "frame" : 162, "file" : "HPS136Wi.bmp"},
|
||||
{ "frame" : 163, "file" : "HPSRAND1.bmp"}, //random hero
|
||||
{ "frame" : 164, "file" : "HPSRAND6.bmp"} //no hero
|
||||
{ "frame" : 156, "file" : "HPSRAND1.bmp"}, // random hero
|
||||
{ "frame" : 157, "file" : "HPSRAND6.bmp"} // no hero
|
||||
]
|
||||
}
|
||||
|
||||
@@ -466,7 +466,7 @@ void ClientCommandManager::giveTurn(const PlayerColor &colorIdentifier)
|
||||
{
|
||||
PlayerStartsTurn yt;
|
||||
yt.player = colorIdentifier;
|
||||
yt.queryID = -1;
|
||||
yt.queryID = QueryID::NONE;
|
||||
|
||||
ApplyClientNetPackVisitor visitor(*CSH->client, *CSH->client->gameState());
|
||||
yt.visit(visitor);
|
||||
|
||||
@@ -403,7 +403,7 @@ void ApplyClientNetPackVisitor::visitPlayerReinitInterface(PlayerReinitInterface
|
||||
if (cl.gameState()->isPlayerMakingTurn(player))
|
||||
{
|
||||
callAllInterfaces(cl, &IGameEventsReceiver::playerStartsTurn, player);
|
||||
callOnlyThatInterface(cl, player, &CGameInterface::yourTurn, -1);
|
||||
callOnlyThatInterface(cl, player, &CGameInterface::yourTurn, QueryID::NONE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -220,7 +220,7 @@ CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
movement = std::make_shared<CAnimImage>(AnimationPath::builtin("IMOBIL"), 0, 0, 0, 1);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsSmall"), hero->portrait, 0, movement->pos.w + 1);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsSmall"), hero->getIconIndex(), 0, movement->pos.w + 1);
|
||||
mana = std::make_shared<CAnimImage>(AnimationPath::builtin("IMANA"), 0, 0, movement->pos.w + portrait->pos.w + 2, 1);
|
||||
|
||||
pos.w = mana->pos.w + mana->pos.x - pos.x;
|
||||
|
||||
@@ -407,7 +407,7 @@ void HeroInfoBasicPanel::initializeData(const InfoAboutHero & hero)
|
||||
auto currentSpellPoints = hero.details->mana;
|
||||
auto maxSpellPoints = hero.details->manaLimit;
|
||||
|
||||
icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero.portrait, 0, 10, 6));
|
||||
icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero.getIconIndex(), 0, 10, 6));
|
||||
|
||||
//primary stats
|
||||
labels.push_back(std::make_shared<CLabel>(9, 75, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[380] + ":"));
|
||||
@@ -506,9 +506,9 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
|
||||
auto heroInfo = owner.cb->getBattle(br.battleID)->battleGetHeroInfo(i);
|
||||
const int xs[] = {21, 392};
|
||||
|
||||
if(heroInfo.portrait >= 0) //attacking hero
|
||||
if(heroInfo.portraitSource.isValid()) //attacking hero
|
||||
{
|
||||
icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), heroInfo.portrait, 0, xs[i], 38));
|
||||
icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), heroInfo.getIconIndex(), 0, xs[i], 38));
|
||||
sideNames[i] = heroInfo.name;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -240,7 +240,7 @@ PlayerColor InterfaceObjectConfigurable::readPlayerColor(const JsonNode & config
|
||||
{
|
||||
logGlobal->debug("Reading PlayerColor");
|
||||
if(!config.isNull() && config.isString())
|
||||
return PlayerColor::decode(config.String());
|
||||
return PlayerColor(PlayerColor::decode(config.String()));
|
||||
|
||||
logGlobal->debug("Unknown PlayerColor attribute");
|
||||
return PlayerColor::CANNOT_DETERMINE;
|
||||
|
||||
@@ -274,7 +274,7 @@ void CBonusSelection::createBonusesIcons()
|
||||
auto superhero = getCampaign()->strongestHero(static_cast<CampaignScenarioID>(bonDescs[i].info2), PlayerColor(bonDescs[i].info1));
|
||||
if(!superhero)
|
||||
logGlobal->warn("No superhero! How could it be transferred?");
|
||||
picNumber = superhero ? superhero->portrait : 0;
|
||||
picNumber = superhero ? superhero->getIconIndex() : 0;
|
||||
desc.appendLocalString(EMetaText::GENERAL_TXT, 719);
|
||||
desc.replaceRawString(getCampaign()->scenario(static_cast<CampaignScenarioID>(bonDescs[i].info2)).scenarioName.toString());
|
||||
break;
|
||||
|
||||
@@ -68,9 +68,9 @@ int ISelectionScreenInfo::getCurrentDifficulty()
|
||||
return getStartInfo()->difficulty;
|
||||
}
|
||||
|
||||
PlayerInfo ISelectionScreenInfo::getPlayerInfo(int color)
|
||||
PlayerInfo ISelectionScreenInfo::getPlayerInfo(PlayerColor color)
|
||||
{
|
||||
return getMapInfo()->mapHeader->players[color];
|
||||
return getMapInfo()->mapHeader->players[color.getNum()];
|
||||
}
|
||||
|
||||
CSelectionBase::CSelectionBase(ESelectionScreen type)
|
||||
@@ -403,8 +403,9 @@ CFlagBox::CFlagBoxTooltipBox::CFlagBoxTooltipBox(std::shared_ptr<CAnimation> ico
|
||||
labelTeamAlignment = std::make_shared<CLabel>(128, 30, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[657]);
|
||||
labelGroupTeams = std::make_shared<CLabelGroup>(FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
||||
|
||||
std::vector<std::set<ui8>> teams(PlayerColor::PLAYER_LIMIT_I);
|
||||
for(ui8 j = 0; j < PlayerColor::PLAYER_LIMIT_I; j++)
|
||||
std::vector<std::set<PlayerColor>> teams(PlayerColor::PLAYER_LIMIT_I);
|
||||
|
||||
for(PlayerColor j(0); j < PlayerColor::PLAYER_LIMIT; j++)
|
||||
{
|
||||
if(SEL->getPlayerInfo(j).canHumanPlay || SEL->getPlayerInfo(j).canComputerPlay)
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
virtual const StartInfo * getStartInfo() = 0;
|
||||
|
||||
virtual int getCurrentDifficulty();
|
||||
virtual PlayerInfo getPlayerInfo(int color);
|
||||
virtual PlayerInfo getPlayerInfo(PlayerColor color);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -291,48 +291,49 @@ size_t OptionsTab::CPlayerSettingsHelper::getImageIndex(bool big)
|
||||
WOOD = 0, ORE = 0, MITHRIL = 10, // resources unavailable in bonuses file
|
||||
|
||||
TOWN_RANDOM = 38, TOWN_NONE = 39, // Special frames in ITPA
|
||||
HERO_RANDOM = 163, HERO_NONE = 164 // Special frames in PortraitsSmall
|
||||
HERO_RANDOM = 156, HERO_NONE = 157 // Special frames in PortraitsSmall
|
||||
};
|
||||
auto factionIndex = playerSettings.castle.getNum() >= CGI->townh->size() ? 0 : playerSettings.castle.getNum();
|
||||
auto factionIndex = playerSettings.getCastleValidated();
|
||||
|
||||
switch(type)
|
||||
switch(selectionType)
|
||||
{
|
||||
case TOWN:
|
||||
switch(playerSettings.castle)
|
||||
{
|
||||
case PlayerSettings::NONE:
|
||||
{
|
||||
if (playerSettings.castle == FactionID::NONE)
|
||||
return TOWN_NONE;
|
||||
case PlayerSettings::RANDOM:
|
||||
|
||||
if (playerSettings.castle == FactionID::RANDOM)
|
||||
return TOWN_RANDOM;
|
||||
default:
|
||||
return (*CGI->townh)[factionIndex]->town->clientInfo.icons[true][false] + (big ? 0 : 2);
|
||||
}
|
||||
|
||||
return (*CGI->townh)[factionIndex]->town->clientInfo.icons[true][false] + (big ? 0 : 2);
|
||||
}
|
||||
|
||||
case HERO:
|
||||
switch(playerSettings.hero)
|
||||
{
|
||||
case PlayerSettings::NONE:
|
||||
{
|
||||
if (playerSettings.hero == HeroTypeID::NONE)
|
||||
return HERO_NONE;
|
||||
case PlayerSettings::RANDOM:
|
||||
|
||||
if (playerSettings.hero == HeroTypeID::RANDOM)
|
||||
return HERO_RANDOM;
|
||||
default:
|
||||
{
|
||||
if(playerSettings.heroPortrait != HeroTypeID::NONE)
|
||||
return playerSettings.heroPortrait;
|
||||
auto index = playerSettings.hero.getNum() >= CGI->heroh->size() ? 0 : playerSettings.hero.getNum();
|
||||
return (*CGI->heroh)[index]->imageIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if(playerSettings.heroPortrait != HeroTypeID::NONE)
|
||||
return playerSettings.heroPortrait;
|
||||
|
||||
auto index = playerSettings.getHeroValidated();
|
||||
return (*CGI->heroh)[index]->imageIndex;
|
||||
}
|
||||
|
||||
case BONUS:
|
||||
{
|
||||
switch(playerSettings.bonus)
|
||||
{
|
||||
case PlayerSettings::RANDOM:
|
||||
case PlayerStartingBonus::RANDOM:
|
||||
return RANDOM;
|
||||
case PlayerSettings::ARTIFACT:
|
||||
case PlayerStartingBonus::ARTIFACT:
|
||||
return ARTIFACT;
|
||||
case PlayerSettings::GOLD:
|
||||
case PlayerStartingBonus::GOLD:
|
||||
return GOLD;
|
||||
case PlayerSettings::RESOURCE:
|
||||
case PlayerStartingBonus::RESOURCE:
|
||||
{
|
||||
switch((*CGI->townh)[factionIndex]->town->primaryRes.toEnum())
|
||||
{
|
||||
@@ -364,7 +365,7 @@ size_t OptionsTab::CPlayerSettingsHelper::getImageIndex(bool big)
|
||||
|
||||
AnimationPath OptionsTab::CPlayerSettingsHelper::getImageName(bool big)
|
||||
{
|
||||
switch(type)
|
||||
switch(selectionType)
|
||||
{
|
||||
case OptionsTab::TOWN:
|
||||
return AnimationPath::builtin(big ? "ITPt": "ITPA");
|
||||
@@ -378,74 +379,63 @@ AnimationPath OptionsTab::CPlayerSettingsHelper::getImageName(bool big)
|
||||
|
||||
std::string OptionsTab::CPlayerSettingsHelper::getName()
|
||||
{
|
||||
switch(type)
|
||||
switch(selectionType)
|
||||
{
|
||||
case TOWN:
|
||||
{
|
||||
switch(playerSettings.castle)
|
||||
case TOWN:
|
||||
{
|
||||
case PlayerSettings::NONE:
|
||||
return CGI->generaltexth->allTexts[523];
|
||||
case PlayerSettings::RANDOM:
|
||||
return CGI->generaltexth->allTexts[522];
|
||||
default:
|
||||
{
|
||||
auto factionIndex = playerSettings.castle.getNum() >= CGI->townh->size() ? 0 : playerSettings.castle.getNum();
|
||||
if (playerSettings.castle == FactionID::NONE)
|
||||
return CGI->generaltexth->allTexts[523];
|
||||
|
||||
if (playerSettings.castle == FactionID::RANDOM)
|
||||
return CGI->generaltexth->allTexts[522];
|
||||
|
||||
auto factionIndex = playerSettings.getCastleValidated();
|
||||
return (*CGI->townh)[factionIndex]->getNameTranslated();
|
||||
}
|
||||
}
|
||||
}
|
||||
case HERO:
|
||||
{
|
||||
switch(playerSettings.hero)
|
||||
{
|
||||
case PlayerSettings::NONE:
|
||||
return CGI->generaltexth->allTexts[523];
|
||||
case PlayerSettings::RANDOM:
|
||||
return CGI->generaltexth->allTexts[522];
|
||||
default:
|
||||
case HERO:
|
||||
{
|
||||
if (playerSettings.hero == HeroTypeID::NONE)
|
||||
return CGI->generaltexth->allTexts[523];
|
||||
|
||||
if (playerSettings.hero == HeroTypeID::RANDOM)
|
||||
return CGI->generaltexth->allTexts[522];
|
||||
|
||||
if(!playerSettings.heroNameTextId.empty())
|
||||
return playerSettings.heroNameTextId;
|
||||
auto index = playerSettings.hero.getNum() >= CGI->heroh->size() ? 0 : playerSettings.hero.getNum();
|
||||
auto index = playerSettings.getHeroValidated();
|
||||
return (*CGI->heroh)[index]->getNameTranslated();
|
||||
}
|
||||
}
|
||||
}
|
||||
case BONUS:
|
||||
{
|
||||
switch(playerSettings.bonus)
|
||||
case BONUS:
|
||||
{
|
||||
case PlayerSettings::RANDOM:
|
||||
return CGI->generaltexth->allTexts[522];
|
||||
default:
|
||||
return CGI->generaltexth->arraytxt[214 + playerSettings.bonus];
|
||||
if (playerSettings.bonus == PlayerStartingBonus::RANDOM)
|
||||
return CGI->generaltexth->allTexts[522];
|
||||
|
||||
return CGI->generaltexth->arraytxt[214 + static_cast<int>(playerSettings.bonus)];
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
std::string OptionsTab::CPlayerSettingsHelper::getTitle()
|
||||
{
|
||||
switch(type)
|
||||
switch(selectionType)
|
||||
{
|
||||
case OptionsTab::TOWN:
|
||||
return (playerSettings.castle.getNum() < 0) ? CGI->generaltexth->allTexts[103] : CGI->generaltexth->allTexts[80];
|
||||
return playerSettings.castle.isValid() ? CGI->generaltexth->allTexts[80] : CGI->generaltexth->allTexts[103];
|
||||
case OptionsTab::HERO:
|
||||
return (playerSettings.hero.getNum() < 0) ? CGI->generaltexth->allTexts[101] : CGI->generaltexth->allTexts[77];
|
||||
return playerSettings.hero.isValid() ? CGI->generaltexth->allTexts[77] : CGI->generaltexth->allTexts[101];
|
||||
case OptionsTab::BONUS:
|
||||
{
|
||||
switch(playerSettings.bonus)
|
||||
{
|
||||
case PlayerSettings::RANDOM:
|
||||
case PlayerStartingBonus::RANDOM:
|
||||
return CGI->generaltexth->allTexts[86]; //{Random Bonus}
|
||||
case PlayerSettings::ARTIFACT:
|
||||
case PlayerStartingBonus::ARTIFACT:
|
||||
return CGI->generaltexth->allTexts[83]; //{Artifact Bonus}
|
||||
case PlayerSettings::GOLD:
|
||||
case PlayerStartingBonus::GOLD:
|
||||
return CGI->generaltexth->allTexts[84]; //{Gold Bonus}
|
||||
case PlayerSettings::RESOURCE:
|
||||
case PlayerStartingBonus::RESOURCE:
|
||||
return CGI->generaltexth->allTexts[85]; //{Resource Bonus}
|
||||
}
|
||||
}
|
||||
@@ -454,16 +444,16 @@ std::string OptionsTab::CPlayerSettingsHelper::getTitle()
|
||||
}
|
||||
std::string OptionsTab::CPlayerSettingsHelper::getSubtitle()
|
||||
{
|
||||
auto factionIndex = playerSettings.castle.getNum() >= CGI->townh->size() ? 0 : playerSettings.castle.getNum();
|
||||
auto heroIndex = playerSettings.hero.getNum() >= CGI->heroh->size() ? 0 : playerSettings.hero.getNum();
|
||||
auto factionIndex = playerSettings.getCastleValidated();
|
||||
auto heroIndex = playerSettings.getHeroValidated();
|
||||
|
||||
switch(type)
|
||||
switch(selectionType)
|
||||
{
|
||||
case TOWN:
|
||||
return getName();
|
||||
case HERO:
|
||||
{
|
||||
if(playerSettings.hero.getNum() >= 0)
|
||||
if(playerSettings.hero.isValid())
|
||||
return getName() + " - " + (*CGI->heroh)[heroIndex]->heroClass->getNameTranslated();
|
||||
return getName();
|
||||
}
|
||||
@@ -472,9 +462,9 @@ std::string OptionsTab::CPlayerSettingsHelper::getSubtitle()
|
||||
{
|
||||
switch(playerSettings.bonus)
|
||||
{
|
||||
case PlayerSettings::GOLD:
|
||||
case PlayerStartingBonus::GOLD:
|
||||
return CGI->generaltexth->allTexts[87]; //500-1000
|
||||
case PlayerSettings::RESOURCE:
|
||||
case PlayerStartingBonus::RESOURCE:
|
||||
{
|
||||
switch((*CGI->townh)[factionIndex]->town->primaryRes.toEnum())
|
||||
{
|
||||
@@ -498,9 +488,9 @@ std::string OptionsTab::CPlayerSettingsHelper::getSubtitle()
|
||||
|
||||
std::string OptionsTab::CPlayerSettingsHelper::getDescription()
|
||||
{
|
||||
auto factionIndex = playerSettings.castle.getNum() >= CGI->townh->size() ? 0 : playerSettings.castle.getNum();
|
||||
auto factionIndex = playerSettings.getCastleValidated();
|
||||
|
||||
switch(type)
|
||||
switch(selectionType)
|
||||
{
|
||||
case TOWN:
|
||||
return CGI->generaltexth->allTexts[104];
|
||||
@@ -510,13 +500,13 @@ std::string OptionsTab::CPlayerSettingsHelper::getDescription()
|
||||
{
|
||||
switch(playerSettings.bonus)
|
||||
{
|
||||
case PlayerSettings::RANDOM:
|
||||
case PlayerStartingBonus::RANDOM:
|
||||
return CGI->generaltexth->allTexts[94]; //Gold, wood and ore, or an artifact is randomly chosen as your starting bonus
|
||||
case PlayerSettings::ARTIFACT:
|
||||
case PlayerStartingBonus::ARTIFACT:
|
||||
return CGI->generaltexth->allTexts[90]; //An artifact is randomly chosen and equipped to your starting hero
|
||||
case PlayerSettings::GOLD:
|
||||
case PlayerStartingBonus::GOLD:
|
||||
return CGI->generaltexth->allTexts[92]; //At the start of the game, 500-1000 gold is added to your Kingdom's resource pool
|
||||
case PlayerSettings::RESOURCE:
|
||||
case PlayerStartingBonus::RESOURCE:
|
||||
{
|
||||
switch((*CGI->townh)[factionIndex]->town->primaryRes.toEnum())
|
||||
{
|
||||
@@ -543,30 +533,19 @@ OptionsTab::CPlayerOptionTooltipBox::CPlayerOptionTooltipBox(CPlayerSettingsHelp
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
int value = PlayerSettings::NONE;
|
||||
|
||||
switch(CPlayerSettingsHelper::type)
|
||||
switch(selectionType)
|
||||
{
|
||||
break;
|
||||
case TOWN:
|
||||
value = playerSettings.castle;
|
||||
break;
|
||||
case HERO:
|
||||
value = playerSettings.hero;
|
||||
break;
|
||||
case BONUS:
|
||||
value = playerSettings.bonus;
|
||||
case TOWN:
|
||||
genTownWindow();
|
||||
break;
|
||||
case HERO:
|
||||
genHeroWindow();
|
||||
break;
|
||||
case BONUS:
|
||||
genBonusWindow();
|
||||
break;
|
||||
}
|
||||
|
||||
if(value == PlayerSettings::RANDOM)
|
||||
genBonusWindow();
|
||||
else if(CPlayerSettingsHelper::type == BONUS)
|
||||
genBonusWindow();
|
||||
else if(CPlayerSettingsHelper::type == HERO)
|
||||
genHeroWindow();
|
||||
else if(CPlayerSettingsHelper::type == TOWN)
|
||||
genTownWindow();
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
@@ -585,7 +564,7 @@ void OptionsTab::CPlayerOptionTooltipBox::genTownWindow()
|
||||
pos = Rect(0, 0, 228, 290);
|
||||
genHeader();
|
||||
labelAssociatedCreatures = std::make_shared<CLabel>(pos.w / 2 + 8, 122, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[79]);
|
||||
auto factionIndex = playerSettings.castle.getNum() >= CGI->townh->size() ? 0 : playerSettings.castle.getNum();
|
||||
auto factionIndex = playerSettings.getCastleValidated();
|
||||
std::vector<std::shared_ptr<CComponent>> components;
|
||||
const CTown * town = (*CGI->townh)[factionIndex]->town;
|
||||
|
||||
@@ -602,7 +581,7 @@ void OptionsTab::CPlayerOptionTooltipBox::genHeroWindow()
|
||||
pos = Rect(0, 0, 292, 226);
|
||||
genHeader();
|
||||
labelHeroSpeciality = std::make_shared<CLabel>(pos.w / 2 + 4, 117, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[78]);
|
||||
auto heroIndex = playerSettings.hero.getNum() >= CGI->heroh->size() ? 0 : playerSettings.hero.getNum();
|
||||
auto heroIndex = playerSettings.getHeroValidated();
|
||||
|
||||
imageSpeciality = std::make_shared<CAnimImage>(AnimationPath::builtin("UN44"), (*CGI->heroh)[heroIndex]->imageIndex, 0, pos.w / 2 - 22, 134);
|
||||
labelSpecialityName = std::make_shared<CLabel>(pos.w / 2, 188, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, (*CGI->heroh)[heroIndex]->getSpecialtyNameTranslated());
|
||||
@@ -630,7 +609,7 @@ OptionsTab::SelectionWindow::SelectionWindow(PlayerColor _color, SelType _type)
|
||||
selectedFaction = initialFaction;
|
||||
selectedHero = initialHero;
|
||||
selectedBonus = initialBonus;
|
||||
allowedFactions = SEL->getPlayerInfo(color.getNum()).allowedFactions;
|
||||
allowedFactions = SEL->getPlayerInfo(color).allowedFactions;
|
||||
std::vector<bool> allowedHeroesFlag = SEL->getMapInfo()->mapHeader->allowedHeroes;
|
||||
for(int i = 0; i < allowedHeroesFlag.size(); i++)
|
||||
if(allowedHeroesFlag[i])
|
||||
@@ -638,16 +617,19 @@ OptionsTab::SelectionWindow::SelectionWindow(PlayerColor _color, SelType _type)
|
||||
|
||||
for(auto & player : SEL->getStartInfo()->playerInfos)
|
||||
{
|
||||
if(player.first != color && (int)player.second.hero > PlayerSettings::RANDOM)
|
||||
if(player.first != color && (int)player.second.hero > HeroTypeID::RANDOM)
|
||||
unusableHeroes.insert(player.second.hero);
|
||||
}
|
||||
|
||||
allowedBonus.push_back(-1); // random
|
||||
if(initialHero.getNum() >= -1 || SEL->getPlayerInfo(color.getNum()).heroesNames.size() > 0)
|
||||
allowedBonus.push_back(0); // artifact
|
||||
allowedBonus.push_back(1); // gold
|
||||
if(initialFaction.getNum() >= 0)
|
||||
allowedBonus.push_back(2); // resource
|
||||
allowedBonus.push_back(PlayerStartingBonus::RANDOM);
|
||||
|
||||
if(initialHero != HeroTypeID::NONE|| SEL->getPlayerInfo(color).heroesNames.size() > 0)
|
||||
allowedBonus.push_back(PlayerStartingBonus::ARTIFACT);
|
||||
|
||||
allowedBonus.push_back(PlayerStartingBonus::GOLD);
|
||||
|
||||
if(initialFaction.isValid())
|
||||
allowedBonus.push_back(PlayerStartingBonus::RESOURCE);
|
||||
|
||||
recreate();
|
||||
}
|
||||
@@ -656,7 +638,7 @@ int OptionsTab::SelectionWindow::calcLines(FactionID faction)
|
||||
{
|
||||
double additionalItems = 1; // random
|
||||
|
||||
if(faction.getNum() < 0)
|
||||
if(!faction.isValid())
|
||||
return std::ceil(((double)allowedFactions.size() + additionalItems) / elementsPerLine);
|
||||
|
||||
int count = 0;
|
||||
@@ -692,7 +674,7 @@ void OptionsTab::SelectionWindow::setSelection()
|
||||
CSH->setPlayerOption(LobbyChangePlayerOption::HERO_ID, selectedHero, color);
|
||||
|
||||
if(selectedBonus != initialBonus)
|
||||
CSH->setPlayerOption(LobbyChangePlayerOption::BONUS_ID, selectedBonus, color);
|
||||
CSH->setPlayerOption(LobbyChangePlayerOption::BONUS_ID, static_cast<int>(selectedBonus), color);
|
||||
}
|
||||
|
||||
void OptionsTab::SelectionWindow::reopen()
|
||||
@@ -728,7 +710,7 @@ void OptionsTab::SelectionWindow::recreate()
|
||||
elementsPerLine = floor(sqrt(count));
|
||||
}
|
||||
|
||||
amountLines = calcLines((type > SelType::TOWN) ? selectedFaction : static_cast<FactionID>(PlayerSettings::RANDOM));
|
||||
amountLines = calcLines((type > SelType::TOWN) ? selectedFaction : FactionID::RANDOM);
|
||||
}
|
||||
|
||||
int x = (elementsPerLine) * (ICON_BIG_WIDTH-1);
|
||||
@@ -777,11 +759,11 @@ void OptionsTab::SelectionWindow::genContentFactions()
|
||||
|
||||
// random
|
||||
PlayerSettings set = PlayerSettings();
|
||||
set.castle = PlayerSettings::RANDOM;
|
||||
set.castle = FactionID::RANDOM;
|
||||
CPlayerSettingsHelper helper = CPlayerSettingsHelper(set, SelType::TOWN);
|
||||
components.push_back(std::make_shared<CAnimImage>(helper.getImageName(), helper.getImageIndex(), 0, 6, (ICON_SMALL_HEIGHT/2)));
|
||||
drawOutlinedText(TEXT_POS_X, TEXT_POS_Y, (selectedFaction.getNum() == PlayerSettings::RANDOM) ? Colors::YELLOW : Colors::WHITE, helper.getName());
|
||||
if(selectedFaction.getNum() == PlayerSettings::RANDOM)
|
||||
drawOutlinedText(TEXT_POS_X, TEXT_POS_Y, (selectedFaction == FactionID::RANDOM) ? Colors::YELLOW : Colors::WHITE, helper.getName());
|
||||
if(selectedFaction == FactionID::RANDOM)
|
||||
components.push_back(std::make_shared<CPicture>(ImagePath::builtin("lobby/townBorderSmallActivated"), 6, (ICON_SMALL_HEIGHT/2)));
|
||||
|
||||
for(auto & elem : allowedFactions)
|
||||
@@ -809,11 +791,11 @@ void OptionsTab::SelectionWindow::genContentHeroes()
|
||||
|
||||
// random
|
||||
PlayerSettings set = PlayerSettings();
|
||||
set.hero = PlayerSettings::RANDOM;
|
||||
set.hero = HeroTypeID::RANDOM;
|
||||
CPlayerSettingsHelper helper = CPlayerSettingsHelper(set, SelType::HERO);
|
||||
components.push_back(std::make_shared<CAnimImage>(helper.getImageName(), helper.getImageIndex(), 0, 6, (ICON_SMALL_HEIGHT/2)));
|
||||
drawOutlinedText(TEXT_POS_X, TEXT_POS_Y, (selectedHero.getNum() == PlayerSettings::RANDOM) ? Colors::YELLOW : Colors::WHITE, helper.getName());
|
||||
if(selectedHero.getNum() == PlayerSettings::RANDOM)
|
||||
drawOutlinedText(TEXT_POS_X, TEXT_POS_Y, (selectedHero == HeroTypeID::RANDOM) ? Colors::YELLOW : Colors::WHITE, helper.getName());
|
||||
if(selectedHero == HeroTypeID::RANDOM)
|
||||
components.push_back(std::make_shared<CPicture>(ImagePath::builtin("lobby/townBorderSmallActivated"), 6, (ICON_SMALL_HEIGHT/2)));
|
||||
|
||||
for(auto & elem : allowedHeroes)
|
||||
@@ -856,7 +838,7 @@ void OptionsTab::SelectionWindow::genContentBonus()
|
||||
int x = i;
|
||||
int y = 0;
|
||||
|
||||
set.bonus = static_cast<PlayerSettings::Ebonus>(elem);
|
||||
set.bonus = elem;
|
||||
CPlayerSettingsHelper helper = CPlayerSettingsHelper(set, SelType::BONUS);
|
||||
components.push_back(std::make_shared<CAnimImage>(helper.getImageName(), helper.getImageIndex(), 0, x * (ICON_BIG_WIDTH-1) + 6, y * (ICON_BIG_HEIGHT-1) + (ICON_SMALL_HEIGHT/2)));
|
||||
drawOutlinedText(x * (ICON_BIG_WIDTH-1) + TEXT_POS_X, y * (ICON_BIG_HEIGHT-1) + TEXT_POS_Y, Colors::WHITE , helper.getName());
|
||||
@@ -892,9 +874,9 @@ void OptionsTab::SelectionWindow::setElement(int elem, bool doApply)
|
||||
}
|
||||
else
|
||||
{
|
||||
set.castle = PlayerSettings::RANDOM;
|
||||
set.castle = FactionID::RANDOM;
|
||||
}
|
||||
if(set.castle.getNum() != PlayerSettings::NONE)
|
||||
if(set.castle != FactionID::NONE)
|
||||
{
|
||||
if(!doApply)
|
||||
{
|
||||
@@ -916,18 +898,18 @@ void OptionsTab::SelectionWindow::setElement(int elem, bool doApply)
|
||||
}
|
||||
else
|
||||
{
|
||||
set.hero = PlayerSettings::RANDOM;
|
||||
set.hero = HeroTypeID::RANDOM;
|
||||
}
|
||||
|
||||
if(doApply && unusableHeroes.count(heroes[elem]))
|
||||
return;
|
||||
|
||||
if(set.hero.getNum() != PlayerSettings::NONE)
|
||||
if(set.hero != HeroTypeID::NONE)
|
||||
{
|
||||
if(!doApply)
|
||||
{
|
||||
CPlayerSettingsHelper helper = CPlayerSettingsHelper(set, SelType::HERO);
|
||||
if(settings["general"]["enableUiEnhancements"].Bool() && helper.playerSettings.hero.getNum() > PlayerSettings::RANDOM && helper.playerSettings.heroNameTextId.empty())
|
||||
if(settings["general"]["enableUiEnhancements"].Bool() && helper.playerSettings.hero.isValid() && helper.playerSettings.heroNameTextId.empty())
|
||||
GH.windows().createAndPushWindow<CHeroOverview>(helper.playerSettings.hero);
|
||||
else
|
||||
GH.windows().createAndPushWindow<CPlayerOptionTooltipBox>(helper);
|
||||
@@ -940,17 +922,15 @@ void OptionsTab::SelectionWindow::setElement(int elem, bool doApply)
|
||||
{
|
||||
if(elem >= 4)
|
||||
return;
|
||||
set.bonus = static_cast<PlayerSettings::Ebonus>(allowedBonus[elem]);
|
||||
if(set.bonus != PlayerSettings::NONE)
|
||||
set.bonus = static_cast<PlayerStartingBonus>(allowedBonus[elem]);
|
||||
|
||||
if(!doApply)
|
||||
{
|
||||
if(!doApply)
|
||||
{
|
||||
CPlayerSettingsHelper helper = CPlayerSettingsHelper(set, SelType::BONUS);
|
||||
GH.windows().createAndPushWindow<CPlayerOptionTooltipBox>(helper);
|
||||
}
|
||||
else
|
||||
selectedBonus = set.bonus;
|
||||
CPlayerSettingsHelper helper = CPlayerSettingsHelper(set, SelType::BONUS);
|
||||
GH.windows().createAndPushWindow<CPlayerOptionTooltipBox>(helper);
|
||||
}
|
||||
else
|
||||
selectedBonus = set.bonus;
|
||||
}
|
||||
|
||||
if(doApply)
|
||||
@@ -1008,12 +988,12 @@ void OptionsTab::SelectedBox::update()
|
||||
void OptionsTab::SelectedBox::showPopupWindow(const Point & cursorPosition)
|
||||
{
|
||||
// cases when we do not need to display a message
|
||||
if(playerSettings.castle.getNum() == PlayerSettings::NONE && CPlayerSettingsHelper::type == TOWN)
|
||||
if(playerSettings.castle == FactionID::NONE && CPlayerSettingsHelper::selectionType == TOWN)
|
||||
return;
|
||||
if(playerSettings.hero.getNum() == PlayerSettings::NONE && !SEL->getPlayerInfo(playerSettings.color.getNum()).hasCustomMainHero() && CPlayerSettingsHelper::type == HERO)
|
||||
if(playerSettings.hero == HeroTypeID::NONE && !SEL->getPlayerInfo(playerSettings.color).hasCustomMainHero() && CPlayerSettingsHelper::selectionType == HERO)
|
||||
return;
|
||||
|
||||
if(settings["general"]["enableUiEnhancements"].Bool() && CPlayerSettingsHelper::type == HERO && playerSettings.hero.getNum() > PlayerSettings::RANDOM && playerSettings.heroNameTextId.empty())
|
||||
if(settings["general"]["enableUiEnhancements"].Bool() && CPlayerSettingsHelper::selectionType == HERO && playerSettings.hero.isValid() && playerSettings.heroNameTextId.empty())
|
||||
GH.windows().createAndPushWindow<CHeroOverview>(playerSettings.hero);
|
||||
else
|
||||
GH.windows().createAndPushWindow<CPlayerOptionTooltipBox>(*this);
|
||||
@@ -1021,20 +1001,20 @@ void OptionsTab::SelectedBox::showPopupWindow(const Point & cursorPosition)
|
||||
|
||||
void OptionsTab::SelectedBox::clickReleased(const Point & cursorPosition)
|
||||
{
|
||||
PlayerInfo pi = SEL->getPlayerInfo(playerSettings.color.getNum());
|
||||
PlayerInfo pi = SEL->getPlayerInfo(playerSettings.color);
|
||||
const bool foreignPlayer = CSH->isGuest() && !CSH->isMyColor(playerSettings.color);
|
||||
|
||||
if(type == SelType::TOWN && ((pi.allowedFactions.size() < 2 && !pi.isFactionRandom) || foreignPlayer))
|
||||
if(selectionType == SelType::TOWN && ((pi.allowedFactions.size() < 2 && !pi.isFactionRandom) || foreignPlayer))
|
||||
return;
|
||||
|
||||
if(type == SelType::HERO && ((pi.defaultHero() != -1 || playerSettings.castle.getNum() < 0) || foreignPlayer))
|
||||
if(selectionType == SelType::HERO && ((pi.defaultHero() == HeroTypeID::NONE || !playerSettings.castle.isValid() || foreignPlayer)))
|
||||
return;
|
||||
|
||||
if(type == SelType::BONUS && foreignPlayer)
|
||||
if(selectionType == SelType::BONUS && foreignPlayer)
|
||||
return;
|
||||
|
||||
GH.input().hapticFeedback();
|
||||
GH.windows().createAndPushWindow<SelectionWindow>(playerSettings.color, type);
|
||||
GH.windows().createAndPushWindow<SelectionWindow>(playerSettings.color, selectionType);
|
||||
}
|
||||
|
||||
void OptionsTab::SelectedBox::scrollBy(int distance)
|
||||
@@ -1044,7 +1024,7 @@ void OptionsTab::SelectedBox::scrollBy(int distance)
|
||||
// so, currently, gesture will always move selection only by 1, and then wait for recreation from server info
|
||||
distance = std::clamp(distance, -1, 1);
|
||||
|
||||
switch(CPlayerSettingsHelper::type)
|
||||
switch(CPlayerSettingsHelper::selectionType)
|
||||
{
|
||||
case TOWN:
|
||||
CSH->setPlayerOption(LobbyChangePlayerOption::TOWN, distance, playerSettings.color);
|
||||
@@ -1061,7 +1041,7 @@ void OptionsTab::SelectedBox::scrollBy(int distance)
|
||||
}
|
||||
|
||||
OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, const OptionsTab & parent)
|
||||
: pi(std::make_unique<PlayerInfo>(SEL->getPlayerInfo(S.color.getNum())))
|
||||
: pi(std::make_unique<PlayerInfo>(SEL->getPlayerInfo(S.color)))
|
||||
, s(std::make_unique<PlayerSettings>(S))
|
||||
, parentTab(parent)
|
||||
{
|
||||
@@ -1069,7 +1049,7 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con
|
||||
defActions |= SHARE_POS;
|
||||
|
||||
int serial = 0;
|
||||
for(int g = 0; g < s->color.getNum(); ++g)
|
||||
for(PlayerColor g = PlayerColor(0); g < s->color; ++g)
|
||||
{
|
||||
auto itred = SEL->getPlayerInfo(g);
|
||||
if(itred.canComputerPlay || itred.canHumanPlay)
|
||||
@@ -1080,7 +1060,7 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con
|
||||
pos.y += 128 + serial * 50;
|
||||
|
||||
assert(CSH->mi && CSH->mi->mapHeader);
|
||||
const PlayerInfo & p = SEL->getPlayerInfo(s->color.getNum());
|
||||
const PlayerInfo & p = SEL->getPlayerInfo(s->color);
|
||||
assert(p.canComputerPlay || p.canHumanPlay); //someone must be able to control this player
|
||||
if(p.canHumanPlay && p.canComputerPlay)
|
||||
whoCanPlay = HUMAN_OR_CPU;
|
||||
@@ -1100,7 +1080,7 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con
|
||||
"ADOPOPNL.bmp", "ADOPPPNL.bmp", "ADOPTPNL.bmp", "ADOPSPNL.bmp"
|
||||
}};
|
||||
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin(bgs[s->color.getNum()]), 0, 0);
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin(bgs[s->color]), 0, 0);
|
||||
labelPlayerName = std::make_shared<CLabel>(55, 10, EFonts::FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, s->name);
|
||||
labelWhoCanPlay = std::make_shared<CMultiLineLabel>(Rect(6, 23, 45, (int)graphics->fonts[EFonts::FONT_TINY]->getLineHeight()*2), EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->arraytxt[206 + whoCanPlay]);
|
||||
|
||||
@@ -1116,7 +1096,7 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con
|
||||
|
||||
hideUnavailableButtons();
|
||||
|
||||
if(SEL->screenType != ESelectionScreen::scenarioInfo && SEL->getPlayerInfo(s->color.getNum()).canHumanPlay)
|
||||
if(SEL->screenType != ESelectionScreen::scenarioInfo && SEL->getPlayerInfo(s->color).canHumanPlay)
|
||||
{
|
||||
flag = std::make_shared<CButton>(
|
||||
Point(-43, 2),
|
||||
@@ -1159,7 +1139,7 @@ void OptionsTab::PlayerOptionsEntry::hideUnavailableButtons()
|
||||
buttonTownRight->enable();
|
||||
}
|
||||
|
||||
if((pi->defaultHero() != -1 || s->castle.getNum() < 0) //fixed hero
|
||||
if((pi->defaultHero() != HeroTypeID::RANDOM || !s->castle.isValid()) //fixed hero
|
||||
|| foreignPlayer) //or not our player
|
||||
{
|
||||
buttonHeroLeft->disable();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
struct PlayerSettings;
|
||||
struct PlayerInfo;
|
||||
enum class PlayerStartingBonus : int8_t;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CLabel;
|
||||
@@ -54,10 +55,10 @@ private:
|
||||
struct CPlayerSettingsHelper
|
||||
{
|
||||
const PlayerSettings & playerSettings;
|
||||
const SelType type;
|
||||
const SelType selectionType;
|
||||
|
||||
CPlayerSettingsHelper(const PlayerSettings & playerSettings, SelType type)
|
||||
: playerSettings(playerSettings), type(type)
|
||||
: playerSettings(playerSettings), selectionType(type)
|
||||
{}
|
||||
|
||||
/// visible image settings
|
||||
@@ -118,14 +119,14 @@ private:
|
||||
|
||||
FactionID initialFaction;
|
||||
HeroTypeID initialHero;
|
||||
int initialBonus;
|
||||
PlayerStartingBonus initialBonus;
|
||||
FactionID selectedFaction;
|
||||
HeroTypeID selectedHero;
|
||||
int selectedBonus;
|
||||
PlayerStartingBonus selectedBonus;
|
||||
|
||||
std::set<FactionID> allowedFactions;
|
||||
std::set<HeroTypeID> allowedHeroes;
|
||||
std::vector<int> allowedBonus;
|
||||
std::vector<PlayerStartingBonus> allowedBonus;
|
||||
|
||||
void genContentGrid(int lines);
|
||||
void genContentFactions();
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "../../lib/ArtifactUtils.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/spells/CSpellHandler.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CSkillHandler.h"
|
||||
@@ -153,7 +154,7 @@ size_t CComponent::getIndex()
|
||||
case morale: return val+3;
|
||||
case luck: return val+3;
|
||||
case building: return val;
|
||||
case hero: return subtype;
|
||||
case hero: return CGI->heroTypes()->getByIndex(subtype)->getIconIndex();
|
||||
case flag: return subtype;
|
||||
}
|
||||
assert(0);
|
||||
|
||||
@@ -131,7 +131,7 @@ CHeroArea::CHeroArea(int x, int y, const CGHeroInstance * hero)
|
||||
|
||||
if(hero)
|
||||
{
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero->portrait);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero->getIconIndex());
|
||||
clickFunctor = [hero]() -> void
|
||||
{
|
||||
LOCPLINT->openHeroWindow(hero);
|
||||
@@ -291,7 +291,7 @@ CArmyTooltip::CArmyTooltip(Point pos, const CArmedInstance * army):
|
||||
void CHeroTooltip::init(const InfoAboutHero & hero)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero.portrait, 0, 3, 2);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero.getIconIndex(), 0, 3, 2);
|
||||
|
||||
if(hero.details)
|
||||
{
|
||||
@@ -329,7 +329,7 @@ CInteractableHeroTooltip::CInteractableHeroTooltip(Point pos, const CGHeroInstan
|
||||
void CInteractableHeroTooltip::init(const InfoAboutHero & hero)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero.portrait, 0, 3, 2);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero.getIconIndex(), 0, 3, 2);
|
||||
title = std::make_shared<CLabel>(66, 2, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, hero.name);
|
||||
|
||||
if(hero.details)
|
||||
|
||||
@@ -450,7 +450,7 @@ void CHeroGSlot::set(const CGHeroInstance * newHero)
|
||||
if(newHero)
|
||||
{
|
||||
portrait->visible = true;
|
||||
portrait->setFrame(newHero->portrait);
|
||||
portrait->setFrame(newHero->getIconIndex());
|
||||
}
|
||||
else if(!upg && owner->showEmpty) //up garrison
|
||||
{
|
||||
|
||||
@@ -64,7 +64,7 @@ CHeroSwitcher::CHeroSwitcher(CHeroWindow * owner_, Point pos_, const CGHeroInsta
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
pos += pos_;
|
||||
|
||||
image = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsSmall"), hero->portrait);
|
||||
image = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsSmall"), hero->getIconIndex());
|
||||
pos.w = image->pos.w;
|
||||
pos.h = image->pos.h;
|
||||
}
|
||||
@@ -202,7 +202,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
|
||||
dismissButton->addHoverText(CButton::NORMAL, boost::str(boost::format(CGI->generaltexth->heroscrn[16]) % curHero->getNameTranslated() % curHero->type->heroClass->getNameTranslated()));
|
||||
portraitArea->hoverText = boost::str(boost::format(CGI->generaltexth->allTexts[15]) % curHero->getNameTranslated() % curHero->type->heroClass->getNameTranslated());
|
||||
portraitArea->text = curHero->getBiographyTranslated();
|
||||
portraitImage->setFrame(curHero->portrait);
|
||||
portraitImage->setFrame(curHero->getIconIndex());
|
||||
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
|
||||
@@ -915,7 +915,7 @@ CHeroItem::CHeroItem(const CGHeroInstance * Hero)
|
||||
|
||||
garr = std::make_shared<CGarrisonInt>(Point(6, 78), 4, Point(), hero, nullptr, true, true);
|
||||
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero->portrait, 0, 5, 6);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero->getIconIndex(), 0, 5, 6);
|
||||
heroArea = std::make_shared<CHeroArea>(5, 6, hero);
|
||||
|
||||
name = std::make_shared<CLabel>(73, 7, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, hero->getNameTranslated());
|
||||
|
||||
@@ -409,7 +409,7 @@ CLevelWindow::CLevelWindow(const CGHeroInstance * hero, PrimarySkill pskill, std
|
||||
box = std::make_shared<CComponentBox>(comps, Rect(75, 300, pos.w - 150, 100));
|
||||
}
|
||||
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero->portrait, 0, 170, 66);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero->getIconIndex(), 0, 170, 66);
|
||||
ok = std::make_shared<CButton>(Point(297, 413), AnimationPath::builtin("IOKAY"), CButton::tooltip(), std::bind(&CLevelWindow::close, this), EShortcut::GLOBAL_ACCEPT);
|
||||
|
||||
//%s has gained a level.
|
||||
@@ -598,7 +598,7 @@ CTavernWindow::HeroPortrait::HeroPortrait(int & sel, int id, int x, int y, const
|
||||
boost::algorithm::replace_first(description, "%s", h->type->heroClass->getNameTranslated());
|
||||
boost::algorithm::replace_first(description, "%d", std::to_string(artifs));
|
||||
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("portraitsLarge"), h->portrait);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("portraitsLarge"), h->getIconIndex());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1246,7 +1246,7 @@ CGarrisonWindow::CGarrisonWindow(const CArmedInstance * up, const CGHeroInstance
|
||||
title = std::make_shared<CLabel>(275, 30, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, titleText);
|
||||
|
||||
banner = std::make_shared<CAnimImage>(AnimationPath::builtin("CREST58"), up->getOwner().getNum(), 0, 28, 124);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), down->portrait, 0, 29, 222);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), down->getIconIndex(), 0, 29, 222);
|
||||
}
|
||||
|
||||
void CGarrisonWindow::updateGarrisons()
|
||||
@@ -1537,9 +1537,9 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner):
|
||||
for(auto & iter : tgi.colorToBestHero)
|
||||
{
|
||||
banners.push_back(std::make_shared<CPicture>(ImagePath::builtin(colorToBox[iter.first.getNum()]), 253 + 66 * counter, 334));
|
||||
if(iter.second.portrait >= 0)
|
||||
if(iter.second.portraitSource.isValid())
|
||||
{
|
||||
bestHeroes.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsSmall"), iter.second.portrait, 0, 260 + 66 * counter, 360));
|
||||
bestHeroes.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsSmall"), iter.second.getIconIndex(), 0, 260 + 66 * counter, 360));
|
||||
//TODO: r-click info:
|
||||
// - r-click on hero
|
||||
// - r-click on primary skill label
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
"config/heroes/stronghold.json",
|
||||
"config/heroes/fortress.json",
|
||||
"config/heroes/conflux.json",
|
||||
"config/heroes/special.json"
|
||||
"config/heroes/special.json",
|
||||
"config/heroes/portraits.json"
|
||||
],
|
||||
|
||||
"objects" :
|
||||
@@ -218,6 +219,11 @@
|
||||
"special2" : 19, // bloodObelisk
|
||||
"special3" : 18 // glyphsOfFear
|
||||
}
|
||||
},
|
||||
|
||||
"portraits" : {
|
||||
"catherine" : 128, // In "RoE" Catherine only has portrait
|
||||
"portraitGeneralKendal" : 129
|
||||
}
|
||||
},
|
||||
"armageddonsBlade" : {
|
||||
@@ -228,11 +234,29 @@
|
||||
"special1" : 10, // artifactMerchants
|
||||
"special2" : 18 // magicUniversity
|
||||
}
|
||||
},
|
||||
|
||||
"portraits" : {
|
||||
"pasis" : 128,
|
||||
"thunar" : 129,
|
||||
"portraitGeneralKendal" : 156,
|
||||
"portraitYoungCristian" : 157,
|
||||
"portraitOrdwald" : 158
|
||||
}
|
||||
},
|
||||
"shadowOfDeath" : {
|
||||
"supported" : true,
|
||||
"iconIndex" : 2
|
||||
"iconIndex" : 2,
|
||||
|
||||
"portraits" : {
|
||||
"portraitGeneralKendal" : 156,
|
||||
"portraitYoungCristian" : 157,
|
||||
"portraitOrdwald" : 158,
|
||||
"portraitFinneas" : 159,
|
||||
"portraitYoungGem" : 160,
|
||||
"portraitYoungSandro" : 161,
|
||||
"portraitYoungYog" : 162
|
||||
}
|
||||
},
|
||||
"jsonVCMI" : {
|
||||
"supported" : true,
|
||||
|
||||
206
config/heroes/portraits.json
Normal file
206
config/heroes/portraits.json
Normal file
@@ -0,0 +1,206 @@
|
||||
{
|
||||
// additional empty heroes for correct loading of hero portraits set in map editor
|
||||
"portraitGeneralKendal" :
|
||||
{
|
||||
"class" : "knight",
|
||||
"special" : true,
|
||||
"images": {
|
||||
"large" : "HPL129MK",
|
||||
"small" : "HPS129MK",
|
||||
"specialtySmall" : "default",
|
||||
"specialtyLarge" : "default"
|
||||
},
|
||||
"texts" : {
|
||||
"name" : "",
|
||||
"biography" : "",
|
||||
"specialty" : {
|
||||
"description" : "",
|
||||
"tooltip" : "",
|
||||
"name" : ""
|
||||
}
|
||||
},
|
||||
"army" : [
|
||||
{
|
||||
"creature" : "pikeman",
|
||||
"min" : 1,
|
||||
"max" : 1
|
||||
}
|
||||
],
|
||||
"skills" : [],
|
||||
"specialty" : {}
|
||||
},
|
||||
"portraitYoungCristian" :
|
||||
{
|
||||
"class" : "knight",
|
||||
"special" : true,
|
||||
"images": {
|
||||
"large" : "HPL002SH",
|
||||
"small" : "HPS002SH",
|
||||
"specialtySmall" : "default",
|
||||
"specialtyLarge" : "default"
|
||||
},
|
||||
"texts" : {
|
||||
"name" : "",
|
||||
"biography" : "",
|
||||
"specialty" : {
|
||||
"description" : "",
|
||||
"tooltip" : "",
|
||||
"name" : ""
|
||||
}
|
||||
},
|
||||
"army" : [
|
||||
{
|
||||
"creature" : "pikeman",
|
||||
"min" : 1,
|
||||
"max" : 1
|
||||
}
|
||||
],
|
||||
"skills" : [],
|
||||
"specialty" : {}
|
||||
},
|
||||
"portraitOrdwald" :
|
||||
{
|
||||
"class" : "druid",
|
||||
"special" : true,
|
||||
"images": {
|
||||
"large" : "HPL132Wl",
|
||||
"small" : "HPS132Wl",
|
||||
"specialtySmall" : "default",
|
||||
"specialtyLarge" : "default"
|
||||
},
|
||||
"texts" : {
|
||||
"name" : "",
|
||||
"biography" : "",
|
||||
"specialty" : {
|
||||
"description" : "",
|
||||
"tooltip" : "",
|
||||
"name" : ""
|
||||
}
|
||||
},
|
||||
"army" : [
|
||||
{
|
||||
"creature" : "centaur",
|
||||
"min" : 1,
|
||||
"max" : 1
|
||||
}
|
||||
],
|
||||
"skills" : [],
|
||||
"specialty" : {}
|
||||
},
|
||||
"portraitFinneas" :
|
||||
{
|
||||
"class" : "necromancer",
|
||||
"special" : true,
|
||||
"images": {
|
||||
"large" : "HPL133Nc",
|
||||
"small" : "HPS133Nc",
|
||||
"specialtySmall" : "default",
|
||||
"specialtyLarge" : "default"
|
||||
},
|
||||
"texts" : {
|
||||
"name" : "",
|
||||
"biography" : "",
|
||||
"specialty" : {
|
||||
"description" : "",
|
||||
"tooltip" : "",
|
||||
"name" : ""
|
||||
}
|
||||
},
|
||||
"army" : [
|
||||
{
|
||||
"creature" : "skeleton",
|
||||
"min" : 1,
|
||||
"max" : 1
|
||||
}
|
||||
],
|
||||
"skills" : [],
|
||||
"specialty" : {}
|
||||
},
|
||||
"portraitYoungGem" :
|
||||
{
|
||||
"class" : "druid",
|
||||
"special" : true,
|
||||
"images": {
|
||||
"large" : "HPL134Nc",
|
||||
"small" : "HPS134Nc",
|
||||
"specialtySmall" : "default",
|
||||
"specialtyLarge" : "default"
|
||||
},
|
||||
"texts" : {
|
||||
"name" : "",
|
||||
"biography" : "",
|
||||
"specialty" : {
|
||||
"description" : "",
|
||||
"tooltip" : "",
|
||||
"name" : ""
|
||||
}
|
||||
},
|
||||
"army" : [
|
||||
{
|
||||
"creature" : "centaur",
|
||||
"min" : 1,
|
||||
"max" : 1
|
||||
}
|
||||
],
|
||||
"skills" : [],
|
||||
"specialty" : {}
|
||||
},
|
||||
"portraitYoungSandro" :
|
||||
{
|
||||
"class" : "necromancer",
|
||||
"special" : true,
|
||||
"images": {
|
||||
"large" : "HPL135Wi",
|
||||
"small" : "HPS135Wi",
|
||||
"specialtySmall" : "default",
|
||||
"specialtyLarge" : "default"
|
||||
},
|
||||
"texts" : {
|
||||
"name" : "",
|
||||
"biography" : "",
|
||||
"specialty" : {
|
||||
"description" : "",
|
||||
"tooltip" : "",
|
||||
"name" : ""
|
||||
}
|
||||
},
|
||||
"army" : [
|
||||
{
|
||||
"creature" : "skeleton",
|
||||
"min" : 1,
|
||||
"max" : 1
|
||||
}
|
||||
],
|
||||
"skills" : [],
|
||||
"specialty" : {}
|
||||
},
|
||||
"portraitYoungYog" :
|
||||
{
|
||||
"class" : "wizard",
|
||||
"special" : true,
|
||||
"images": {
|
||||
"large" : "HPL136Wi",
|
||||
"small" : "HPS136Wi",
|
||||
"specialtySmall" : "default",
|
||||
"specialtyLarge" : "default"
|
||||
},
|
||||
"texts" : {
|
||||
"name" : "",
|
||||
"biography" : "",
|
||||
"specialty" : {
|
||||
"description" : "",
|
||||
"tooltip" : "",
|
||||
"name" : ""
|
||||
}
|
||||
},
|
||||
"army" : [
|
||||
{
|
||||
"creature" : "gremlin",
|
||||
"min" : 1,
|
||||
"max" : 1
|
||||
}
|
||||
],
|
||||
"skills" : [],
|
||||
"specialty" : {}
|
||||
}
|
||||
}
|
||||
@@ -298,7 +298,7 @@ CHeroClass * CHeroClassHandler::loadFromJson(const std::string & scope, const Js
|
||||
VLC->identifiers()->requestIdentifier("faction", node["faction"],
|
||||
[=](si32 factionID)
|
||||
{
|
||||
heroClass->faction = factionID;
|
||||
heroClass->faction.setNum(factionID);
|
||||
});
|
||||
|
||||
VLC->identifiers()->requestIdentifier(scope, "object", "hero", [=](si32 index)
|
||||
@@ -722,8 +722,9 @@ std::vector<JsonNode> CHeroHandler::loadLegacyData()
|
||||
void CHeroHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
|
||||
{
|
||||
size_t index = objects.size();
|
||||
static const int specialFramesCount = 2; // reserved for 2 special frames
|
||||
auto * object = loadFromJson(scope, data, name, index);
|
||||
object->imageIndex = static_cast<si32>(index) + GameConstants::HERO_PORTRAIT_SHIFT; // 2 special frames + some extra portraits
|
||||
object->imageIndex = static_cast<si32>(index) + specialFramesCount;
|
||||
|
||||
objects.emplace_back(object);
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "StartInfo.h"
|
||||
|
||||
#include "CGeneralTextHandler.h"
|
||||
#include "CTownHandler.h"
|
||||
#include "CHeroHandler.h"
|
||||
#include "VCMI_Lib.h"
|
||||
#include "rmg/CMapGenOptions.h"
|
||||
#include "mapping/CMapInfo.h"
|
||||
@@ -22,9 +24,28 @@
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
PlayerSettings::PlayerSettings()
|
||||
: bonus(RANDOM), castle(NONE), hero(RANDOM), heroPortrait(RANDOM), color(0), handicap(NO_HANDICAP), compOnly(false)
|
||||
: bonus(PlayerStartingBonus::RANDOM), color(0), handicap(NO_HANDICAP), compOnly(false)
|
||||
{
|
||||
}
|
||||
|
||||
FactionID PlayerSettings::getCastleValidated() const
|
||||
{
|
||||
if (!castle.isValid())
|
||||
return FactionID(0);
|
||||
if (castle.getNum() < VLC->townh->size())
|
||||
return castle;
|
||||
|
||||
return FactionID(0);
|
||||
}
|
||||
|
||||
HeroTypeID PlayerSettings::getHeroValidated() const
|
||||
{
|
||||
if (!hero.isValid())
|
||||
return HeroTypeID(0);
|
||||
if (hero.getNum() < VLC->heroh->size())
|
||||
return hero;
|
||||
|
||||
return HeroTypeID(0);
|
||||
}
|
||||
|
||||
bool PlayerSettings::isControlledByAI() const
|
||||
@@ -196,15 +217,15 @@ ui8 LobbyInfo::clientFirstId(int clientId) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
PlayerInfo & LobbyInfo::getPlayerInfo(int color)
|
||||
PlayerInfo & LobbyInfo::getPlayerInfo(PlayerColor color)
|
||||
{
|
||||
return mi->mapHeader->players[color];
|
||||
return mi->mapHeader->players[color.getNum()];
|
||||
}
|
||||
|
||||
TeamID LobbyInfo::getPlayerTeamId(const PlayerColor & color)
|
||||
{
|
||||
if(color.isValidPlayer())
|
||||
return getPlayerInfo(color.getNum()).team;
|
||||
return getPlayerInfo(color).team;
|
||||
else
|
||||
return TeamID::NO_TEAM;
|
||||
}
|
||||
|
||||
@@ -41,20 +41,20 @@ struct DLL_LINKAGE SimturnsInfo
|
||||
}
|
||||
};
|
||||
|
||||
enum class PlayerStartingBonus : int8_t
|
||||
{
|
||||
RANDOM = -1,
|
||||
ARTIFACT = 0,
|
||||
GOLD = 1,
|
||||
RESOURCE = 2
|
||||
};
|
||||
|
||||
/// Struct which describes the name, the color, the starting bonus of a player
|
||||
struct DLL_LINKAGE PlayerSettings
|
||||
{
|
||||
enum { PLAYER_AI = 0 }; // for use in playerID
|
||||
|
||||
enum Ebonus {
|
||||
NONE = -2,
|
||||
RANDOM = -1,
|
||||
ARTIFACT = 0,
|
||||
GOLD = 1,
|
||||
RESOURCE = 2
|
||||
};
|
||||
|
||||
Ebonus bonus;
|
||||
PlayerStartingBonus bonus;
|
||||
FactionID castle;
|
||||
HeroTypeID hero;
|
||||
HeroTypeID heroPortrait; //-1 if default, else ID
|
||||
@@ -85,6 +85,9 @@ struct DLL_LINKAGE PlayerSettings
|
||||
PlayerSettings();
|
||||
bool isControlledByAI() const;
|
||||
bool isControlledByHuman() const;
|
||||
|
||||
FactionID getCastleValidated() const;
|
||||
HeroTypeID getHeroValidated() const;
|
||||
};
|
||||
|
||||
/// Struct which describes the difficulty, the turn time,.. of a heroes match.
|
||||
@@ -197,7 +200,7 @@ struct DLL_LINKAGE LobbyInfo : public LobbyState
|
||||
PlayerColor clientFirstColor(int clientId) const;
|
||||
bool isClientColor(int clientId, const PlayerColor & color) const;
|
||||
ui8 clientFirstId(int clientId) const; // Used by chat only!
|
||||
PlayerInfo & getPlayerInfo(int color);
|
||||
PlayerInfo & getPlayerInfo(PlayerColor color);
|
||||
TeamID getPlayerTeamId(const PlayerColor & color);
|
||||
};
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ CampaignTravel CampaignHandler::readScenarioTravelFromJson(JsonNode & reader)
|
||||
break;
|
||||
case CampaignStartOptions::START_BONUS: //reading of bonuses player can choose
|
||||
{
|
||||
ret.playerColor = reader["playerColor"].Integer();
|
||||
ret.playerColor = PlayerColor(PlayerColor::decode(reader["playerColor"].String()));
|
||||
for(auto & bjson : reader["bonuses"].Vector())
|
||||
{
|
||||
CampaignBonus bonus;
|
||||
@@ -472,7 +472,7 @@ CampaignTravel CampaignHandler::readScenarioTravelFromMemory(CBinaryReader & rea
|
||||
break;
|
||||
case CampaignStartOptions::START_BONUS: //reading of bonuses player can choose
|
||||
{
|
||||
ret.playerColor = reader.readUInt8();
|
||||
ret.playerColor.setNum(reader.readUInt8());
|
||||
ui8 numOfBonuses = reader.readUInt8();
|
||||
for (int g=0; g<numOfBonuses; ++g)
|
||||
{
|
||||
|
||||
@@ -38,60 +38,60 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
const BattleID BattleID::NONE = BattleID(-1);
|
||||
const QueryID QueryID::NONE = QueryID(-1);
|
||||
const HeroTypeID HeroTypeID::NONE = HeroTypeID(-1);
|
||||
const ObjectInstanceID ObjectInstanceID::NONE = ObjectInstanceID(-1);
|
||||
const BattleID BattleID::NONE(-1);
|
||||
const QueryID QueryID::NONE(-1);
|
||||
const HeroTypeID HeroTypeID::NONE(-1);
|
||||
const HeroTypeID HeroTypeID::RANDOM(-2);
|
||||
const ObjectInstanceID ObjectInstanceID::NONE(-1);
|
||||
|
||||
const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2);
|
||||
const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(-3);
|
||||
const SlotID SlotID::WAR_MACHINES_SLOT = SlotID(-4);
|
||||
const SlotID SlotID::ARROW_TOWERS_SLOT = SlotID(-5);
|
||||
const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER(-2);
|
||||
const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER(-3);
|
||||
const SlotID SlotID::WAR_MACHINES_SLOT(-4);
|
||||
const SlotID SlotID::ARROW_TOWERS_SLOT(-5);
|
||||
|
||||
const PlayerColor PlayerColor::SPECTATOR = PlayerColor(-4);
|
||||
const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(-3);
|
||||
const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(-2);
|
||||
const PlayerColor PlayerColor::NEUTRAL = PlayerColor(-1);
|
||||
const PlayerColor PlayerColor::PLAYER_LIMIT = PlayerColor(PLAYER_LIMIT_I);
|
||||
const TeamID TeamID::NO_TEAM = TeamID(-1);
|
||||
const PlayerColor PlayerColor::SPECTATOR(-4);
|
||||
const PlayerColor PlayerColor::CANNOT_DETERMINE(-3);
|
||||
const PlayerColor PlayerColor::UNFLAGGABLE(-2);
|
||||
const PlayerColor PlayerColor::NEUTRAL(-1);
|
||||
const PlayerColor PlayerColor::PLAYER_LIMIT(PLAYER_LIMIT_I);
|
||||
const TeamID TeamID::NO_TEAM(-1);
|
||||
|
||||
const SpellSchool SpellSchool::ANY = -1;
|
||||
const SpellSchool SpellSchool::AIR = 0;
|
||||
const SpellSchool SpellSchool::FIRE = 1;
|
||||
const SpellSchool SpellSchool::WATER = 2;
|
||||
const SpellSchool SpellSchool::EARTH = 3;
|
||||
const SpellSchool SpellSchool::ANY(-1);
|
||||
const SpellSchool SpellSchool::AIR(0);
|
||||
const SpellSchool SpellSchool::FIRE(1);
|
||||
const SpellSchool SpellSchool::WATER(2);
|
||||
const SpellSchool SpellSchool::EARTH(3);
|
||||
|
||||
const FactionID FactionID::NONE = -2;
|
||||
const FactionID FactionID::DEFAULT = -1;
|
||||
const FactionID FactionID::RANDOM = -1;
|
||||
const FactionID FactionID::ANY = -1;
|
||||
const FactionID FactionID::CASTLE = 0;
|
||||
const FactionID FactionID::RAMPART = 1;
|
||||
const FactionID FactionID::TOWER = 2;
|
||||
const FactionID FactionID::INFERNO = 3;
|
||||
const FactionID FactionID::NECROPOLIS = 4;
|
||||
const FactionID FactionID::DUNGEON = 5;
|
||||
const FactionID FactionID::STRONGHOLD = 6;
|
||||
const FactionID FactionID::FORTRESS = 7;
|
||||
const FactionID FactionID::CONFLUX = 8;
|
||||
const FactionID FactionID::NEUTRAL = 9;
|
||||
const FactionID FactionID::NONE(-2);
|
||||
const FactionID FactionID::DEFAULT(-1);
|
||||
const FactionID FactionID::RANDOM(-1);
|
||||
const FactionID FactionID::ANY(-1);
|
||||
const FactionID FactionID::CASTLE(0);
|
||||
const FactionID FactionID::RAMPART(1);
|
||||
const FactionID FactionID::TOWER(2);
|
||||
const FactionID FactionID::INFERNO(3);
|
||||
const FactionID FactionID::NECROPOLIS(4);
|
||||
const FactionID FactionID::DUNGEON(5);
|
||||
const FactionID FactionID::STRONGHOLD(6);
|
||||
const FactionID FactionID::FORTRESS(7);
|
||||
const FactionID FactionID::CONFLUX(8);
|
||||
const FactionID FactionID::NEUTRAL(9);
|
||||
|
||||
const BoatId BoatId::NONE = -1;
|
||||
const BoatId BoatId::NECROPOLIS = 0;
|
||||
const BoatId BoatId::CASTLE = 1;
|
||||
const BoatId BoatId::FORTRESS = 2;
|
||||
const BoatId BoatId::NONE(-1);
|
||||
const BoatId BoatId::NECROPOLIS(0);
|
||||
const BoatId BoatId::CASTLE(1);
|
||||
const BoatId BoatId::FORTRESS(2);
|
||||
|
||||
const RiverId RiverId::NO_RIVER = 0;
|
||||
const RiverId RiverId::WATER_RIVER = 1;
|
||||
const RiverId RiverId::ICY_RIVER = 2;
|
||||
const RiverId RiverId::MUD_RIVER = 3;
|
||||
const RiverId RiverId::LAVA_RIVER = 4;
|
||||
|
||||
const RoadId RoadId::NO_ROAD = 0;
|
||||
const RoadId RoadId::DIRT_ROAD = 1;
|
||||
const RoadId RoadId::GRAVEL_ROAD = 2;
|
||||
const RoadId RoadId::COBBLESTONE_ROAD = 3;
|
||||
const RiverId RiverId::NO_RIVER(0);
|
||||
const RiverId RiverId::WATER_RIVER(1);
|
||||
const RiverId RiverId::ICY_RIVER(2);
|
||||
const RiverId RiverId::MUD_RIVER(3);
|
||||
const RiverId RiverId::LAVA_RIVER(4);
|
||||
|
||||
const RoadId RoadId::NO_ROAD(0);
|
||||
const RoadId RoadId::DIRT_ROAD(1);
|
||||
const RoadId RoadId::GRAVEL_ROAD(2);
|
||||
const RoadId RoadId::COBBLESTONE_ROAD(3);
|
||||
|
||||
namespace GameConstants
|
||||
{
|
||||
|
||||
@@ -38,7 +38,11 @@ class CNonConstInfoCallback;
|
||||
class IdentifierBase
|
||||
{
|
||||
protected:
|
||||
constexpr IdentifierBase(int32_t value = -1 ):
|
||||
constexpr IdentifierBase():
|
||||
num(-1)
|
||||
{}
|
||||
|
||||
explicit constexpr IdentifierBase(int32_t value):
|
||||
num(value)
|
||||
{}
|
||||
|
||||
@@ -51,6 +55,11 @@ public:
|
||||
return num;
|
||||
}
|
||||
|
||||
constexpr void setNum(int32_t value)
|
||||
{
|
||||
num = value;
|
||||
}
|
||||
|
||||
struct hash
|
||||
{
|
||||
size_t operator()(const IdentifierBase & id) const
|
||||
@@ -88,8 +97,11 @@ class Identifier : public IdentifierBase
|
||||
{
|
||||
using BaseClass = IdentifierBase;
|
||||
public:
|
||||
constexpr Identifier(int32_t _num = -1)
|
||||
:IdentifierBase(_num)
|
||||
constexpr Identifier()
|
||||
{}
|
||||
|
||||
explicit constexpr Identifier(int32_t value):
|
||||
IdentifierBase(value)
|
||||
{}
|
||||
|
||||
constexpr bool operator == (const Identifier & b) const { return BaseClass::num == b.num; }
|
||||
@@ -105,6 +117,19 @@ public:
|
||||
return static_cast<FinalClass&>(*this);
|
||||
}
|
||||
|
||||
constexpr FinalClass & operator--()
|
||||
{
|
||||
--BaseClass::num;
|
||||
return static_cast<FinalClass&>(*this);
|
||||
}
|
||||
|
||||
constexpr FinalClass operator--(int)
|
||||
{
|
||||
FinalClass ret(num);
|
||||
--BaseClass::num;
|
||||
return ret;
|
||||
}
|
||||
|
||||
constexpr FinalClass operator++(int)
|
||||
{
|
||||
FinalClass ret(num);
|
||||
@@ -209,6 +234,12 @@ public:
|
||||
static std::string entityType();
|
||||
|
||||
DLL_LINKAGE static const HeroTypeID NONE;
|
||||
DLL_LINKAGE static const HeroTypeID RANDOM;
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return getNum() >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
class SlotID : public Identifier<SlotID>
|
||||
@@ -336,6 +367,11 @@ public:
|
||||
static si32 decode(const std::string& identifier);
|
||||
static std::string encode(const si32 index);
|
||||
static std::string entityType();
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return getNum() >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
class BuildingIDBase : public IdentifierBase
|
||||
|
||||
@@ -50,8 +50,6 @@ namespace GameConstants
|
||||
constexpr int CREATURES_COUNT = 197;
|
||||
|
||||
constexpr ui32 BASE_MOVEMENT_COST = 100; //default cost for non-diagonal movement
|
||||
|
||||
constexpr int HERO_PORTRAIT_SHIFT = 9;// 2 special frames + 7 extra portraits
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
@@ -824,7 +824,7 @@ void CGameState::placeStartingHeroes()
|
||||
if (campaign && campaign->playerHasStartingHero(playerColor))
|
||||
continue;
|
||||
|
||||
int heroTypeId = pickNextHeroType(playerColor);
|
||||
HeroTypeID heroTypeId = pickNextHeroType(playerColor);
|
||||
if(playerSettingPair.second.hero == HeroTypeID::NONE)
|
||||
playerSettingPair.second.hero = heroTypeId;
|
||||
|
||||
@@ -959,14 +959,15 @@ void CGameState::initStartingBonus()
|
||||
for(auto & elem : players)
|
||||
{
|
||||
//starting bonus
|
||||
if(scenarioOps->playerInfos[elem.first].bonus==PlayerSettings::RANDOM)
|
||||
scenarioOps->playerInfos[elem.first].bonus = static_cast<PlayerSettings::Ebonus>(getRandomGenerator().nextInt(2));
|
||||
if(scenarioOps->playerInfos[elem.first].bonus == PlayerStartingBonus::RANDOM)
|
||||
scenarioOps->playerInfos[elem.first].bonus = static_cast<PlayerStartingBonus>(getRandomGenerator().nextInt(2));
|
||||
|
||||
switch(scenarioOps->playerInfos[elem.first].bonus)
|
||||
{
|
||||
case PlayerSettings::GOLD:
|
||||
case PlayerStartingBonus::GOLD:
|
||||
elem.second.resources[EGameResID::GOLD] += getRandomGenerator().nextInt(5, 10) * 100;
|
||||
break;
|
||||
case PlayerSettings::RESOURCE:
|
||||
case PlayerStartingBonus::RESOURCE:
|
||||
{
|
||||
auto res = (*VLC->townh)[scenarioOps->playerInfos[elem.first].castle]->town->primaryRes;
|
||||
if(res == EGameResID::WOOD_AND_ORE)
|
||||
@@ -981,7 +982,7 @@ void CGameState::initStartingBonus()
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PlayerSettings::ARTIFACT:
|
||||
case PlayerStartingBonus::ARTIFACT:
|
||||
{
|
||||
if(elem.second.heroes.empty())
|
||||
{
|
||||
@@ -2117,7 +2118,7 @@ std::set<HeroTypeID> CGameState::getUnusedAllowedHeroes(bool alsoIncludeNotAllow
|
||||
|
||||
for(const auto & playerSettingPair : scenarioOps->playerInfos) //remove uninitialized yet heroes picked for start by other players
|
||||
{
|
||||
if(playerSettingPair.second.hero.getNum() != PlayerSettings::RANDOM)
|
||||
if(playerSettingPair.second.hero != HeroTypeID::RANDOM)
|
||||
ret -= HeroTypeID(playerSettingPair.second.hero);
|
||||
}
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ void CGameStateCampaign::placeCampaignHeroes()
|
||||
// now add removed heroes again with unused type ID
|
||||
for(auto * hero : removedHeroes)
|
||||
{
|
||||
si32 heroTypeId = 0;
|
||||
HeroTypeID heroTypeId;
|
||||
if(hero->ID == Obj::HERO)
|
||||
{
|
||||
heroTypeId = gameState->pickUnusedHeroTypeRandomly(hero->tempOwner);
|
||||
@@ -243,7 +243,7 @@ void CGameStateCampaign::placeCampaignHeroes()
|
||||
auto unusedHeroTypeIds = gameState->getUnusedAllowedHeroes();
|
||||
if(!unusedHeroTypeIds.empty())
|
||||
{
|
||||
heroTypeId = (*RandomGeneratorUtil::nextItem(unusedHeroTypeIds, gameState->getRandomGenerator())).getNum();
|
||||
heroTypeId = (*RandomGeneratorUtil::nextItem(unusedHeroTypeIds, gameState->getRandomGenerator()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -257,7 +257,6 @@ void CGameStateCampaign::placeCampaignHeroes()
|
||||
}
|
||||
|
||||
hero->subID = heroTypeId;
|
||||
hero->portrait = hero->subID;
|
||||
gameState->map->getEditManager()->insertObject(hero);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,18 +73,18 @@ void InfoAboutHero::assign(const InfoAboutHero & iah)
|
||||
|
||||
details = (iah.details ? new Details(*iah.details) : nullptr);
|
||||
hclass = iah.hclass;
|
||||
portrait = iah.portrait;
|
||||
portraitSource = iah.portraitSource;
|
||||
}
|
||||
|
||||
InfoAboutHero::InfoAboutHero(): portrait(-1) {}
|
||||
InfoAboutHero::InfoAboutHero()
|
||||
{}
|
||||
|
||||
InfoAboutHero::InfoAboutHero(const InfoAboutHero & iah): InfoAboutArmy(iah)
|
||||
{
|
||||
assign(iah);
|
||||
}
|
||||
|
||||
InfoAboutHero::InfoAboutHero(const CGHeroInstance * h, InfoAboutHero::EInfoLevel infoLevel):
|
||||
portrait(-1)
|
||||
InfoAboutHero::InfoAboutHero(const CGHeroInstance * h, InfoAboutHero::EInfoLevel infoLevel)
|
||||
{
|
||||
initFromHero(h, infoLevel);
|
||||
}
|
||||
@@ -100,6 +100,11 @@ InfoAboutHero & InfoAboutHero::operator=(const InfoAboutHero & iah)
|
||||
return *this;
|
||||
}
|
||||
|
||||
int32_t InfoAboutHero::getIconIndex() const
|
||||
{
|
||||
return VLC->heroTypes()->getById(portraitSource)->getIconIndex();
|
||||
}
|
||||
|
||||
void InfoAboutHero::initFromHero(const CGHeroInstance *h, InfoAboutHero::EInfoLevel infoLevel)
|
||||
{
|
||||
vstd::clear_pointer(details);
|
||||
@@ -112,7 +117,7 @@ void InfoAboutHero::initFromHero(const CGHeroInstance *h, InfoAboutHero::EInfoLe
|
||||
|
||||
hclass = h->type->heroClass;
|
||||
name = h->getNameTranslated();
|
||||
portrait = h->portrait;
|
||||
portraitSource = h->getPortraitSource();
|
||||
|
||||
if(detailed)
|
||||
{
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
Details * details = nullptr;
|
||||
|
||||
const CHeroClass *hclass;
|
||||
int portrait;
|
||||
HeroTypeID portraitSource;
|
||||
|
||||
enum EInfoLevel
|
||||
{
|
||||
@@ -72,6 +72,7 @@ public:
|
||||
InfoAboutHero & operator=(const InfoAboutHero & iah);
|
||||
|
||||
void initFromHero(const CGHeroInstance *h, EInfoLevel infoLevel);
|
||||
int32_t getIconIndex() const;
|
||||
};
|
||||
|
||||
/// Struct which holds a int information about a town
|
||||
|
||||
@@ -246,7 +246,6 @@ CGHeroInstance::CGHeroInstance():
|
||||
moveDir(4),
|
||||
mana(UNINITIALIZED_MANA),
|
||||
movement(UNINITIALIZED_MOVEMENT),
|
||||
portrait(UNINITIALIZED_PORTRAIT),
|
||||
level(1),
|
||||
exp(UNINITIALIZED_EXPERIENCE),
|
||||
gender(EHeroGender::DEFAULT),
|
||||
@@ -273,7 +272,7 @@ void CGHeroInstance::setType(si32 ID, si32 subID)
|
||||
{
|
||||
assert(ID == Obj::HERO); // just in case
|
||||
type = VLC->heroh->objects[subID];
|
||||
portrait = type->imageIndex;
|
||||
|
||||
CGObjectInstance::setType(ID, type->heroClass->getIndex()); // to find object handler we must use heroClass->id
|
||||
this->subID = subID; // after setType subID used to store unique hero identify id. Check issue 2277 for details
|
||||
randomizeArmy(type->heroClass->faction);
|
||||
@@ -309,8 +308,6 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
|
||||
if(!getArt(ArtifactPosition::MACH4))
|
||||
putArtifact(ArtifactPosition::MACH4, ArtifactUtils::createNewArtifactInstance(ArtifactID::CATAPULT)); //everyone has a catapult
|
||||
|
||||
if(portrait < 0 || portrait == 255)
|
||||
portrait = type->imageIndex;
|
||||
if(!hasBonus(Selector::sourceType()(BonusSource::HERO_BASE_SKILL)))
|
||||
{
|
||||
for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
|
||||
@@ -1028,6 +1025,19 @@ si32 CGHeroInstance::manaLimit() const
|
||||
* (valOfBonuses(BonusType::MANA_PER_KNOWLEDGE)));
|
||||
}
|
||||
|
||||
HeroTypeID CGHeroInstance::getPortraitSource() const
|
||||
{
|
||||
if (customPortraitSource.isValid())
|
||||
return customPortraitSource;
|
||||
else
|
||||
return HeroTypeID(subID);
|
||||
}
|
||||
|
||||
int32_t CGHeroInstance::getIconIndex() const
|
||||
{
|
||||
return VLC->heroTypes()->getById(getPortraitSource())->getIconIndex();
|
||||
}
|
||||
|
||||
std::string CGHeroInstance::getNameTranslated() const
|
||||
{
|
||||
return VLC->generaltexth->translate(getNameTextID());
|
||||
@@ -1528,40 +1538,7 @@ void CGHeroInstance::serializeCommonOptions(JsonSerializeFormat & handler)
|
||||
|
||||
handler.serializeString("name", nameCustomTextId);
|
||||
handler.serializeInt("gender", gender, 0);
|
||||
|
||||
{
|
||||
const int legacyHeroes = VLC->settings()->getInteger(EGameSettings::TEXTS_HERO);
|
||||
const int moddedStart = legacyHeroes + GameConstants::HERO_PORTRAIT_SHIFT;
|
||||
|
||||
if(handler.saving)
|
||||
{
|
||||
if(portrait >= 0)
|
||||
{
|
||||
if(portrait < legacyHeroes || portrait >= moddedStart)
|
||||
{
|
||||
int tempPortrait = portrait >= moddedStart
|
||||
? portrait - GameConstants::HERO_PORTRAIT_SHIFT
|
||||
: portrait;
|
||||
handler.serializeId<si32, si32, HeroTypeID>("portrait", tempPortrait, -1);
|
||||
}
|
||||
else
|
||||
handler.serializeInt("portrait", portrait, -1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const JsonNode & portraitNode = handler.getCurrent()["portrait"];
|
||||
|
||||
if(portraitNode.getType() == JsonNode::JsonType::DATA_STRING)
|
||||
{
|
||||
handler.serializeId<si32, si32, HeroTypeID>("portrait", portrait, -1);
|
||||
if(portrait >= legacyHeroes)
|
||||
portrait += GameConstants::HERO_PORTRAIT_SHIFT;
|
||||
}
|
||||
else
|
||||
handler.serializeInt("portrait", portrait, -1);
|
||||
}
|
||||
}
|
||||
handler.serializeId("portrait", customPortraitSource, HeroTypeID::NONE);
|
||||
|
||||
//primary skills
|
||||
if(handler.saving)
|
||||
|
||||
@@ -69,7 +69,9 @@ public:
|
||||
ConstTransitivePtr<CHero> type;
|
||||
TExpType exp; //experience points
|
||||
ui32 level; //current level of hero
|
||||
si32 portrait; //may be custom
|
||||
|
||||
/// If not NONE - then hero should use portrait from referenced hero type
|
||||
HeroTypeID customPortraitSource;
|
||||
si32 mana; // remaining spell points
|
||||
std::vector<std::pair<SecondarySkill,ui8> > secSkills; //first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert); if hero has ability (-1, -1) it meansthat it should have default secondary abilities
|
||||
EHeroGender gender;
|
||||
@@ -82,7 +84,6 @@ public:
|
||||
ConstTransitivePtr<CCommanderInstance> commander;
|
||||
const CGBoat * boat = nullptr; //set to CGBoat when sailing
|
||||
|
||||
static constexpr si32 UNINITIALIZED_PORTRAIT = -1;
|
||||
static constexpr si32 UNINITIALIZED_MANA = -1;
|
||||
static constexpr ui32 UNINITIALIZED_MOVEMENT = -1;
|
||||
static constexpr TExpType UNINITIALIZED_EXPERIENCE = std::numeric_limits<TExpType>::max();
|
||||
@@ -144,6 +145,9 @@ public:
|
||||
std::string getBiographyTranslated() const;
|
||||
std::string getNameTranslated() const;
|
||||
|
||||
HeroTypeID getPortraitSource() const;
|
||||
int32_t getIconIndex() const;
|
||||
|
||||
private:
|
||||
std::string getNameTextID() const;
|
||||
std::string getBiographyTextID() const;
|
||||
@@ -321,7 +325,7 @@ public:
|
||||
h & level;
|
||||
h & nameCustomTextId;
|
||||
h & biographyCustomTextId;
|
||||
h & portrait;
|
||||
h & customPortraitSource;
|
||||
h & mana;
|
||||
h & secSkills;
|
||||
h & movement;
|
||||
|
||||
@@ -44,7 +44,6 @@ CQuest::CQuest():
|
||||
textOption(0),
|
||||
completedOption(0),
|
||||
stackDirection(0),
|
||||
heroPortrait(-1),
|
||||
isCustomFirst(false),
|
||||
isCustomNext(false),
|
||||
isCustomComplete(false)
|
||||
@@ -555,7 +554,7 @@ void CGSeerHut::setObjToKill()
|
||||
else if(quest->missionType == CQuest::MISSION_KILL_HERO)
|
||||
{
|
||||
quest->heroName = getHeroToKill(false)->getNameTranslated();
|
||||
quest->heroPortrait = getHeroToKill(false)->portrait;
|
||||
quest->heroPortrait = getHeroToKill(false)->getPortraitSource();
|
||||
}
|
||||
|
||||
quest->getCompletionText(configuration.onSelect);
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
CStackBasicDescriptor stackToKill;
|
||||
ui8 stackDirection;
|
||||
std::string heroName; //backup of hero name
|
||||
si32 heroPortrait;
|
||||
HeroTypeID heroPortrait;
|
||||
|
||||
MetaString firstVisitText, nextVisitText, completedText;
|
||||
bool isCustomFirst;
|
||||
|
||||
@@ -32,29 +32,29 @@ PlayerInfo::PlayerInfo(): canHumanPlay(false), canComputerPlay(false),
|
||||
allowedFactions = VLC->townh->getAllowedFactions();
|
||||
}
|
||||
|
||||
si8 PlayerInfo::defaultCastle() const
|
||||
FactionID PlayerInfo::defaultCastle() const
|
||||
{
|
||||
//if random allowed set it as default
|
||||
if(isFactionRandom)
|
||||
return -1;
|
||||
return FactionID::RANDOM;
|
||||
|
||||
if(!allowedFactions.empty())
|
||||
return *allowedFactions.begin();
|
||||
|
||||
// fall back to random
|
||||
return -1;
|
||||
return FactionID::RANDOM;
|
||||
}
|
||||
|
||||
si8 PlayerInfo::defaultHero() const
|
||||
HeroTypeID PlayerInfo::defaultHero() const
|
||||
{
|
||||
// we will generate hero in front of main town
|
||||
if((generateHeroAtMainTown && hasMainTown) || hasRandomHero)
|
||||
{
|
||||
//random hero
|
||||
return -1;
|
||||
return HeroTypeID::RANDOM;
|
||||
}
|
||||
|
||||
return -2;
|
||||
return HeroTypeID::NONE;
|
||||
}
|
||||
|
||||
bool PlayerInfo::canAnyonePlay() const
|
||||
@@ -64,7 +64,7 @@ bool PlayerInfo::canAnyonePlay() const
|
||||
|
||||
bool PlayerInfo::hasCustomMainHero() const
|
||||
{
|
||||
return !mainCustomHeroNameTextId.empty() && mainCustomHeroPortrait != -1;
|
||||
return mainCustomHeroId.isValid();
|
||||
}
|
||||
|
||||
EventCondition::EventCondition(EWinLoseType condition):
|
||||
|
||||
@@ -27,7 +27,7 @@ struct DLL_LINKAGE SHeroName
|
||||
{
|
||||
SHeroName();
|
||||
|
||||
int heroId;
|
||||
HeroTypeID heroId;
|
||||
std::string heroName;
|
||||
|
||||
template <typename Handler>
|
||||
@@ -45,9 +45,9 @@ struct DLL_LINKAGE PlayerInfo
|
||||
PlayerInfo();
|
||||
|
||||
/// Gets the default faction id or -1 for a random faction.
|
||||
si8 defaultCastle() const;
|
||||
FactionID defaultCastle() const;
|
||||
/// Gets the default hero id or -1 for a random hero.
|
||||
si8 defaultHero() const;
|
||||
HeroTypeID defaultHero() const;
|
||||
bool canAnyonePlay() const;
|
||||
bool hasCustomMainHero() const;
|
||||
|
||||
@@ -63,10 +63,10 @@ struct DLL_LINKAGE PlayerInfo
|
||||
/// Player has a random main hero
|
||||
bool hasRandomHero;
|
||||
/// The default value is -1.
|
||||
si32 mainCustomHeroPortrait;
|
||||
HeroTypeID mainCustomHeroPortrait;
|
||||
std::string mainCustomHeroNameTextId;
|
||||
/// ID of custom hero (only if portrait and hero name are set, otherwise unpredicted value), -1 if none (not always -1)
|
||||
si32 mainCustomHeroId;
|
||||
HeroTypeID mainCustomHeroId;
|
||||
|
||||
std::vector<SHeroName> heroesNames; /// list of placed heroes on the map
|
||||
bool hasMainTown; /// The default value is false.
|
||||
|
||||
@@ -80,7 +80,7 @@ MapFormatFeaturesH3M MapFormatFeaturesH3M::getFeaturesAB()
|
||||
result.creaturesCount = 145; // + Conflux and new neutrals
|
||||
|
||||
result.heroesCount = 156; // + Conflux and campaign heroes
|
||||
result.heroesPortraitsCount = 163;
|
||||
result.heroesPortraitsCount = 159; // +Kendal, +young Cristian, +Ordwald
|
||||
result.heroesBytes = 20;
|
||||
|
||||
result.artifactsCount = 129; // + Armaggedon Blade and Vial of Dragon Blood
|
||||
@@ -100,6 +100,8 @@ MapFormatFeaturesH3M MapFormatFeaturesH3M::getFeaturesSOD()
|
||||
result.artifactsCount = 141; // + Combined artifacts
|
||||
result.artifactsBytes = 18;
|
||||
|
||||
result.heroesPortraitsCount = 163; // +Finneas +young Gem +young Sandro +young Yog
|
||||
|
||||
result.artifactSlotsCount = 19; // + MISC_5 slot
|
||||
|
||||
return result;
|
||||
|
||||
@@ -248,9 +248,9 @@ void CMapLoaderH3M::readPlayerInfo()
|
||||
}
|
||||
|
||||
playerInfo.hasRandomHero = reader->readBool();
|
||||
playerInfo.mainCustomHeroId = reader->readHero().getNum();
|
||||
playerInfo.mainCustomHeroId = reader->readHero();
|
||||
|
||||
if(playerInfo.mainCustomHeroId != -1)
|
||||
if(playerInfo.mainCustomHeroId != HeroTypeID::NONE)
|
||||
{
|
||||
playerInfo.mainCustomHeroPortrait = reader->readHeroPortrait();
|
||||
playerInfo.mainCustomHeroNameTextId = readLocalizedString(TextIdentifier("header", "player", i, "mainHeroName"));
|
||||
@@ -263,7 +263,7 @@ void CMapLoaderH3M::readPlayerInfo()
|
||||
for(int pp = 0; pp < heroCount; ++pp)
|
||||
{
|
||||
SHeroName vv;
|
||||
vv.heroId = reader->readUInt8();
|
||||
vv.heroId = reader->readHero();
|
||||
vv.heroName = readLocalizedString(TextIdentifier("header", "heroNames", vv.heroId));
|
||||
|
||||
playerInfo.heroesNames.push_back(vv);
|
||||
@@ -547,7 +547,6 @@ void CMapLoaderH3M::readVictoryLossConditions()
|
||||
}
|
||||
);
|
||||
|
||||
assert(playersOnMap > 1);
|
||||
if(playersOnMap == 1)
|
||||
{
|
||||
logGlobal->warn("Map %s: Only one player exists, but normal victory allowed!", mapName);
|
||||
@@ -703,8 +702,8 @@ void CMapLoaderH3M::readDisposedHeroes()
|
||||
map->disposedHeroes.resize(disp);
|
||||
for(int g = 0; g < disp; ++g)
|
||||
{
|
||||
map->disposedHeroes[g].heroId = reader->readHero().getNum();
|
||||
map->disposedHeroes[g].portrait = reader->readHeroPortrait();
|
||||
map->disposedHeroes[g].heroId = reader->readHero();
|
||||
map->disposedHeroes[g].portrait.setNum(reader->readHeroPortrait());
|
||||
map->disposedHeroes[g].name = readLocalizedString(TextIdentifier("header", "heroes", map->disposedHeroes[g].heroId));
|
||||
reader->readBitmaskPlayers(map->disposedHeroes[g].players, false);
|
||||
}
|
||||
@@ -1679,14 +1678,13 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
|
||||
}
|
||||
|
||||
setOwnerAndValidate(mapPosition, object, owner);
|
||||
object->portrait = CGHeroInstance::UNINITIALIZED_PORTRAIT;
|
||||
|
||||
for(auto & elem : map->disposedHeroes)
|
||||
{
|
||||
if(elem.heroId.getNum() == object->subID)
|
||||
{
|
||||
object->nameCustomTextId = elem.name;
|
||||
object->portrait = elem.portrait;
|
||||
object->customPortraitSource = elem.portrait;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1712,7 +1710,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
|
||||
|
||||
bool hasPortrait = reader->readBool();
|
||||
if(hasPortrait)
|
||||
object->portrait = reader->readHeroPortrait();
|
||||
object->customPortraitSource = reader->readHeroPortrait();
|
||||
|
||||
bool hasSecSkills = reader->readBool();
|
||||
if(hasSecSkills)
|
||||
|
||||
@@ -562,11 +562,11 @@ void CMapFormatJson::serializePlayerInfo(JsonSerializeFormat & handler)
|
||||
const std::string instanceName = hero.first;
|
||||
|
||||
SHeroName hname;
|
||||
hname.heroId = -1;
|
||||
hname.heroId = HeroTypeID::NONE;
|
||||
std::string rawId = data["type"].String();
|
||||
|
||||
if(!rawId.empty())
|
||||
hname.heroId = HeroTypeID::decode(rawId);
|
||||
hname.heroId = HeroTypeID(HeroTypeID::decode(rawId));
|
||||
|
||||
hname.heroName = data["name"].String();
|
||||
|
||||
@@ -574,9 +574,9 @@ void CMapFormatJson::serializePlayerInfo(JsonSerializeFormat & handler)
|
||||
{
|
||||
//this is main hero
|
||||
info.mainCustomHeroNameTextId = hname.heroName;
|
||||
info.hasRandomHero = (hname.heroId == -1);
|
||||
info.hasRandomHero = (hname.heroId == HeroTypeID::NONE);
|
||||
info.mainCustomHeroId = hname.heroId;
|
||||
info.mainCustomHeroPortrait = -1;
|
||||
info.mainCustomHeroPortrait = HeroTypeID::NONE;
|
||||
//todo:mainHeroPortrait
|
||||
}
|
||||
|
||||
@@ -744,7 +744,7 @@ void CMapFormatJson::readDisposedHeroes(JsonSerializeFormat & handler)
|
||||
{
|
||||
DisposedHero hero;
|
||||
|
||||
hero.heroId = type.getNum();
|
||||
hero.heroId = type;
|
||||
hero.players = mask;
|
||||
//name and portrait are not used
|
||||
|
||||
|
||||
@@ -87,15 +87,7 @@ void MapIdentifiersH3M::loadMapping(const JsonNode & mapping)
|
||||
}
|
||||
}
|
||||
|
||||
for (auto entry : mapping["portraits"].Struct())
|
||||
{
|
||||
int32_t sourceID = entry.second.Integer();
|
||||
int32_t targetID = *VLC->identifiers()->getIdentifier(entry.second.meta, "hero", entry.first);
|
||||
int32_t iconID = VLC->heroTypes()->getByIndex(targetID)->getIconIndex();
|
||||
|
||||
mappingHeroPortrait[sourceID] = iconID;
|
||||
}
|
||||
|
||||
loadMapping(mappingHeroPortrait, mapping["portraits"], "hero");
|
||||
loadMapping(mappingBuilding, mapping["buildingsCommon"], "building.core:random");
|
||||
loadMapping(mappingFaction, mapping["factions"], "faction");
|
||||
loadMapping(mappingCreature, mapping["creatures"], "creature");
|
||||
@@ -168,7 +160,7 @@ HeroTypeID MapIdentifiersH3M::remap(HeroTypeID input) const
|
||||
return input;
|
||||
}
|
||||
|
||||
int32_t MapIdentifiersH3M::remapPortrrait(int32_t input) const
|
||||
HeroTypeID MapIdentifiersH3M::remapPortrait(HeroTypeID input) const
|
||||
{
|
||||
if (mappingHeroPortrait.count(input))
|
||||
return mappingHeroPortrait.at(input);
|
||||
|
||||
@@ -38,7 +38,7 @@ class MapIdentifiersH3M
|
||||
std::map<FactionID, FactionID> mappingFaction;
|
||||
std::map<CreatureID, CreatureID> mappingCreature;
|
||||
std::map<HeroTypeID, HeroTypeID> mappingHeroType;
|
||||
std::map<int32_t, int32_t> mappingHeroPortrait;
|
||||
std::map<HeroTypeID, HeroTypeID> mappingHeroPortrait;
|
||||
std::map<HeroClassID, HeroClassID> mappingHeroClass;
|
||||
std::map<TerrainId, TerrainId> mappingTerrain;
|
||||
std::map<ArtifactID, ArtifactID> mappingArtifact;
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
void remapTemplate(ObjectTemplate & objectTemplate);
|
||||
|
||||
BuildingID remapBuilding(std::optional<FactionID> owner, BuildingID input) const;
|
||||
int32_t remapPortrrait(int32_t input) const;
|
||||
HeroTypeID remapPortrait(HeroTypeID input) const;
|
||||
FactionID remap(FactionID input) const;
|
||||
CreatureID remap(CreatureID input) const;
|
||||
HeroTypeID remap(HeroTypeID input) const;
|
||||
|
||||
@@ -106,20 +106,20 @@ HeroTypeID MapReaderH3M::readHero()
|
||||
return remapIdentifier(result);
|
||||
}
|
||||
|
||||
int32_t MapReaderH3M::readHeroPortrait()
|
||||
HeroTypeID MapReaderH3M::readHeroPortrait()
|
||||
{
|
||||
HeroTypeID result(reader->readUInt8());
|
||||
|
||||
if(result.getNum() == features.heroIdentifierInvalid)
|
||||
return int32_t(-1);
|
||||
return HeroTypeID::NONE;
|
||||
|
||||
if (result.getNum() >= features.heroesPortraitsCount)
|
||||
{
|
||||
logGlobal->warn("Map contains invalid hero portrait ID %d. Will be reset!", result.getNum() );
|
||||
return int32_t(-1);
|
||||
return HeroTypeID::NONE;
|
||||
}
|
||||
|
||||
return remapper.remapPortrrait(result);
|
||||
return remapper.remapPortrait(result);
|
||||
}
|
||||
|
||||
CreatureID MapReaderH3M::readCreature()
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
ArtifactID readArtifact32();
|
||||
CreatureID readCreature();
|
||||
HeroTypeID readHero();
|
||||
int32_t readHeroPortrait();
|
||||
HeroTypeID readHeroPortrait();
|
||||
TerrainId readTerrain();
|
||||
RoadId readRoad();
|
||||
RiverId readRiver();
|
||||
|
||||
@@ -158,7 +158,6 @@ void Initializer::initialize(CGHeroInstance * o)
|
||||
// o->type = VLC->heroh->objects.at(o->subID);
|
||||
|
||||
o->gender = o->type->gender;
|
||||
o->portrait = o->type->imageIndex;
|
||||
o->randomizeArmy(o->type->heroClass->faction);
|
||||
}
|
||||
}
|
||||
@@ -279,7 +278,7 @@ void Inspector::updateProperties(CGHeroInstance * o)
|
||||
}
|
||||
addProperty("Name", o->getNameTranslated(), false);
|
||||
addProperty("Biography", o->getBiographyTranslated(), new MessageDelegate, false);
|
||||
addProperty("Portrait", o->portrait, false);
|
||||
addProperty("Portrait", o->customPortraitSource, false);
|
||||
|
||||
auto * delegate = new HeroSkillsDelegate(*o);
|
||||
addProperty("Skills", PropertyEditorPlaceholder(), delegate, false);
|
||||
@@ -622,7 +621,6 @@ void Inspector::setProperty(CGHeroInstance * o, const QString & key, const QVari
|
||||
o->type = t.get();
|
||||
}
|
||||
o->gender = o->type->gender;
|
||||
o->portrait = o->type->imageIndex;
|
||||
o->randomizeArmy(o->type->heroClass->faction);
|
||||
updateProperties(); //updating other properties after change
|
||||
}
|
||||
|
||||
@@ -184,9 +184,6 @@ void MapController::repairMap(CMap * map) const
|
||||
nih->putArtifact(ArtifactPosition::SPELLBOOK, ArtifactUtils::createNewArtifactInstance(ArtifactID::SPELLBOOK));
|
||||
}
|
||||
|
||||
//fix portrait
|
||||
if(nih->portrait < 0 || nih->portrait == 255)
|
||||
nih->portrait = type->imageIndex;
|
||||
}
|
||||
//fix town instance
|
||||
if(auto * tnh = dynamic_cast<CGTownInstance*>(obj.get()))
|
||||
|
||||
@@ -172,7 +172,7 @@ void PlayerParams::on_mainTown_currentIndexChanged(int index)
|
||||
|
||||
void PlayerParams::on_teamId_activated(int index)
|
||||
{
|
||||
playerInfo.team = ui->teamId->currentData().toInt();
|
||||
playerInfo.team.setNum(ui->teamId->currentData().toInt());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -729,7 +729,7 @@ void CVCMIServer::updateStartInfoOnMapChange(std::shared_ptr<CMapInfo> mapInfo,
|
||||
pset.castle = pinfo.defaultCastle();
|
||||
pset.hero = pinfo.defaultHero();
|
||||
|
||||
if(pset.hero.getNum() != PlayerSettings::RANDOM && pinfo.hasCustomMainHero())
|
||||
if(pset.hero != HeroTypeID::RANDOM && pinfo.hasCustomMainHero())
|
||||
{
|
||||
pset.hero = pinfo.mainCustomHeroId;
|
||||
pset.heroNameTextId = pinfo.mainCustomHeroNameTextId;
|
||||
@@ -839,13 +839,13 @@ void CVCMIServer::optionNextCastle(PlayerColor player, int dir)
|
||||
{
|
||||
PlayerSettings & s = si->playerInfos[player];
|
||||
FactionID & cur = s.castle;
|
||||
auto & allowed = getPlayerInfo(player.getNum()).allowedFactions;
|
||||
const bool allowRandomTown = getPlayerInfo(player.getNum()).isFactionRandom;
|
||||
auto & allowed = getPlayerInfo(player).allowedFactions;
|
||||
const bool allowRandomTown = getPlayerInfo(player).isFactionRandom;
|
||||
|
||||
if(cur.getNum() == PlayerSettings::NONE) //no change
|
||||
if(cur == FactionID::NONE) //no change
|
||||
return;
|
||||
|
||||
if(cur.getNum() == PlayerSettings::RANDOM) //first/last available
|
||||
if(cur == FactionID::RANDOM) //first/last available
|
||||
{
|
||||
if(dir > 0)
|
||||
cur = *allowed.begin(); //id of first town
|
||||
@@ -859,7 +859,7 @@ void CVCMIServer::optionNextCastle(PlayerColor player, int dir)
|
||||
{
|
||||
if(allowRandomTown)
|
||||
{
|
||||
cur = PlayerSettings::RANDOM;
|
||||
cur = FactionID::RANDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -878,34 +878,34 @@ void CVCMIServer::optionNextCastle(PlayerColor player, int dir)
|
||||
}
|
||||
}
|
||||
|
||||
if(s.hero.getNum() >= 0 && !getPlayerInfo(player.getNum()).hasCustomMainHero()) // remove hero unless it set to fixed one in map editor
|
||||
if(s.hero.isValid() && !getPlayerInfo(player).hasCustomMainHero()) // remove hero unless it set to fixed one in map editor
|
||||
{
|
||||
s.hero = PlayerSettings::RANDOM;
|
||||
s.hero = HeroTypeID::RANDOM;
|
||||
}
|
||||
if(cur.getNum() < 0 && s.bonus == PlayerSettings::RESOURCE)
|
||||
s.bonus = PlayerSettings::RANDOM;
|
||||
if(!cur.isValid() && s.bonus == PlayerStartingBonus::RESOURCE)
|
||||
s.bonus = PlayerStartingBonus::RANDOM;
|
||||
}
|
||||
|
||||
void CVCMIServer::optionSetCastle(PlayerColor player, int id)
|
||||
void CVCMIServer::optionSetCastle(PlayerColor player, FactionID id)
|
||||
{
|
||||
PlayerSettings & s = si->playerInfos[player];
|
||||
FactionID & cur = s.castle;
|
||||
auto & allowed = getPlayerInfo(player.getNum()).allowedFactions;
|
||||
auto & allowed = getPlayerInfo(player).allowedFactions;
|
||||
|
||||
if(cur.getNum() == PlayerSettings::NONE) //no change
|
||||
if(cur == FactionID::NONE) //no change
|
||||
return;
|
||||
|
||||
if(allowed.find(static_cast<FactionID>(id)) == allowed.end() && id != PlayerSettings::RANDOM) // valid id
|
||||
if(allowed.find(id) == allowed.end() && id != FactionID::RANDOM) // valid id
|
||||
return;
|
||||
|
||||
cur = static_cast<FactionID>(id);
|
||||
|
||||
if(s.hero.getNum() >= 0 && !getPlayerInfo(player.getNum()).hasCustomMainHero()) // remove hero unless it set to fixed one in map editor
|
||||
if(s.hero.isValid() && !getPlayerInfo(player).hasCustomMainHero()) // remove hero unless it set to fixed one in map editor
|
||||
{
|
||||
s.hero = PlayerSettings::RANDOM;
|
||||
s.hero = HeroTypeID::RANDOM;
|
||||
}
|
||||
if(cur.getNum() < 0 && s.bonus == PlayerSettings::RESOURCE)
|
||||
s.bonus = PlayerSettings::RANDOM;
|
||||
if(!cur.isValid() && s.bonus == PlayerStartingBonus::RESOURCE)
|
||||
s.bonus = PlayerStartingBonus::RANDOM;
|
||||
}
|
||||
|
||||
void CVCMIServer::setCampaignMap(CampaignScenarioID mapId)
|
||||
@@ -937,105 +937,105 @@ void CVCMIServer::setCampaignBonus(int bonusId)
|
||||
void CVCMIServer::optionNextHero(PlayerColor player, int dir)
|
||||
{
|
||||
PlayerSettings & s = si->playerInfos[player];
|
||||
if(s.castle.getNum() < 0 || s.hero.getNum() == PlayerSettings::NONE)
|
||||
if(!s.castle.isValid() || s.hero == HeroTypeID::NONE)
|
||||
return;
|
||||
|
||||
if(s.hero.getNum() == PlayerSettings::RANDOM) // first/last available
|
||||
if(s.hero == HeroTypeID::RANDOM) // first/last available
|
||||
{
|
||||
int max = static_cast<int>(VLC->heroh->size()),
|
||||
min = 0;
|
||||
s.hero = nextAllowedHero(player, min, max, 0, dir);
|
||||
if (dir > 0)
|
||||
s.hero = nextAllowedHero(player, HeroTypeID(-1), dir);
|
||||
else
|
||||
s.hero = nextAllowedHero(player, HeroTypeID(VLC->heroh->size()), dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dir > 0)
|
||||
s.hero = nextAllowedHero(player, s.hero, (int)VLC->heroh->size(), 1, dir);
|
||||
else
|
||||
s.hero = nextAllowedHero(player, -1, s.hero, 1, dir); // min needs to be -1 -- hero at index 0 would be skipped otherwise
|
||||
s.hero = nextAllowedHero(player, s.hero, dir);
|
||||
}
|
||||
}
|
||||
|
||||
void CVCMIServer::optionSetHero(PlayerColor player, int id)
|
||||
void CVCMIServer::optionSetHero(PlayerColor player, HeroTypeID id)
|
||||
{
|
||||
PlayerSettings & s = si->playerInfos[player];
|
||||
if(s.castle.getNum() < 0 || s.hero.getNum() == PlayerSettings::NONE)
|
||||
if(!s.castle.isValid() || s.hero == HeroTypeID::NONE)
|
||||
return;
|
||||
|
||||
if(id == PlayerSettings::RANDOM)
|
||||
if(id == HeroTypeID::RANDOM)
|
||||
{
|
||||
s.hero = PlayerSettings::RANDOM;
|
||||
s.hero = HeroTypeID::RANDOM;
|
||||
}
|
||||
if(canUseThisHero(player, id))
|
||||
s.hero = static_cast<HeroTypeID>(id);
|
||||
}
|
||||
|
||||
HeroTypeID CVCMIServer::nextAllowedHero(PlayerColor player, int min, int max, int incl, int dir)
|
||||
HeroTypeID CVCMIServer::nextAllowedHero(PlayerColor player, HeroTypeID initial, int direction)
|
||||
{
|
||||
if(dir > 0)
|
||||
HeroTypeID first(initial.getNum() + direction);
|
||||
|
||||
if(direction > 0)
|
||||
{
|
||||
for(int i = min + incl; i <= max - incl; i++)
|
||||
for (auto i = first; i.getNum() < VLC->heroh->size(); ++i)
|
||||
if(canUseThisHero(player, i))
|
||||
return HeroTypeID(i);
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = max - incl; i >= min + incl; i--)
|
||||
for (auto i = first; i.getNum() >= 0; --i)
|
||||
if(canUseThisHero(player, i))
|
||||
return HeroTypeID(i);
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
return HeroTypeID::RANDOM;
|
||||
}
|
||||
|
||||
void CVCMIServer::optionNextBonus(PlayerColor player, int dir)
|
||||
{
|
||||
PlayerSettings & s = si->playerInfos[player];
|
||||
PlayerSettings::Ebonus & ret = s.bonus = static_cast<PlayerSettings::Ebonus>(static_cast<int>(s.bonus) + dir);
|
||||
PlayerStartingBonus & ret = s.bonus = static_cast<PlayerStartingBonus>(static_cast<int>(s.bonus) + dir);
|
||||
|
||||
if(s.hero.getNum() == PlayerSettings::NONE &&
|
||||
!getPlayerInfo(player.getNum()).heroesNames.size() &&
|
||||
ret == PlayerSettings::ARTIFACT) //no hero - can't be artifact
|
||||
if(s.hero == HeroTypeID::NONE &&
|
||||
!getPlayerInfo(player).heroesNames.size() &&
|
||||
ret == PlayerStartingBonus::ARTIFACT) //no hero - can't be artifact
|
||||
{
|
||||
if(dir < 0)
|
||||
ret = PlayerSettings::RANDOM;
|
||||
ret = PlayerStartingBonus::RANDOM;
|
||||
else
|
||||
ret = PlayerSettings::GOLD;
|
||||
ret = PlayerStartingBonus::GOLD;
|
||||
}
|
||||
|
||||
if(ret > PlayerSettings::RESOURCE)
|
||||
ret = PlayerSettings::RANDOM;
|
||||
if(ret < PlayerSettings::RANDOM)
|
||||
ret = PlayerSettings::RESOURCE;
|
||||
if(ret > PlayerStartingBonus::RESOURCE)
|
||||
ret = PlayerStartingBonus::RANDOM;
|
||||
if(ret < PlayerStartingBonus::RANDOM)
|
||||
ret = PlayerStartingBonus::RESOURCE;
|
||||
|
||||
if(s.castle.getNum() == PlayerSettings::RANDOM && ret == PlayerSettings::RESOURCE) //random castle - can't be resource
|
||||
if(s.castle == FactionID::RANDOM && ret == PlayerStartingBonus::RESOURCE) //random castle - can't be resource
|
||||
{
|
||||
if(dir < 0)
|
||||
ret = PlayerSettings::GOLD;
|
||||
ret = PlayerStartingBonus::GOLD;
|
||||
else
|
||||
ret = PlayerSettings::RANDOM;
|
||||
ret = PlayerStartingBonus::RANDOM;
|
||||
}
|
||||
}
|
||||
|
||||
void CVCMIServer::optionSetBonus(PlayerColor player, int id)
|
||||
void CVCMIServer::optionSetBonus(PlayerColor player, PlayerStartingBonus id)
|
||||
{
|
||||
PlayerSettings & s = si->playerInfos[player];
|
||||
|
||||
if(s.hero.getNum() == PlayerSettings::NONE &&
|
||||
!getPlayerInfo(player.getNum()).heroesNames.size() &&
|
||||
id == PlayerSettings::ARTIFACT) //no hero - can't be artifact
|
||||
if(s.hero == HeroTypeID::NONE &&
|
||||
!getPlayerInfo(player).heroesNames.size() &&
|
||||
id == PlayerStartingBonus::ARTIFACT) //no hero - can't be artifact
|
||||
return;
|
||||
|
||||
if(id > PlayerSettings::RESOURCE)
|
||||
if(id > PlayerStartingBonus::RESOURCE)
|
||||
return;
|
||||
if(id < PlayerSettings::RANDOM)
|
||||
if(id < PlayerStartingBonus::RANDOM)
|
||||
return;
|
||||
|
||||
if(s.castle.getNum() == PlayerSettings::RANDOM && id == PlayerSettings::RESOURCE) //random castle - can't be resource
|
||||
if(s.castle == FactionID::RANDOM && id == PlayerStartingBonus::RESOURCE) //random castle - can't be resource
|
||||
return;
|
||||
|
||||
s.bonus = static_cast<PlayerSettings::Ebonus>(static_cast<int>(id));
|
||||
s.bonus = id;;
|
||||
}
|
||||
|
||||
bool CVCMIServer::canUseThisHero(PlayerColor player, int ID)
|
||||
bool CVCMIServer::canUseThisHero(PlayerColor player, HeroTypeID ID)
|
||||
{
|
||||
return VLC->heroh->size() > ID
|
||||
&& si->playerInfos[player].castle == VLC->heroh->objects[ID]->heroClass->faction
|
||||
@@ -1043,17 +1043,17 @@ bool CVCMIServer::canUseThisHero(PlayerColor player, int ID)
|
||||
&& mi->mapHeader->allowedHeroes[ID];
|
||||
}
|
||||
|
||||
std::vector<int> CVCMIServer::getUsedHeroes()
|
||||
std::vector<HeroTypeID> CVCMIServer::getUsedHeroes()
|
||||
{
|
||||
std::vector<int> heroIds;
|
||||
std::vector<HeroTypeID> heroIds;
|
||||
for(auto & p : si->playerInfos)
|
||||
{
|
||||
const auto & heroes = getPlayerInfo(p.first.getNum()).heroesNames;
|
||||
const auto & heroes = getPlayerInfo(p.first).heroesNames;
|
||||
for(auto & hero : heroes)
|
||||
if(hero.heroId >= 0) //in VCMI map format heroId = -1 means random hero
|
||||
heroIds.push_back(hero.heroId);
|
||||
|
||||
if(p.second.hero.getNum() != PlayerSettings::RANDOM)
|
||||
if(p.second.hero != HeroTypeID::RANDOM)
|
||||
heroIds.push_back(p.second.hero);
|
||||
}
|
||||
return heroIds;
|
||||
|
||||
@@ -108,14 +108,14 @@ public:
|
||||
// Work with LobbyInfo
|
||||
void setPlayer(PlayerColor clickedColor);
|
||||
void optionNextHero(PlayerColor player, int dir); //dir == -1 or +1
|
||||
void optionSetHero(PlayerColor player, int id);
|
||||
HeroTypeID nextAllowedHero(PlayerColor player, int min, int max, int incl, int dir);
|
||||
bool canUseThisHero(PlayerColor player, int ID);
|
||||
std::vector<int> getUsedHeroes();
|
||||
void optionSetHero(PlayerColor player, HeroTypeID id);
|
||||
HeroTypeID nextAllowedHero(PlayerColor player, HeroTypeID id, int direction);
|
||||
bool canUseThisHero(PlayerColor player, HeroTypeID ID);
|
||||
std::vector<HeroTypeID> getUsedHeroes();
|
||||
void optionNextBonus(PlayerColor player, int dir); //dir == -1 or +1
|
||||
void optionSetBonus(PlayerColor player, int id);
|
||||
void optionSetBonus(PlayerColor player, PlayerStartingBonus id);
|
||||
void optionNextCastle(PlayerColor player, int dir); //dir == -1 or +
|
||||
void optionSetCastle(PlayerColor player, int id);
|
||||
void optionSetCastle(PlayerColor player, FactionID id);
|
||||
|
||||
// Campaigns
|
||||
void setCampaignMap(CampaignScenarioID mapId);
|
||||
|
||||
@@ -369,19 +369,19 @@ void ApplyOnServerNetPackVisitor::visitLobbyChangePlayerOption(LobbyChangePlayer
|
||||
switch(pack.what)
|
||||
{
|
||||
case LobbyChangePlayerOption::TOWN_ID:
|
||||
srv.optionSetCastle(pack.color, pack.value);
|
||||
srv.optionSetCastle(pack.color, FactionID(pack.value));
|
||||
break;
|
||||
case LobbyChangePlayerOption::TOWN:
|
||||
srv.optionNextCastle(pack.color, pack.value);
|
||||
break;
|
||||
case LobbyChangePlayerOption::HERO_ID:
|
||||
srv.optionSetHero(pack.color, pack.value);
|
||||
srv.optionSetHero(pack.color, HeroTypeID(pack.value));
|
||||
break;
|
||||
case LobbyChangePlayerOption::HERO:
|
||||
srv.optionNextHero(pack.color, pack.value);
|
||||
break;
|
||||
case LobbyChangePlayerOption::BONUS_ID:
|
||||
srv.optionSetBonus(pack.color, pack.value);
|
||||
srv.optionSetBonus(pack.color, PlayerStartingBonus(pack.value));
|
||||
break;
|
||||
case LobbyChangePlayerOption::BONUS:
|
||||
srv.optionNextBonus(pack.color, pack.value);
|
||||
|
||||
@@ -277,7 +277,7 @@ void BattleResultProcessor::endBattle(const CBattleInfoCallback & battle)
|
||||
gameHandler->queries->addQuery(battleDialogQuery);
|
||||
}
|
||||
else
|
||||
battleResult->queryID = -1;
|
||||
battleResult->queryID = QueryID::NONE;
|
||||
|
||||
//set same battle result for all gameHandler->queries
|
||||
for(auto q : gameHandler->queries->allQueries())
|
||||
|
||||
@@ -72,7 +72,7 @@ void HeroPoolProcessor::onHeroSurrendered(const PlayerColor & color, const CGHer
|
||||
|
||||
sah.slotID = selectSlotForRole(color, sah.roleID);
|
||||
sah.player = color;
|
||||
sah.hid = hero->subID;
|
||||
sah.hid.setNum(hero->subID);
|
||||
gameHandler->sendAndApply(&sah);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ void HeroPoolProcessor::onHeroEscaped(const PlayerColor & color, const CGHeroIns
|
||||
|
||||
sah.slotID = selectSlotForRole(color, sah.roleID);
|
||||
sah.player = color;
|
||||
sah.hid = hero->subID;
|
||||
sah.hid.setNum(hero->subID);
|
||||
sah.army.clearSlots();
|
||||
sah.army.setCreature(SlotID(0), hero->type->initialArmy.at(0).creature, 1);
|
||||
|
||||
@@ -110,7 +110,7 @@ void HeroPoolProcessor::selectNewHeroForSlot(const PlayerColor & color, TavernHe
|
||||
|
||||
if (newHero)
|
||||
{
|
||||
sah.hid = newHero->subID;
|
||||
sah.hid.setNum(newHero->subID);
|
||||
|
||||
if (giveArmy)
|
||||
{
|
||||
@@ -126,7 +126,7 @@ void HeroPoolProcessor::selectNewHeroForSlot(const PlayerColor & color, TavernHe
|
||||
}
|
||||
else
|
||||
{
|
||||
sah.hid = -1;
|
||||
sah.hid = HeroTypeID::NONE;
|
||||
}
|
||||
gameHandler->sendAndApply(&sah);
|
||||
}
|
||||
@@ -205,7 +205,7 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy
|
||||
|
||||
HeroRecruited hr;
|
||||
hr.tid = mapObject->id;
|
||||
hr.hid = recruitedHero->subID;
|
||||
hr.hid.setNum(recruitedHero->subID);
|
||||
hr.player = player;
|
||||
hr.tile = recruitedHero->convertFromVisitablePos(targetPos );
|
||||
if(gameHandler->getTile(targetPos)->isWater() && !recruitedHero->boat)
|
||||
|
||||
@@ -167,11 +167,11 @@ public:
|
||||
pset.castle = pinfo.defaultCastle();
|
||||
pset.hero = pinfo.defaultHero();
|
||||
|
||||
if(pset.hero.getNum() != PlayerSettings::RANDOM && pinfo.hasCustomMainHero())
|
||||
if(pset.hero != HeroTypeID::RANDOM && pinfo.hasCustomMainHero())
|
||||
{
|
||||
pset.hero = pinfo.mainCustomHeroId;
|
||||
pset.heroNameTextId = pinfo.mainCustomHeroNameTextId;
|
||||
pset.heroPortrait = pinfo.mainCustomHeroPortrait;
|
||||
pset.heroPortrait = HeroTypeID(pinfo.mainCustomHeroPortrait);
|
||||
}
|
||||
|
||||
pset.handicap = PlayerSettings::NO_HANDICAP;
|
||||
|
||||
Reference in New Issue
Block a user