1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00
vcmi/lib/mapping/CMapHeader.cpp

208 lines
6.1 KiB
C++
Raw Normal View History

2023-05-24 00:14:06 +02:00
/*
* CMapHeader.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "CMapHeader.h"
#include "MapFormat.h"
#include "../VCMI_Lib.h"
#include "../CTownHandler.h"
#include "../CGeneralTextHandler.h"
#include "../json/JsonUtils.h"
2023-09-29 00:24:45 +02:00
#include "../modding/CModHandler.h"
2023-05-24 00:14:06 +02:00
#include "../CHeroHandler.h"
2023-09-28 13:09:01 +02:00
#include "../Languages.h"
2023-05-24 00:14:06 +02:00
2023-05-24 01:12:25 +02:00
VCMI_LIB_NAMESPACE_BEGIN
2023-05-24 00:14:06 +02:00
SHeroName::SHeroName() : heroId(-1)
{
}
PlayerInfo::PlayerInfo(): canHumanPlay(false), canComputerPlay(false),
aiTactic(EAiTactic::RANDOM), isFactionRandom(false), hasRandomHero(false), mainCustomHeroPortrait(-1), mainCustomHeroId(-1), hasMainTown(false),
generateHeroAtMainTown(false), posOfMainTown(-1), team(TeamID::NO_TEAM)
{
allowedFactions = VLC->townh->getAllowedFactions();
}
FactionID PlayerInfo::defaultCastle() const
2023-05-24 00:14:06 +02:00
{
//if random allowed set it as default
if(isFactionRandom)
return FactionID::RANDOM;
2023-05-24 00:14:06 +02:00
if(!allowedFactions.empty())
return *allowedFactions.begin();
// fall back to random
return FactionID::RANDOM;
2023-05-24 00:14:06 +02:00
}
HeroTypeID PlayerInfo::defaultHero() const
2023-05-24 00:14:06 +02:00
{
// we will generate hero in front of main town
if((generateHeroAtMainTown && hasMainTown) || hasRandomHero)
{
//random hero
return HeroTypeID::RANDOM;
2023-05-24 00:14:06 +02:00
}
return HeroTypeID::NONE;
2023-05-24 00:14:06 +02:00
}
bool PlayerInfo::canAnyonePlay() const
{
return canHumanPlay || canComputerPlay;
}
bool PlayerInfo::hasCustomMainHero() const
{
return mainCustomHeroId.isValid();
2023-05-24 00:14:06 +02:00
}
EventCondition::EventCondition(EWinLoseType condition):
value(-1),
position(-1, -1, -1),
condition(condition)
{
}
EventCondition::EventCondition(EWinLoseType condition, si32 value, TargetTypeID objectType, const int3 & position):
2023-05-24 00:14:06 +02:00
value(value),
objectType(objectType),
position(position),
condition(condition)
{}
void CMapHeader::setupEvents()
{
EventCondition victoryCondition(EventCondition::STANDARD_WIN);
EventCondition defeatCondition(EventCondition::DAYS_WITHOUT_TOWN);
defeatCondition.value = 7;
//Victory condition - defeat all
TriggeredEvent standardVictory;
standardVictory.effect.type = EventEffect::VICTORY;
standardVictory.effect.toOtherMessage.appendTextID("core.genrltxt.5");
2023-05-24 00:14:06 +02:00
standardVictory.identifier = "standardVictory";
standardVictory.description.clear(); // TODO: display in quest window
standardVictory.onFulfill.appendTextID("core.genrltxt.659");
2023-05-24 00:14:06 +02:00
standardVictory.trigger = EventExpression(victoryCondition);
//Loss condition - 7 days without town
TriggeredEvent standardDefeat;
standardDefeat.effect.type = EventEffect::DEFEAT;
standardDefeat.effect.toOtherMessage.appendTextID("core.genrltxt.8");
2023-05-24 00:14:06 +02:00
standardDefeat.identifier = "standardDefeat";
standardDefeat.description.clear(); // TODO: display in quest window
standardDefeat.onFulfill.appendTextID("core.genrltxt.7");
2023-05-24 00:14:06 +02:00
standardDefeat.trigger = EventExpression(defeatCondition);
triggeredEvents.push_back(standardVictory);
triggeredEvents.push_back(standardDefeat);
victoryIconIndex = 11;
victoryMessage.appendTextID("core.vcdesc.0");
2023-05-24 00:14:06 +02:00
defeatIconIndex = 3;
defeatMessage.appendTextID("core.lcdesc.0");
2023-05-24 00:14:06 +02:00
}
CMapHeader::CMapHeader() : version(EMapFormat::VCMI), height(72), width(72),
twoLevel(true), difficulty(EMapDifficulty::NORMAL), levelLimit(0), howManyTeams(0), areAnyPlayers(false)
2023-05-24 00:14:06 +02:00
{
setupEvents();
allowedHeroes = VLC->heroh->getDefaultAllowed();
players.resize(PlayerColor::PLAYER_LIMIT_I);
}
CMapHeader::~CMapHeader() = default;
2023-05-24 00:14:06 +02:00
ui8 CMapHeader::levels() const
{
return (twoLevel ? 2 : 1);
}
2023-05-24 01:12:25 +02:00
2023-09-28 13:09:01 +02:00
void CMapHeader::registerMapStrings()
{
2023-10-01 18:00:36 +02:00
//get supported languages. Assuming that translation containing most strings is the base language
2024-01-10 02:23:24 +02:00
std::set<std::string, std::less<>> mapLanguages;
std::set<std::string, std::less<>> mapBaseLanguages;
2023-10-01 18:00:36 +02:00
int maxStrings = 0;
for(auto & translation : translations.Struct())
2023-09-28 13:09:01 +02:00
{
2023-10-01 18:00:36 +02:00
if(translation.first.empty() || !translation.second.isStruct() || translation.second.Struct().empty())
continue;
2023-09-28 13:09:01 +02:00
2023-10-01 18:00:36 +02:00
if(translation.second.Struct().size() > maxStrings)
maxStrings = translation.second.Struct().size();
mapLanguages.insert(translation.first);
2023-09-28 13:09:01 +02:00
}
2023-10-01 18:00:36 +02:00
if(maxStrings == 0 || mapLanguages.empty())
2023-10-01 18:00:36 +02:00
{
2024-02-05 21:11:00 +02:00
logGlobal->trace("Map %s doesn't have any supported translation", name.toString());
2023-10-01 18:00:36 +02:00
return;
}
//identifying base languages
for(auto & translation : translations.Struct())
{
if(translation.second.isStruct() && translation.second.Struct().size() == maxStrings)
mapBaseLanguages.insert(translation.first);
}
std::string baseLanguage;
std::string language;
2023-10-01 18:00:36 +02:00
//english is preferrable as base language
if(mapBaseLanguages.count(Languages::getLanguageOptions(Languages::ELanguages::ENGLISH).identifier))
baseLanguage = Languages::getLanguageOptions(Languages::ELanguages::ENGLISH).identifier;
else
baseLanguage = *mapBaseLanguages.begin();
if(mapBaseLanguages.count(CGeneralTextHandler::getPreferredLanguage()))
{
language = CGeneralTextHandler::getPreferredLanguage(); //preferred language is base language - use it
baseLanguage = language;
}
else
{
if(mapLanguages.count(CGeneralTextHandler::getPreferredLanguage()))
language = CGeneralTextHandler::getPreferredLanguage();
else
language = baseLanguage; //preferred language is not supported, use base language
}
assert(!language.empty());
JsonNode data = translations[baseLanguage];
if(language != baseLanguage)
JsonUtils::mergeCopy(data, translations[language]);
for(auto & s : data.Struct())
texts.registerString("map", TextIdentifier(s.first), s.second.String(), language);
2023-09-28 13:09:01 +02:00
}
2023-09-29 00:24:45 +02:00
std::string mapRegisterLocalizedString(const std::string & modContext, CMapHeader & mapHeader, const TextIdentifier & UID, const std::string & localized)
2023-09-28 14:38:31 +02:00
{
2023-09-29 00:24:45 +02:00
return mapRegisterLocalizedString(modContext, mapHeader, UID, localized, VLC->modh->getModLanguage(modContext));
2023-09-28 14:38:31 +02:00
}
2023-09-29 00:24:45 +02:00
std::string mapRegisterLocalizedString(const std::string & modContext, CMapHeader & mapHeader, const TextIdentifier & UID, const std::string & localized, const std::string & language)
2023-09-28 14:38:31 +02:00
{
mapHeader.texts.registerString(modContext, UID, localized, language);
2023-09-28 14:38:31 +02:00
mapHeader.translations.Struct()[language].Struct()[UID.get()].String() = localized;
return UID.get();
}
2023-05-24 01:12:25 +02:00
VCMI_LIB_NAMESPACE_END