diff --git a/Global.h b/Global.h index 5123efcaf..3e4c6186b 100644 --- a/Global.h +++ b/Global.h @@ -632,7 +632,7 @@ namespace vstd template typename Container::const_reference atOrDefault(const Container &r, size_t index, const typename Container::const_reference &defaultValue) { - if(isValidIndex(r, index)) + if(index < r.size()) return r[index]; return defaultValue; diff --git a/Mods/WoG/config/wog/creatures.json b/Mods/WoG/config/wog/creatures.json index a5de5bb3f..82fbb9e45 100644 --- a/Mods/WoG/config/wog/creatures.json +++ b/Mods/WoG/config/wog/creatures.json @@ -174,7 +174,7 @@ "faction": "fortress", "abilities" : { - "SHOOTER" : null + "SHOOTING_ARMY" : null }, "graphics" : { diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index e51dfacfc..f916fa3dc 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -943,7 +943,7 @@ size_t CComponent::getIndex() case morale: return val+3; case luck: return val+3; case building: return val; - case hero: return CGI->heroh->heroes[subtype]->imageIndex; + case hero: return subtype; case flag: return subtype; } assert(0); @@ -965,7 +965,7 @@ std::string CComponent::getDescription() case morale: return CGI->generaltexth->heroscrn[ 4 - (val>0) + (val<0)]; case luck: return CGI->generaltexth->heroscrn[ 7 - (val>0) + (val<0)]; case building: return CGI->townh->factions[subtype]->town->buildings[BuildingID(val)]->Description(); - case hero: return CGI->heroh->heroes[subtype]->name; + case hero: return ""; case flag: return ""; } assert(0); @@ -1007,7 +1007,7 @@ std::string CComponent::getSubtitleInternal() case morale: return ""; case luck: return ""; case building: return CGI->townh->factions[subtype]->town->buildings[BuildingID(val)]->Name(); - case hero: return CGI->heroh->heroes[subtype]->name; + case hero: return ""; case flag: return CGI->generaltexth->capColors[subtype]; } assert(0); diff --git a/client/gui/Fonts.cpp b/client/gui/Fonts.cpp index c52829d36..e32c5cf2b 100644 --- a/client/gui/Fonts.cpp +++ b/client/gui/Fonts.cpp @@ -270,9 +270,9 @@ void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, { SDL_Surface * rendered; if (blended) - rendered = TTF_RenderText_Blended(font.get(), data.c_str(), color); + rendered = TTF_RenderUTF8_Blended(font.get(), data.c_str(), color); else - rendered = TTF_RenderText_Solid(font.get(), data.c_str(), color); + rendered = TTF_RenderUTF8_Solid(font.get(), data.c_str(), color); assert(rendered); diff --git a/config/creatures/neutral.json b/config/creatures/neutral.json index c16bbbffa..3d74d624c 100644 --- a/config/creatures/neutral.json +++ b/config/creatures/neutral.json @@ -117,7 +117,7 @@ { "type" : "DRAGON_NATURE" }, - "FLYING" : null + "FLYING_ARMY" : null }, "graphics" : { diff --git a/config/schemas/settings.json b/config/schemas/settings.json index a5d923a60..7c88ba4cd 100644 --- a/config/schemas/settings.json +++ b/config/schemas/settings.json @@ -17,7 +17,7 @@ "type" : "object", "default": {}, "additionalProperties" : false, - "required" : [ "classicCreatureWindow", "playerName", "showfps", "music", "sound" ], + "required" : [ "classicCreatureWindow", "playerName", "showfps", "music", "sound", "encoding" ], "properties" : { "classicCreatureWindow" : { "type" : "boolean", @@ -38,6 +38,10 @@ "sound" : { "type" : "number", "default" : 88 + }, + "encoding" : { + "type" : "string", + "default" : "native" } } }, diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 42fadbbf0..cfb592fa0 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -22,6 +22,7 @@ set(launcher_SRCS main.cpp mainwindow_moc.cpp launcherdirs.cpp + jsonutils.cpp ) set(launcher_FORMS diff --git a/launcher/jsonutils.cpp b/launcher/jsonutils.cpp new file mode 100644 index 000000000..7ef4cbca8 --- /dev/null +++ b/launcher/jsonutils.cpp @@ -0,0 +1,96 @@ +#include "StdInc.h" +#include "jsonutils.h" + +static QVariantMap JsonToMap(const JsonMap & json) +{ + QVariantMap map; + for (auto & entry : json) + { + map.insert(QString::fromUtf8(entry.first.c_str()), JsonUtils::toVariant(entry.second)); + } + return map; +} + +static QVariantList JsonToList(const JsonVector & json) +{ + QVariantList list; + for (auto & entry : json) + { + list.push_back(JsonUtils::toVariant(entry)); + } + return list; +} + +static JsonVector VariantToList(QVariantList variant) +{ + JsonVector vector; + for (auto & entry : variant) + { + vector.push_back(JsonUtils::toJson(entry)); + } + return vector; +} + +static JsonMap VariantToMap(QVariantMap variant) +{ + JsonMap map; + for (auto & entry : variant.toStdMap()) + { + map[entry.first.toUtf8().data()] = JsonUtils::toJson(entry.second); + } + return map; +} + +namespace JsonUtils +{ + +QVariant toVariant(const JsonNode & node) +{ + switch (node.getType()) + { + break; case JsonNode::DATA_NULL: return QVariant(); + break; case JsonNode::DATA_BOOL: return QVariant(node.Bool()); + break; case JsonNode::DATA_FLOAT: return QVariant(node.Float()); + break; case JsonNode::DATA_STRING: return QVariant(QString::fromUtf8(node.String().c_str())); + break; case JsonNode::DATA_VECTOR: return JsonToList(node.Vector()); + break; case JsonNode::DATA_STRUCT: return JsonToMap(node.Struct()); + } + return QVariant(); +} + +QVariant JsonFromFile(QString filename) +{ + QFile file(filename); + file.open(QFile::ReadOnly); + auto data = file.readAll(); + + JsonNode node(data.data(), data.size()); + return toVariant(node); +} + +JsonNode toJson(QVariant object) +{ + JsonNode ret; + + if (object.canConvert()) + ret.Struct() = VariantToMap(object.toMap()); + if (object.canConvert()) + ret.Vector() = VariantToList(object.toList()); + if (object.canConvert()) + ret.String() = object.toString().toUtf8().data(); + if (object.canConvert()) + ret.Bool() = object.toFloat(); + if (object.canConvert()) + ret.Bool() = object.toBool(); + + return ret; +} + +void JsonToFile(QString filename, QVariant object) +{ + std::ofstream file(filename.toUtf8().data(), std::ofstream::binary); + + file << toJson(object); +} + +} \ No newline at end of file diff --git a/launcher/jsonutils.h b/launcher/jsonutils.h new file mode 100644 index 000000000..81988e56a --- /dev/null +++ b/launcher/jsonutils.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include "../lib/JsonNode.h" + +namespace JsonUtils +{ + QVariant toVariant(const JsonNode & node); + QVariant JsonFromFile(QString filename); + + JsonNode toJson(QVariant object); + void JsonToFile(QString filename, QVariant object); +} \ No newline at end of file diff --git a/launcher/modManager/cmodlist.cpp b/launcher/modManager/cmodlist.cpp index a33e68e60..68a3fccb0 100644 --- a/launcher/modManager/cmodlist.cpp +++ b/launcher/modManager/cmodlist.cpp @@ -1,6 +1,9 @@ #include "StdInc.h" #include "cmodlist.h" +#include "../../lib/JsonNode.h" +#include "../../lib/filesystem/CFileInputStream.h" + bool CModEntry::compareVersions(QString lesser, QString greater) { static const int maxSections = 3; // versions consist from up to 3 sections, major.minor.patch @@ -25,7 +28,7 @@ bool CModEntry::compareVersions(QString lesser, QString greater) return false; } -CModEntry::CModEntry(QJsonObject repository, QJsonObject localData, QJsonValue modSettings, QString modname): +CModEntry::CModEntry(QVariantMap repository, QVariantMap localData, QVariant modSettings, QString modname): repository(repository), localData(localData), modSettings(modSettings), @@ -38,7 +41,7 @@ bool CModEntry::isEnabled() const if (!isInstalled()) return false; - return modSettings.toBool(false); + return modSettings.toBool(); } bool CModEntry::isDisabled() const @@ -89,24 +92,24 @@ QString CModEntry::getName() const QVariant CModEntry::getValue(QString value) const { if (repository.contains(value)) - return repository[value].toVariant(); + return repository[value]; if (localData.contains(value)) - return localData[value].toVariant(); + return localData[value]; return QVariant(); } -QJsonObject CModList::copyField(QJsonObject data, QString from, QString to) +QVariantMap CModList::copyField(QVariantMap data, QString from, QString to) { - QJsonObject renamed; + QVariantMap renamed; for (auto it = data.begin(); it != data.end(); it++) { - QJsonObject object = it.value().toObject(); + QVariant object = it.value(); - object.insert(to, object.value(from)); - renamed.insert(it.key(), QJsonValue(object)); + object.toMap().insert(to, object.toMap().value(from)); + renamed.insert(it.key(), object.toMap()); } return renamed; } @@ -116,40 +119,40 @@ void CModList::resetRepositories() repositories.clear(); } -void CModList::addRepository(QJsonObject data) +void CModList::addRepository(QVariantMap data) { repositories.push_back(copyField(data, "version", "latestVersion")); } -void CModList::setLocalModList(QJsonObject data) +void CModList::setLocalModList(QVariantMap data) { localModList = copyField(data, "version", "installedVersion"); } -void CModList::setModSettings(QJsonObject data) +void CModList::setModSettings(QVariant data) { - modSettings = data; + modSettings = data.toMap(); } CModEntry CModList::getMod(QString modname) const { assert(hasMod(modname)); - QJsonObject repo; - QJsonObject local = localModList[modname].toObject(); - QJsonValue settings = modSettings[modname]; + QVariantMap repo; + QVariantMap local = localModList[modname].toMap(); + QVariant settings = modSettings[modname]; for (auto entry : repositories) { if (entry.contains(modname)) { if (repo.empty()) - repo = entry[modname].toObject(); + repo = entry[modname].toMap(); else { if (CModEntry::compareVersions(repo["version"].toString(), - entry[modname].toObject()["version"].toString())) - repo = entry[modname].toObject(); + entry[modname].toMap()["version"].toString())) + repo = entry[modname].toMap(); } } } diff --git a/launcher/modManager/cmodlist.h b/launcher/modManager/cmodlist.h index 766421608..15009050a 100644 --- a/launcher/modManager/cmodlist.h +++ b/launcher/modManager/cmodlist.h @@ -1,9 +1,10 @@ #pragma once -#include -#include +#include #include +class JsonNode; + namespace ModStatus { enum EModStatus @@ -19,13 +20,13 @@ namespace ModStatus class CModEntry { // repository contains newest version only (if multiple are available) - QJsonObject repository; - QJsonObject localData; - QJsonValue modSettings; + QVariantMap repository; + QVariantMap localData; + QVariant modSettings; QString modname; public: - CModEntry(QJsonObject repository, QJsonObject localData, QJsonValue modSettings, QString modname); + CModEntry(QVariantMap repository, QVariantMap localData, QVariant modSettings, QString modname); // installed and enabled bool isEnabled() const; @@ -52,16 +53,16 @@ public: class CModList { - QVector repositories; - QJsonObject localModList; - QJsonObject modSettings; + QVector repositories; + QVariantMap localModList; + QVariantMap modSettings; - QJsonObject copyField(QJsonObject data, QString from, QString to); + QVariantMap copyField(QVariantMap data, QString from, QString to); public: virtual void resetRepositories(); - virtual void addRepository(QJsonObject data); - virtual void setLocalModList(QJsonObject data); - virtual void setModSettings(QJsonObject data); + virtual void addRepository(QVariantMap data); + virtual void setLocalModList(QVariantMap data); + virtual void setModSettings(QVariant data); // returns mod by name. Note: mod MUST exist CModEntry getMod(QString modname) const; diff --git a/launcher/modManager/cmodlistmodel_moc.cpp b/launcher/modManager/cmodlistmodel_moc.cpp index 1e3969b2b..f8e991b1c 100644 --- a/launcher/modManager/cmodlistmodel_moc.cpp +++ b/launcher/modManager/cmodlistmodel_moc.cpp @@ -117,21 +117,21 @@ void CModListModel::resetRepositories() endResetModel(); } -void CModListModel::addRepository(QJsonObject data) +void CModListModel::addRepository(QVariantMap data) { beginResetModel(); CModList::addRepository(data); endResetModel(); } -void CModListModel::setLocalModList(QJsonObject data) +void CModListModel::setLocalModList(QVariantMap data) { beginResetModel(); CModList::setLocalModList(data); endResetModel(); } -void CModListModel::setModSettings(QJsonObject data) +void CModListModel::setModSettings(QVariant data) { beginResetModel(); CModList::setModSettings(data); diff --git a/launcher/modManager/cmodlistmodel_moc.h b/launcher/modManager/cmodlistmodel_moc.h index 01ef3145a..bb1e0ab74 100644 --- a/launcher/modManager/cmodlistmodel_moc.h +++ b/launcher/modManager/cmodlistmodel_moc.h @@ -30,9 +30,9 @@ class CModListModel : public QAbstractTableModel, public CModList public: /// CModListContainer overrides void resetRepositories(); - void addRepository(QJsonObject data); - void setLocalModList(QJsonObject data); - void setModSettings(QJsonObject data); + void addRepository(QVariantMap data); + void setLocalModList(QVariantMap data); + void setModSettings(QVariant data); QString modIndexToName(int index) const; diff --git a/launcher/modManager/cmodmanager.cpp b/launcher/modManager/cmodmanager.cpp index ad2e0b763..e01de1e4b 100644 --- a/launcher/modManager/cmodmanager.cpp +++ b/launcher/modManager/cmodmanager.cpp @@ -5,23 +5,9 @@ #include "../../lib/filesystem/Filesystem.h" #include "../../lib/filesystem/CZipLoader.h" +#include "../jsonutils.h" #include "../launcherdirs.h" -static QJsonObject JsonFromFile(QString filename) -{ - QFile file(filename); - file.open(QFile::ReadOnly); - - return QJsonDocument::fromJson(file.readAll()).object(); -} - -static void JsonToFile(QString filename, QJsonObject object) -{ - QFile file(filename); - file.open(QFile::WriteOnly); - file.write(QJsonDocument(object).toJson()); -} - static QString detectModArchive(QString path, QString modName) { auto files = ZipArchive::listFiles(path.toUtf8().data()); @@ -57,8 +43,8 @@ QString CModManager::settingsPath() void CModManager::loadModSettings() { - modSettings = JsonFromFile(settingsPath()); - modList->setModSettings(modSettings["activeMods"].toObject()); + modSettings = JsonUtils::JsonFromFile(settingsPath()).toMap(); + modList->setModSettings(modSettings["activeMods"]); } void CModManager::resetRepositories() @@ -68,7 +54,7 @@ void CModManager::resetRepositories() void CModManager::loadRepository(QString file) { - modList->addRepository(JsonFromFile(file)); + modList->addRepository(JsonUtils::JsonFromFile(file).toMap()); } void CModManager::loadMods() @@ -78,17 +64,9 @@ void CModManager::loadMods() for (auto modname : installedMods) { ResourceID resID("Mods/" + modname + "/mod.json"); - - if (CResourceHandler::get()->existsResource(resID)) - { - auto data = CResourceHandler::get()->load(resID)->readAll(); - auto array = QByteArray(reinterpret_cast(data.first.get()), data.second); - - auto mod = QJsonDocument::fromJson(array); - assert (mod.isObject()); // TODO: use JsonNode from vcmi code here - QJsonNode parser is just too pedantic - - localMods.insert(QString::fromUtf8(modname.c_str()).toLower(), QJsonValue(mod.object())); - } + std::string name = *CResourceHandler::get()->getResourceName(resID); + auto mod = JsonUtils::JsonFromFile(QString::fromUtf8(name.c_str())); + localMods.insert(QString::fromUtf8(modname.c_str()).toLower(), mod); } modList->setLocalModList(localMods); } @@ -209,15 +187,15 @@ bool CModManager::canDisableMod(QString modname) bool CModManager::doEnableMod(QString mod, bool on) { - QJsonValue value(on); - QJsonObject list = modSettings["activeMods"].toObject(); + QVariant value(on); + QVariantMap list = modSettings["activeMods"].toMap(); list.insert(mod, value); modSettings.insert("activeMods", list); - modList->setModSettings(modSettings["activeMods"].toObject()); + modList->setModSettings(modSettings["activeMods"]); - JsonToFile(settingsPath(), modSettings); + JsonUtils::JsonToFile(settingsPath(), modSettings); return true; } @@ -245,7 +223,7 @@ bool CModManager::doInstallMod(QString modname, QString archivePath) return addError(modname, "Failed to extract mod data"); } - QJsonObject json = JsonFromFile(destDir + modDirName + "/mod.json"); + QVariantMap json = JsonUtils::JsonFromFile(destDir + modDirName + "/mod.json").toMap(); localMods.insert(modname, json); modList->setLocalModList(localMods); diff --git a/launcher/modManager/cmodmanager.h b/launcher/modManager/cmodmanager.h index 4c0582128..800db6b5d 100644 --- a/launcher/modManager/cmodmanager.h +++ b/launcher/modManager/cmodmanager.h @@ -13,8 +13,8 @@ class CModManager bool doInstallMod(QString mod, QString archivePath); bool doUninstallMod(QString mod); - QJsonObject modSettings; - QJsonObject localMods; + QVariantMap modSettings; + QVariantMap localMods; QStringList recentErrors; bool addError(QString modname, QString message); diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index 88f319498..0141f7a88 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -108,5 +108,17 @@ void CSettingsView::on_plainTextEditRepos_textChanged() node->Vector().push_back(entry); } } - +} + +void CSettingsView::on_comboBoxEncoding_currentIndexChanged(int index) +{ + std::string encodings[] = + { + "native", // right now indicates disabled unicode, may be removed in future + "CP1250", "CP1251", "CP1252", // european Windows-125X encoding + "GBK", "gb2312" // chinese, aka CP936. Same encoding rules but different font files. + }; + + Settings node = settings.write["general"]["encoding"]; + node->String() = encodings[index]; } diff --git a/launcher/settingsView/csettingsview_moc.h b/launcher/settingsView/csettingsview_moc.h index 419b91302..fc81c9f46 100644 --- a/launcher/settingsView/csettingsview_moc.h +++ b/launcher/settingsView/csettingsview_moc.h @@ -29,6 +29,8 @@ private slots: void on_plainTextEditRepos_textChanged(); + void on_comboBoxEncoding_currentIndexChanged(int index); + private: Ui::CSettingsView *ui; }; diff --git a/launcher/settingsView/csettingsview_moc.ui b/launcher/settingsView/csettingsview_moc.ui index d28ce195c..4febd56ed 100644 --- a/launcher/settingsView/csettingsview_moc.ui +++ b/launcher/settingsView/csettingsview_moc.ui @@ -7,13 +7,82 @@ 0 0 700 - 303 + 308 Form + + + + 0 + + + + Off + + + + + On + + + + + + + + QPlainTextEdit::NoWrap + + + http://downloads.vcmi.eu/Mods/repository.json + + + + + + + false + + + + 150 + 0 + + + + /home/user/.vcmi + + + true + + + + + + + Player AI + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 8 + 20 + + + + @@ -33,7 +102,54 @@ - + + + + Enable mods on install + + + + + + + 1024 + + + 65535 + + + 3030 + + + + + + + User data directory + + + + + + + Game directory + + + + + + + + 75 + true + + + + AI Settings + + + + Qt::Vertical @@ -56,39 +172,55 @@ - - - - Qt::Vertical + + + + + 75 + true + - - QSizePolicy::Fixed - - - - 56 - 8 - - - - - - - Fullscreen + Video - - - - 1024 + + + + + 75 + true + - - 65535 + + Data Directories (unchangeable) - - 3030 + + + + + + + 75 + true + + + + Repositories + + + + + + + + 75 + true + + + + General @@ -167,14 +299,7 @@ - - - - User data directory - - - - + 1 @@ -191,100 +316,61 @@ - - - - - 75 - true - - - - Repositories - - - - - - - QPlainTextEdit::NoWrap - - - http://downloads.vcmi.eu/Mods/repository.json - - - - - - - Player AI - - - - - + + - Qt::Horizontal + Qt::Vertical QSizePolicy::Fixed - 8 - 20 + 56 + 8 - - - - 0 + + + + Fullscreen + + + + - Off + Native (unicode disabled) - On + Central European (Windows 1250) + + + + + Cyrillic script (Windows 1251) + + + + + Western European (Windows 1252) + + + + + Simplified Chinese (GBK) + + + + + Simplified Chinese (GB2312) - - - - - - Enable mods on install - - - - - - - false - - - - 150 - 0 - - - - /home/user/.vcmi - - - true - - - - - - - Neutral AI - @@ -301,62 +387,17 @@ - - + + - Game directory + Neutral AI - - - - - 75 - true - - + + - AI Settings - - - - - - - - 75 - true - - - - Video - - - - - - - - 75 - true - - - - Data Directories (unchangeable) - - - - - - - - 75 - true - - - - General + Heroes III character set diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index 0d96e6d32..b8826817e 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -472,7 +472,7 @@ void CHeroHandler::loadObject(std::string scope, std::string name, const JsonNod { auto object = loadFromJson(data); object->ID = HeroTypeID(heroes.size()); - object->imageIndex = heroes.size() + 10; // 2 special frames + some extra portraits + object->imageIndex = heroes.size() + 30; // 2 special frames + some extra portraits heroes.push_back(object); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 589579a37..9a02628de 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -95,7 +95,7 @@ set(lib_HEADERS add_library(vcmi SHARED ${lib_SRCS} ${lib_HEADERS}) set_target_properties(vcmi PROPERTIES XCODE_ATTRIBUTE_LD_DYLIB_INSTALL_NAME "@executable_path/libvcmi.dylib") -target_link_libraries(vcmi minizip ${Boost_LIBRARIES} ${SDL_LIBRARY} ${ZLIB_LIBRARIES}) +target_link_libraries(vcmi minizip ${Boost_LIBRARIES} ${SDL_LIBRARY} ${ZLIB_LIBRARIES} ${RT_LIB} ${DL_LIB}) if (NOT APPLE) # Already inside vcmiclient bundle install(TARGETS vcmi DESTINATION ${LIB_DIR}) diff --git a/lib/CModHandler.cpp b/lib/CModHandler.cpp index cbe5ad214..65c981adf 100644 --- a/lib/CModHandler.cpp +++ b/lib/CModHandler.cpp @@ -141,17 +141,29 @@ bool CIdentifierStorage::resolveIdentifier(const ObjectCallback & request) auto entries = registeredObjects.equal_range(fullID); if (entries.first != entries.second) { + size_t matchesFound = 0; + for (auto it = entries.first; it != entries.second; it++) { if (vstd::contains(allowedScopes, it->second.scope)) { - request.callback(it->second.id); - return true; + if (matchesFound == 0) // trigger only once + request.callback(it->second.id); + matchesFound++; } } + if (matchesFound == 1) + return true; // success, only one matching ID + // error found. Try to generate some debug info - logGlobal->errorStream() << "Unknown identifier " << request.type << "." << request.name << " from mod " << request.localScope; + if (matchesFound == 0) + logGlobal->errorStream() << "Unknown identifier!"; + else + logGlobal->errorStream() << "Ambiguous identifier request!"; + + logGlobal->errorStream() << "Request for " << request.type << "." << request.name << " from mod " << request.localScope; + for (auto it = entries.first; it != entries.second; it++) { logGlobal->errorStream() << "\tID is available in mod " << it->second.scope; diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index 1a5034d59..0f809b026 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -4494,12 +4494,13 @@ void CQuest::getVisitText (MetaString &iwText, std::vector &component } break; case MISSION_KILL_HERO: - components.push_back(Component(Component::HERO, heroPortrait, 0, 0)); + components.push_back(Component(Component::HERO_PORTRAIT, heroPortrait, 0, 0)); if (!isCustom) addReplacements(iwText, text); break; case MISSION_HERO: - components.push_back(Component (Component::HERO, m13489val, 0, 0)); + //FIXME: portrait may not match hero, if custom portrait was set in map editor + components.push_back(Component (Component::HERO_PORTRAIT, VLC->heroh->heroes[m13489val]->imageIndex, 0, 0)); if (!isCustom) iwText.addReplacement(VLC->heroh->heroes[m13489val]->name); break; diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 2dae86d70..ec2bcee53 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1138,7 +1138,7 @@ struct NewTurn : public CPackForClient //101 struct Component : public CPack //2002 helper for object scrips informations { - enum EComponentType {PRIM_SKILL, SEC_SKILL, RESOURCE, CREATURE, ARTIFACT, EXPERIENCE, SPELL, MORALE, LUCK, BUILDING, HERO, FLAG}; + enum EComponentType {PRIM_SKILL, SEC_SKILL, RESOURCE, CREATURE, ARTIFACT, EXPERIENCE, SPELL, MORALE, LUCK, BUILDING, HERO_PORTRAIT, FLAG}; ui16 id, subtype; //id uses ^^^ enums, when id==EXPPERIENCE subtype==0 means exp points and subtype==1 levels) si32 val; // + give; - take si16 when; // 0 - now; +x - within x days; -x - per x days diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 8a1e878f0..5409c20f0 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1011,15 +1011,15 @@ DLL_LINKAGE void HeroLevelUp::applyGs( CGameState *gs ) CGHeroInstance* h = gs->getHero(hero->id); h->level = level; //deterministic secondary skills - h->skillsInfo.magicSchoolCounter = (++h->skillsInfo.magicSchoolCounter) % h->maxlevelsToMagicSchool(); - h->skillsInfo.wisdomCounter = (++h->skillsInfo.wisdomCounter) % h->maxlevelsToWisdom(); + h->skillsInfo.magicSchoolCounter = (h->skillsInfo.magicSchoolCounter + 1) % h->maxlevelsToMagicSchool(); + h->skillsInfo.wisdomCounter = (h->skillsInfo.wisdomCounter + 1) % h->maxlevelsToWisdom(); if (vstd::contains(skills, SecondarySkill::WISDOM)) h->skillsInfo.resetWisdomCounter(); SecondarySkill spellSchools[] = { SecondarySkill::FIRE_MAGIC, SecondarySkill::WATER_MAGIC, SecondarySkill::EARTH_MAGIC, SecondarySkill::EARTH_MAGIC}; for (auto skill : spellSchools) { - if (vstd::contains(skills, SecondarySkill::WISDOM)) + if (vstd::contains(skills, skill)) { h->skillsInfo.resetMagicSchoolCounter(); break; diff --git a/lib/filesystem/Filesystem.cpp b/lib/filesystem/Filesystem.cpp index de553f5a3..b13227f02 100644 --- a/lib/filesystem/Filesystem.cpp +++ b/lib/filesystem/Filesystem.cpp @@ -300,7 +300,9 @@ std::vector CResourceHandler::getAvailableMods() continue; } } - foundMods.push_back(name); + + if (!name.empty()) + foundMods.push_back(name); } return foundMods; }