Permalink
Browse files

Add preliminary support for Skyrim Special Edition

Using a non-release snapshot of libloadorder until it's verified to
work.
  • Loading branch information...
WrinklyNinja committed Oct 27, 2016
1 parent 13b0841 commit 480f386167aefb3b53879e0fd7db11e321e86e79
View
@@ -82,7 +82,7 @@ set(LIBGIT2_LIBRARIES "${BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_
ExternalProject_Add(libloadorder
PREFIX "external"
DEPENDS libespm
URL "https://github.com/WrinklyNinja/libloadorder/archive/9.4.1.tar.gz"
URL "https://github.com/WrinklyNinja/libloadorder/archive/skyrim-se-support.tar.gz"
CMAKE_ARGS -DBOOST_INCLUDEDIR=${Boost_INCLUDE_DIR} -DMSVC_STATIC_RUNTIME=${MSVC_STATIC_RUNTIME}
BUILD_COMMAND ${CMAKE_COMMAND} --build . --target loadorder --config $(CONFIGURATION)
INSTALL_COMMAND "")
@@ -42,6 +42,8 @@ enum struct GameType : unsigned int {
fonv,
/** Fallout 4 */
fo4,
/** The Elder Scrolls IV: Skyrim Special Edition */

This comment has been minimized.

Show comment
Hide comment
@Vultraz

Vultraz Oct 28, 2016

Er.... 4?

@Vultraz

This comment has been minimized.

Show comment
Hide comment
@WrinklyNinja

WrinklyNinja Oct 28, 2016

Member

Whoops, fixed in 176275c.

@WrinklyNinja

WrinklyNinja Oct 28, 2016

Member

Whoops, fixed in 176275c.

tes5se,
};
}
@@ -44,6 +44,7 @@ LootSettings::LootSettings() :
GameSettings(GameType::fo3),
GameSettings(GameType::fonv),
GameSettings(GameType::fo4),
GameSettings(GameType::tes5se),
GameSettings(GameType::tes4, "Nehrim")
.SetName("Nehrim - At Fate's Edge")
.SetMaster("Nehrim.esm")
@@ -100,6 +101,9 @@ void LootSettings::load(YAML::Node& settings) {
if (find(begin(gameSettings_), end(gameSettings_), GameSettings(GameType::fo4)) == end(gameSettings_))
gameSettings_.push_back(GameSettings(GameType::fo4));
if (find(begin(gameSettings_), end(gameSettings_), GameSettings(GameType::tes5se)) == end(gameSettings_))
gameSettings_.push_back(GameSettings(GameType::tes5se));
}
if (settings["filters"])
@@ -57,10 +57,6 @@ Game::Game(const GameSettings& gameSettings) : GameSettings(gameSettings), plugi
Game::Game(const GameType gameType, const std::string& folder) : GameSettings(gameType, folder), pluginsFullyLoaded_(false) {}
void Game::Init(bool createFolder, const boost::filesystem::path& gameLocalAppData) {
if (Type() != GameType::tes4 && Type() != GameType::tes5 && Type() != GameType::fo3 && Type() != GameType::fonv && Type() != GameType::fo4) {
throw std::invalid_argument(translate("Invalid game ID supplied.").str());
}
BOOST_LOG_TRIVIAL(info) << "Initialising filesystem-related data for game: " << Name();
if (!this->IsInstalled()) {
@@ -49,10 +49,16 @@ GameSettings::GameSettings(const GameType gameCode, const std::string& folder) :
lootFolderName_ = "Oblivion";
masterFile_ = "Oblivion.esm";
repositoryURL_ = "https://github.com/loot/oblivion.git";
} else if (Type() == GameType::tes5) {
name_ = "TES V: Skyrim";
registryKey_ = "Software\\Bethesda Softworks\\Skyrim\\Installed Path";
lootFolderName_ = "Skyrim";
} else if (Type() == GameType::tes5 || Type() == GameType::tes5se) {
if (Type() == GameType::tes5) {
name_ = "TES V: Skyrim";
registryKey_ = "Software\\Bethesda Softworks\\Skyrim\\Installed Path";
lootFolderName_ = "Skyrim";
} else {
name_ = "TES V: Skyrim Special Edition";
registryKey_ = "Software\\Bethesda Softworks\\Skyrim Special Edition\\Installed Path";
lootFolderName_ = "SkyrimSE";
}
masterFile_ = "Skyrim.esm";
repositoryURL_ = "https://github.com/loot/skyrim.git";
} else if (Type() == GameType::fo3) {
@@ -122,7 +128,7 @@ GameType GameSettings::Type() const {
libespm::GameId GameSettings::LibespmId() const {
if (type_ == GameType::tes4)
return libespm::GameId::OBLIVION;
else if (type_ == GameType::tes5)
else if (type_ == GameType::tes5 || type_ == GameType::tes5se)
return libespm::GameId::SKYRIM;
else if (type_ == GameType::fo3)
return libespm::GameId::FALLOUT3;
@@ -124,6 +124,8 @@ struct convert<loot::GameSettings> {
rhs = GameSettings(GameType::fonv, node["folder"].as<std::string>());
else if (node["type"].as<std::string>() == GameSettings(GameType::fo4).FolderName())
rhs = GameSettings(GameType::fo4, node["folder"].as<std::string>());
else if (node["type"].as<std::string>() == GameSettings(GameType::tes5se).FolderName())
rhs = GameSettings(GameType::tes5se, node["folder"].as<std::string>());
else
throw RepresentationException(node.Mark(), "bad conversion: invalid value for 'type' key in 'game settings' object");
@@ -41,14 +41,6 @@ LoadOrderHandler::~LoadOrderHandler() {
}
void LoadOrderHandler::Init(const GameSettings& game, const boost::filesystem::path& gameLocalAppData) {
if (game.Type() != GameType::tes4
&& game.Type() != GameType::tes5
&& game.Type() != GameType::fo3
&& game.Type() != GameType::fonv
&& game.Type() != GameType::fo4) {
throw std::invalid_argument(translate("Unsupported game ID supplied.").str());
}
if (game.GamePath().empty()) {
BOOST_LOG_TRIVIAL(error) << "Game path is not initialised.";
throw std::invalid_argument(translate("Game path is not initialised.").str());
@@ -76,6 +68,8 @@ void LoadOrderHandler::Init(const GameSettings& game, const boost::filesystem::p
ret = lo_create_handle(&gh_, LIBLO_GAME_FNV, game.GamePath().string().c_str(), gameLocalDataPath);
else if (game.Type() == GameType::fo4)
ret = lo_create_handle(&gh_, LIBLO_GAME_FO4, game.GamePath().string().c_str(), gameLocalDataPath);
else if (game.Type() == GameType::tes5se)
ret = lo_create_handle(&gh_, LIBLO_GAME_TES5SE, game.GamePath().string().c_str(), gameLocalDataPath);
else
ret = LIBLO_ERROR_INVALID_ARGS;
@@ -46,6 +46,7 @@ class GetGameTypesQuery : public Query {
temp.push_back(GameSettings(GameType::fo3).FolderName());
temp.push_back(GameSettings(GameType::fonv).FolderName());
temp.push_back(GameSettings(GameType::fo4).FolderName());
temp.push_back(GameSettings(GameType::tes5se).FolderName());
return JSON::stringify(temp);
}
@@ -51,7 +51,9 @@ class SortPluginsQuery : public MetadataQuery {
//Sort plugins into their load order.
std::vector<Plugin> plugins = sortPlugins();
if ((state_.getCurrentGame().Type() == GameType::tes5 || state_.getCurrentGame().Type() == GameType::fo4))
if ((state_.getCurrentGame().Type() == GameType::tes5
|| state_.getCurrentGame().Type() == GameType::fo4
|| state_.getCurrentGame().Type() == GameType::tes5se))
applyUnchangedLoadOrder(plugins);
std::string json = generateJsonResponse(plugins);
@@ -69,7 +69,8 @@ INSTANTIATE_TEST_CASE_P(,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4));
GameType::fo4,
GameType::tes5se));
TEST_P(CreateDatabaseTest, shouldSucceedIfPassedValidParametersWithRelativePaths) {
EXPECT_NO_THROW(db_ = CreateDatabase(GetParam(), dataPath.parent_path().string(), localPath.string()));
@@ -98,7 +98,8 @@ INSTANTIATE_TEST_CASE_P(,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4));
GameType::fo4,
GameType::tes5se));
TEST_P(DatabaseInterfaceTest, loadListsShouldThrowIfNoMasterlistIsPresent) {
EXPECT_ANY_THROW(db_->LoadLists(masterlistPath.string(), ""));
@@ -53,6 +53,7 @@ TEST_F(LootSettingsTest, defaultConstructorShouldSetDefaultValues) {
GameSettings(GameType::fo3),
GameSettings(GameType::fonv),
GameSettings(GameType::fo4),
GameSettings(GameType::tes5se),
GameSettings(GameType::tes4, "Nehrim")
.SetName("Nehrim - At Fate's Edge")
.SetMaster("Nehrim.esm")
@@ -304,6 +305,7 @@ TEST_F(LootSettingsTest, loadingFromYamlShouldAddMissingBaseGames) {
GameSettings(GameType::fo3),
GameSettings(GameType::fonv),
GameSettings(GameType::fo4),
GameSettings(GameType::tes5se),
});
EXPECT_EQ(expectedGameSettings, settings_.getGameSettings());
}
@@ -53,7 +53,8 @@ INSTANTIATE_TEST_CASE_P(,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4));
GameType::fo4,
GameType::tes5se));
TEST_P(GameTest, constructingFromGameSettingsShouldUseTheirValues) {
GameSettings settings = GameSettings(GetParam(), "folder");
@@ -45,7 +45,8 @@ INSTANTIATE_TEST_CASE_P(,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4));
GameType::fo4,
GameType::tes5se));
TEST_P(LoadOrderHandlerTest, initShouldThrowIfNoGamePathIsSet) {
GameSettings game(GetParam());
@@ -136,7 +137,7 @@ TEST_P(LoadOrderHandlerTest, setLoadOrderShouldSetTheLoadOrder) {
});
EXPECT_NO_THROW(loadOrderHandler_.SetLoadOrder(loadOrder));
if (GetParam() == GameType::fo4)
if (GetParam() == GameType::fo4 || GetParam() == GameType::tes5se)
loadOrder.erase(begin(loadOrder));
EXPECT_EQ(loadOrder, getLoadOrder());
@@ -73,7 +73,8 @@ INSTANTIATE_TEST_CASE_P(,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4));
GameType::fo4,
GameType::tes5se));
TEST_P(MasterlistTest, updateWithGameParameterShouldReturnTrueIfNoMasterlistExists) {
Game game(GetParam());
@@ -74,7 +74,8 @@ INSTANTIATE_TEST_CASE_P(,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4));
GameType::fo4,
GameType::tes5se));
TEST_P(ConditionGrammarTest, parsingInvalidSyntaxShouldThrow) {
Grammar grammar(nullptr);
@@ -45,7 +45,8 @@ INSTANTIATE_TEST_CASE_P(,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4));
GameType::fo4,
GameType::tes5se));
TEST_P(ConditionalMetadataTest, defaultConstructorShouldSetEmptyConditionString) {
EXPECT_TRUE(conditionalMetadata_.Condition().empty());
@@ -91,7 +91,8 @@ INSTANTIATE_TEST_CASE_P(,
GameType::tes5,
GameType::fo3,
GameType::fonv,
GameType::fo4));
GameType::fo4,
GameType::tes5se));
TEST_P(PluginTest, loadingHeaderOnlyShouldReadHeaderData) {
Plugin plugin(game_, blankEsm, true);
@@ -196,7 +196,7 @@ class CommonGameTestFixture : public ::testing::TestWithParam<GameType> {
inline std::string getMasterFile() const {
if (GetParam() == GameType::tes4)
return "Oblivion.esm";
else if (GetParam() == GameType::tes5)
else if (GetParam() == GameType::tes5 || GetParam() == GameType::tes5se)
return "Skyrim.esm";
else if (GetParam() == GameType::fo3)
return "Fallout3.esm";
@@ -216,9 +216,10 @@ class CommonGameTestFixture : public ::testing::TestWithParam<GameType> {
void setLoadOrder(const std::vector<std::pair<std::string, bool>>& loadOrder) const {
boost::filesystem::ofstream out(localPath / "plugins.txt");
for (const auto &plugin : loadOrder) {
if (GetParam() == GameType::fo4 && plugin.second)
out << '*';
else if (GetParam() != GameType::fo4 && !plugin.second)
if (GetParam() == GameType::fo4 || GetParam() == GameType::tes5se) {
if (plugin.second)
out << '*';
} else if (!plugin.second)
continue;
out << plugin.first << std::endl;

0 comments on commit 480f386

Please sign in to comment.